From f1ce98eb07f6c95222f7ed591ecfef712bef48ba Mon Sep 17 00:00:00 2001 From: qianlifeng Date: Thu, 10 Jul 2014 23:57:08 +0800 Subject: [PATCH] Implement #15 --- Plugins/Wox.Plugin.HackerNews/main.py | 10 +- Plugins/Wox.Plugin.HackerNews/run.bat | 3 +- PythonHome/DLLs/pyc.ico | Bin 19790 -> 0 bytes PythonHome/Lib/BaseHTTPServer.py | 603 ++ PythonHome/Lib/BaseHTTPServer.pyc | Bin 21389 -> 0 bytes PythonHome/Lib/Bastion.py | 180 + PythonHome/Lib/Bastion.pyc | Bin 6435 -> 0 bytes PythonHome/Lib/CGIHTTPServer.py | 377 + PythonHome/Lib/CGIHTTPServer.pyc | Bin 10868 -> 0 bytes PythonHome/Lib/ConfigParser.py | 753 ++ PythonHome/Lib/ConfigParser.pyc | Bin 24918 -> 0 bytes PythonHome/Lib/Cookie.py | 758 ++ PythonHome/Lib/Cookie.pyc | Bin 22230 -> 23522 bytes PythonHome/Lib/DocXMLRPCServer.py | 279 + PythonHome/Lib/DocXMLRPCServer.pyc | Bin 9564 -> 0 bytes PythonHome/Lib/HTMLParser.py | 475 ++ PythonHome/Lib/HTMLParser.pyc | Bin 13574 -> 14662 bytes .../Lib/{MimeWriter.pyc => MimeWriter.py} | Bin 7229 -> 6482 bytes PythonHome/Lib/Queue.py | 244 + PythonHome/Lib/Queue.pyc | Bin 9284 -> 10236 bytes PythonHome/Lib/SimpleHTTPServer.py | 230 + PythonHome/Lib/SimpleHTTPServer.pyc | Bin 7701 -> 0 bytes PythonHome/Lib/SimpleXMLRPCServer.py | 708 ++ PythonHome/Lib/SimpleXMLRPCServer.pyc | Bin 22322 -> 0 bytes PythonHome/Lib/SocketServer.py | 733 ++ PythonHome/Lib/SocketServer.pyc | Bin 23733 -> 0 bytes PythonHome/Lib/StringIO.py | 324 + PythonHome/Lib/StringIO.pyc | Bin 11385 -> 12031 bytes PythonHome/Lib/UserDict.py | 180 + PythonHome/Lib/UserDict.pyc | Bin 8595 -> 10125 bytes PythonHome/Lib/UserList.py | 88 + PythonHome/Lib/UserList.pyc | Bin 6067 -> 0 bytes PythonHome/Lib/UserString.py | 228 + PythonHome/Lib/UserString.pyc | Bin 13844 -> 0 bytes PythonHome/Lib/_LWPCookieJar.py | 170 + PythonHome/Lib/_LWPCookieJar.pyc | Bin 5504 -> 5708 bytes PythonHome/Lib/_MozillaCookieJar.py | 149 + PythonHome/Lib/_MozillaCookieJar.pyc | Bin 4440 -> 4576 bytes PythonHome/Lib/__future__.py | 128 + PythonHome/Lib/__future__.pyc | Bin 4262 -> 4402 bytes PythonHome/Lib/__phello__.foo.py | 1 + PythonHome/Lib/__phello__.foo.pyc | Bin 110 -> 0 bytes PythonHome/Lib/_abcoll.py | 690 ++ PythonHome/Lib/_abcoll.pyc | Bin 25060 -> 28596 bytes PythonHome/Lib/_osx_support.py | 502 ++ PythonHome/Lib/_osx_support.pyc | Bin 11527 -> 0 bytes PythonHome/Lib/_pyio.py | 2030 ++++++ PythonHome/Lib/_pyio.pyc | Bin 61784 -> 0 bytes PythonHome/Lib/_strptime.py | 467 ++ PythonHome/Lib/_strptime.pyc | Bin 14575 -> 0 bytes PythonHome/Lib/_threading_local.py | 251 + PythonHome/Lib/_threading_local.pyc | Bin 6469 -> 0 bytes PythonHome/Lib/_weakrefset.py | 204 + PythonHome/Lib/_weakrefset.pyc | Bin 9438 -> 11070 bytes PythonHome/Lib/abc.py | 185 + PythonHome/Lib/abc.pyc | Bin 6088 -> 6462 bytes PythonHome/Lib/aifc.py | 986 +++ PythonHome/Lib/aifc.pyc | Bin 29358 -> 0 bytes PythonHome/Lib/antigravity.py | 4 + PythonHome/Lib/antigravity.pyc | Bin 188 -> 0 bytes PythonHome/Lib/{anydbm.pyc => anydbm.py} | Bin 2755 -> 2663 bytes PythonHome/Lib/argparse.py | 2367 +++++++ PythonHome/Lib/argparse.pyc | Bin 61934 -> 0 bytes PythonHome/Lib/ast.py | 311 + PythonHome/Lib/ast.pyc | Bin 12834 -> 0 bytes PythonHome/Lib/asynchat.py | 314 + PythonHome/Lib/asynchat.pyc | Bin 8190 -> 0 bytes PythonHome/Lib/asyncore.py | 659 ++ PythonHome/Lib/asyncore.pyc | Bin 17953 -> 0 bytes PythonHome/Lib/atexit.py | 65 + PythonHome/Lib/atexit.pyc | Bin 2173 -> 2377 bytes PythonHome/Lib/audiodev.py | 260 + PythonHome/Lib/audiodev.pyc | Bin 8063 -> 0 bytes PythonHome/Lib/base64.py | 360 + PythonHome/Lib/base64.pyc | Bin 10798 -> 11410 bytes PythonHome/Lib/bdb.py | 645 ++ PythonHome/Lib/bdb.pyc | Bin 18186 -> 0 bytes PythonHome/Lib/binhex.py | 508 ++ PythonHome/Lib/binhex.pyc | Bin 14635 -> 0 bytes PythonHome/Lib/bisect.py | 92 + PythonHome/Lib/bisect.pyc | Bin 3046 -> 3216 bytes PythonHome/Lib/bsddb/__init__.py | 455 ++ PythonHome/Lib/bsddb/__init__.pyc | Bin 11893 -> 0 bytes PythonHome/Lib/bsddb/db.py | 60 + PythonHome/Lib/bsddb/db.pyc | Bin 577 -> 0 bytes PythonHome/Lib/bsddb/dbobj.py | 266 + PythonHome/Lib/bsddb/dbobj.pyc | Bin 17218 -> 0 bytes PythonHome/Lib/bsddb/dbrecio.py | 190 + PythonHome/Lib/bsddb/dbrecio.pyc | Bin 5121 -> 0 bytes PythonHome/Lib/bsddb/dbshelve.py | 381 + PythonHome/Lib/bsddb/dbshelve.pyc | Bin 12242 -> 0 bytes PythonHome/Lib/bsddb/dbtables.py | 843 +++ PythonHome/Lib/bsddb/dbtables.pyc | Bin 23627 -> 0 bytes PythonHome/Lib/bsddb/dbutils.py | 83 + PythonHome/Lib/bsddb/dbutils.pyc | Bin 1597 -> 0 bytes PythonHome/Lib/cProfile.py | 199 + PythonHome/Lib/cProfile.pyc | Bin 6098 -> 0 bytes PythonHome/Lib/calendar.py | 713 ++ PythonHome/Lib/calendar.pyc | Bin 27394 -> 30076 bytes PythonHome/Lib/cgi.py | 1059 +++ PythonHome/Lib/cgi.pyc | Bin 32214 -> 34560 bytes PythonHome/Lib/cgitb.py | 323 + PythonHome/Lib/cgitb.pyc | Bin 11914 -> 0 bytes PythonHome/Lib/chunk.py | 167 + PythonHome/Lib/chunk.pyc | Bin 5426 -> 0 bytes PythonHome/Lib/cmd.py | 404 ++ PythonHome/Lib/cmd.pyc | Bin 13724 -> 0 bytes PythonHome/Lib/code.py | 310 + PythonHome/Lib/code.pyc | Bin 10093 -> 0 bytes PythonHome/Lib/codecs.py | 1095 +++ PythonHome/Lib/codecs.pyc | Bin 36115 -> 39311 bytes PythonHome/Lib/{codeop.pyc => codeop.py} | Bin 6447 -> 5999 bytes PythonHome/Lib/collections.py | 702 ++ PythonHome/Lib/collections.pyc | Bin 24547 -> 26315 bytes PythonHome/Lib/colorsys.py | 156 + PythonHome/Lib/colorsys.pyc | Bin 3871 -> 0 bytes PythonHome/Lib/commands.py | 90 + PythonHome/Lib/commands.pyc | Bin 2379 -> 0 bytes PythonHome/Lib/compileall.py | 227 + PythonHome/Lib/compileall.pyc | Bin 6986 -> 0 bytes .../compiler/{__init__.pyc => __init__.py} | Bin 1282 -> 1023 bytes PythonHome/Lib/compiler/ast.py | 1419 ++++ PythonHome/Lib/compiler/ast.pyc | Bin 66290 -> 0 bytes PythonHome/Lib/compiler/consts.py | 23 + PythonHome/Lib/compiler/consts.pyc | Bin 722 -> 0 bytes PythonHome/Lib/compiler/future.py | 74 + PythonHome/Lib/compiler/future.pyc | Bin 2806 -> 0 bytes PythonHome/Lib/compiler/misc.py | 73 + PythonHome/Lib/compiler/misc.pyc | Bin 3448 -> 0 bytes PythonHome/Lib/compiler/pyassem.py | 763 ++ PythonHome/Lib/compiler/pyassem.pyc | Bin 24734 -> 0 bytes PythonHome/Lib/compiler/pycodegen.pyc | Bin 53920 -> 0 bytes PythonHome/Lib/compiler/symbols.py | 462 ++ PythonHome/Lib/compiler/symbols.pyc | Bin 16837 -> 0 bytes PythonHome/Lib/compiler/syntax.py | 46 + PythonHome/Lib/compiler/syntax.pyc | Bin 1792 -> 0 bytes PythonHome/Lib/compiler/transformer.py | 1535 ++++ PythonHome/Lib/compiler/transformer.pyc | Bin 45754 -> 0 bytes PythonHome/Lib/compiler/visitor.py | 113 + PythonHome/Lib/compiler/visitor.pyc | Bin 4037 -> 0 bytes PythonHome/Lib/contextlib.py | 154 + PythonHome/Lib/contextlib.pyc | Bin 4394 -> 0 bytes PythonHome/Lib/cookielib.py | 1794 +++++ PythonHome/Lib/cookielib.pyc | Bin 54236 -> 57534 bytes PythonHome/Lib/copy.py | 433 ++ PythonHome/Lib/copy.pyc | Bin 12064 -> 12948 bytes PythonHome/Lib/copy_reg.py | 201 + PythonHome/Lib/copy_reg.pyc | Bin 5058 -> 5432 bytes PythonHome/Lib/csv.py | 456 ++ PythonHome/Lib/csv.pyc | Bin 13375 -> 0 bytes PythonHome/Lib/ctypes/__init__.py | 555 ++ PythonHome/Lib/ctypes/__init__.pyc | Bin 20021 -> 22027 bytes PythonHome/Lib/ctypes/_endian.py | 64 + PythonHome/Lib/ctypes/_endian.pyc | Bin 2277 -> 2481 bytes PythonHome/Lib/ctypes/macholib/__init__.py | 12 + PythonHome/Lib/ctypes/macholib/__init__.pyc | Bin 301 -> 0 bytes PythonHome/Lib/ctypes/macholib/dyld.py | 169 + PythonHome/Lib/ctypes/macholib/dyld.pyc | Bin 5547 -> 0 bytes PythonHome/Lib/ctypes/macholib/dylib.py | 66 + PythonHome/Lib/ctypes/macholib/dylib.pyc | Bin 2255 -> 0 bytes PythonHome/Lib/ctypes/macholib/framework.py | 68 + PythonHome/Lib/ctypes/macholib/framework.pyc | Bin 2565 -> 0 bytes PythonHome/Lib/ctypes/util.py | 276 + PythonHome/Lib/ctypes/util.pyc | Bin 7914 -> 8492 bytes PythonHome/Lib/ctypes/wintypes.py | 185 + PythonHome/Lib/ctypes/wintypes.pyc | Bin 5890 -> 0 bytes PythonHome/Lib/curses/__init__.py | 59 + PythonHome/Lib/curses/__init__.pyc | Bin 1508 -> 0 bytes PythonHome/Lib/curses/ascii.py | 99 + PythonHome/Lib/curses/ascii.pyc | Bin 4775 -> 0 bytes PythonHome/Lib/curses/has_key.py | 192 + PythonHome/Lib/curses/has_key.pyc | Bin 5907 -> 0 bytes PythonHome/Lib/curses/panel.py | 8 + PythonHome/Lib/curses/panel.pyc | Bin 262 -> 0 bytes PythonHome/Lib/curses/textpad.py | 188 + PythonHome/Lib/curses/textpad.pyc | Bin 6719 -> 0 bytes PythonHome/Lib/curses/wrapper.py | 50 + PythonHome/Lib/curses/wrapper.pyc | Bin 1188 -> 0 bytes PythonHome/Lib/dbhash.py | 18 + PythonHome/Lib/dbhash.pyc | Bin 688 -> 0 bytes PythonHome/Lib/decimal.py | 6198 +++++++++++++++++ PythonHome/Lib/decimal.pyc | Bin 167489 -> 0 bytes PythonHome/Lib/difflib.py | 2057 ++++++ PythonHome/Lib/difflib.pyc | Bin 61139 -> 0 bytes PythonHome/Lib/dircache.py | 41 + PythonHome/Lib/dircache.pyc | Bin 1516 -> 0 bytes PythonHome/Lib/dis.py | 224 + PythonHome/Lib/dis.pyc | Bin 6108 -> 6460 bytes PythonHome/Lib/distutils/__init__.py | 19 + PythonHome/Lib/distutils/__init__.pyc | Bin 380 -> 0 bytes PythonHome/Lib/distutils/archive_util.py | 243 + PythonHome/Lib/distutils/archive_util.pyc | Bin 7416 -> 0 bytes PythonHome/Lib/distutils/bcppcompiler.py | 394 ++ PythonHome/Lib/distutils/bcppcompiler.pyc | Bin 7747 -> 0 bytes PythonHome/Lib/distutils/ccompiler.py | 1095 +++ PythonHome/Lib/distutils/ccompiler.pyc | Bin 36549 -> 0 bytes PythonHome/Lib/distutils/cmd.py | 457 ++ PythonHome/Lib/distutils/cmd.pyc | Bin 16619 -> 0 bytes PythonHome/Lib/distutils/command/__init__.py | 33 + PythonHome/Lib/distutils/command/__init__.pyc | Bin 660 -> 0 bytes PythonHome/Lib/distutils/command/bdist.py | 146 + PythonHome/Lib/distutils/command/bdist.pyc | Bin 5129 -> 0 bytes .../Lib/distutils/command/bdist_dumb.py | 133 + .../Lib/distutils/command/bdist_dumb.pyc | Bin 4968 -> 0 bytes PythonHome/Lib/distutils/command/bdist_msi.py | 742 ++ .../Lib/distutils/command/bdist_msi.pyc | Bin 23758 -> 0 bytes PythonHome/Lib/distutils/command/bdist_rpm.py | 588 ++ .../Lib/distutils/command/bdist_rpm.pyc | Bin 17601 -> 0 bytes .../Lib/distutils/command/bdist_wininst.py | 368 + .../Lib/distutils/command/bdist_wininst.pyc | Bin 10650 -> 0 bytes PythonHome/Lib/distutils/command/build.py | 147 + PythonHome/Lib/distutils/command/build.pyc | Bin 5097 -> 0 bytes .../Lib/distutils/command/build_clib.py | 209 + .../Lib/distutils/command/build_clib.pyc | Bin 6283 -> 0 bytes PythonHome/Lib/distutils/command/build_ext.py | 766 ++ .../Lib/distutils/command/build_ext.pyc | Bin 19280 -> 0 bytes PythonHome/Lib/distutils/command/build_py.py | 394 ++ PythonHome/Lib/distutils/command/build_py.pyc | Bin 11218 -> 0 bytes .../Lib/distutils/command/build_scripts.py | 131 + .../Lib/distutils/command/build_scripts.pyc | Bin 4429 -> 0 bytes PythonHome/Lib/distutils/command/check.py | 149 + PythonHome/Lib/distutils/command/check.pyc | Bin 6045 -> 0 bytes PythonHome/Lib/distutils/command/clean.py | 80 + PythonHome/Lib/distutils/command/clean.pyc | Bin 3101 -> 0 bytes PythonHome/Lib/distutils/command/config.py | 357 + PythonHome/Lib/distutils/command/config.pyc | Bin 12389 -> 0 bytes PythonHome/Lib/distutils/command/install.py | 672 ++ PythonHome/Lib/distutils/command/install.pyc | Bin 16755 -> 0 bytes .../Lib/distutils/command/install_data.py | 81 + .../Lib/distutils/command/install_data.pyc | Bin 3059 -> 0 bytes .../Lib/distutils/command/install_egg_info.py | 78 + .../distutils/command/install_egg_info.pyc | Bin 3631 -> 0 bytes .../Lib/distutils/command/install_headers.py | 51 + .../Lib/distutils/command/install_headers.pyc | Bin 2191 -> 0 bytes .../Lib/distutils/command/install_lib.py | 219 + .../Lib/distutils/command/install_lib.pyc | Bin 6604 -> 0 bytes .../Lib/distutils/command/install_scripts.py | 64 + .../Lib/distutils/command/install_scripts.pyc | Bin 2893 -> 0 bytes PythonHome/Lib/distutils/command/register.py | 315 + PythonHome/Lib/distutils/command/register.pyc | Bin 10027 -> 0 bytes PythonHome/Lib/distutils/command/sdist.py | 477 ++ PythonHome/Lib/distutils/command/sdist.pyc | Bin 16430 -> 0 bytes PythonHome/Lib/distutils/command/upload.py | 195 + PythonHome/Lib/distutils/command/upload.pyc | Bin 6238 -> 0 bytes PythonHome/Lib/distutils/config.py | 116 + PythonHome/Lib/distutils/config.pyc | Bin 3535 -> 0 bytes PythonHome/Lib/distutils/core.py | 239 + PythonHome/Lib/distutils/core.pyc | Bin 7638 -> 0 bytes PythonHome/Lib/distutils/cygwinccompiler.py | 463 ++ PythonHome/Lib/distutils/cygwinccompiler.pyc | Bin 9645 -> 0 bytes PythonHome/Lib/distutils/debug.py | 7 + PythonHome/Lib/distutils/debug.pyc | Bin 249 -> 0 bytes PythonHome/Lib/distutils/dep_util.py | 89 + PythonHome/Lib/distutils/dep_util.pyc | Bin 3160 -> 0 bytes PythonHome/Lib/distutils/dir_util.py | 214 + PythonHome/Lib/distutils/dir_util.pyc | Bin 6753 -> 0 bytes PythonHome/Lib/distutils/dist.py | 1249 ++++ PythonHome/Lib/distutils/dist.pyc | Bin 39231 -> 0 bytes PythonHome/Lib/distutils/emxccompiler.py | 319 + PythonHome/Lib/distutils/emxccompiler.pyc | Bin 7332 -> 0 bytes PythonHome/Lib/distutils/errors.py | 88 + PythonHome/Lib/distutils/errors.pyc | Bin 6185 -> 0 bytes PythonHome/Lib/distutils/extension.py | 255 + PythonHome/Lib/distutils/extension.pyc | Bin 7391 -> 0 bytes PythonHome/Lib/distutils/fancy_getopt.py | 484 ++ PythonHome/Lib/distutils/fancy_getopt.pyc | Bin 11853 -> 0 bytes PythonHome/Lib/distutils/file_util.py | 231 + PythonHome/Lib/distutils/file_util.pyc | Bin 6601 -> 0 bytes PythonHome/Lib/distutils/filelist.py | 343 + PythonHome/Lib/distutils/filelist.pyc | Bin 10508 -> 0 bytes PythonHome/Lib/distutils/log.py | 71 + PythonHome/Lib/distutils/log.pyc | Bin 2726 -> 0 bytes PythonHome/Lib/distutils/msvc9compiler.py | 801 +++ PythonHome/Lib/distutils/msvc9compiler.pyc | Bin 21387 -> 0 bytes PythonHome/Lib/distutils/msvccompiler.py | 659 ++ PythonHome/Lib/distutils/msvccompiler.pyc | Bin 17393 -> 0 bytes PythonHome/Lib/distutils/spawn.py | 226 + PythonHome/Lib/distutils/spawn.pyc | Bin 6363 -> 0 bytes PythonHome/Lib/distutils/sysconfig.py | 482 ++ PythonHome/Lib/distutils/sysconfig.pyc | Bin 13137 -> 0 bytes PythonHome/Lib/distutils/text_file.py | 304 + PythonHome/Lib/distutils/text_file.pyc | Bin 9079 -> 0 bytes PythonHome/Lib/distutils/unixccompiler.py | 288 + PythonHome/Lib/distutils/unixccompiler.pyc | Bin 7433 -> 0 bytes PythonHome/Lib/distutils/util.py | 477 ++ PythonHome/Lib/distutils/util.pyc | Bin 14295 -> 0 bytes PythonHome/Lib/distutils/version.py | 299 + PythonHome/Lib/distutils/version.pyc | Bin 7133 -> 0 bytes PythonHome/Lib/distutils/versionpredicate.py | 164 + PythonHome/Lib/distutils/versionpredicate.pyc | Bin 5437 -> 0 bytes PythonHome/Lib/doctest.py | 2817 ++++++++ PythonHome/Lib/doctest.pyc | Bin 81866 -> 0 bytes PythonHome/Lib/dumbdbm.py | 246 + PythonHome/Lib/dumbdbm.pyc | Bin 6242 -> 0 bytes PythonHome/Lib/dummy_thread.py | 145 + PythonHome/Lib/dummy_thread.pyc | Bin 5169 -> 0 bytes PythonHome/Lib/dummy_threading.py | 78 + PythonHome/Lib/dummy_threading.pyc | Bin 1270 -> 0 bytes PythonHome/Lib/email/__init__.py | 123 + PythonHome/Lib/email/__init__.pyc | Bin 2842 -> 3046 bytes PythonHome/Lib/email/_parseaddr.py | 497 ++ PythonHome/Lib/email/_parseaddr.pyc | Bin 13690 -> 14608 bytes PythonHome/Lib/email/base64mime.py | 183 + PythonHome/Lib/email/base64mime.pyc | Bin 5298 -> 0 bytes PythonHome/Lib/email/charset.py | 397 ++ PythonHome/Lib/email/charset.pyc | Bin 13456 -> 0 bytes PythonHome/Lib/email/encoders.py | 82 + PythonHome/Lib/email/encoders.pyc | Bin 2197 -> 2435 bytes PythonHome/Lib/email/errors.py | 57 + PythonHome/Lib/email/errors.pyc | Bin 3454 -> 0 bytes PythonHome/Lib/email/feedparser.py | 484 ++ PythonHome/Lib/email/feedparser.pyc | Bin 11027 -> 0 bytes PythonHome/Lib/email/generator.py | 371 + PythonHome/Lib/email/generator.pyc | Bin 10095 -> 0 bytes PythonHome/Lib/email/header.py | 514 ++ PythonHome/Lib/email/header.pyc | Bin 13422 -> 0 bytes PythonHome/Lib/email/iterators.py | 73 + PythonHome/Lib/email/iterators.pyc | Bin 2341 -> 0 bytes PythonHome/Lib/email/message.py | 797 +++ PythonHome/Lib/email/message.pyc | Bin 28454 -> 0 bytes PythonHome/Lib/email/mime/__init__.py | 0 PythonHome/Lib/email/mime/__init__.pyc | Bin 125 -> 159 bytes PythonHome/Lib/email/mime/application.py | 36 + PythonHome/Lib/email/mime/application.pyc | Bin 1539 -> 0 bytes PythonHome/Lib/email/mime/audio.py | 73 + PythonHome/Lib/email/mime/audio.pyc | Bin 2849 -> 0 bytes PythonHome/Lib/email/mime/base.py | 26 + PythonHome/Lib/email/mime/base.pyc | Bin 1071 -> 0 bytes PythonHome/Lib/email/mime/image.py | 46 + PythonHome/Lib/email/mime/image.pyc | Bin 2004 -> 0 bytes PythonHome/Lib/email/mime/message.py | 34 + PythonHome/Lib/email/mime/message.pyc | Bin 1403 -> 0 bytes PythonHome/Lib/email/mime/multipart.py | 47 + PythonHome/Lib/email/mime/multipart.pyc | Bin 1624 -> 0 bytes PythonHome/Lib/email/mime/nonmultipart.py | 22 + PythonHome/Lib/email/mime/nonmultipart.pyc | Bin 841 -> 0 bytes PythonHome/Lib/email/mime/text.py | 30 + PythonHome/Lib/email/mime/text.pyc | Bin 1263 -> 0 bytes PythonHome/Lib/email/parser.py | 91 + PythonHome/Lib/email/parser.pyc | Bin 3789 -> 0 bytes PythonHome/Lib/email/quoprimime.py | 336 + PythonHome/Lib/email/quoprimime.pyc | Bin 8785 -> 0 bytes PythonHome/Lib/email/utils.py | 324 + PythonHome/Lib/email/utils.pyc | Bin 9083 -> 9627 bytes PythonHome/Lib/encodings/__init__.py | 157 + PythonHome/Lib/encodings/__init__.pyc | Bin 4358 -> 4494 bytes PythonHome/Lib/encodings/aliases.py | 527 ++ PythonHome/Lib/encodings/aliases.pyc | Bin 8765 -> 8799 bytes PythonHome/Lib/encodings/ascii.py | 50 + PythonHome/Lib/encodings/ascii.pyc | Bin 2231 -> 2571 bytes PythonHome/Lib/encodings/base64_codec.py | 79 + PythonHome/Lib/encodings/base64_codec.pyc | Bin 3633 -> 0 bytes PythonHome/Lib/encodings/big5.py | 39 + PythonHome/Lib/encodings/big5.pyc | Bin 1665 -> 0 bytes PythonHome/Lib/encodings/big5hkscs.py | 39 + PythonHome/Lib/encodings/big5hkscs.pyc | Bin 1705 -> 0 bytes PythonHome/Lib/encodings/bz2_codec.py | 102 + PythonHome/Lib/encodings/bz2_codec.pyc | Bin 4473 -> 0 bytes PythonHome/Lib/encodings/charmap.py | 69 + PythonHome/Lib/encodings/charmap.pyc | Bin 3278 -> 0 bytes PythonHome/Lib/encodings/cp037.py | 307 + PythonHome/Lib/encodings/cp037.pyc | Bin 2694 -> 0 bytes PythonHome/Lib/encodings/cp1006.py | 307 + PythonHome/Lib/encodings/cp1006.pyc | Bin 2780 -> 0 bytes PythonHome/Lib/encodings/cp1026.py | 307 + PythonHome/Lib/encodings/cp1026.pyc | Bin 2708 -> 0 bytes PythonHome/Lib/encodings/cp1140.py | 307 + PythonHome/Lib/encodings/cp1140.pyc | Bin 2694 -> 0 bytes PythonHome/Lib/encodings/cp1250.py | 307 + PythonHome/Lib/encodings/cp1250.pyc | Bin 2731 -> 0 bytes PythonHome/Lib/encodings/cp1251.py | 307 + PythonHome/Lib/encodings/cp1251.pyc | Bin 2728 -> 0 bytes PythonHome/Lib/encodings/cp1252.py | 307 + PythonHome/Lib/encodings/cp1252.pyc | Bin 2731 -> 0 bytes PythonHome/Lib/encodings/cp1253.py | 307 + PythonHome/Lib/encodings/cp1253.pyc | Bin 2744 -> 0 bytes PythonHome/Lib/encodings/cp1254.py | 307 + PythonHome/Lib/encodings/cp1254.pyc | Bin 2733 -> 0 bytes PythonHome/Lib/encodings/cp1255.py | 307 + PythonHome/Lib/encodings/cp1255.pyc | Bin 2752 -> 0 bytes PythonHome/Lib/encodings/cp1256.py | 307 + PythonHome/Lib/encodings/cp1256.pyc | Bin 2730 -> 0 bytes PythonHome/Lib/encodings/cp1257.py | 307 + PythonHome/Lib/encodings/cp1257.pyc | Bin 2738 -> 0 bytes PythonHome/Lib/encodings/cp1258.py | 307 + PythonHome/Lib/encodings/cp1258.pyc | Bin 2736 -> 0 bytes PythonHome/Lib/encodings/cp424.py | 307 + PythonHome/Lib/encodings/cp424.pyc | Bin 2724 -> 0 bytes PythonHome/Lib/encodings/cp437.py | 698 ++ PythonHome/Lib/encodings/cp437.pyc | Bin 7929 -> 0 bytes PythonHome/Lib/encodings/cp500.py | 307 + PythonHome/Lib/encodings/cp500.pyc | Bin 2694 -> 0 bytes PythonHome/Lib/encodings/cp720.py | 309 + PythonHome/Lib/encodings/cp720.pyc | Bin 2791 -> 0 bytes PythonHome/Lib/encodings/cp737.py | 698 ++ PythonHome/Lib/encodings/cp737.pyc | Bin 8157 -> 0 bytes PythonHome/Lib/encodings/cp775.py | 697 ++ PythonHome/Lib/encodings/cp775.pyc | Bin 7943 -> 0 bytes PythonHome/Lib/encodings/cp850.py | 698 ++ PythonHome/Lib/encodings/cp850.pyc | Bin 7676 -> 0 bytes PythonHome/Lib/encodings/cp852.py | 698 ++ PythonHome/Lib/encodings/cp852.pyc | Bin 7945 -> 0 bytes PythonHome/Lib/encodings/cp855.py | 698 ++ PythonHome/Lib/encodings/cp855.pyc | Bin 8126 -> 0 bytes PythonHome/Lib/encodings/cp856.py | 307 + PythonHome/Lib/encodings/cp856.pyc | Bin 2756 -> 0 bytes PythonHome/Lib/encodings/cp857.py | 694 ++ PythonHome/Lib/encodings/cp857.pyc | Bin 7666 -> 0 bytes PythonHome/Lib/encodings/cp858.py | 698 ++ PythonHome/Lib/encodings/cp858.pyc | Bin 7646 -> 0 bytes PythonHome/Lib/encodings/cp860.py | 698 ++ PythonHome/Lib/encodings/cp860.pyc | Bin 7912 -> 0 bytes PythonHome/Lib/encodings/cp861.py | 698 ++ PythonHome/Lib/encodings/cp861.pyc | Bin 7923 -> 0 bytes PythonHome/Lib/encodings/cp862.py | 698 ++ PythonHome/Lib/encodings/cp862.pyc | Bin 8058 -> 0 bytes PythonHome/Lib/encodings/cp863.py | 698 ++ PythonHome/Lib/encodings/cp863.pyc | Bin 7923 -> 0 bytes PythonHome/Lib/encodings/cp864.py | 690 ++ PythonHome/Lib/encodings/cp864.pyc | Bin 8054 -> 0 bytes PythonHome/Lib/encodings/cp865.py | 698 ++ PythonHome/Lib/encodings/cp865.pyc | Bin 7923 -> 0 bytes PythonHome/Lib/encodings/cp866.py | 698 ++ PythonHome/Lib/encodings/cp866.pyc | Bin 8158 -> 0 bytes PythonHome/Lib/encodings/cp869.py | 689 ++ PythonHome/Lib/encodings/cp869.pyc | Bin 7970 -> 0 bytes PythonHome/Lib/encodings/cp874.py | 307 + PythonHome/Lib/encodings/cp874.pyc | Bin 2822 -> 0 bytes PythonHome/Lib/encodings/cp875.py | 307 + PythonHome/Lib/encodings/cp875.pyc | Bin 2691 -> 0 bytes PythonHome/Lib/encodings/cp932.py | 39 + PythonHome/Lib/encodings/cp932.pyc | Bin 1673 -> 0 bytes PythonHome/Lib/encodings/cp949.py | 39 + PythonHome/Lib/encodings/cp949.pyc | Bin 1673 -> 0 bytes PythonHome/Lib/encodings/cp950.py | 39 + PythonHome/Lib/encodings/cp950.pyc | Bin 1673 -> 0 bytes PythonHome/Lib/encodings/euc_jis_2004.py | 39 + PythonHome/Lib/encodings/euc_jis_2004.pyc | Bin 1729 -> 0 bytes PythonHome/Lib/encodings/euc_jisx0213.py | 39 + PythonHome/Lib/encodings/euc_jisx0213.pyc | Bin 1729 -> 0 bytes PythonHome/Lib/encodings/euc_jp.py | 39 + PythonHome/Lib/encodings/euc_jp.pyc | Bin 1681 -> 0 bytes PythonHome/Lib/encodings/euc_kr.py | 39 + PythonHome/Lib/encodings/euc_kr.pyc | Bin 1681 -> 0 bytes PythonHome/Lib/encodings/gb18030.py | 39 + PythonHome/Lib/encodings/gb18030.pyc | Bin 1689 -> 0 bytes PythonHome/Lib/encodings/gb2312.py | 39 + PythonHome/Lib/encodings/gb2312.pyc | Bin 1681 -> 0 bytes PythonHome/Lib/encodings/gbk.py | 39 + PythonHome/Lib/encodings/gbk.pyc | Bin 1727 -> 1965 bytes PythonHome/Lib/encodings/hex_codec.py | 79 + PythonHome/Lib/encodings/hex_codec.pyc | Bin 3715 -> 4157 bytes PythonHome/Lib/encodings/hp_roman8.py | 152 + PythonHome/Lib/encodings/hp_roman8.pyc | Bin 3977 -> 0 bytes PythonHome/Lib/encodings/hz.py | 39 + PythonHome/Lib/encodings/hz.pyc | Bin 1649 -> 0 bytes PythonHome/Lib/encodings/idna.py | 288 + PythonHome/Lib/encodings/idna.pyc | Bin 6334 -> 6810 bytes PythonHome/Lib/encodings/iso2022_jp.py | 39 + PythonHome/Lib/encodings/iso2022_jp.pyc | Bin 1718 -> 0 bytes PythonHome/Lib/encodings/iso2022_jp_1.py | 39 + PythonHome/Lib/encodings/iso2022_jp_1.pyc | Bin 1734 -> 0 bytes PythonHome/Lib/encodings/iso2022_jp_2.py | 39 + PythonHome/Lib/encodings/iso2022_jp_2.pyc | Bin 1734 -> 0 bytes PythonHome/Lib/encodings/iso2022_jp_2004.py | 39 + PythonHome/Lib/encodings/iso2022_jp_2004.pyc | Bin 1758 -> 0 bytes PythonHome/Lib/encodings/iso2022_jp_3.py | 39 + PythonHome/Lib/encodings/iso2022_jp_3.pyc | Bin 1734 -> 0 bytes PythonHome/Lib/encodings/iso2022_jp_ext.py | 39 + PythonHome/Lib/encodings/iso2022_jp_ext.pyc | Bin 1750 -> 0 bytes PythonHome/Lib/encodings/iso2022_kr.py | 39 + PythonHome/Lib/encodings/iso2022_kr.pyc | Bin 1718 -> 0 bytes PythonHome/Lib/encodings/iso8859_1.py | 307 + PythonHome/Lib/encodings/iso8859_1.pyc | Bin 2733 -> 0 bytes PythonHome/Lib/encodings/iso8859_10.py | 307 + PythonHome/Lib/encodings/iso8859_10.pyc | Bin 2748 -> 0 bytes PythonHome/Lib/encodings/iso8859_11.py | 307 + PythonHome/Lib/encodings/iso8859_11.pyc | Bin 2842 -> 0 bytes PythonHome/Lib/encodings/iso8859_13.py | 307 + PythonHome/Lib/encodings/iso8859_13.pyc | Bin 2751 -> 0 bytes PythonHome/Lib/encodings/iso8859_14.py | 307 + PythonHome/Lib/encodings/iso8859_14.pyc | Bin 2769 -> 0 bytes PythonHome/Lib/encodings/iso8859_15.py | 307 + PythonHome/Lib/encodings/iso8859_15.pyc | Bin 2748 -> 0 bytes PythonHome/Lib/encodings/iso8859_16.py | 307 + PythonHome/Lib/encodings/iso8859_16.pyc | Bin 2750 -> 0 bytes PythonHome/Lib/encodings/iso8859_2.py | 307 + PythonHome/Lib/encodings/iso8859_2.pyc | Bin 2733 -> 0 bytes PythonHome/Lib/encodings/iso8859_3.py | 307 + PythonHome/Lib/encodings/iso8859_3.pyc | Bin 2740 -> 0 bytes PythonHome/Lib/encodings/iso8859_4.py | 307 + PythonHome/Lib/encodings/iso8859_4.pyc | Bin 2733 -> 0 bytes PythonHome/Lib/encodings/iso8859_5.py | 307 + PythonHome/Lib/encodings/iso8859_5.pyc | Bin 2734 -> 0 bytes PythonHome/Lib/encodings/iso8859_6.py | 307 + PythonHome/Lib/encodings/iso8859_6.pyc | Bin 2778 -> 0 bytes PythonHome/Lib/encodings/iso8859_7.py | 307 + PythonHome/Lib/encodings/iso8859_7.pyc | Bin 2741 -> 0 bytes PythonHome/Lib/encodings/iso8859_8.py | 307 + PythonHome/Lib/encodings/iso8859_8.pyc | Bin 2772 -> 0 bytes PythonHome/Lib/encodings/iso8859_9.py | 307 + PythonHome/Lib/encodings/iso8859_9.pyc | Bin 2733 -> 0 bytes PythonHome/Lib/encodings/johab.py | 39 + PythonHome/Lib/encodings/johab.pyc | Bin 1673 -> 0 bytes PythonHome/Lib/encodings/koi8_r.py | 307 + PythonHome/Lib/encodings/koi8_r.pyc | Bin 2755 -> 0 bytes PythonHome/Lib/encodings/koi8_u.py | 307 + PythonHome/Lib/encodings/koi8_u.pyc | Bin 2741 -> 0 bytes PythonHome/Lib/encodings/latin_1.py | 50 + PythonHome/Lib/encodings/latin_1.pyc | Bin 2261 -> 0 bytes PythonHome/Lib/encodings/mac_arabic.py | 698 ++ PythonHome/Lib/encodings/mac_arabic.pyc | Bin 7879 -> 0 bytes PythonHome/Lib/encodings/mac_centeuro.py | 307 + PythonHome/Lib/encodings/mac_centeuro.pyc | Bin 2802 -> 0 bytes PythonHome/Lib/encodings/mac_croatian.py | 307 + PythonHome/Lib/encodings/mac_croatian.pyc | Bin 2810 -> 0 bytes PythonHome/Lib/encodings/mac_cyrillic.py | 307 + PythonHome/Lib/encodings/mac_cyrillic.pyc | Bin 2800 -> 0 bytes PythonHome/Lib/encodings/mac_farsi.py | 307 + PythonHome/Lib/encodings/mac_farsi.pyc | Bin 2714 -> 0 bytes PythonHome/Lib/encodings/mac_greek.py | 307 + PythonHome/Lib/encodings/mac_greek.pyc | Bin 2754 -> 0 bytes PythonHome/Lib/encodings/mac_iceland.py | 307 + PythonHome/Lib/encodings/mac_iceland.pyc | Bin 2793 -> 0 bytes PythonHome/Lib/encodings/mac_latin2.py | 183 + PythonHome/Lib/encodings/mac_latin2.pyc | Bin 4772 -> 0 bytes PythonHome/Lib/encodings/mac_roman.py | 307 + PythonHome/Lib/encodings/mac_roman.pyc | Bin 2771 -> 0 bytes PythonHome/Lib/encodings/mac_romanian.py | 307 + PythonHome/Lib/encodings/mac_romanian.pyc | Bin 2811 -> 0 bytes PythonHome/Lib/encodings/mac_turkish.py | 307 + PythonHome/Lib/encodings/mac_turkish.pyc | Bin 2794 -> 0 bytes PythonHome/Lib/encodings/mbcs.py | 47 + PythonHome/Lib/encodings/mbcs.pyc | Bin 2003 -> 0 bytes PythonHome/Lib/encodings/palmos.py | 83 + PythonHome/Lib/encodings/palmos.pyc | Bin 2931 -> 0 bytes PythonHome/Lib/encodings/ptcp154.py | 175 + PythonHome/Lib/encodings/ptcp154.pyc | Bin 4755 -> 0 bytes PythonHome/Lib/encodings/punycode.py | 238 + PythonHome/Lib/encodings/punycode.pyc | Bin 7685 -> 0 bytes PythonHome/Lib/encodings/quopri_codec.py | 75 + PythonHome/Lib/encodings/quopri_codec.pyc | Bin 3430 -> 0 bytes .../Lib/encodings/raw_unicode_escape.py | 45 + .../Lib/encodings/raw_unicode_escape.pyc | Bin 2093 -> 0 bytes PythonHome/Lib/encodings/rot_13.py | 118 + PythonHome/Lib/encodings/rot_13.pyc | Bin 3473 -> 0 bytes PythonHome/Lib/encodings/shift_jis.py | 39 + PythonHome/Lib/encodings/shift_jis.pyc | Bin 1705 -> 0 bytes PythonHome/Lib/encodings/shift_jis_2004.py | 39 + PythonHome/Lib/encodings/shift_jis_2004.pyc | Bin 1745 -> 0 bytes PythonHome/Lib/encodings/shift_jisx0213.py | 39 + PythonHome/Lib/encodings/shift_jisx0213.pyc | Bin 1745 -> 0 bytes PythonHome/Lib/encodings/string_escape.py | 38 + PythonHome/Lib/encodings/string_escape.pyc | Bin 1952 -> 0 bytes PythonHome/Lib/encodings/tis_620.py | 307 + PythonHome/Lib/encodings/tis_620.pyc | Bin 2803 -> 0 bytes PythonHome/Lib/encodings/undefined.py | 49 + PythonHome/Lib/encodings/undefined.pyc | Bin 2454 -> 0 bytes PythonHome/Lib/encodings/unicode_escape.py | 45 + PythonHome/Lib/encodings/unicode_escape.pyc | Bin 2041 -> 0 bytes PythonHome/Lib/encodings/unicode_internal.py | 45 + PythonHome/Lib/encodings/unicode_internal.pyc | Bin 2067 -> 0 bytes PythonHome/Lib/encodings/utf_16.py | 126 + PythonHome/Lib/encodings/utf_16.pyc | Bin 4908 -> 0 bytes PythonHome/Lib/encodings/utf_16_be.py | 42 + PythonHome/Lib/encodings/utf_16_be.pyc | Bin 1894 -> 0 bytes PythonHome/Lib/encodings/utf_16_le.py | 42 + PythonHome/Lib/encodings/utf_16_le.pyc | Bin 1894 -> 0 bytes PythonHome/Lib/encodings/utf_32.py | 150 + PythonHome/Lib/encodings/utf_32.pyc | Bin 5446 -> 0 bytes PythonHome/Lib/encodings/utf_32_be.py | 37 + PythonHome/Lib/encodings/utf_32_be.pyc | Bin 1787 -> 0 bytes PythonHome/Lib/encodings/utf_32_le.py | 37 + PythonHome/Lib/encodings/utf_32_le.pyc | Bin 1787 -> 0 bytes PythonHome/Lib/encodings/utf_7.py | 38 + PythonHome/Lib/encodings/utf_7.pyc | Bin 1787 -> 0 bytes PythonHome/Lib/encodings/utf_8.py | 42 + PythonHome/Lib/encodings/utf_8.pyc | Bin 1926 -> 2198 bytes PythonHome/Lib/encodings/utf_8_sig.py | 117 + PythonHome/Lib/encodings/utf_8_sig.pyc | Bin 4725 -> 0 bytes PythonHome/Lib/encodings/uu_codec.py | 129 + PythonHome/Lib/encodings/uu_codec.pyc | Bin 4711 -> 0 bytes PythonHome/Lib/encodings/zlib_codec.py | 102 + PythonHome/Lib/encodings/zlib_codec.pyc | Bin 4393 -> 0 bytes PythonHome/Lib/filecmp.py | 296 + PythonHome/Lib/filecmp.pyc | Bin 9322 -> 0 bytes PythonHome/Lib/fileinput.py | 413 ++ PythonHome/Lib/fileinput.pyc | Bin 14415 -> 0 bytes PythonHome/Lib/fnmatch.py | 116 + PythonHome/Lib/fnmatch.pyc | Bin 3504 -> 0 bytes PythonHome/Lib/formatter.py | 445 ++ PythonHome/Lib/formatter.pyc | Bin 18023 -> 0 bytes PythonHome/Lib/fpformat.py | 145 + PythonHome/Lib/fpformat.pyc | Bin 4551 -> 0 bytes PythonHome/Lib/fractions.py | 605 ++ PythonHome/Lib/fractions.pyc | Bin 19148 -> 0 bytes PythonHome/Lib/ftplib.py | 1061 +++ PythonHome/Lib/ftplib.pyc | Bin 33147 -> 0 bytes PythonHome/Lib/functools.py | 100 + PythonHome/Lib/functools.pyc | Bin 5959 -> 6843 bytes PythonHome/Lib/genericpath.py | 105 + PythonHome/Lib/genericpath.pyc | Bin 3213 -> 3553 bytes PythonHome/Lib/getopt.py | 210 + PythonHome/Lib/getopt.pyc | Bin 6604 -> 0 bytes PythonHome/Lib/getpass.py | 179 + PythonHome/Lib/getpass.pyc | Bin 4708 -> 0 bytes PythonHome/Lib/gettext.py | 591 ++ PythonHome/Lib/gettext.pyc | Bin 15309 -> 0 bytes PythonHome/Lib/glob.py | 95 + PythonHome/Lib/glob.pyc | Bin 2857 -> 0 bytes PythonHome/Lib/gzip.py | 518 ++ PythonHome/Lib/gzip.pyc | Bin 14921 -> 0 bytes PythonHome/Lib/hashlib.py | 213 + PythonHome/Lib/hashlib.pyc | Bin 6650 -> 6956 bytes PythonHome/Lib/heapq.py | 485 ++ PythonHome/Lib/heapq.pyc | Bin 14474 -> 15086 bytes PythonHome/Lib/hmac.py | 136 + PythonHome/Lib/hmac.pyc | Bin 4392 -> 0 bytes PythonHome/Lib/hotshot/__init__.py | 78 + PythonHome/Lib/hotshot/__init__.pyc | Bin 3319 -> 0 bytes PythonHome/Lib/hotshot/log.py | 194 + PythonHome/Lib/hotshot/log.pyc | Bin 5332 -> 0 bytes PythonHome/Lib/hotshot/stats.py | 93 + PythonHome/Lib/hotshot/stats.pyc | Bin 3083 -> 0 bytes PythonHome/Lib/hotshot/stones.py | 30 + PythonHome/Lib/hotshot/stones.pyc | Bin 1126 -> 0 bytes PythonHome/Lib/htmlentitydefs.py | 273 + PythonHome/Lib/htmlentitydefs.pyc | Bin 6362 -> 6396 bytes PythonHome/Lib/htmllib.py | 491 ++ PythonHome/Lib/htmllib.pyc | Bin 18944 -> 0 bytes PythonHome/Lib/httplib.py | 1364 ++++ PythonHome/Lib/httplib.pyc | Bin 35522 -> 38072 bytes PythonHome/Lib/idlelib/AutoComplete.py | 229 + PythonHome/Lib/idlelib/AutoComplete.pyc | Bin 7818 -> 0 bytes PythonHome/Lib/idlelib/AutoCompleteWindow.py | 406 ++ PythonHome/Lib/idlelib/AutoCompleteWindow.pyc | Bin 12198 -> 0 bytes PythonHome/Lib/idlelib/AutoExpand.py | 104 + PythonHome/Lib/idlelib/AutoExpand.pyc | Bin 3412 -> 0 bytes PythonHome/Lib/idlelib/Bindings.py | 89 + PythonHome/Lib/idlelib/Bindings.pyc | Bin 4565 -> 0 bytes PythonHome/Lib/idlelib/CallTipWindow.py | 168 + PythonHome/Lib/idlelib/CallTipWindow.pyc | Bin 6200 -> 0 bytes PythonHome/Lib/idlelib/CallTips.py | 219 + PythonHome/Lib/idlelib/CallTips.pyc | Bin 7888 -> 0 bytes PythonHome/Lib/idlelib/ClassBrowser.py | 229 + PythonHome/Lib/idlelib/ClassBrowser.pyc | Bin 9054 -> 0 bytes PythonHome/Lib/idlelib/CodeContext.py | 176 + PythonHome/Lib/idlelib/CodeContext.pyc | Bin 6522 -> 0 bytes PythonHome/Lib/idlelib/ColorDelegator.py | 275 + PythonHome/Lib/idlelib/ColorDelegator.pyc | Bin 9036 -> 0 bytes PythonHome/Lib/idlelib/Debugger.py | 481 ++ PythonHome/Lib/idlelib/Debugger.pyc | Bin 16270 -> 0 bytes PythonHome/Lib/idlelib/Delegator.py | 25 + PythonHome/Lib/idlelib/Delegator.pyc | Bin 1178 -> 0 bytes PythonHome/Lib/idlelib/EditorWindow.py | 1729 +++++ PythonHome/Lib/idlelib/EditorWindow.pyc | Bin 55973 -> 0 bytes PythonHome/Lib/idlelib/FileList.py | 124 + PythonHome/Lib/idlelib/FileList.pyc | Bin 3783 -> 0 bytes PythonHome/Lib/idlelib/FormatParagraph.py | 193 + PythonHome/Lib/idlelib/FormatParagraph.pyc | Bin 6912 -> 0 bytes PythonHome/Lib/idlelib/GrepDialog.py | 159 + PythonHome/Lib/idlelib/GrepDialog.pyc | Bin 6126 -> 0 bytes PythonHome/Lib/idlelib/HyperParser.py | 255 + PythonHome/Lib/idlelib/HyperParser.pyc | Bin 6520 -> 0 bytes PythonHome/Lib/idlelib/IOBinding.py | 595 ++ PythonHome/Lib/idlelib/IOBinding.pyc | Bin 16827 -> 0 bytes PythonHome/Lib/idlelib/IdleHistory.py | 104 + PythonHome/Lib/idlelib/IdleHistory.pyc | Bin 3954 -> 0 bytes PythonHome/Lib/idlelib/MultiCall.py | 430 ++ PythonHome/Lib/idlelib/MultiCall.pyc | Bin 15859 -> 0 bytes PythonHome/Lib/idlelib/MultiStatusBar.py | 45 + PythonHome/Lib/idlelib/MultiStatusBar.pyc | Bin 2120 -> 0 bytes PythonHome/Lib/idlelib/ObjectBrowser.py | 156 + PythonHome/Lib/idlelib/ObjectBrowser.pyc | Bin 6647 -> 0 bytes PythonHome/Lib/idlelib/OutputWindow.py | 149 + PythonHome/Lib/idlelib/OutputWindow.pyc | Bin 5007 -> 0 bytes PythonHome/Lib/idlelib/ParenMatch.py | 178 + PythonHome/Lib/idlelib/ParenMatch.pyc | Bin 6874 -> 0 bytes PythonHome/Lib/idlelib/PathBrowser.py | 104 + PythonHome/Lib/idlelib/PathBrowser.pyc | Bin 4238 -> 0 bytes PythonHome/Lib/idlelib/Percolator.py | 103 + PythonHome/Lib/idlelib/Percolator.pyc | Bin 4383 -> 0 bytes PythonHome/Lib/idlelib/PyParse.py | 594 ++ PythonHome/Lib/idlelib/PyParse.pyc | Bin 9749 -> 0 bytes PythonHome/Lib/idlelib/PyShell.py | 1616 +++++ PythonHome/Lib/idlelib/PyShell.pyc | Bin 50039 -> 0 bytes PythonHome/Lib/idlelib/RemoteDebugger.py | 380 + PythonHome/Lib/idlelib/RemoteDebugger.pyc | Bin 15420 -> 0 bytes PythonHome/Lib/idlelib/RemoteObjectBrowser.py | 36 + .../Lib/idlelib/RemoteObjectBrowser.pyc | Bin 2000 -> 0 bytes PythonHome/Lib/idlelib/ReplaceDialog.py | 220 + PythonHome/Lib/idlelib/ReplaceDialog.pyc | Bin 7446 -> 0 bytes PythonHome/Lib/idlelib/RstripExtension.py | 33 + PythonHome/Lib/idlelib/RstripExtension.pyc | Bin 1553 -> 0 bytes PythonHome/Lib/idlelib/ScriptBinding.py | 222 + PythonHome/Lib/idlelib/ScriptBinding.pyc | Bin 7973 -> 0 bytes PythonHome/Lib/idlelib/ScrolledList.py | 140 + PythonHome/Lib/idlelib/ScrolledList.pyc | Bin 5974 -> 0 bytes PythonHome/Lib/idlelib/SearchDialog.py | 89 + PythonHome/Lib/idlelib/SearchDialog.pyc | Bin 3811 -> 0 bytes PythonHome/Lib/idlelib/SearchDialogBase.py | 184 + PythonHome/Lib/idlelib/SearchDialogBase.pyc | Bin 7626 -> 0 bytes PythonHome/Lib/idlelib/SearchEngine.py | 233 + PythonHome/Lib/idlelib/SearchEngine.pyc | Bin 7992 -> 0 bytes PythonHome/Lib/idlelib/StackViewer.py | 152 + PythonHome/Lib/idlelib/StackViewer.pyc | Bin 6076 -> 0 bytes PythonHome/Lib/idlelib/ToolTip.py | 97 + PythonHome/Lib/idlelib/ToolTip.pyc | Bin 4414 -> 0 bytes PythonHome/Lib/idlelib/TreeWidget.py | 466 ++ PythonHome/Lib/idlelib/TreeWidget.pyc | Bin 16916 -> 0 bytes PythonHome/Lib/idlelib/UndoDelegator.py | 365 + PythonHome/Lib/idlelib/UndoDelegator.pyc | Bin 12790 -> 0 bytes PythonHome/Lib/idlelib/WidgetRedirector.py | 125 + PythonHome/Lib/idlelib/WidgetRedirector.pyc | Bin 5341 -> 0 bytes PythonHome/Lib/idlelib/WindowList.py | 90 + PythonHome/Lib/idlelib/WindowList.pyc | Bin 3411 -> 0 bytes PythonHome/Lib/idlelib/ZoomHeight.py | 51 + PythonHome/Lib/idlelib/ZoomHeight.pyc | Bin 1571 -> 0 bytes PythonHome/Lib/idlelib/__init__.py | 1 + PythonHome/Lib/idlelib/__init__.pyc | Bin 112 -> 0 bytes PythonHome/Lib/idlelib/aboutDialog.py | 145 + PythonHome/Lib/idlelib/aboutDialog.pyc | Bin 6448 -> 0 bytes PythonHome/Lib/idlelib/configDialog.py | 1160 +++ PythonHome/Lib/idlelib/configDialog.pyc | Bin 43516 -> 0 bytes PythonHome/Lib/idlelib/configHandler.py | 721 ++ PythonHome/Lib/idlelib/configHandler.pyc | Bin 26737 -> 0 bytes .../Lib/idlelib/configHelpSourceEdit.py | 166 + .../Lib/idlelib/configHelpSourceEdit.pyc | Bin 6414 -> 0 bytes .../Lib/idlelib/configSectionNameDialog.py | 92 + .../Lib/idlelib/configSectionNameDialog.pyc | Bin 4268 -> 0 bytes PythonHome/Lib/idlelib/dynOptionMenuWidget.py | 57 + .../Lib/idlelib/dynOptionMenuWidget.pyc | Bin 2761 -> 0 bytes PythonHome/Lib/idlelib/idle.py | 11 + PythonHome/Lib/idlelib/idle.pyc | Bin 391 -> 0 bytes PythonHome/Lib/idlelib/idlever.py | 1 + PythonHome/Lib/idlelib/idlever.pyc | Bin 144 -> 0 bytes PythonHome/Lib/idlelib/keybindingDialog.py | 266 + PythonHome/Lib/idlelib/keybindingDialog.pyc | Bin 11901 -> 0 bytes PythonHome/Lib/idlelib/macosxSupport.py | 235 + PythonHome/Lib/idlelib/macosxSupport.pyc | Bin 8284 -> 0 bytes PythonHome/Lib/idlelib/rpc.py | 600 ++ PythonHome/Lib/idlelib/rpc.pyc | Bin 20887 -> 0 bytes PythonHome/Lib/idlelib/run.py | 374 + PythonHome/Lib/idlelib/run.pyc | Bin 12421 -> 0 bytes PythonHome/Lib/idlelib/tabbedpages.py | 498 ++ PythonHome/Lib/idlelib/tabbedpages.pyc | Bin 17961 -> 0 bytes PythonHome/Lib/idlelib/testcode.py | 31 + PythonHome/Lib/idlelib/testcode.pyc | Bin 1289 -> 0 bytes PythonHome/Lib/idlelib/textView.py | 90 + PythonHome/Lib/idlelib/textView.pyc | Bin 3724 -> 0 bytes PythonHome/Lib/ihooks.py | 554 ++ PythonHome/Lib/ihooks.pyc | Bin 20337 -> 0 bytes PythonHome/Lib/imaplib.py | 1535 ++++ PythonHome/Lib/imaplib.pyc | Bin 43871 -> 0 bytes PythonHome/Lib/imghdr.py | 159 + PythonHome/Lib/imghdr.pyc | Bin 4598 -> 0 bytes PythonHome/Lib/importlib/__init__.py | 38 + PythonHome/Lib/importlib/__init__.pyc | Bin 1457 -> 0 bytes PythonHome/Lib/imputil.py | 725 ++ PythonHome/Lib/imputil.pyc | Bin 15053 -> 0 bytes PythonHome/Lib/inspect.py | 1059 +++ PythonHome/Lib/inspect.pyc | Bin 38962 -> 42006 bytes PythonHome/Lib/io.py | 90 + PythonHome/Lib/io.pyc | Bin 3563 -> 3733 bytes PythonHome/Lib/json/__init__.py | 351 + PythonHome/Lib/json/__init__.pyc | Bin 13930 -> 14100 bytes PythonHome/Lib/json/decoder.py | 385 + PythonHome/Lib/json/decoder.pyc | Bin 12034 -> 12442 bytes PythonHome/Lib/json/encoder.py | 448 ++ PythonHome/Lib/json/encoder.pyc | Bin 13625 -> 14203 bytes PythonHome/Lib/json/scanner.py | 67 + PythonHome/Lib/json/scanner.pyc | Bin 2214 -> 2316 bytes PythonHome/Lib/json/tool.py | 40 + PythonHome/Lib/json/tool.pyc | Bin 1264 -> 0 bytes PythonHome/Lib/keyword.py | 93 + PythonHome/Lib/keyword.pyc | Bin 2095 -> 2163 bytes PythonHome/Lib/lib-tk/Canvas.py | 194 + PythonHome/Lib/lib-tk/Canvas.pyc | Bin 14364 -> 0 bytes PythonHome/Lib/lib-tk/Dialog.py | 49 + PythonHome/Lib/lib-tk/Dialog.pyc | Bin 1845 -> 0 bytes PythonHome/Lib/lib-tk/FileDialog.py | 274 + PythonHome/Lib/lib-tk/FileDialog.pyc | Bin 9394 -> 0 bytes PythonHome/Lib/lib-tk/FixTk.py | 78 + PythonHome/Lib/lib-tk/FixTk.pyc | Bin 1956 -> 0 bytes PythonHome/Lib/lib-tk/ScrolledText.py | 55 + PythonHome/Lib/lib-tk/ScrolledText.pyc | Bin 2589 -> 0 bytes PythonHome/Lib/lib-tk/SimpleDialog.py | 112 + PythonHome/Lib/lib-tk/SimpleDialog.pyc | Bin 4174 -> 0 bytes PythonHome/Lib/lib-tk/Tix.py | 1945 ++++++ PythonHome/Lib/lib-tk/Tix.pyc | Bin 91067 -> 0 bytes PythonHome/Lib/lib-tk/Tkconstants.py | 110 + PythonHome/Lib/lib-tk/Tkconstants.pyc | Bin 2231 -> 0 bytes PythonHome/Lib/lib-tk/Tkdnd.py | 321 + PythonHome/Lib/lib-tk/Tkdnd.pyc | Bin 12435 -> 0 bytes PythonHome/Lib/lib-tk/Tkinter.py | 3809 ++++++++++ PythonHome/Lib/lib-tk/Tkinter.pyc | Bin 189968 -> 0 bytes PythonHome/Lib/lib-tk/tkColorChooser.py | 72 + PythonHome/Lib/lib-tk/tkColorChooser.pyc | Bin 1345 -> 0 bytes PythonHome/Lib/lib-tk/tkCommonDialog.py | 60 + PythonHome/Lib/lib-tk/tkCommonDialog.pyc | Bin 1426 -> 0 bytes PythonHome/Lib/lib-tk/tkFileDialog.py | 215 + PythonHome/Lib/lib-tk/tkFileDialog.pyc | Bin 4921 -> 0 bytes PythonHome/Lib/lib-tk/tkFont.py | 217 + PythonHome/Lib/lib-tk/tkFont.pyc | Bin 6815 -> 0 bytes PythonHome/Lib/lib-tk/tkMessageBox.py | 134 + PythonHome/Lib/lib-tk/tkMessageBox.pyc | Bin 3729 -> 0 bytes PythonHome/Lib/lib-tk/tkSimpleDialog.py | 323 + PythonHome/Lib/lib-tk/tkSimpleDialog.pyc | Bin 8723 -> 0 bytes PythonHome/Lib/lib-tk/ttk.py | 1624 +++++ PythonHome/Lib/lib-tk/ttk.pyc | Bin 60597 -> 0 bytes PythonHome/Lib/lib-tk/turtle.py | 4035 +++++++++++ PythonHome/Lib/lib-tk/turtle.pyc | Bin 135965 -> 0 bytes PythonHome/Lib/lib2to3/__init__.py | 1 + PythonHome/Lib/lib2to3/__init__.pyc | Bin 112 -> 0 bytes PythonHome/Lib/lib2to3/__main__.py | 4 + PythonHome/Lib/lib2to3/__main__.pyc | Bin 227 -> 0 bytes PythonHome/Lib/lib2to3/btm_matcher.py | 168 + PythonHome/Lib/lib2to3/btm_matcher.pyc | Bin 5665 -> 0 bytes PythonHome/Lib/lib2to3/btm_utils.py | 283 + PythonHome/Lib/lib2to3/btm_utils.pyc | Bin 7368 -> 0 bytes PythonHome/Lib/lib2to3/fixer_base.py | 189 + PythonHome/Lib/lib2to3/fixer_base.pyc | Bin 7017 -> 0 bytes PythonHome/Lib/lib2to3/fixer_util.py | 432 ++ PythonHome/Lib/lib2to3/fixer_util.pyc | Bin 14173 -> 0 bytes PythonHome/Lib/lib2to3/fixes/__init__.py | 1 + PythonHome/Lib/lib2to3/fixes/__init__.pyc | Bin 118 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_apply.py | 59 + PythonHome/Lib/lib2to3/fixes/fix_apply.pyc | Bin 1838 -> 0 bytes .../Lib/lib2to3/fixes/fix_basestring.py | 14 + .../Lib/lib2to3/fixes/fix_basestring.pyc | Bin 762 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_buffer.py | 22 + PythonHome/Lib/lib2to3/fixes/fix_buffer.pyc | Bin 919 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_callable.py | 37 + PythonHome/Lib/lib2to3/fixes/fix_callable.pyc | Bin 1462 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_dict.py | 107 + PythonHome/Lib/lib2to3/fixes/fix_dict.pyc | Bin 3709 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_except.py | 93 + PythonHome/Lib/lib2to3/fixes/fix_except.pyc | Bin 2949 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_exec.py | 40 + PythonHome/Lib/lib2to3/fixes/fix_exec.pyc | Bin 1387 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_execfile.py | 52 + PythonHome/Lib/lib2to3/fixes/fix_execfile.pyc | Bin 2028 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_exitfunc.py | 72 + PythonHome/Lib/lib2to3/fixes/fix_exitfunc.pyc | Bin 2682 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_filter.py | 76 + PythonHome/Lib/lib2to3/fixes/fix_filter.pyc | Bin 2225 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_funcattrs.py | 21 + .../Lib/lib2to3/fixes/fix_funcattrs.pyc | Bin 1083 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_future.py | 22 + PythonHome/Lib/lib2to3/fixes/fix_future.pyc | Bin 888 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_getcwdu.py | 19 + PythonHome/Lib/lib2to3/fixes/fix_getcwdu.pyc | Bin 895 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_has_key.py | 110 + PythonHome/Lib/lib2to3/fixes/fix_has_key.pyc | Bin 3153 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_idioms.py | 152 + PythonHome/Lib/lib2to3/fixes/fix_idioms.pyc | Bin 4432 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_import.py | 99 + PythonHome/Lib/lib2to3/fixes/fix_import.pyc | Bin 3163 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_imports.py | 145 + PythonHome/Lib/lib2to3/fixes/fix_imports.pyc | Bin 5230 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_imports2.py | 16 + PythonHome/Lib/lib2to3/fixes/fix_imports2.pyc | Bin 604 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_input.py | 26 + PythonHome/Lib/lib2to3/fixes/fix_input.pyc | Bin 1103 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_intern.py | 46 + PythonHome/Lib/lib2to3/fixes/fix_intern.pyc | Bin 1574 -> 0 bytes .../Lib/lib2to3/fixes/fix_isinstance.py | 52 + .../Lib/lib2to3/fixes/fix_isinstance.pyc | Bin 1807 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_itertools.py | 43 + .../Lib/lib2to3/fixes/fix_itertools.pyc | Bin 1760 -> 0 bytes .../lib2to3/fixes/fix_itertools_imports.py | 57 + .../lib2to3/fixes/fix_itertools_imports.pyc | Bin 1985 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_long.py | 19 + PythonHome/Lib/lib2to3/fixes/fix_long.pyc | Bin 810 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_map.py | 91 + PythonHome/Lib/lib2to3/fixes/fix_map.pyc | Bin 3009 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_metaclass.py | 228 + .../Lib/lib2to3/fixes/fix_metaclass.pyc | Bin 6469 -> 0 bytes .../Lib/lib2to3/fixes/fix_methodattrs.py | 24 + .../Lib/lib2to3/fixes/fix_methodattrs.pyc | Bin 1107 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_ne.py | 23 + PythonHome/Lib/lib2to3/fixes/fix_ne.pyc | Bin 941 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_next.py | 103 + PythonHome/Lib/lib2to3/fixes/fix_next.pyc | Bin 3435 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_nonzero.py | 21 + PythonHome/Lib/lib2to3/fixes/fix_nonzero.pyc | Bin 1055 -> 0 bytes .../Lib/lib2to3/fixes/fix_numliterals.py | 28 + .../Lib/lib2to3/fixes/fix_numliterals.pyc | Bin 1205 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_operator.py | 96 + PythonHome/Lib/lib2to3/fixes/fix_operator.pyc | Bin 4925 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_paren.py | 44 + PythonHome/Lib/lib2to3/fixes/fix_paren.pyc | Bin 1512 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_print.py | 87 + PythonHome/Lib/lib2to3/fixes/fix_print.pyc | Bin 2683 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_raise.py | 90 + PythonHome/Lib/lib2to3/fixes/fix_raise.pyc | Bin 2467 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_raw_input.py | 17 + .../Lib/lib2to3/fixes/fix_raw_input.pyc | Bin 905 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_reduce.py | 35 + PythonHome/Lib/lib2to3/fixes/fix_reduce.pyc | Bin 1231 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_renames.py | 70 + PythonHome/Lib/lib2to3/fixes/fix_renames.pyc | Bin 2366 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_repr.py | 23 + PythonHome/Lib/lib2to3/fixes/fix_repr.pyc | Bin 985 -> 0 bytes .../Lib/lib2to3/fixes/fix_set_literal.py | 53 + .../Lib/lib2to3/fixes/fix_set_literal.pyc | Bin 1944 -> 0 bytes .../Lib/lib2to3/fixes/fix_standarderror.py | 18 + .../Lib/lib2to3/fixes/fix_standarderror.pyc | Bin 822 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_sys_exc.py | 30 + PythonHome/Lib/lib2to3/fixes/fix_sys_exc.pyc | Bin 1661 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_throw.py | 56 + PythonHome/Lib/lib2to3/fixes/fix_throw.pyc | Bin 1965 -> 0 bytes .../Lib/lib2to3/fixes/fix_tuple_params.py | 175 + .../Lib/lib2to3/fixes/fix_tuple_params.pyc | Bin 5308 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_types.py | 62 + PythonHome/Lib/lib2to3/fixes/fix_types.pyc | Bin 2154 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_unicode.py | 42 + PythonHome/Lib/lib2to3/fixes/fix_unicode.pyc | Bin 1672 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_urllib.py | 197 + PythonHome/Lib/lib2to3/fixes/fix_urllib.pyc | Bin 7025 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_ws_comma.py | 39 + PythonHome/Lib/lib2to3/fixes/fix_ws_comma.pyc | Bin 1351 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_xrange.py | 73 + PythonHome/Lib/lib2to3/fixes/fix_xrange.pyc | Bin 2967 -> 0 bytes .../Lib/lib2to3/fixes/fix_xreadlines.py | 25 + .../Lib/lib2to3/fixes/fix_xreadlines.pyc | Bin 1121 -> 0 bytes PythonHome/Lib/lib2to3/fixes/fix_zip.py | 35 + PythonHome/Lib/lib2to3/fixes/fix_zip.pyc | Bin 1315 -> 0 bytes PythonHome/Lib/lib2to3/main.py | 269 + PythonHome/Lib/lib2to3/main.pyc | Bin 9681 -> 0 bytes PythonHome/Lib/lib2to3/patcomp.py | 205 + PythonHome/Lib/lib2to3/patcomp.pyc | Bin 6486 -> 0 bytes PythonHome/Lib/lib2to3/pgen2/__init__.py | 4 + PythonHome/Lib/lib2to3/pgen2/__init__.pyc | Bin 159 -> 0 bytes PythonHome/Lib/lib2to3/pgen2/conv.py | 257 + PythonHome/Lib/lib2to3/pgen2/conv.pyc | Bin 8099 -> 0 bytes PythonHome/Lib/lib2to3/pgen2/driver.py | 157 + PythonHome/Lib/lib2to3/pgen2/driver.pyc | Bin 5223 -> 0 bytes .../lib2to3/pgen2/{grammar.pyc => grammar.py} | Bin 5921 -> 5374 bytes PythonHome/Lib/lib2to3/pgen2/literals.py | 60 + PythonHome/Lib/lib2to3/pgen2/literals.pyc | Bin 1958 -> 0 bytes PythonHome/Lib/lib2to3/pgen2/parse.py | 201 + PythonHome/Lib/lib2to3/pgen2/parse.pyc | Bin 7056 -> 0 bytes PythonHome/Lib/lib2to3/pgen2/pgen.py | 386 + PythonHome/Lib/lib2to3/pgen2/pgen.pyc | Bin 11693 -> 0 bytes PythonHome/Lib/lib2to3/pgen2/token.py | 83 + PythonHome/Lib/lib2to3/pgen2/token.pyc | Bin 2243 -> 0 bytes PythonHome/Lib/lib2to3/pgen2/tokenize.py | 499 ++ PythonHome/Lib/lib2to3/pgen2/tokenize.pyc | Bin 16570 -> 0 bytes PythonHome/Lib/lib2to3/pygram.py | 40 + PythonHome/Lib/lib2to3/pygram.pyc | Bin 1369 -> 0 bytes PythonHome/Lib/lib2to3/pytree.py | 887 +++ PythonHome/Lib/lib2to3/pytree.pyc | Bin 29163 -> 0 bytes PythonHome/Lib/lib2to3/refactor.py | 747 ++ PythonHome/Lib/lib2to3/refactor.pyc | Bin 23342 -> 0 bytes PythonHome/Lib/linecache.py | 135 + PythonHome/Lib/linecache.pyc | Bin 3181 -> 3385 bytes PythonHome/Lib/locale.py | 1947 ++++++ PythonHome/Lib/locale.pyc | Bin 50811 -> 51899 bytes PythonHome/Lib/logging/__init__.py | 1737 +++++ PythonHome/Lib/logging/__init__.pyc | Bin 56945 -> 60991 bytes PythonHome/Lib/logging/config.py | 919 +++ PythonHome/Lib/logging/config.pyc | Bin 25686 -> 0 bytes PythonHome/Lib/logging/handlers.py | 1222 ++++ PythonHome/Lib/logging/handlers.pyc | Bin 38918 -> 0 bytes PythonHome/Lib/macpath.py | 215 + PythonHome/Lib/macpath.pyc | Bin 7362 -> 0 bytes PythonHome/Lib/macurl2path.py | 77 + PythonHome/Lib/macurl2path.pyc | Bin 2184 -> 0 bytes PythonHome/Lib/mailbox.py | 2236 ++++++ PythonHome/Lib/mailbox.pyc | Bin 73406 -> 0 bytes PythonHome/Lib/mailcap.py | 255 + PythonHome/Lib/mailcap.pyc | Bin 6883 -> 0 bytes PythonHome/Lib/markupbase.py | 396 ++ PythonHome/Lib/markupbase.pyc | Bin 9226 -> 9810 bytes PythonHome/Lib/md5.py | 14 + PythonHome/Lib/md5.pyc | Bin 363 -> 0 bytes PythonHome/Lib/mhlib.py | 1005 +++ PythonHome/Lib/mhlib.pyc | Bin 32633 -> 0 bytes PythonHome/Lib/mimetools.py | 250 + PythonHome/Lib/mimetools.pyc | Bin 8122 -> 8802 bytes PythonHome/Lib/mimetypes.py | 591 ++ PythonHome/Lib/mimetypes.pyc | Bin 18162 -> 18808 bytes PythonHome/Lib/mimify.py | 468 ++ PythonHome/Lib/mimify.pyc | Bin 11765 -> 0 bytes PythonHome/Lib/modulefinder.py | 671 ++ PythonHome/Lib/modulefinder.pyc | Bin 18201 -> 0 bytes PythonHome/Lib/msilib/__init__.py | 475 ++ PythonHome/Lib/msilib/__init__.pyc | Bin 18635 -> 0 bytes PythonHome/Lib/msilib/schema.py | 1007 +++ PythonHome/Lib/msilib/schema.pyc | Bin 59836 -> 0 bytes PythonHome/Lib/msilib/sequence.py | 126 + PythonHome/Lib/msilib/sequence.pyc | Bin 6262 -> 0 bytes PythonHome/Lib/msilib/text.py | 129 + PythonHome/Lib/msilib/text.pyc | Bin 18475 -> 0 bytes PythonHome/Lib/multifile.py | 162 + PythonHome/Lib/multifile.pyc | Bin 5194 -> 0 bytes PythonHome/Lib/multiprocessing/__init__.py | 277 + PythonHome/Lib/multiprocessing/__init__.pyc | Bin 8075 -> 0 bytes PythonHome/Lib/multiprocessing/connection.py | 473 ++ PythonHome/Lib/multiprocessing/connection.pyc | Bin 13915 -> 0 bytes .../Lib/multiprocessing/dummy/__init__.py | 153 + .../Lib/multiprocessing/dummy/__init__.pyc | Bin 5160 -> 0 bytes .../Lib/multiprocessing/dummy/connection.py | 87 + .../Lib/multiprocessing/dummy/connection.pyc | Bin 2584 -> 0 bytes PythonHome/Lib/multiprocessing/forking.py | 512 ++ PythonHome/Lib/multiprocessing/forking.pyc | Bin 13866 -> 0 bytes PythonHome/Lib/multiprocessing/heap.py | 254 + PythonHome/Lib/multiprocessing/heap.pyc | Bin 6609 -> 0 bytes PythonHome/Lib/multiprocessing/managers.py | 1117 +++ PythonHome/Lib/multiprocessing/managers.pyc | Bin 36869 -> 0 bytes PythonHome/Lib/multiprocessing/pool.py | 735 ++ PythonHome/Lib/multiprocessing/pool.pyc | Bin 21436 -> 0 bytes PythonHome/Lib/multiprocessing/process.py | 323 + PythonHome/Lib/multiprocessing/process.pyc | Bin 9105 -> 0 bytes PythonHome/Lib/multiprocessing/queues.py | 393 ++ PythonHome/Lib/multiprocessing/queues.pyc | Bin 11070 -> 0 bytes PythonHome/Lib/multiprocessing/reduction.py | 215 + PythonHome/Lib/multiprocessing/reduction.pyc | Bin 5758 -> 0 bytes .../Lib/multiprocessing/sharedctypes.py | 266 + .../Lib/multiprocessing/sharedctypes.pyc | Bin 8202 -> 0 bytes PythonHome/Lib/multiprocessing/synchronize.py | 344 + .../Lib/multiprocessing/synchronize.pyc | Bin 10489 -> 0 bytes PythonHome/Lib/multiprocessing/util.py | 350 + PythonHome/Lib/multiprocessing/util.pyc | Bin 9710 -> 0 bytes PythonHome/Lib/mutex.py | 55 + PythonHome/Lib/mutex.pyc | Bin 2410 -> 0 bytes PythonHome/Lib/netrc.py | 145 + PythonHome/Lib/netrc.pyc | Bin 4534 -> 4930 bytes PythonHome/Lib/new.py | 17 + PythonHome/Lib/new.pyc | Bin 847 -> 0 bytes PythonHome/Lib/nntplib.py | 636 ++ PythonHome/Lib/nntplib.pyc | Bin 20381 -> 0 bytes PythonHome/Lib/ntpath.py | 549 ++ PythonHome/Lib/ntpath.pyc | Bin 12974 -> 13722 bytes PythonHome/Lib/nturl2path.py | 66 + PythonHome/Lib/nturl2path.pyc | Bin 1800 -> 1902 bytes PythonHome/Lib/numbers.py | 391 ++ PythonHome/Lib/numbers.pyc | Bin 13082 -> 0 bytes PythonHome/Lib/opcode.py | 192 + PythonHome/Lib/opcode.pyc | Bin 6124 -> 6297 bytes PythonHome/Lib/optparse.py | 1704 +++++ PythonHome/Lib/optparse.pyc | Bin 53424 -> 0 bytes PythonHome/Lib/os.py | 742 ++ PythonHome/Lib/os.pyc | Bin 25437 -> 27239 bytes PythonHome/Lib/os2emxpath.py | 159 + PythonHome/Lib/os2emxpath.pyc | Bin 4357 -> 0 bytes PythonHome/Lib/pdb.py | 1338 ++++ PythonHome/Lib/pdb.pyc | Bin 41897 -> 0 bytes PythonHome/Lib/pickle.py | 1391 ++++ PythonHome/Lib/pickle.pyc | Bin 36909 -> 0 bytes PythonHome/Lib/pickletools.py | 2274 ++++++ PythonHome/Lib/pickletools.pyc | Bin 56630 -> 0 bytes PythonHome/Lib/pipes.py | 278 + PythonHome/Lib/pipes.pyc | Bin 9068 -> 0 bytes PythonHome/Lib/pkgutil.py | 591 ++ PythonHome/Lib/pkgutil.pyc | Bin 18768 -> 0 bytes PythonHome/Lib/platform.py | 1655 +++++ PythonHome/Lib/platform.pyc | Bin 36867 -> 38459 bytes PythonHome/Lib/plistlib.py | 474 ++ PythonHome/Lib/plistlib.pyc | Bin 18384 -> 0 bytes PythonHome/Lib/popen2.py | 201 + PythonHome/Lib/popen2.pyc | Bin 8785 -> 0 bytes PythonHome/Lib/poplib.py | 417 ++ PythonHome/Lib/poplib.pyc | Bin 12688 -> 0 bytes PythonHome/Lib/posixfile.py | 237 + PythonHome/Lib/posixfile.pyc | Bin 7472 -> 0 bytes PythonHome/Lib/posixpath.py | 446 ++ PythonHome/Lib/posixpath.pyc | Bin 11495 -> 12311 bytes PythonHome/Lib/pprint.py | 346 + PythonHome/Lib/pprint.pyc | Bin 9909 -> 0 bytes PythonHome/Lib/profile.py | 610 ++ PythonHome/Lib/profile.pyc | Bin 15873 -> 0 bytes PythonHome/Lib/pstats.py | 705 ++ PythonHome/Lib/pstats.pyc | Bin 24113 -> 0 bytes PythonHome/Lib/pty.py | 180 + PythonHome/Lib/pty.pyc | Bin 4816 -> 0 bytes PythonHome/Lib/py_compile.py | 170 + PythonHome/Lib/py_compile.pyc | Bin 6389 -> 0 bytes PythonHome/Lib/pyclbr.pyc | Bin 9456 -> 0 bytes PythonHome/Lib/pydoc.py | 2398 +++++++ PythonHome/Lib/pydoc.pyc | Bin 88903 -> 0 bytes PythonHome/Lib/pydoc_data/__init__.py | 0 PythonHome/Lib/pydoc_data/__init__.pyc | Bin 115 -> 0 bytes PythonHome/Lib/pydoc_data/topics.py | 79 + PythonHome/Lib/pydoc_data/topics.pyc | Bin 400488 -> 0 bytes PythonHome/Lib/quopri.py | 237 + PythonHome/Lib/quopri.pyc | Bin 6517 -> 6891 bytes PythonHome/Lib/random.py | 910 +++ PythonHome/Lib/random.pyc | Bin 25353 -> 26815 bytes PythonHome/Lib/re.py | 327 + PythonHome/Lib/re.pyc | Bin 13045 -> 13759 bytes PythonHome/Lib/repr.py | 132 + PythonHome/Lib/repr.pyc | Bin 5130 -> 0 bytes PythonHome/Lib/rexec.py | 588 ++ PythonHome/Lib/rexec.pyc | Bin 23253 -> 0 bytes PythonHome/Lib/rfc822.py | 1011 +++ PythonHome/Lib/rfc822.pyc | Bin 31491 -> 33531 bytes PythonHome/Lib/rlcompleter.py | 166 + PythonHome/Lib/rlcompleter.pyc | Bin 5858 -> 0 bytes PythonHome/Lib/robotparser.py | 233 + PythonHome/Lib/robotparser.pyc | Bin 7600 -> 0 bytes PythonHome/Lib/runpy.py | 278 + PythonHome/Lib/runpy.pyc | Bin 8308 -> 0 bytes PythonHome/Lib/sched.py | 134 + PythonHome/Lib/sched.pyc | Bin 4859 -> 0 bytes PythonHome/Lib/sets.py | 557 ++ PythonHome/Lib/sets.pyc | Bin 16055 -> 0 bytes PythonHome/Lib/sgmllib.py | 553 ++ PythonHome/Lib/sgmllib.pyc | Bin 14731 -> 0 bytes PythonHome/Lib/sha.py | 15 + PythonHome/Lib/sha.pyc | Bin 406 -> 0 bytes PythonHome/Lib/shelve.py | 239 + PythonHome/Lib/shelve.pyc | Bin 9862 -> 0 bytes PythonHome/Lib/shlex.py | 292 + PythonHome/Lib/shlex.pyc | Bin 7347 -> 7919 bytes PythonHome/Lib/shutil.py | 555 ++ PythonHome/Lib/shutil.pyc | Bin 18236 -> 0 bytes .../Lib/site-packages/_markerlib/__init__.py | 16 + .../Lib/site-packages/_markerlib/__init__.pyc | Bin 1032 -> 0 bytes .../Lib/site-packages/_markerlib/markers.py | 119 + .../Lib/site-packages/_markerlib/markers.pyc | Bin 4894 -> 0 bytes .../PKG-INFO | 20 + .../SOURCES.txt | 22 + .../dependency_links.txt | 1 + .../installed-files.txt | 39 + .../top_level.txt | 1 + PythonHome/Lib/site-packages/bs4/__init__.py | 406 ++ PythonHome/Lib/site-packages/bs4/__init__.pyc | Bin 0 -> 14358 bytes .../Lib/site-packages/bs4/builder/__init__.py | 321 + .../site-packages/bs4/builder/__init__.pyc | Bin 0 -> 11503 bytes .../site-packages/bs4/builder/_html5lib.py | 285 + .../site-packages/bs4/builder/_html5lib.pyc | Bin 0 -> 13108 bytes .../site-packages/bs4/builder/_htmlparser.py | 258 + .../site-packages/bs4/builder/_htmlparser.pyc | Bin 0 -> 9215 bytes .../Lib/site-packages/bs4/builder/_lxml.py | 233 + .../Lib/site-packages/bs4/builder/_lxml.pyc | Bin 0 -> 8730 bytes PythonHome/Lib/site-packages/bs4/dammit.py | 829 +++ PythonHome/Lib/site-packages/bs4/dammit.pyc | Bin 0 -> 22961 bytes PythonHome/Lib/site-packages/bs4/diagnose.py | 204 + PythonHome/Lib/site-packages/bs4/element.py | 1611 +++++ PythonHome/Lib/site-packages/bs4/element.pyc | Bin 0 -> 57630 bytes PythonHome/Lib/site-packages/bs4/testing.py | 592 ++ PythonHome/Lib/site-packages/easy_install.py | 5 + PythonHome/Lib/site-packages/easy_install.pyc | Bin 302 -> 0 bytes .../site-packages/pip-1.5.6.dist-info/RECORD | 6 +- PythonHome/Lib/site-packages/pip/__init__.py | 277 + PythonHome/Lib/site-packages/pip/__init__.pyc | Bin 8946 -> 0 bytes PythonHome/Lib/site-packages/pip/__main__.py | 7 + PythonHome/Lib/site-packages/pip/__main__.pyc | Bin 288 -> 0 bytes .../Lib/site-packages/pip/_vendor/__init__.py | 8 + .../site-packages/pip/_vendor/__init__.pyc | Bin 473 -> 0 bytes .../pip/_vendor/_markerlib/__init__.py | 16 + .../pip/_vendor/_markerlib/__init__.pyc | Bin 1264 -> 0 bytes .../pip/_vendor/_markerlib/markers.py | 119 + .../pip/_vendor/_markerlib/markers.pyc | Bin 5466 -> 0 bytes .../pip/_vendor/colorama/__init__.py | 7 + .../pip/_vendor/colorama/__init__.pyc | Bin 451 -> 0 bytes .../pip/_vendor/colorama/ansi.py | 50 + .../pip/_vendor/colorama/ansi.pyc | Bin 2317 -> 0 bytes .../pip/_vendor/colorama/ansitowin32.py | 190 + .../pip/_vendor/colorama/ansitowin32.pyc | Bin 7700 -> 0 bytes .../pip/_vendor/colorama/initialise.py | 56 + .../pip/_vendor/colorama/initialise.pyc | Bin 2007 -> 0 bytes .../pip/_vendor/colorama/win32.py | 137 + .../pip/_vendor/colorama/win32.pyc | Bin 4352 -> 0 bytes .../pip/_vendor/colorama/winterm.py | 120 + .../pip/_vendor/colorama/winterm.pyc | Bin 5164 -> 0 bytes .../pip/_vendor/distlib/__init__.py | 23 + .../pip/_vendor/distlib/__init__.pyc | Bin 1455 -> 0 bytes .../pip/_vendor/distlib/_backport/__init__.py | 6 + .../_vendor/distlib/_backport/__init__.pyc | Bin 470 -> 0 bytes .../pip/_vendor/distlib/_backport/misc.py | 41 + .../pip/_vendor/distlib/_backport/misc.pyc | Bin 1376 -> 0 bytes .../pip/_vendor/distlib/_backport/shutil.py | 761 ++ .../pip/_vendor/distlib/_backport/shutil.pyc | Bin 27281 -> 0 bytes .../_vendor/distlib/_backport/sysconfig.py | 788 +++ .../_vendor/distlib/_backport/sysconfig.pyc | Bin 20509 -> 0 bytes .../pip/_vendor/distlib/_backport/tarfile.py | 2607 +++++++ .../pip/_vendor/distlib/_backport/tarfile.pyc | Bin 82723 -> 0 bytes .../pip/_vendor/distlib/compat.py | 1064 +++ .../pip/_vendor/distlib/compat.pyc | Bin 40799 -> 0 bytes .../pip/_vendor/distlib/database.py | 1301 ++++ .../pip/_vendor/distlib/database.pyc | Bin 47938 -> 0 bytes .../pip/_vendor/distlib/index.py | 488 ++ .../pip/_vendor/distlib/index.pyc | Bin 18609 -> 0 bytes .../pip/_vendor/distlib/locators.py | 1194 ++++ .../pip/_vendor/distlib/locators.pyc | Bin 42636 -> 0 bytes .../pip/_vendor/distlib/manifest.py | 364 + .../pip/_vendor/distlib/manifest.pyc | Bin 11644 -> 0 bytes .../pip/_vendor/distlib/markers.py | 190 + .../pip/_vendor/distlib/markers.pyc | Bin 7863 -> 0 bytes .../pip/_vendor/distlib/metadata.py | 1026 +++ .../pip/_vendor/distlib/metadata.pyc | Bin 33141 -> 0 bytes .../pip/_vendor/distlib/resources.py | 317 + .../pip/_vendor/distlib/resources.pyc | Bin 13903 -> 0 bytes .../pip/_vendor/distlib/scripts.py | 323 + .../pip/_vendor/distlib/scripts.pyc | Bin 10967 -> 0 bytes .../site-packages/pip/_vendor/distlib/util.py | 1575 +++++ .../pip/_vendor/distlib/util.pyc | Bin 58360 -> 0 bytes .../pip/_vendor/distlib/version.py | 721 ++ .../pip/_vendor/distlib/version.pyc | Bin 27211 -> 0 bytes .../pip/_vendor/distlib/wheel.py | 958 +++ .../pip/_vendor/distlib/wheel.pyc | Bin 30135 -> 0 bytes .../pip/_vendor/html5lib/__init__.py | 23 + .../pip/_vendor/html5lib/__init__.pyc | Bin 1116 -> 0 bytes .../pip/_vendor/html5lib/constants.py | 3104 +++++++++ .../pip/_vendor/html5lib/constants.pyc | Bin 86932 -> 0 bytes .../pip/_vendor/html5lib/filters/__init__.py | 0 .../pip/_vendor/html5lib/filters/__init__.pyc | Bin 147 -> 0 bytes .../pip/_vendor/html5lib/filters/_base.py | 12 + .../pip/_vendor/html5lib/filters/_base.pyc | Bin 1046 -> 0 bytes .../filters/alphabeticalattributes.py | 20 + .../filters/alphabeticalattributes.pyc | Bin 1343 -> 0 bytes .../html5lib/filters/inject_meta_charset.py | 65 + .../html5lib/filters/inject_meta_charset.pyc | Bin 2202 -> 0 bytes .../pip/_vendor/html5lib/filters/lint.py | 93 + .../pip/_vendor/html5lib/filters/lint.pyc | Bin 3668 -> 0 bytes .../_vendor/html5lib/filters/optionaltags.py | 205 + .../_vendor/html5lib/filters/optionaltags.pyc | Bin 4310 -> 0 bytes .../pip/_vendor/html5lib/filters/sanitizer.py | 12 + .../_vendor/html5lib/filters/sanitizer.pyc | Bin 872 -> 0 bytes .../_vendor/html5lib/filters/whitespace.py | 38 + .../_vendor/html5lib/filters/whitespace.pyc | Bin 1612 -> 0 bytes .../pip/_vendor/html5lib/html5parser.py | 2713 ++++++++ .../pip/_vendor/html5lib/html5parser.pyc | Bin 127539 -> 0 bytes .../pip/_vendor/html5lib/ihatexml.py | 285 + .../pip/_vendor/html5lib/ihatexml.pyc | Bin 15797 -> 0 bytes .../pip/_vendor/html5lib/inputstream.py | 881 +++ .../pip/_vendor/html5lib/inputstream.pyc | Bin 28518 -> 0 bytes .../pip/_vendor/html5lib/sanitizer.py | 271 + .../pip/_vendor/html5lib/sanitizer.pyc | Bin 14121 -> 0 bytes .../_vendor/html5lib/serializer/__init__.py | 16 + .../_vendor/html5lib/serializer/__init__.pyc | Bin 904 -> 0 bytes .../html5lib/serializer/htmlserializer.py | 320 + .../html5lib/serializer/htmlserializer.pyc | Bin 11481 -> 0 bytes .../pip/_vendor/html5lib/tokenizer.py | 1731 +++++ .../pip/_vendor/html5lib/tokenizer.pyc | Bin 55403 -> 0 bytes .../_vendor/html5lib/treeadapters/__init__.py | 0 .../html5lib/treeadapters/__init__.pyc | Bin 152 -> 0 bytes .../pip/_vendor/html5lib/treeadapters/sax.py | 44 + .../pip/_vendor/html5lib/treeadapters/sax.pyc | Bin 1735 -> 0 bytes .../{__init__.pyc => __init__.py} | Bin 3419 -> 3405 bytes .../_vendor/html5lib/treebuilders/_base.py | 377 + .../_vendor/html5lib/treebuilders/_base.pyc | Bin 14889 -> 0 bytes .../pip/_vendor/html5lib/treebuilders/dom.py | 227 + .../pip/_vendor/html5lib/treebuilders/dom.pyc | Bin 11062 -> 0 bytes .../_vendor/html5lib/treebuilders/etree.py | 337 + .../_vendor/html5lib/treebuilders/etree.pyc | Bin 15563 -> 0 bytes .../html5lib/treebuilders/etree_lxml.py | 369 + .../html5lib/treebuilders/etree_lxml.pyc | Bin 14788 -> 0 bytes .../_vendor/html5lib/treewalkers/__init__.py | 57 + .../_vendor/html5lib/treewalkers/__init__.pyc | Bin 2510 -> 0 bytes .../pip/_vendor/html5lib/treewalkers/_base.py | 200 + .../_vendor/html5lib/treewalkers/_base.pyc | Bin 8349 -> 0 bytes .../pip/_vendor/html5lib/treewalkers/dom.py | 46 + .../pip/_vendor/html5lib/treewalkers/dom.pyc | Bin 2201 -> 0 bytes .../pip/_vendor/html5lib/treewalkers/etree.py | 138 + .../_vendor/html5lib/treewalkers/etree.pyc | Bin 4461 -> 0 bytes .../html5lib/treewalkers/genshistream.py | 69 + .../html5lib/treewalkers/genshistream.pyc | Bin 2397 -> 0 bytes .../_vendor/html5lib/treewalkers/lxmletree.py | 208 + .../html5lib/treewalkers/lxmletree.pyc | Bin 8870 -> 0 bytes .../_vendor/html5lib/treewalkers/pulldom.py | 63 + .../_vendor/html5lib/treewalkers/pulldom.pyc | Bin 2316 -> 0 bytes .../pip/_vendor/html5lib/trie/__init__.py | 12 + .../pip/_vendor/html5lib/trie/__init__.pyc | Bin 460 -> 0 bytes .../pip/_vendor/html5lib/trie/_base.py | 37 + .../pip/_vendor/html5lib/trie/_base.pyc | Bin 1859 -> 0 bytes .../pip/_vendor/html5lib/trie/datrie.py | 44 + .../pip/_vendor/html5lib/trie/datrie.pyc | Bin 2977 -> 0 bytes .../pip/_vendor/html5lib/trie/py.py | 67 + .../pip/_vendor/html5lib/trie/py.pyc | Bin 3199 -> 0 bytes .../pip/_vendor/html5lib/utils.py | 82 + .../pip/_vendor/html5lib/utils.pyc | Bin 3432 -> 0 bytes .../pip/_vendor/pkg_resources.py | 2762 ++++++++ .../pip/_vendor/pkg_resources.pyc | Bin 114459 -> 0 bytes .../site-packages/pip/_vendor/re-vendor.py | 34 + .../site-packages/pip/_vendor/re-vendor.pyc | Bin 1396 -> 0 bytes .../pip/_vendor/requests/__init__.py | 77 + .../pip/_vendor/requests/__init__.pyc | Bin 2603 -> 0 bytes .../pip/_vendor/requests/adapters.py | 388 ++ .../pip/_vendor/requests/adapters.pyc | Bin 14350 -> 0 bytes .../pip/_vendor/requests/{api.pyc => api.py} | Bin 5551 -> 4344 bytes .../pip/_vendor/requests/auth.py | 193 + .../pip/_vendor/requests/auth.pyc | Bin 7663 -> 0 bytes .../pip/_vendor/requests/certs.py | 24 + .../pip/_vendor/requests/certs.pyc | Bin 849 -> 0 bytes .../pip/_vendor/requests/compat.py | 115 + .../pip/_vendor/requests/compat.pyc | Bin 2608 -> 0 bytes .../pip/_vendor/requests/cookies.py | 454 ++ .../pip/_vendor/requests/cookies.pyc | Bin 21748 -> 0 bytes .../pip/_vendor/requests/exceptions.py | 75 + .../pip/_vendor/requests/exceptions.pyc | Bin 4491 -> 0 bytes .../pip/_vendor/requests/hooks.py | 45 + .../pip/_vendor/requests/hooks.pyc | Bin 1148 -> 0 bytes .../pip/_vendor/requests/models.py | 803 +++ .../pip/_vendor/requests/models.pyc | Bin 25332 -> 0 bytes .../pip/_vendor/requests/sessions.py | 637 ++ .../pip/_vendor/requests/sessions.pyc | Bin 19371 -> 0 bytes .../pip/_vendor/requests/status_codes.py | 88 + .../pip/_vendor/requests/status_codes.pyc | Bin 4556 -> 0 bytes .../pip/_vendor/requests/structures.py | 127 + .../pip/_vendor/requests/structures.pyc | Bin 7071 -> 0 bytes .../pip/_vendor/requests/utils.py | 673 ++ .../pip/_vendor/requests/utils.pyc | Bin 20475 -> 0 bytes .../Lib/site-packages/pip/_vendor/six.py | 646 ++ .../Lib/site-packages/pip/_vendor/six.pyc | Bin 24370 -> 0 bytes .../pip/backwardcompat/__init__.py | 138 + .../pip/backwardcompat/__init__.pyc | Bin 5504 -> 0 bytes .../Lib/site-packages/pip/basecommand.py | 201 + .../Lib/site-packages/pip/basecommand.pyc | Bin 6383 -> 0 bytes .../Lib/site-packages/pip/baseparser.py | 224 + .../Lib/site-packages/pip/baseparser.pyc | Bin 10265 -> 0 bytes .../Lib/site-packages/pip/cmdoptions.py | 371 + .../Lib/site-packages/pip/cmdoptions.pyc | Bin 8216 -> 0 bytes .../site-packages/pip/commands/__init__.py | 88 + .../site-packages/pip/commands/__init__.pyc | Bin 2708 -> 0 bytes .../Lib/site-packages/pip/commands/bundle.py | 42 + .../Lib/site-packages/pip/commands/bundle.pyc | Bin 2302 -> 0 bytes .../site-packages/pip/commands/completion.py | 59 + .../site-packages/pip/commands/completion.pyc | Bin 2457 -> 0 bytes .../Lib/site-packages/pip/commands/freeze.py | 114 + .../Lib/site-packages/pip/commands/freeze.pyc | Bin 4615 -> 0 bytes .../Lib/site-packages/pip/commands/help.py | 33 + .../Lib/site-packages/pip/commands/help.pyc | Bin 1346 -> 0 bytes .../Lib/site-packages/pip/commands/install.py | 314 + .../site-packages/pip/commands/install.pyc | Bin 9923 -> 0 bytes .../Lib/site-packages/pip/commands/list.py | 162 + .../Lib/site-packages/pip/commands/list.pyc | Bin 6653 -> 0 bytes .../Lib/site-packages/pip/commands/search.py | 132 + .../Lib/site-packages/pip/commands/search.pyc | Bin 5536 -> 0 bytes .../Lib/site-packages/pip/commands/show.py | 80 + .../Lib/site-packages/pip/commands/show.pyc | Bin 3457 -> 0 bytes .../site-packages/pip/commands/uninstall.py | 59 + .../site-packages/pip/commands/uninstall.pyc | Bin 2732 -> 0 bytes .../Lib/site-packages/pip/commands/unzip.py | 7 + .../Lib/site-packages/pip/commands/unzip.pyc | Bin 589 -> 0 bytes .../Lib/site-packages/pip/commands/wheel.py | 195 + .../Lib/site-packages/pip/commands/wheel.pyc | Bin 6130 -> 0 bytes .../Lib/site-packages/pip/commands/zip.py | 351 + .../Lib/site-packages/pip/commands/zip.pyc | Bin 12014 -> 0 bytes PythonHome/Lib/site-packages/pip/download.py | 644 ++ PythonHome/Lib/site-packages/pip/download.pyc | Bin 20848 -> 0 bytes .../Lib/site-packages/pip/exceptions.py | 46 + .../Lib/site-packages/pip/exceptions.pyc | Bin 3167 -> 0 bytes PythonHome/Lib/site-packages/pip/index.py | 990 +++ PythonHome/Lib/site-packages/pip/index.pyc | Bin 33949 -> 0 bytes PythonHome/Lib/site-packages/pip/locations.py | 172 + .../Lib/site-packages/pip/locations.pyc | Bin 5595 -> 0 bytes PythonHome/Lib/site-packages/pip/log.py | 276 + PythonHome/Lib/site-packages/pip/log.pyc | Bin 10140 -> 0 bytes .../Lib/site-packages/pip/pep425tags.py | 102 + .../Lib/site-packages/pip/pep425tags.pyc | Bin 3246 -> 0 bytes PythonHome/Lib/site-packages/pip/req.py | 1931 +++++ PythonHome/Lib/site-packages/pip/req.pyc | Bin 62014 -> 0 bytes PythonHome/Lib/site-packages/pip/runner.py | 18 + PythonHome/Lib/site-packages/pip/runner.pyc | Bin 573 -> 0 bytes .../Lib/site-packages/pip/status_codes.py | 6 + .../Lib/site-packages/pip/status_codes.pyc | Bin 349 -> 0 bytes PythonHome/Lib/site-packages/pip/util.py | 720 ++ PythonHome/Lib/site-packages/pip/util.pyc | Bin 26477 -> 0 bytes .../Lib/site-packages/pip/vcs/__init__.py | 251 + .../Lib/site-packages/pip/vcs/__init__.pyc | Bin 11238 -> 0 bytes .../Lib/site-packages/pip/vcs/bazaar.py | 131 + .../Lib/site-packages/pip/vcs/bazaar.pyc | Bin 6081 -> 0 bytes PythonHome/Lib/site-packages/pip/vcs/git.py | 194 + PythonHome/Lib/site-packages/pip/vcs/git.pyc | Bin 8417 -> 0 bytes .../Lib/site-packages/pip/vcs/mercurial.py | 151 + .../Lib/site-packages/pip/vcs/mercurial.pyc | Bin 6836 -> 0 bytes .../Lib/site-packages/pip/vcs/subversion.py | 273 + .../Lib/site-packages/pip/vcs/subversion.pyc | Bin 10370 -> 0 bytes PythonHome/Lib/site-packages/pip/wheel.py | 560 ++ PythonHome/Lib/site-packages/pip/wheel.pyc | Bin 18465 -> 0 bytes PythonHome/Lib/site-packages/pkg_resources.py | 2891 ++++++++ .../Lib/site-packages/pkg_resources.pyc | Bin 104832 -> 0 bytes .../Lib/site-packages/requests/__init__.py | 77 + .../Lib/site-packages/requests/__init__.pyc | Bin 2600 -> 2603 bytes .../Lib/site-packages/requests/adapters.py | 388 ++ .../Lib/site-packages/requests/adapters.pyc | Bin 14331 -> 14350 bytes PythonHome/Lib/site-packages/requests/api.py | 120 + PythonHome/Lib/site-packages/requests/api.pyc | Bin 5542 -> 5551 bytes PythonHome/Lib/site-packages/requests/auth.py | 193 + .../Lib/site-packages/requests/auth.pyc | Bin 7646 -> 7663 bytes .../Lib/site-packages/requests/certs.py | 24 + .../Lib/site-packages/requests/certs.pyc | Bin 847 -> 849 bytes .../Lib/site-packages/requests/compat.py | 115 + .../Lib/site-packages/requests/compat.pyc | Bin 2607 -> 2608 bytes .../Lib/site-packages/requests/cookies.py | 454 ++ .../Lib/site-packages/requests/cookies.pyc | Bin 21697 -> 21748 bytes .../Lib/site-packages/requests/exceptions.py | 75 + .../Lib/site-packages/requests/exceptions.pyc | Bin 4476 -> 4491 bytes .../Lib/site-packages/requests/hooks.py | 45 + .../Lib/site-packages/requests/hooks.pyc | Bin 1145 -> 1148 bytes .../Lib/site-packages/requests/models.py | 803 +++ .../Lib/site-packages/requests/models.pyc | Bin 25284 -> 25332 bytes .../Lib/site-packages/requests/sessions.py | 637 ++ .../Lib/site-packages/requests/sessions.pyc | Bin 19342 -> 19371 bytes .../site-packages/requests/status_codes.py | 88 + .../site-packages/requests/status_codes.pyc | Bin 5954 -> 4552 bytes .../Lib/site-packages/requests/structures.py | 127 + .../Lib/site-packages/requests/structures.pyc | Bin 7047 -> 7071 bytes .../Lib/site-packages/requests/utils.py | 673 ++ .../Lib/site-packages/requests/utils.pyc | Bin 20442 -> 20475 bytes .../setuptools-5.4.1.dist-info/RECORD | 4 +- .../Lib/site-packages/setuptools/__init__.py | 154 + .../Lib/site-packages/setuptools/__init__.pyc | Bin 7123 -> 0 bytes .../site-packages/setuptools/archive_util.py | 166 + .../site-packages/setuptools/archive_util.pyc | Bin 6077 -> 0 bytes .../setuptools/command/__init__.py | 18 + .../setuptools/command/__init__.pyc | Bin 818 -> 0 bytes .../site-packages/setuptools/command/alias.py | 78 + .../setuptools/command/alias.pyc | Bin 2948 -> 0 bytes .../setuptools/command/bdist_egg.py | 479 ++ .../setuptools/command/bdist_egg.pyc | Bin 17465 -> 0 bytes .../setuptools/command/bdist_rpm.py | 43 + .../setuptools/command/bdist_rpm.pyc | Bin 1862 -> 0 bytes .../setuptools/command/bdist_wininst.py | 21 + .../setuptools/command/bdist_wininst.pyc | Bin 1150 -> 0 bytes .../setuptools/command/build_ext.py | 305 + .../setuptools/command/build_ext.pyc | Bin 10130 -> 0 bytes .../setuptools/command/build_py.py | 230 + .../setuptools/command/build_py.pyc | Bin 8996 -> 0 bytes .../setuptools/command/develop.py | 169 + .../setuptools/command/develop.pyc | Bin 5739 -> 0 bytes .../setuptools/command/easy_install.py | 2152 ++++++ .../setuptools/command/easy_install.pyc | Bin 70984 -> 0 bytes .../setuptools/command/egg_info.py | 435 ++ .../setuptools/command/egg_info.pyc | Bin 17590 -> 0 bytes .../setuptools/command/install.py | 125 + .../setuptools/command/install.pyc | Bin 4823 -> 0 bytes .../setuptools/command/install_egg_info.py | 116 + .../setuptools/command/install_egg_info.pyc | Bin 5313 -> 0 bytes .../setuptools/command/install_lib.py | 65 + .../setuptools/command/install_lib.pyc | Bin 2744 -> 0 bytes .../setuptools/command/install_scripts.py | 55 + .../setuptools/command/install_scripts.pyc | Bin 2547 -> 0 bytes .../setuptools/command/launcher manifest.xml | 15 - .../setuptools/command/register.py | 10 + .../setuptools/command/register.pyc | Bin 671 -> 0 bytes .../setuptools/command/rotate.py | 61 + .../setuptools/command/rotate.pyc | Bin 2885 -> 0 bytes .../setuptools/command/saveopts.py | 22 + .../setuptools/command/saveopts.pyc | Bin 1090 -> 0 bytes .../site-packages/setuptools/command/sdist.py | 250 + .../setuptools/command/sdist.pyc | Bin 8560 -> 0 bytes .../setuptools/command/setopt.py | 150 + .../setuptools/command/setopt.pyc | Bin 5921 -> 0 bytes .../site-packages/setuptools/command/test.py | 175 + .../site-packages/setuptools/command/test.pyc | Bin 6399 -> 0 bytes .../setuptools/command/upload_docs.py | 191 + .../setuptools/command/upload_docs.pyc | Bin 6898 -> 0 bytes .../Lib/site-packages/setuptools/compat.py | 66 + .../Lib/site-packages/setuptools/compat.pyc | Bin 3411 -> 0 bytes .../Lib/site-packages/setuptools/depends.py | 215 + .../Lib/site-packages/setuptools/depends.pyc | Bin 7019 -> 0 bytes .../Lib/site-packages/setuptools/dist.py | 821 +++ .../Lib/site-packages/setuptools/dist.pyc | Bin 32446 -> 0 bytes .../Lib/site-packages/setuptools/extension.py | 53 + .../site-packages/setuptools/extension.pyc | Bin 2442 -> 0 bytes .../site-packages/setuptools/lib2to3_ex.py | 58 + .../site-packages/setuptools/lib2to3_ex.pyc | Bin 2887 -> 0 bytes .../site-packages/setuptools/package_index.py | 1055 +++ .../setuptools/package_index.pyc | Bin 37678 -> 0 bytes .../site-packages/setuptools/py26compat.py | 19 + .../site-packages/setuptools/py26compat.pyc | Bin 877 -> 0 bytes .../site-packages/setuptools/py27compat.py | 15 + .../site-packages/setuptools/py27compat.pyc | Bin 704 -> 0 bytes .../site-packages/setuptools/py31compat.py | 52 + .../site-packages/setuptools/py31compat.pyc | Bin 2299 -> 0 bytes .../Lib/site-packages/setuptools/sandbox.py | 331 + .../Lib/site-packages/setuptools/sandbox.pyc | Bin 12603 -> 0 bytes .../site-packages/setuptools/site-patch.py | 76 + .../site-packages/setuptools/site-patch.pyc | Bin 1713 -> 0 bytes .../site-packages/setuptools/ssl_support.py | 241 + .../site-packages/setuptools/ssl_support.pyc | Bin 7472 -> 0 bytes .../Lib/site-packages/setuptools/svn_utils.py | 583 ++ .../site-packages/setuptools/svn_utils.pyc | Bin 19506 -> 0 bytes .../site-packages/setuptools/unicode_utils.py | 41 + .../setuptools/unicode_utils.pyc | Bin 1389 -> 0 bytes .../Lib/site-packages/setuptools/version.py | 1 + .../Lib/site-packages/setuptools/version.pyc | Bin 160 -> 0 bytes PythonHome/Lib/site.py | 600 ++ PythonHome/Lib/site.pyc | Bin 19035 -> 20225 bytes PythonHome/Lib/smtpd.py | 555 ++ PythonHome/Lib/smtpd.pyc | Bin 15426 -> 0 bytes PythonHome/Lib/smtplib.py | 863 +++ PythonHome/Lib/smtplib.pyc | Bin 29134 -> 0 bytes PythonHome/Lib/sndhdr.py | 228 + PythonHome/Lib/sndhdr.pyc | Bin 7102 -> 0 bytes PythonHome/Lib/socket.py | 573 ++ PythonHome/Lib/socket.pyc | Bin 15956 -> 16976 bytes PythonHome/Lib/sqlite3/__init__.py | 24 + PythonHome/Lib/sqlite3/__init__.pyc | Bin 149 -> 0 bytes PythonHome/Lib/sqlite3/dbapi2.py | 90 + PythonHome/Lib/sqlite3/dbapi2.pyc | Bin 2573 -> 0 bytes PythonHome/Lib/sqlite3/dump.py | 70 + PythonHome/Lib/sqlite3/dump.pyc | Bin 2026 -> 0 bytes PythonHome/Lib/sre.py | 13 + PythonHome/Lib/sre.pyc | Bin 504 -> 0 bytes PythonHome/Lib/sre_compile.py | 522 ++ PythonHome/Lib/sre_compile.pyc | Bin 10909 -> 11351 bytes PythonHome/Lib/sre_constants.py | 263 + PythonHome/Lib/sre_constants.pyc | Bin 6170 -> 6340 bytes PythonHome/Lib/sre_parse.py | 805 +++ PythonHome/Lib/sre_parse.pyc | Bin 19314 -> 20538 bytes PythonHome/Lib/ssl.py | 484 ++ PythonHome/Lib/ssl.pyc | Bin 14734 -> 15788 bytes PythonHome/Lib/stat.py | 96 + PythonHome/Lib/stat.pyc | Bin 2701 -> 3041 bytes PythonHome/Lib/statvfs.py | 18 + PythonHome/Lib/statvfs.pyc | Bin 605 -> 0 bytes PythonHome/Lib/string.py | 642 ++ PythonHome/Lib/string.pyc | Bin 19753 -> 21487 bytes PythonHome/Lib/stringold.py | 432 ++ PythonHome/Lib/stringold.pyc | Bin 12144 -> 0 bytes PythonHome/Lib/stringprep.py | 272 + PythonHome/Lib/stringprep.pyc | Bin 14387 -> 15067 bytes PythonHome/Lib/struct.py | 3 + PythonHome/Lib/struct.pyc | Bin 234 -> 268 bytes PythonHome/Lib/subprocess.py | 1621 +++++ PythonHome/Lib/subprocess.pyc | Bin 41615 -> 43349 bytes PythonHome/Lib/sunau.py | 493 ++ PythonHome/Lib/sunau.pyc | Bin 17685 -> 0 bytes PythonHome/Lib/sunaudio.py | 49 + PythonHome/Lib/sunaudio.pyc | Bin 1912 -> 0 bytes PythonHome/Lib/symbol.py | 114 + PythonHome/Lib/symbol.pyc | Bin 3016 -> 0 bytes PythonHome/Lib/symtable.py | 239 + PythonHome/Lib/symtable.pyc | Bin 11036 -> 0 bytes PythonHome/Lib/sysconfig.py | 636 ++ PythonHome/Lib/sysconfig.pyc | Bin 17350 -> 18234 bytes PythonHome/Lib/tabnanny.py | 329 + PythonHome/Lib/tabnanny.pyc | Bin 7943 -> 0 bytes PythonHome/Lib/tarfile.py | 2596 +++++++ PythonHome/Lib/tarfile.pyc | Bin 74351 -> 0 bytes PythonHome/Lib/telnetlib.py | 790 +++ PythonHome/Lib/telnetlib.pyc | Bin 22638 -> 0 bytes PythonHome/Lib/tempfile.py | 626 ++ PythonHome/Lib/tempfile.pyc | Bin 19647 -> 21483 bytes PythonHome/Lib/textwrap.py | 425 ++ PythonHome/Lib/textwrap.pyc | Bin 11829 -> 12305 bytes PythonHome/Lib/{this.pyc => this.py} | Bin 1205 -> 1002 bytes PythonHome/Lib/threading.py | 1331 ++++ PythonHome/Lib/threading.pyc | Bin 42118 -> 45552 bytes PythonHome/Lib/timeit.py | 330 + PythonHome/Lib/timeit.pyc | Bin 11578 -> 0 bytes PythonHome/Lib/toaiff.py | 110 + PythonHome/Lib/toaiff.pyc | Bin 3046 -> 0 bytes PythonHome/Lib/token.py | 140 + PythonHome/Lib/token.pyc | Bin 3791 -> 3961 bytes PythonHome/Lib/tokenize.py | 432 ++ PythonHome/Lib/tokenize.pyc | Bin 14142 -> 14686 bytes PythonHome/Lib/trace.py | 819 +++ PythonHome/Lib/trace.pyc | Bin 22282 -> 0 bytes PythonHome/Lib/traceback.py | 320 + PythonHome/Lib/traceback.pyc | Bin 11579 -> 12259 bytes PythonHome/Lib/tty.py | 36 + PythonHome/Lib/tty.pyc | Bin 1272 -> 0 bytes PythonHome/Lib/types.py | 84 + PythonHome/Lib/types.pyc | Bin 2476 -> 2680 bytes .../unittest/{__init__.pyc => __init__.py} | Bin 2949 -> 2718 bytes PythonHome/Lib/unittest/__main__.py | 12 + PythonHome/Lib/unittest/__main__.pyc | Bin 473 -> 0 bytes PythonHome/Lib/unittest/case.py | 1076 +++ PythonHome/Lib/unittest/case.pyc | Bin 38986 -> 0 bytes PythonHome/Lib/unittest/loader.py | 316 + PythonHome/Lib/unittest/loader.pyc | Bin 11050 -> 0 bytes PythonHome/Lib/unittest/main.py | 236 + PythonHome/Lib/unittest/main.pyc | Bin 7876 -> 0 bytes PythonHome/Lib/unittest/result.py | 193 + PythonHome/Lib/unittest/result.pyc | Bin 7564 -> 0 bytes PythonHome/Lib/unittest/runner.py | 196 + PythonHome/Lib/unittest/runner.pyc | Bin 7334 -> 0 bytes PythonHome/Lib/unittest/signals.py | 71 + PythonHome/Lib/unittest/signals.pyc | Bin 2616 -> 0 bytes PythonHome/Lib/unittest/suite.py | 303 + PythonHome/Lib/unittest/suite.pyc | Bin 10013 -> 0 bytes PythonHome/Lib/unittest/test/__init__.py | 21 + PythonHome/Lib/unittest/test/dummy.py | 1 + PythonHome/Lib/unittest/test/support.py | 119 + .../Lib/unittest/test/test_assertions.py | 290 + PythonHome/Lib/unittest/test/test_break.py | 284 + PythonHome/Lib/unittest/test/test_case.py | 1130 +++ .../Lib/unittest/test/test_discovery.py | 398 ++ .../unittest/test/test_functiontestcase.py | 148 + PythonHome/Lib/unittest/test/test_loader.py | 1301 ++++ PythonHome/Lib/unittest/test/test_program.py | 255 + PythonHome/Lib/unittest/test/test_result.py | 567 ++ PythonHome/Lib/unittest/test/test_runner.py | 266 + PythonHome/Lib/unittest/test/test_setups.py | 508 ++ PythonHome/Lib/unittest/test/test_skipping.py | 168 + PythonHome/Lib/unittest/test/test_suite.py | 367 + PythonHome/Lib/unittest/util.py | 156 + PythonHome/Lib/unittest/util.pyc | Bin 4398 -> 0 bytes PythonHome/Lib/urllib.py | 1622 +++++ PythonHome/Lib/urllib.pyc | Bin 49747 -> 53249 bytes PythonHome/Lib/urllib2.py | 1470 ++++ PythonHome/Lib/urllib2.pyc | Bin 46168 -> 50494 bytes PythonHome/Lib/urlparse.py | 428 ++ PythonHome/Lib/urlparse.pyc | Bin 14386 -> 15270 bytes PythonHome/Lib/{user.pyc => user.py} | Bin 1709 -> 1627 bytes PythonHome/Lib/uu.py | 196 + PythonHome/Lib/uu.pyc | Bin 4287 -> 0 bytes PythonHome/Lib/uuid.py | 575 ++ PythonHome/Lib/uuid.pyc | Bin 21299 -> 22625 bytes PythonHome/Lib/warnings.py | 400 ++ PythonHome/Lib/warnings.pyc | Bin 13025 -> 13807 bytes PythonHome/Lib/wave.py | 515 ++ PythonHome/Lib/wave.pyc | Bin 19235 -> 0 bytes PythonHome/Lib/weakref.py | 443 ++ PythonHome/Lib/weakref.pyc | Bin 15095 -> 16897 bytes PythonHome/Lib/webbrowser.py | 704 ++ PythonHome/Lib/webbrowser.pyc | Bin 19104 -> 21092 bytes PythonHome/Lib/whichdb.py | 117 + PythonHome/Lib/whichdb.pyc | Bin 2211 -> 0 bytes PythonHome/Lib/wox.py | 14 +- PythonHome/Lib/wox.pyc | Bin 0 -> 1788 bytes .../Lib/wsgiref/{__init__.pyc => __init__.py} | Bin 714 -> 586 bytes PythonHome/Lib/wsgiref/handlers.py | 450 ++ PythonHome/Lib/wsgiref/handlers.pyc | Bin 15699 -> 0 bytes PythonHome/Lib/wsgiref/headers.py | 169 + PythonHome/Lib/wsgiref/headers.pyc | Bin 7203 -> 0 bytes PythonHome/Lib/wsgiref/simple_server.py | 156 + PythonHome/Lib/wsgiref/simple_server.pyc | Bin 5876 -> 0 bytes PythonHome/Lib/wsgiref/util.py | 165 + PythonHome/Lib/wsgiref/util.pyc | Bin 5813 -> 0 bytes PythonHome/Lib/wsgiref/validate.py | 432 ++ PythonHome/Lib/wsgiref/validate.pyc | Bin 16252 -> 0 bytes PythonHome/Lib/xdrlib.py | 231 + PythonHome/Lib/xdrlib.pyc | Bin 8688 -> 0 bytes PythonHome/Lib/xml/__init__.py | 41 + PythonHome/Lib/xml/__init__.pyc | Bin 1073 -> 0 bytes PythonHome/Lib/xml/dom/NodeFilter.py | 27 + PythonHome/Lib/xml/dom/NodeFilter.pyc | Bin 1081 -> 0 bytes PythonHome/Lib/xml/dom/__init__.py | 139 + PythonHome/Lib/xml/dom/__init__.pyc | Bin 6149 -> 0 bytes PythonHome/Lib/xml/dom/domreg.py | 99 + PythonHome/Lib/xml/dom/domreg.pyc | Bin 3236 -> 0 bytes PythonHome/Lib/xml/dom/expatbuilder.py | 983 +++ PythonHome/Lib/xml/dom/expatbuilder.pyc | Bin 31853 -> 0 bytes PythonHome/Lib/xml/dom/minicompat.py | 110 + PythonHome/Lib/xml/dom/minicompat.pyc | Bin 3334 -> 0 bytes PythonHome/Lib/xml/dom/minidom.py | 1941 ++++++ PythonHome/Lib/xml/dom/minidom.pyc | Bin 62271 -> 0 bytes PythonHome/Lib/xml/dom/pulldom.py | 351 + PythonHome/Lib/xml/dom/pulldom.pyc | Bin 12448 -> 0 bytes PythonHome/Lib/xml/dom/xmlbuilder.py | 386 + PythonHome/Lib/xml/dom/xmlbuilder.pyc | Bin 15689 -> 0 bytes PythonHome/Lib/xml/etree/ElementInclude.py | 142 + PythonHome/Lib/xml/etree/ElementInclude.pyc | Bin 1907 -> 0 bytes PythonHome/Lib/xml/etree/ElementPath.py | 303 + PythonHome/Lib/xml/etree/ElementPath.pyc | Bin 7491 -> 0 bytes PythonHome/Lib/xml/etree/ElementTree.py | 1667 +++++ PythonHome/Lib/xml/etree/ElementTree.pyc | Bin 34357 -> 0 bytes PythonHome/Lib/xml/etree/__init__.py | 33 + PythonHome/Lib/xml/etree/__init__.pyc | Bin 124 -> 0 bytes PythonHome/Lib/xml/etree/cElementTree.py | 3 + PythonHome/Lib/xml/etree/cElementTree.pyc | Bin 171 -> 0 bytes PythonHome/Lib/xml/parsers/__init__.py | 8 + PythonHome/Lib/xml/parsers/__init__.pyc | Bin 309 -> 0 bytes PythonHome/Lib/xml/parsers/expat.py | 4 + PythonHome/Lib/xml/parsers/expat.pyc | Bin 282 -> 0 bytes PythonHome/Lib/xml/sax/__init__.py | 108 + PythonHome/Lib/xml/sax/__init__.pyc | Bin 3669 -> 0 bytes PythonHome/Lib/xml/sax/_exceptions.py | 131 + PythonHome/Lib/xml/sax/_exceptions.pyc | Bin 6084 -> 0 bytes PythonHome/Lib/xml/sax/expatreader.py | 417 ++ PythonHome/Lib/xml/sax/expatreader.pyc | Bin 13861 -> 0 bytes PythonHome/Lib/xml/sax/handler.py | 342 + PythonHome/Lib/xml/sax/handler.pyc | Bin 12903 -> 0 bytes PythonHome/Lib/xml/sax/saxutils.py | 350 + PythonHome/Lib/xml/sax/saxutils.pyc | Bin 14542 -> 0 bytes PythonHome/Lib/xml/sax/xmlreader.py | 381 + PythonHome/Lib/xml/sax/xmlreader.pyc | Bin 18882 -> 0 bytes PythonHome/Lib/xmllib.py | 930 +++ PythonHome/Lib/xmllib.pyc | Bin 26037 -> 0 bytes PythonHome/Lib/xmlrpclib.py | 1632 +++++ PythonHome/Lib/xmlrpclib.pyc | Bin 42804 -> 0 bytes PythonHome/Lib/zipfile.py | 1527 ++++ PythonHome/Lib/zipfile.pyc | Bin 41193 -> 0 bytes PythonHome/Scripts/easy_install-2.7.exe | Bin 91496 -> 91530 bytes PythonHome/Scripts/easy_install.exe | Bin 91496 -> 91530 bytes PythonHome/Scripts/pip.exe | Bin 91468 -> 91502 bytes PythonHome/Scripts/pip2.7.exe | Bin 91468 -> 91502 bytes PythonHome/Scripts/pip2.exe | Bin 91468 -> 91502 bytes PythonHome/install_requirements.bat | 1 + PythonHome/requirements.txt | 2 + Wox.Plugin.SystemPlugins/UrlPlugin.cs | 2 +- Wox.Plugin/IPublicAPI.cs | 2 - Wox.Plugin/PluginInitContext.cs | 6 - Wox/JsonRPC/JsonPRCModel.cs | 30 +- Wox/MainWindow.xaml.cs | 9 - Wox/PluginLoader/BasePlugin.cs | 52 +- Wox/PluginLoader/PythonPlugin.cs | 2 +- 1695 files changed, 304635 insertions(+), 56 deletions(-) delete mode 100644 PythonHome/DLLs/pyc.ico create mode 100644 PythonHome/Lib/BaseHTTPServer.py delete mode 100644 PythonHome/Lib/BaseHTTPServer.pyc create mode 100644 PythonHome/Lib/Bastion.py delete mode 100644 PythonHome/Lib/Bastion.pyc create mode 100644 PythonHome/Lib/CGIHTTPServer.py delete mode 100644 PythonHome/Lib/CGIHTTPServer.pyc create mode 100644 PythonHome/Lib/ConfigParser.py delete mode 100644 PythonHome/Lib/ConfigParser.pyc create mode 100644 PythonHome/Lib/Cookie.py create mode 100644 PythonHome/Lib/DocXMLRPCServer.py delete mode 100644 PythonHome/Lib/DocXMLRPCServer.pyc create mode 100644 PythonHome/Lib/HTMLParser.py rename PythonHome/Lib/{MimeWriter.pyc => MimeWriter.py} (58%) create mode 100644 PythonHome/Lib/Queue.py create mode 100644 PythonHome/Lib/SimpleHTTPServer.py delete mode 100644 PythonHome/Lib/SimpleHTTPServer.pyc create mode 100644 PythonHome/Lib/SimpleXMLRPCServer.py delete mode 100644 PythonHome/Lib/SimpleXMLRPCServer.pyc create mode 100644 PythonHome/Lib/SocketServer.py delete mode 100644 PythonHome/Lib/SocketServer.pyc create mode 100644 PythonHome/Lib/StringIO.py create mode 100644 PythonHome/Lib/UserDict.py create mode 100644 PythonHome/Lib/UserList.py delete mode 100644 PythonHome/Lib/UserList.pyc create mode 100644 PythonHome/Lib/UserString.py delete mode 100644 PythonHome/Lib/UserString.pyc create mode 100644 PythonHome/Lib/_LWPCookieJar.py create mode 100644 PythonHome/Lib/_MozillaCookieJar.py create mode 100644 PythonHome/Lib/__future__.py create mode 100644 PythonHome/Lib/__phello__.foo.py delete mode 100644 PythonHome/Lib/__phello__.foo.pyc create mode 100644 PythonHome/Lib/_abcoll.py create mode 100644 PythonHome/Lib/_osx_support.py delete mode 100644 PythonHome/Lib/_osx_support.pyc create mode 100644 PythonHome/Lib/_pyio.py delete mode 100644 PythonHome/Lib/_pyio.pyc create mode 100644 PythonHome/Lib/_strptime.py delete mode 100644 PythonHome/Lib/_strptime.pyc create mode 100644 PythonHome/Lib/_threading_local.py delete mode 100644 PythonHome/Lib/_threading_local.pyc create mode 100644 PythonHome/Lib/_weakrefset.py create mode 100644 PythonHome/Lib/abc.py create mode 100644 PythonHome/Lib/aifc.py delete mode 100644 PythonHome/Lib/aifc.pyc create mode 100644 PythonHome/Lib/antigravity.py delete mode 100644 PythonHome/Lib/antigravity.pyc rename PythonHome/Lib/{anydbm.pyc => anydbm.py} (54%) create mode 100644 PythonHome/Lib/argparse.py delete mode 100644 PythonHome/Lib/argparse.pyc create mode 100644 PythonHome/Lib/ast.py delete mode 100644 PythonHome/Lib/ast.pyc create mode 100644 PythonHome/Lib/asynchat.py delete mode 100644 PythonHome/Lib/asynchat.pyc create mode 100644 PythonHome/Lib/asyncore.py delete mode 100644 PythonHome/Lib/asyncore.pyc create mode 100644 PythonHome/Lib/atexit.py create mode 100644 PythonHome/Lib/audiodev.py delete mode 100644 PythonHome/Lib/audiodev.pyc create mode 100644 PythonHome/Lib/base64.py create mode 100644 PythonHome/Lib/bdb.py delete mode 100644 PythonHome/Lib/bdb.pyc create mode 100644 PythonHome/Lib/binhex.py delete mode 100644 PythonHome/Lib/binhex.pyc create mode 100644 PythonHome/Lib/bisect.py create mode 100644 PythonHome/Lib/bsddb/__init__.py delete mode 100644 PythonHome/Lib/bsddb/__init__.pyc create mode 100644 PythonHome/Lib/bsddb/db.py delete mode 100644 PythonHome/Lib/bsddb/db.pyc create mode 100644 PythonHome/Lib/bsddb/dbobj.py delete mode 100644 PythonHome/Lib/bsddb/dbobj.pyc create mode 100644 PythonHome/Lib/bsddb/dbrecio.py delete mode 100644 PythonHome/Lib/bsddb/dbrecio.pyc create mode 100644 PythonHome/Lib/bsddb/dbshelve.py delete mode 100644 PythonHome/Lib/bsddb/dbshelve.pyc create mode 100644 PythonHome/Lib/bsddb/dbtables.py delete mode 100644 PythonHome/Lib/bsddb/dbtables.pyc create mode 100644 PythonHome/Lib/bsddb/dbutils.py delete mode 100644 PythonHome/Lib/bsddb/dbutils.pyc create mode 100644 PythonHome/Lib/cProfile.py delete mode 100644 PythonHome/Lib/cProfile.pyc create mode 100644 PythonHome/Lib/calendar.py create mode 100644 PythonHome/Lib/cgi.py create mode 100644 PythonHome/Lib/cgitb.py delete mode 100644 PythonHome/Lib/cgitb.pyc create mode 100644 PythonHome/Lib/chunk.py delete mode 100644 PythonHome/Lib/chunk.pyc create mode 100644 PythonHome/Lib/cmd.py delete mode 100644 PythonHome/Lib/cmd.pyc create mode 100644 PythonHome/Lib/code.py delete mode 100644 PythonHome/Lib/code.pyc create mode 100644 PythonHome/Lib/codecs.py rename PythonHome/Lib/{codeop.pyc => codeop.py} (56%) create mode 100644 PythonHome/Lib/collections.py create mode 100644 PythonHome/Lib/colorsys.py delete mode 100644 PythonHome/Lib/colorsys.pyc create mode 100644 PythonHome/Lib/commands.py delete mode 100644 PythonHome/Lib/commands.pyc create mode 100644 PythonHome/Lib/compileall.py delete mode 100644 PythonHome/Lib/compileall.pyc rename PythonHome/Lib/compiler/{__init__.pyc => __init__.py} (53%) create mode 100644 PythonHome/Lib/compiler/ast.py delete mode 100644 PythonHome/Lib/compiler/ast.pyc create mode 100644 PythonHome/Lib/compiler/consts.py delete mode 100644 PythonHome/Lib/compiler/consts.pyc create mode 100644 PythonHome/Lib/compiler/future.py delete mode 100644 PythonHome/Lib/compiler/future.pyc create mode 100644 PythonHome/Lib/compiler/misc.py delete mode 100644 PythonHome/Lib/compiler/misc.pyc create mode 100644 PythonHome/Lib/compiler/pyassem.py delete mode 100644 PythonHome/Lib/compiler/pyassem.pyc delete mode 100644 PythonHome/Lib/compiler/pycodegen.pyc create mode 100644 PythonHome/Lib/compiler/symbols.py delete mode 100644 PythonHome/Lib/compiler/symbols.pyc create mode 100644 PythonHome/Lib/compiler/syntax.py delete mode 100644 PythonHome/Lib/compiler/syntax.pyc create mode 100644 PythonHome/Lib/compiler/transformer.py delete mode 100644 PythonHome/Lib/compiler/transformer.pyc create mode 100644 PythonHome/Lib/compiler/visitor.py delete mode 100644 PythonHome/Lib/compiler/visitor.pyc create mode 100644 PythonHome/Lib/contextlib.py delete mode 100644 PythonHome/Lib/contextlib.pyc create mode 100644 PythonHome/Lib/cookielib.py create mode 100644 PythonHome/Lib/copy.py create mode 100644 PythonHome/Lib/copy_reg.py create mode 100644 PythonHome/Lib/csv.py delete mode 100644 PythonHome/Lib/csv.pyc create mode 100644 PythonHome/Lib/ctypes/__init__.py create mode 100644 PythonHome/Lib/ctypes/_endian.py create mode 100644 PythonHome/Lib/ctypes/macholib/__init__.py delete mode 100644 PythonHome/Lib/ctypes/macholib/__init__.pyc create mode 100644 PythonHome/Lib/ctypes/macholib/dyld.py delete mode 100644 PythonHome/Lib/ctypes/macholib/dyld.pyc create mode 100644 PythonHome/Lib/ctypes/macholib/dylib.py delete mode 100644 PythonHome/Lib/ctypes/macholib/dylib.pyc create mode 100644 PythonHome/Lib/ctypes/macholib/framework.py delete mode 100644 PythonHome/Lib/ctypes/macholib/framework.pyc create mode 100644 PythonHome/Lib/ctypes/util.py create mode 100644 PythonHome/Lib/ctypes/wintypes.py delete mode 100644 PythonHome/Lib/ctypes/wintypes.pyc create mode 100644 PythonHome/Lib/curses/__init__.py delete mode 100644 PythonHome/Lib/curses/__init__.pyc create mode 100644 PythonHome/Lib/curses/ascii.py delete mode 100644 PythonHome/Lib/curses/ascii.pyc create mode 100644 PythonHome/Lib/curses/has_key.py delete mode 100644 PythonHome/Lib/curses/has_key.pyc create mode 100644 PythonHome/Lib/curses/panel.py delete mode 100644 PythonHome/Lib/curses/panel.pyc create mode 100644 PythonHome/Lib/curses/textpad.py delete mode 100644 PythonHome/Lib/curses/textpad.pyc create mode 100644 PythonHome/Lib/curses/wrapper.py delete mode 100644 PythonHome/Lib/curses/wrapper.pyc create mode 100644 PythonHome/Lib/dbhash.py delete mode 100644 PythonHome/Lib/dbhash.pyc create mode 100644 PythonHome/Lib/decimal.py delete mode 100644 PythonHome/Lib/decimal.pyc create mode 100644 PythonHome/Lib/difflib.py delete mode 100644 PythonHome/Lib/difflib.pyc create mode 100644 PythonHome/Lib/dircache.py delete mode 100644 PythonHome/Lib/dircache.pyc create mode 100644 PythonHome/Lib/dis.py create mode 100644 PythonHome/Lib/distutils/__init__.py delete mode 100644 PythonHome/Lib/distutils/__init__.pyc create mode 100644 PythonHome/Lib/distutils/archive_util.py delete mode 100644 PythonHome/Lib/distutils/archive_util.pyc create mode 100644 PythonHome/Lib/distutils/bcppcompiler.py delete mode 100644 PythonHome/Lib/distutils/bcppcompiler.pyc create mode 100644 PythonHome/Lib/distutils/ccompiler.py delete mode 100644 PythonHome/Lib/distutils/ccompiler.pyc create mode 100644 PythonHome/Lib/distutils/cmd.py delete mode 100644 PythonHome/Lib/distutils/cmd.pyc create mode 100644 PythonHome/Lib/distutils/command/__init__.py delete mode 100644 PythonHome/Lib/distutils/command/__init__.pyc create mode 100644 PythonHome/Lib/distutils/command/bdist.py delete mode 100644 PythonHome/Lib/distutils/command/bdist.pyc create mode 100644 PythonHome/Lib/distutils/command/bdist_dumb.py delete mode 100644 PythonHome/Lib/distutils/command/bdist_dumb.pyc create mode 100644 PythonHome/Lib/distutils/command/bdist_msi.py delete mode 100644 PythonHome/Lib/distutils/command/bdist_msi.pyc create mode 100644 PythonHome/Lib/distutils/command/bdist_rpm.py delete mode 100644 PythonHome/Lib/distutils/command/bdist_rpm.pyc create mode 100644 PythonHome/Lib/distutils/command/bdist_wininst.py delete mode 100644 PythonHome/Lib/distutils/command/bdist_wininst.pyc create mode 100644 PythonHome/Lib/distutils/command/build.py delete mode 100644 PythonHome/Lib/distutils/command/build.pyc create mode 100644 PythonHome/Lib/distutils/command/build_clib.py delete mode 100644 PythonHome/Lib/distutils/command/build_clib.pyc create mode 100644 PythonHome/Lib/distutils/command/build_ext.py delete mode 100644 PythonHome/Lib/distutils/command/build_ext.pyc create mode 100644 PythonHome/Lib/distutils/command/build_py.py delete mode 100644 PythonHome/Lib/distutils/command/build_py.pyc create mode 100644 PythonHome/Lib/distutils/command/build_scripts.py delete mode 100644 PythonHome/Lib/distutils/command/build_scripts.pyc create mode 100644 PythonHome/Lib/distutils/command/check.py delete mode 100644 PythonHome/Lib/distutils/command/check.pyc create mode 100644 PythonHome/Lib/distutils/command/clean.py delete mode 100644 PythonHome/Lib/distutils/command/clean.pyc create mode 100644 PythonHome/Lib/distutils/command/config.py delete mode 100644 PythonHome/Lib/distutils/command/config.pyc create mode 100644 PythonHome/Lib/distutils/command/install.py delete mode 100644 PythonHome/Lib/distutils/command/install.pyc create mode 100644 PythonHome/Lib/distutils/command/install_data.py delete mode 100644 PythonHome/Lib/distutils/command/install_data.pyc create mode 100644 PythonHome/Lib/distutils/command/install_egg_info.py delete mode 100644 PythonHome/Lib/distutils/command/install_egg_info.pyc create mode 100644 PythonHome/Lib/distutils/command/install_headers.py delete mode 100644 PythonHome/Lib/distutils/command/install_headers.pyc create mode 100644 PythonHome/Lib/distutils/command/install_lib.py delete mode 100644 PythonHome/Lib/distutils/command/install_lib.pyc create mode 100644 PythonHome/Lib/distutils/command/install_scripts.py delete mode 100644 PythonHome/Lib/distutils/command/install_scripts.pyc create mode 100644 PythonHome/Lib/distutils/command/register.py delete mode 100644 PythonHome/Lib/distutils/command/register.pyc create mode 100644 PythonHome/Lib/distutils/command/sdist.py delete mode 100644 PythonHome/Lib/distutils/command/sdist.pyc create mode 100644 PythonHome/Lib/distutils/command/upload.py delete mode 100644 PythonHome/Lib/distutils/command/upload.pyc create mode 100644 PythonHome/Lib/distutils/config.py delete mode 100644 PythonHome/Lib/distutils/config.pyc create mode 100644 PythonHome/Lib/distutils/core.py delete mode 100644 PythonHome/Lib/distutils/core.pyc create mode 100644 PythonHome/Lib/distutils/cygwinccompiler.py delete mode 100644 PythonHome/Lib/distutils/cygwinccompiler.pyc create mode 100644 PythonHome/Lib/distutils/debug.py delete mode 100644 PythonHome/Lib/distutils/debug.pyc create mode 100644 PythonHome/Lib/distutils/dep_util.py delete mode 100644 PythonHome/Lib/distutils/dep_util.pyc create mode 100644 PythonHome/Lib/distutils/dir_util.py delete mode 100644 PythonHome/Lib/distutils/dir_util.pyc create mode 100644 PythonHome/Lib/distutils/dist.py delete mode 100644 PythonHome/Lib/distutils/dist.pyc create mode 100644 PythonHome/Lib/distutils/emxccompiler.py delete mode 100644 PythonHome/Lib/distutils/emxccompiler.pyc create mode 100644 PythonHome/Lib/distutils/errors.py delete mode 100644 PythonHome/Lib/distutils/errors.pyc create mode 100644 PythonHome/Lib/distutils/extension.py delete mode 100644 PythonHome/Lib/distutils/extension.pyc create mode 100644 PythonHome/Lib/distutils/fancy_getopt.py delete mode 100644 PythonHome/Lib/distutils/fancy_getopt.pyc create mode 100644 PythonHome/Lib/distutils/file_util.py delete mode 100644 PythonHome/Lib/distutils/file_util.pyc create mode 100644 PythonHome/Lib/distutils/filelist.py delete mode 100644 PythonHome/Lib/distutils/filelist.pyc create mode 100644 PythonHome/Lib/distutils/log.py delete mode 100644 PythonHome/Lib/distutils/log.pyc create mode 100644 PythonHome/Lib/distutils/msvc9compiler.py delete mode 100644 PythonHome/Lib/distutils/msvc9compiler.pyc create mode 100644 PythonHome/Lib/distutils/msvccompiler.py delete mode 100644 PythonHome/Lib/distutils/msvccompiler.pyc create mode 100644 PythonHome/Lib/distutils/spawn.py delete mode 100644 PythonHome/Lib/distutils/spawn.pyc create mode 100644 PythonHome/Lib/distutils/sysconfig.py delete mode 100644 PythonHome/Lib/distutils/sysconfig.pyc create mode 100644 PythonHome/Lib/distutils/text_file.py delete mode 100644 PythonHome/Lib/distutils/text_file.pyc create mode 100644 PythonHome/Lib/distutils/unixccompiler.py delete mode 100644 PythonHome/Lib/distutils/unixccompiler.pyc create mode 100644 PythonHome/Lib/distutils/util.py delete mode 100644 PythonHome/Lib/distutils/util.pyc create mode 100644 PythonHome/Lib/distutils/version.py delete mode 100644 PythonHome/Lib/distutils/version.pyc create mode 100644 PythonHome/Lib/distutils/versionpredicate.py delete mode 100644 PythonHome/Lib/distutils/versionpredicate.pyc create mode 100644 PythonHome/Lib/doctest.py delete mode 100644 PythonHome/Lib/doctest.pyc create mode 100644 PythonHome/Lib/dumbdbm.py delete mode 100644 PythonHome/Lib/dumbdbm.pyc create mode 100644 PythonHome/Lib/dummy_thread.py delete mode 100644 PythonHome/Lib/dummy_thread.pyc create mode 100644 PythonHome/Lib/dummy_threading.py delete mode 100644 PythonHome/Lib/dummy_threading.pyc create mode 100644 PythonHome/Lib/email/__init__.py create mode 100644 PythonHome/Lib/email/_parseaddr.py create mode 100644 PythonHome/Lib/email/base64mime.py delete mode 100644 PythonHome/Lib/email/base64mime.pyc create mode 100644 PythonHome/Lib/email/charset.py delete mode 100644 PythonHome/Lib/email/charset.pyc create mode 100644 PythonHome/Lib/email/encoders.py create mode 100644 PythonHome/Lib/email/errors.py delete mode 100644 PythonHome/Lib/email/errors.pyc create mode 100644 PythonHome/Lib/email/feedparser.py delete mode 100644 PythonHome/Lib/email/feedparser.pyc create mode 100644 PythonHome/Lib/email/generator.py delete mode 100644 PythonHome/Lib/email/generator.pyc create mode 100644 PythonHome/Lib/email/header.py delete mode 100644 PythonHome/Lib/email/header.pyc create mode 100644 PythonHome/Lib/email/iterators.py delete mode 100644 PythonHome/Lib/email/iterators.pyc create mode 100644 PythonHome/Lib/email/message.py delete mode 100644 PythonHome/Lib/email/message.pyc create mode 100644 PythonHome/Lib/email/mime/__init__.py create mode 100644 PythonHome/Lib/email/mime/application.py delete mode 100644 PythonHome/Lib/email/mime/application.pyc create mode 100644 PythonHome/Lib/email/mime/audio.py delete mode 100644 PythonHome/Lib/email/mime/audio.pyc create mode 100644 PythonHome/Lib/email/mime/base.py delete mode 100644 PythonHome/Lib/email/mime/base.pyc create mode 100644 PythonHome/Lib/email/mime/image.py delete mode 100644 PythonHome/Lib/email/mime/image.pyc create mode 100644 PythonHome/Lib/email/mime/message.py delete mode 100644 PythonHome/Lib/email/mime/message.pyc create mode 100644 PythonHome/Lib/email/mime/multipart.py delete mode 100644 PythonHome/Lib/email/mime/multipart.pyc create mode 100644 PythonHome/Lib/email/mime/nonmultipart.py delete mode 100644 PythonHome/Lib/email/mime/nonmultipart.pyc create mode 100644 PythonHome/Lib/email/mime/text.py delete mode 100644 PythonHome/Lib/email/mime/text.pyc create mode 100644 PythonHome/Lib/email/parser.py delete mode 100644 PythonHome/Lib/email/parser.pyc create mode 100644 PythonHome/Lib/email/quoprimime.py delete mode 100644 PythonHome/Lib/email/quoprimime.pyc create mode 100644 PythonHome/Lib/email/utils.py create mode 100644 PythonHome/Lib/encodings/__init__.py create mode 100644 PythonHome/Lib/encodings/aliases.py create mode 100644 PythonHome/Lib/encodings/ascii.py create mode 100644 PythonHome/Lib/encodings/base64_codec.py delete mode 100644 PythonHome/Lib/encodings/base64_codec.pyc create mode 100644 PythonHome/Lib/encodings/big5.py delete mode 100644 PythonHome/Lib/encodings/big5.pyc create mode 100644 PythonHome/Lib/encodings/big5hkscs.py delete mode 100644 PythonHome/Lib/encodings/big5hkscs.pyc create mode 100644 PythonHome/Lib/encodings/bz2_codec.py delete mode 100644 PythonHome/Lib/encodings/bz2_codec.pyc create mode 100644 PythonHome/Lib/encodings/charmap.py delete mode 100644 PythonHome/Lib/encodings/charmap.pyc create mode 100644 PythonHome/Lib/encodings/cp037.py delete mode 100644 PythonHome/Lib/encodings/cp037.pyc create mode 100644 PythonHome/Lib/encodings/cp1006.py delete mode 100644 PythonHome/Lib/encodings/cp1006.pyc create mode 100644 PythonHome/Lib/encodings/cp1026.py delete mode 100644 PythonHome/Lib/encodings/cp1026.pyc create mode 100644 PythonHome/Lib/encodings/cp1140.py delete mode 100644 PythonHome/Lib/encodings/cp1140.pyc create mode 100644 PythonHome/Lib/encodings/cp1250.py delete mode 100644 PythonHome/Lib/encodings/cp1250.pyc create mode 100644 PythonHome/Lib/encodings/cp1251.py delete mode 100644 PythonHome/Lib/encodings/cp1251.pyc create mode 100644 PythonHome/Lib/encodings/cp1252.py delete mode 100644 PythonHome/Lib/encodings/cp1252.pyc create mode 100644 PythonHome/Lib/encodings/cp1253.py delete mode 100644 PythonHome/Lib/encodings/cp1253.pyc create mode 100644 PythonHome/Lib/encodings/cp1254.py delete mode 100644 PythonHome/Lib/encodings/cp1254.pyc create mode 100644 PythonHome/Lib/encodings/cp1255.py delete mode 100644 PythonHome/Lib/encodings/cp1255.pyc create mode 100644 PythonHome/Lib/encodings/cp1256.py delete mode 100644 PythonHome/Lib/encodings/cp1256.pyc create mode 100644 PythonHome/Lib/encodings/cp1257.py delete mode 100644 PythonHome/Lib/encodings/cp1257.pyc create mode 100644 PythonHome/Lib/encodings/cp1258.py delete mode 100644 PythonHome/Lib/encodings/cp1258.pyc create mode 100644 PythonHome/Lib/encodings/cp424.py delete mode 100644 PythonHome/Lib/encodings/cp424.pyc create mode 100644 PythonHome/Lib/encodings/cp437.py delete mode 100644 PythonHome/Lib/encodings/cp437.pyc create mode 100644 PythonHome/Lib/encodings/cp500.py delete mode 100644 PythonHome/Lib/encodings/cp500.pyc create mode 100644 PythonHome/Lib/encodings/cp720.py delete mode 100644 PythonHome/Lib/encodings/cp720.pyc create mode 100644 PythonHome/Lib/encodings/cp737.py delete mode 100644 PythonHome/Lib/encodings/cp737.pyc create mode 100644 PythonHome/Lib/encodings/cp775.py delete mode 100644 PythonHome/Lib/encodings/cp775.pyc create mode 100644 PythonHome/Lib/encodings/cp850.py delete mode 100644 PythonHome/Lib/encodings/cp850.pyc create mode 100644 PythonHome/Lib/encodings/cp852.py delete mode 100644 PythonHome/Lib/encodings/cp852.pyc create mode 100644 PythonHome/Lib/encodings/cp855.py delete mode 100644 PythonHome/Lib/encodings/cp855.pyc create mode 100644 PythonHome/Lib/encodings/cp856.py delete mode 100644 PythonHome/Lib/encodings/cp856.pyc create mode 100644 PythonHome/Lib/encodings/cp857.py delete mode 100644 PythonHome/Lib/encodings/cp857.pyc create mode 100644 PythonHome/Lib/encodings/cp858.py delete mode 100644 PythonHome/Lib/encodings/cp858.pyc create mode 100644 PythonHome/Lib/encodings/cp860.py delete mode 100644 PythonHome/Lib/encodings/cp860.pyc create mode 100644 PythonHome/Lib/encodings/cp861.py delete mode 100644 PythonHome/Lib/encodings/cp861.pyc create mode 100644 PythonHome/Lib/encodings/cp862.py delete mode 100644 PythonHome/Lib/encodings/cp862.pyc create mode 100644 PythonHome/Lib/encodings/cp863.py delete mode 100644 PythonHome/Lib/encodings/cp863.pyc create mode 100644 PythonHome/Lib/encodings/cp864.py delete mode 100644 PythonHome/Lib/encodings/cp864.pyc create mode 100644 PythonHome/Lib/encodings/cp865.py delete mode 100644 PythonHome/Lib/encodings/cp865.pyc create mode 100644 PythonHome/Lib/encodings/cp866.py delete mode 100644 PythonHome/Lib/encodings/cp866.pyc create mode 100644 PythonHome/Lib/encodings/cp869.py delete mode 100644 PythonHome/Lib/encodings/cp869.pyc create mode 100644 PythonHome/Lib/encodings/cp874.py delete mode 100644 PythonHome/Lib/encodings/cp874.pyc create mode 100644 PythonHome/Lib/encodings/cp875.py delete mode 100644 PythonHome/Lib/encodings/cp875.pyc create mode 100644 PythonHome/Lib/encodings/cp932.py delete mode 100644 PythonHome/Lib/encodings/cp932.pyc create mode 100644 PythonHome/Lib/encodings/cp949.py delete mode 100644 PythonHome/Lib/encodings/cp949.pyc create mode 100644 PythonHome/Lib/encodings/cp950.py delete mode 100644 PythonHome/Lib/encodings/cp950.pyc create mode 100644 PythonHome/Lib/encodings/euc_jis_2004.py delete mode 100644 PythonHome/Lib/encodings/euc_jis_2004.pyc create mode 100644 PythonHome/Lib/encodings/euc_jisx0213.py delete mode 100644 PythonHome/Lib/encodings/euc_jisx0213.pyc create mode 100644 PythonHome/Lib/encodings/euc_jp.py delete mode 100644 PythonHome/Lib/encodings/euc_jp.pyc create mode 100644 PythonHome/Lib/encodings/euc_kr.py delete mode 100644 PythonHome/Lib/encodings/euc_kr.pyc create mode 100644 PythonHome/Lib/encodings/gb18030.py delete mode 100644 PythonHome/Lib/encodings/gb18030.pyc create mode 100644 PythonHome/Lib/encodings/gb2312.py delete mode 100644 PythonHome/Lib/encodings/gb2312.pyc create mode 100644 PythonHome/Lib/encodings/gbk.py create mode 100644 PythonHome/Lib/encodings/hex_codec.py create mode 100644 PythonHome/Lib/encodings/hp_roman8.py delete mode 100644 PythonHome/Lib/encodings/hp_roman8.pyc create mode 100644 PythonHome/Lib/encodings/hz.py delete mode 100644 PythonHome/Lib/encodings/hz.pyc create mode 100644 PythonHome/Lib/encodings/idna.py create mode 100644 PythonHome/Lib/encodings/iso2022_jp.py delete mode 100644 PythonHome/Lib/encodings/iso2022_jp.pyc create mode 100644 PythonHome/Lib/encodings/iso2022_jp_1.py delete mode 100644 PythonHome/Lib/encodings/iso2022_jp_1.pyc create mode 100644 PythonHome/Lib/encodings/iso2022_jp_2.py delete mode 100644 PythonHome/Lib/encodings/iso2022_jp_2.pyc create mode 100644 PythonHome/Lib/encodings/iso2022_jp_2004.py delete mode 100644 PythonHome/Lib/encodings/iso2022_jp_2004.pyc create mode 100644 PythonHome/Lib/encodings/iso2022_jp_3.py delete mode 100644 PythonHome/Lib/encodings/iso2022_jp_3.pyc create mode 100644 PythonHome/Lib/encodings/iso2022_jp_ext.py delete mode 100644 PythonHome/Lib/encodings/iso2022_jp_ext.pyc create mode 100644 PythonHome/Lib/encodings/iso2022_kr.py delete mode 100644 PythonHome/Lib/encodings/iso2022_kr.pyc create mode 100644 PythonHome/Lib/encodings/iso8859_1.py delete mode 100644 PythonHome/Lib/encodings/iso8859_1.pyc create mode 100644 PythonHome/Lib/encodings/iso8859_10.py delete mode 100644 PythonHome/Lib/encodings/iso8859_10.pyc create mode 100644 PythonHome/Lib/encodings/iso8859_11.py delete mode 100644 PythonHome/Lib/encodings/iso8859_11.pyc create mode 100644 PythonHome/Lib/encodings/iso8859_13.py delete mode 100644 PythonHome/Lib/encodings/iso8859_13.pyc create mode 100644 PythonHome/Lib/encodings/iso8859_14.py delete mode 100644 PythonHome/Lib/encodings/iso8859_14.pyc create mode 100644 PythonHome/Lib/encodings/iso8859_15.py delete mode 100644 PythonHome/Lib/encodings/iso8859_15.pyc create mode 100644 PythonHome/Lib/encodings/iso8859_16.py delete mode 100644 PythonHome/Lib/encodings/iso8859_16.pyc create mode 100644 PythonHome/Lib/encodings/iso8859_2.py delete mode 100644 PythonHome/Lib/encodings/iso8859_2.pyc create mode 100644 PythonHome/Lib/encodings/iso8859_3.py delete mode 100644 PythonHome/Lib/encodings/iso8859_3.pyc create mode 100644 PythonHome/Lib/encodings/iso8859_4.py delete mode 100644 PythonHome/Lib/encodings/iso8859_4.pyc create mode 100644 PythonHome/Lib/encodings/iso8859_5.py delete mode 100644 PythonHome/Lib/encodings/iso8859_5.pyc create mode 100644 PythonHome/Lib/encodings/iso8859_6.py delete mode 100644 PythonHome/Lib/encodings/iso8859_6.pyc create mode 100644 PythonHome/Lib/encodings/iso8859_7.py delete mode 100644 PythonHome/Lib/encodings/iso8859_7.pyc create mode 100644 PythonHome/Lib/encodings/iso8859_8.py delete mode 100644 PythonHome/Lib/encodings/iso8859_8.pyc create mode 100644 PythonHome/Lib/encodings/iso8859_9.py delete mode 100644 PythonHome/Lib/encodings/iso8859_9.pyc create mode 100644 PythonHome/Lib/encodings/johab.py delete mode 100644 PythonHome/Lib/encodings/johab.pyc create mode 100644 PythonHome/Lib/encodings/koi8_r.py delete mode 100644 PythonHome/Lib/encodings/koi8_r.pyc create mode 100644 PythonHome/Lib/encodings/koi8_u.py delete mode 100644 PythonHome/Lib/encodings/koi8_u.pyc create mode 100644 PythonHome/Lib/encodings/latin_1.py delete mode 100644 PythonHome/Lib/encodings/latin_1.pyc create mode 100644 PythonHome/Lib/encodings/mac_arabic.py delete mode 100644 PythonHome/Lib/encodings/mac_arabic.pyc create mode 100644 PythonHome/Lib/encodings/mac_centeuro.py delete mode 100644 PythonHome/Lib/encodings/mac_centeuro.pyc create mode 100644 PythonHome/Lib/encodings/mac_croatian.py delete mode 100644 PythonHome/Lib/encodings/mac_croatian.pyc create mode 100644 PythonHome/Lib/encodings/mac_cyrillic.py delete mode 100644 PythonHome/Lib/encodings/mac_cyrillic.pyc create mode 100644 PythonHome/Lib/encodings/mac_farsi.py delete mode 100644 PythonHome/Lib/encodings/mac_farsi.pyc create mode 100644 PythonHome/Lib/encodings/mac_greek.py delete mode 100644 PythonHome/Lib/encodings/mac_greek.pyc create mode 100644 PythonHome/Lib/encodings/mac_iceland.py delete mode 100644 PythonHome/Lib/encodings/mac_iceland.pyc create mode 100644 PythonHome/Lib/encodings/mac_latin2.py delete mode 100644 PythonHome/Lib/encodings/mac_latin2.pyc create mode 100644 PythonHome/Lib/encodings/mac_roman.py delete mode 100644 PythonHome/Lib/encodings/mac_roman.pyc create mode 100644 PythonHome/Lib/encodings/mac_romanian.py delete mode 100644 PythonHome/Lib/encodings/mac_romanian.pyc create mode 100644 PythonHome/Lib/encodings/mac_turkish.py delete mode 100644 PythonHome/Lib/encodings/mac_turkish.pyc create mode 100644 PythonHome/Lib/encodings/mbcs.py delete mode 100644 PythonHome/Lib/encodings/mbcs.pyc create mode 100644 PythonHome/Lib/encodings/palmos.py delete mode 100644 PythonHome/Lib/encodings/palmos.pyc create mode 100644 PythonHome/Lib/encodings/ptcp154.py delete mode 100644 PythonHome/Lib/encodings/ptcp154.pyc create mode 100644 PythonHome/Lib/encodings/punycode.py delete mode 100644 PythonHome/Lib/encodings/punycode.pyc create mode 100644 PythonHome/Lib/encodings/quopri_codec.py delete mode 100644 PythonHome/Lib/encodings/quopri_codec.pyc create mode 100644 PythonHome/Lib/encodings/raw_unicode_escape.py delete mode 100644 PythonHome/Lib/encodings/raw_unicode_escape.pyc create mode 100644 PythonHome/Lib/encodings/rot_13.py delete mode 100644 PythonHome/Lib/encodings/rot_13.pyc create mode 100644 PythonHome/Lib/encodings/shift_jis.py delete mode 100644 PythonHome/Lib/encodings/shift_jis.pyc create mode 100644 PythonHome/Lib/encodings/shift_jis_2004.py delete mode 100644 PythonHome/Lib/encodings/shift_jis_2004.pyc create mode 100644 PythonHome/Lib/encodings/shift_jisx0213.py delete mode 100644 PythonHome/Lib/encodings/shift_jisx0213.pyc create mode 100644 PythonHome/Lib/encodings/string_escape.py delete mode 100644 PythonHome/Lib/encodings/string_escape.pyc create mode 100644 PythonHome/Lib/encodings/tis_620.py delete mode 100644 PythonHome/Lib/encodings/tis_620.pyc create mode 100644 PythonHome/Lib/encodings/undefined.py delete mode 100644 PythonHome/Lib/encodings/undefined.pyc create mode 100644 PythonHome/Lib/encodings/unicode_escape.py delete mode 100644 PythonHome/Lib/encodings/unicode_escape.pyc create mode 100644 PythonHome/Lib/encodings/unicode_internal.py delete mode 100644 PythonHome/Lib/encodings/unicode_internal.pyc create mode 100644 PythonHome/Lib/encodings/utf_16.py delete mode 100644 PythonHome/Lib/encodings/utf_16.pyc create mode 100644 PythonHome/Lib/encodings/utf_16_be.py delete mode 100644 PythonHome/Lib/encodings/utf_16_be.pyc create mode 100644 PythonHome/Lib/encodings/utf_16_le.py delete mode 100644 PythonHome/Lib/encodings/utf_16_le.pyc create mode 100644 PythonHome/Lib/encodings/utf_32.py delete mode 100644 PythonHome/Lib/encodings/utf_32.pyc create mode 100644 PythonHome/Lib/encodings/utf_32_be.py delete mode 100644 PythonHome/Lib/encodings/utf_32_be.pyc create mode 100644 PythonHome/Lib/encodings/utf_32_le.py delete mode 100644 PythonHome/Lib/encodings/utf_32_le.pyc create mode 100644 PythonHome/Lib/encodings/utf_7.py delete mode 100644 PythonHome/Lib/encodings/utf_7.pyc create mode 100644 PythonHome/Lib/encodings/utf_8.py create mode 100644 PythonHome/Lib/encodings/utf_8_sig.py delete mode 100644 PythonHome/Lib/encodings/utf_8_sig.pyc create mode 100644 PythonHome/Lib/encodings/uu_codec.py delete mode 100644 PythonHome/Lib/encodings/uu_codec.pyc create mode 100644 PythonHome/Lib/encodings/zlib_codec.py delete mode 100644 PythonHome/Lib/encodings/zlib_codec.pyc create mode 100644 PythonHome/Lib/filecmp.py delete mode 100644 PythonHome/Lib/filecmp.pyc create mode 100644 PythonHome/Lib/fileinput.py delete mode 100644 PythonHome/Lib/fileinput.pyc create mode 100644 PythonHome/Lib/fnmatch.py delete mode 100644 PythonHome/Lib/fnmatch.pyc create mode 100644 PythonHome/Lib/formatter.py delete mode 100644 PythonHome/Lib/formatter.pyc create mode 100644 PythonHome/Lib/fpformat.py delete mode 100644 PythonHome/Lib/fpformat.pyc create mode 100644 PythonHome/Lib/fractions.py delete mode 100644 PythonHome/Lib/fractions.pyc create mode 100644 PythonHome/Lib/ftplib.py delete mode 100644 PythonHome/Lib/ftplib.pyc create mode 100644 PythonHome/Lib/functools.py create mode 100644 PythonHome/Lib/genericpath.py create mode 100644 PythonHome/Lib/getopt.py delete mode 100644 PythonHome/Lib/getopt.pyc create mode 100644 PythonHome/Lib/getpass.py delete mode 100644 PythonHome/Lib/getpass.pyc create mode 100644 PythonHome/Lib/gettext.py delete mode 100644 PythonHome/Lib/gettext.pyc create mode 100644 PythonHome/Lib/glob.py delete mode 100644 PythonHome/Lib/glob.pyc create mode 100644 PythonHome/Lib/gzip.py delete mode 100644 PythonHome/Lib/gzip.pyc create mode 100644 PythonHome/Lib/hashlib.py create mode 100644 PythonHome/Lib/heapq.py create mode 100644 PythonHome/Lib/hmac.py delete mode 100644 PythonHome/Lib/hmac.pyc create mode 100644 PythonHome/Lib/hotshot/__init__.py delete mode 100644 PythonHome/Lib/hotshot/__init__.pyc create mode 100644 PythonHome/Lib/hotshot/log.py delete mode 100644 PythonHome/Lib/hotshot/log.pyc create mode 100644 PythonHome/Lib/hotshot/stats.py delete mode 100644 PythonHome/Lib/hotshot/stats.pyc create mode 100644 PythonHome/Lib/hotshot/stones.py delete mode 100644 PythonHome/Lib/hotshot/stones.pyc create mode 100644 PythonHome/Lib/htmlentitydefs.py create mode 100644 PythonHome/Lib/htmllib.py delete mode 100644 PythonHome/Lib/htmllib.pyc create mode 100644 PythonHome/Lib/httplib.py create mode 100644 PythonHome/Lib/idlelib/AutoComplete.py delete mode 100644 PythonHome/Lib/idlelib/AutoComplete.pyc create mode 100644 PythonHome/Lib/idlelib/AutoCompleteWindow.py delete mode 100644 PythonHome/Lib/idlelib/AutoCompleteWindow.pyc create mode 100644 PythonHome/Lib/idlelib/AutoExpand.py delete mode 100644 PythonHome/Lib/idlelib/AutoExpand.pyc create mode 100644 PythonHome/Lib/idlelib/Bindings.py delete mode 100644 PythonHome/Lib/idlelib/Bindings.pyc create mode 100644 PythonHome/Lib/idlelib/CallTipWindow.py delete mode 100644 PythonHome/Lib/idlelib/CallTipWindow.pyc create mode 100644 PythonHome/Lib/idlelib/CallTips.py delete mode 100644 PythonHome/Lib/idlelib/CallTips.pyc create mode 100644 PythonHome/Lib/idlelib/ClassBrowser.py delete mode 100644 PythonHome/Lib/idlelib/ClassBrowser.pyc create mode 100644 PythonHome/Lib/idlelib/CodeContext.py delete mode 100644 PythonHome/Lib/idlelib/CodeContext.pyc create mode 100644 PythonHome/Lib/idlelib/ColorDelegator.py delete mode 100644 PythonHome/Lib/idlelib/ColorDelegator.pyc create mode 100644 PythonHome/Lib/idlelib/Debugger.py delete mode 100644 PythonHome/Lib/idlelib/Debugger.pyc create mode 100644 PythonHome/Lib/idlelib/Delegator.py delete mode 100644 PythonHome/Lib/idlelib/Delegator.pyc create mode 100644 PythonHome/Lib/idlelib/EditorWindow.py delete mode 100644 PythonHome/Lib/idlelib/EditorWindow.pyc create mode 100644 PythonHome/Lib/idlelib/FileList.py delete mode 100644 PythonHome/Lib/idlelib/FileList.pyc create mode 100644 PythonHome/Lib/idlelib/FormatParagraph.py delete mode 100644 PythonHome/Lib/idlelib/FormatParagraph.pyc create mode 100644 PythonHome/Lib/idlelib/GrepDialog.py delete mode 100644 PythonHome/Lib/idlelib/GrepDialog.pyc create mode 100644 PythonHome/Lib/idlelib/HyperParser.py delete mode 100644 PythonHome/Lib/idlelib/HyperParser.pyc create mode 100644 PythonHome/Lib/idlelib/IOBinding.py delete mode 100644 PythonHome/Lib/idlelib/IOBinding.pyc create mode 100644 PythonHome/Lib/idlelib/IdleHistory.py delete mode 100644 PythonHome/Lib/idlelib/IdleHistory.pyc create mode 100644 PythonHome/Lib/idlelib/MultiCall.py delete mode 100644 PythonHome/Lib/idlelib/MultiCall.pyc create mode 100644 PythonHome/Lib/idlelib/MultiStatusBar.py delete mode 100644 PythonHome/Lib/idlelib/MultiStatusBar.pyc create mode 100644 PythonHome/Lib/idlelib/ObjectBrowser.py delete mode 100644 PythonHome/Lib/idlelib/ObjectBrowser.pyc create mode 100644 PythonHome/Lib/idlelib/OutputWindow.py delete mode 100644 PythonHome/Lib/idlelib/OutputWindow.pyc create mode 100644 PythonHome/Lib/idlelib/ParenMatch.py delete mode 100644 PythonHome/Lib/idlelib/ParenMatch.pyc create mode 100644 PythonHome/Lib/idlelib/PathBrowser.py delete mode 100644 PythonHome/Lib/idlelib/PathBrowser.pyc create mode 100644 PythonHome/Lib/idlelib/Percolator.py delete mode 100644 PythonHome/Lib/idlelib/Percolator.pyc create mode 100644 PythonHome/Lib/idlelib/PyParse.py delete mode 100644 PythonHome/Lib/idlelib/PyParse.pyc create mode 100644 PythonHome/Lib/idlelib/PyShell.py delete mode 100644 PythonHome/Lib/idlelib/PyShell.pyc create mode 100644 PythonHome/Lib/idlelib/RemoteDebugger.py delete mode 100644 PythonHome/Lib/idlelib/RemoteDebugger.pyc create mode 100644 PythonHome/Lib/idlelib/RemoteObjectBrowser.py delete mode 100644 PythonHome/Lib/idlelib/RemoteObjectBrowser.pyc create mode 100644 PythonHome/Lib/idlelib/ReplaceDialog.py delete mode 100644 PythonHome/Lib/idlelib/ReplaceDialog.pyc create mode 100644 PythonHome/Lib/idlelib/RstripExtension.py delete mode 100644 PythonHome/Lib/idlelib/RstripExtension.pyc create mode 100644 PythonHome/Lib/idlelib/ScriptBinding.py delete mode 100644 PythonHome/Lib/idlelib/ScriptBinding.pyc create mode 100644 PythonHome/Lib/idlelib/ScrolledList.py delete mode 100644 PythonHome/Lib/idlelib/ScrolledList.pyc create mode 100644 PythonHome/Lib/idlelib/SearchDialog.py delete mode 100644 PythonHome/Lib/idlelib/SearchDialog.pyc create mode 100644 PythonHome/Lib/idlelib/SearchDialogBase.py delete mode 100644 PythonHome/Lib/idlelib/SearchDialogBase.pyc create mode 100644 PythonHome/Lib/idlelib/SearchEngine.py delete mode 100644 PythonHome/Lib/idlelib/SearchEngine.pyc create mode 100644 PythonHome/Lib/idlelib/StackViewer.py delete mode 100644 PythonHome/Lib/idlelib/StackViewer.pyc create mode 100644 PythonHome/Lib/idlelib/ToolTip.py delete mode 100644 PythonHome/Lib/idlelib/ToolTip.pyc create mode 100644 PythonHome/Lib/idlelib/TreeWidget.py delete mode 100644 PythonHome/Lib/idlelib/TreeWidget.pyc create mode 100644 PythonHome/Lib/idlelib/UndoDelegator.py delete mode 100644 PythonHome/Lib/idlelib/UndoDelegator.pyc create mode 100644 PythonHome/Lib/idlelib/WidgetRedirector.py delete mode 100644 PythonHome/Lib/idlelib/WidgetRedirector.pyc create mode 100644 PythonHome/Lib/idlelib/WindowList.py delete mode 100644 PythonHome/Lib/idlelib/WindowList.pyc create mode 100644 PythonHome/Lib/idlelib/ZoomHeight.py delete mode 100644 PythonHome/Lib/idlelib/ZoomHeight.pyc create mode 100644 PythonHome/Lib/idlelib/__init__.py delete mode 100644 PythonHome/Lib/idlelib/__init__.pyc create mode 100644 PythonHome/Lib/idlelib/aboutDialog.py delete mode 100644 PythonHome/Lib/idlelib/aboutDialog.pyc create mode 100644 PythonHome/Lib/idlelib/configDialog.py delete mode 100644 PythonHome/Lib/idlelib/configDialog.pyc create mode 100644 PythonHome/Lib/idlelib/configHandler.py delete mode 100644 PythonHome/Lib/idlelib/configHandler.pyc create mode 100644 PythonHome/Lib/idlelib/configHelpSourceEdit.py delete mode 100644 PythonHome/Lib/idlelib/configHelpSourceEdit.pyc create mode 100644 PythonHome/Lib/idlelib/configSectionNameDialog.py delete mode 100644 PythonHome/Lib/idlelib/configSectionNameDialog.pyc create mode 100644 PythonHome/Lib/idlelib/dynOptionMenuWidget.py delete mode 100644 PythonHome/Lib/idlelib/dynOptionMenuWidget.pyc create mode 100644 PythonHome/Lib/idlelib/idle.py delete mode 100644 PythonHome/Lib/idlelib/idle.pyc create mode 100644 PythonHome/Lib/idlelib/idlever.py delete mode 100644 PythonHome/Lib/idlelib/idlever.pyc create mode 100644 PythonHome/Lib/idlelib/keybindingDialog.py delete mode 100644 PythonHome/Lib/idlelib/keybindingDialog.pyc create mode 100644 PythonHome/Lib/idlelib/macosxSupport.py delete mode 100644 PythonHome/Lib/idlelib/macosxSupport.pyc create mode 100644 PythonHome/Lib/idlelib/rpc.py delete mode 100644 PythonHome/Lib/idlelib/rpc.pyc create mode 100644 PythonHome/Lib/idlelib/run.py delete mode 100644 PythonHome/Lib/idlelib/run.pyc create mode 100644 PythonHome/Lib/idlelib/tabbedpages.py delete mode 100644 PythonHome/Lib/idlelib/tabbedpages.pyc create mode 100644 PythonHome/Lib/idlelib/testcode.py delete mode 100644 PythonHome/Lib/idlelib/testcode.pyc create mode 100644 PythonHome/Lib/idlelib/textView.py delete mode 100644 PythonHome/Lib/idlelib/textView.pyc create mode 100644 PythonHome/Lib/ihooks.py delete mode 100644 PythonHome/Lib/ihooks.pyc create mode 100644 PythonHome/Lib/imaplib.py delete mode 100644 PythonHome/Lib/imaplib.pyc create mode 100644 PythonHome/Lib/imghdr.py delete mode 100644 PythonHome/Lib/imghdr.pyc create mode 100644 PythonHome/Lib/importlib/__init__.py delete mode 100644 PythonHome/Lib/importlib/__init__.pyc create mode 100644 PythonHome/Lib/imputil.py delete mode 100644 PythonHome/Lib/imputil.pyc create mode 100644 PythonHome/Lib/inspect.py create mode 100644 PythonHome/Lib/io.py create mode 100644 PythonHome/Lib/json/__init__.py create mode 100644 PythonHome/Lib/json/decoder.py create mode 100644 PythonHome/Lib/json/encoder.py create mode 100644 PythonHome/Lib/json/scanner.py create mode 100644 PythonHome/Lib/json/tool.py delete mode 100644 PythonHome/Lib/json/tool.pyc create mode 100644 PythonHome/Lib/keyword.py create mode 100644 PythonHome/Lib/lib-tk/Canvas.py delete mode 100644 PythonHome/Lib/lib-tk/Canvas.pyc create mode 100644 PythonHome/Lib/lib-tk/Dialog.py delete mode 100644 PythonHome/Lib/lib-tk/Dialog.pyc create mode 100644 PythonHome/Lib/lib-tk/FileDialog.py delete mode 100644 PythonHome/Lib/lib-tk/FileDialog.pyc create mode 100644 PythonHome/Lib/lib-tk/FixTk.py delete mode 100644 PythonHome/Lib/lib-tk/FixTk.pyc create mode 100644 PythonHome/Lib/lib-tk/ScrolledText.py delete mode 100644 PythonHome/Lib/lib-tk/ScrolledText.pyc create mode 100644 PythonHome/Lib/lib-tk/SimpleDialog.py delete mode 100644 PythonHome/Lib/lib-tk/SimpleDialog.pyc create mode 100644 PythonHome/Lib/lib-tk/Tix.py delete mode 100644 PythonHome/Lib/lib-tk/Tix.pyc create mode 100644 PythonHome/Lib/lib-tk/Tkconstants.py delete mode 100644 PythonHome/Lib/lib-tk/Tkconstants.pyc create mode 100644 PythonHome/Lib/lib-tk/Tkdnd.py delete mode 100644 PythonHome/Lib/lib-tk/Tkdnd.pyc create mode 100644 PythonHome/Lib/lib-tk/Tkinter.py delete mode 100644 PythonHome/Lib/lib-tk/Tkinter.pyc create mode 100644 PythonHome/Lib/lib-tk/tkColorChooser.py delete mode 100644 PythonHome/Lib/lib-tk/tkColorChooser.pyc create mode 100644 PythonHome/Lib/lib-tk/tkCommonDialog.py delete mode 100644 PythonHome/Lib/lib-tk/tkCommonDialog.pyc create mode 100644 PythonHome/Lib/lib-tk/tkFileDialog.py delete mode 100644 PythonHome/Lib/lib-tk/tkFileDialog.pyc create mode 100644 PythonHome/Lib/lib-tk/tkFont.py delete mode 100644 PythonHome/Lib/lib-tk/tkFont.pyc create mode 100644 PythonHome/Lib/lib-tk/tkMessageBox.py delete mode 100644 PythonHome/Lib/lib-tk/tkMessageBox.pyc create mode 100644 PythonHome/Lib/lib-tk/tkSimpleDialog.py delete mode 100644 PythonHome/Lib/lib-tk/tkSimpleDialog.pyc create mode 100644 PythonHome/Lib/lib-tk/ttk.py delete mode 100644 PythonHome/Lib/lib-tk/ttk.pyc create mode 100644 PythonHome/Lib/lib-tk/turtle.py delete mode 100644 PythonHome/Lib/lib-tk/turtle.pyc create mode 100644 PythonHome/Lib/lib2to3/__init__.py delete mode 100644 PythonHome/Lib/lib2to3/__init__.pyc create mode 100644 PythonHome/Lib/lib2to3/__main__.py delete mode 100644 PythonHome/Lib/lib2to3/__main__.pyc create mode 100644 PythonHome/Lib/lib2to3/btm_matcher.py delete mode 100644 PythonHome/Lib/lib2to3/btm_matcher.pyc create mode 100644 PythonHome/Lib/lib2to3/btm_utils.py delete mode 100644 PythonHome/Lib/lib2to3/btm_utils.pyc create mode 100644 PythonHome/Lib/lib2to3/fixer_base.py delete mode 100644 PythonHome/Lib/lib2to3/fixer_base.pyc create mode 100644 PythonHome/Lib/lib2to3/fixer_util.py delete mode 100644 PythonHome/Lib/lib2to3/fixer_util.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/__init__.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/__init__.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_apply.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_apply.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_basestring.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_basestring.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_buffer.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_buffer.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_callable.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_callable.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_dict.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_dict.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_except.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_except.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_exec.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_exec.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_execfile.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_execfile.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_exitfunc.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_exitfunc.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_filter.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_filter.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_funcattrs.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_funcattrs.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_future.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_future.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_getcwdu.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_getcwdu.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_has_key.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_has_key.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_idioms.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_idioms.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_import.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_import.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_imports.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_imports.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_imports2.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_imports2.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_input.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_input.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_intern.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_intern.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_isinstance.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_isinstance.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_itertools.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_itertools.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_itertools_imports.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_itertools_imports.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_long.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_long.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_map.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_map.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_metaclass.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_metaclass.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_methodattrs.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_methodattrs.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_ne.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_ne.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_next.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_next.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_nonzero.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_nonzero.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_numliterals.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_numliterals.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_operator.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_operator.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_paren.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_paren.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_print.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_print.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_raise.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_raise.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_raw_input.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_raw_input.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_reduce.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_reduce.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_renames.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_renames.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_repr.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_repr.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_set_literal.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_set_literal.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_standarderror.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_standarderror.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_sys_exc.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_sys_exc.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_throw.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_throw.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_tuple_params.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_tuple_params.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_types.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_types.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_unicode.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_unicode.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_urllib.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_urllib.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_ws_comma.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_ws_comma.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_xrange.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_xrange.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_xreadlines.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_xreadlines.pyc create mode 100644 PythonHome/Lib/lib2to3/fixes/fix_zip.py delete mode 100644 PythonHome/Lib/lib2to3/fixes/fix_zip.pyc create mode 100644 PythonHome/Lib/lib2to3/main.py delete mode 100644 PythonHome/Lib/lib2to3/main.pyc create mode 100644 PythonHome/Lib/lib2to3/patcomp.py delete mode 100644 PythonHome/Lib/lib2to3/patcomp.pyc create mode 100644 PythonHome/Lib/lib2to3/pgen2/__init__.py delete mode 100644 PythonHome/Lib/lib2to3/pgen2/__init__.pyc create mode 100644 PythonHome/Lib/lib2to3/pgen2/conv.py delete mode 100644 PythonHome/Lib/lib2to3/pgen2/conv.pyc create mode 100644 PythonHome/Lib/lib2to3/pgen2/driver.py delete mode 100644 PythonHome/Lib/lib2to3/pgen2/driver.pyc rename PythonHome/Lib/lib2to3/pgen2/{grammar.pyc => grammar.py} (56%) create mode 100644 PythonHome/Lib/lib2to3/pgen2/literals.py delete mode 100644 PythonHome/Lib/lib2to3/pgen2/literals.pyc create mode 100644 PythonHome/Lib/lib2to3/pgen2/parse.py delete mode 100644 PythonHome/Lib/lib2to3/pgen2/parse.pyc create mode 100644 PythonHome/Lib/lib2to3/pgen2/pgen.py delete mode 100644 PythonHome/Lib/lib2to3/pgen2/pgen.pyc create mode 100644 PythonHome/Lib/lib2to3/pgen2/token.py delete mode 100644 PythonHome/Lib/lib2to3/pgen2/token.pyc create mode 100644 PythonHome/Lib/lib2to3/pgen2/tokenize.py delete mode 100644 PythonHome/Lib/lib2to3/pgen2/tokenize.pyc create mode 100644 PythonHome/Lib/lib2to3/pygram.py delete mode 100644 PythonHome/Lib/lib2to3/pygram.pyc create mode 100644 PythonHome/Lib/lib2to3/pytree.py delete mode 100644 PythonHome/Lib/lib2to3/pytree.pyc create mode 100644 PythonHome/Lib/lib2to3/refactor.py delete mode 100644 PythonHome/Lib/lib2to3/refactor.pyc create mode 100644 PythonHome/Lib/linecache.py create mode 100644 PythonHome/Lib/locale.py create mode 100644 PythonHome/Lib/logging/__init__.py create mode 100644 PythonHome/Lib/logging/config.py delete mode 100644 PythonHome/Lib/logging/config.pyc create mode 100644 PythonHome/Lib/logging/handlers.py delete mode 100644 PythonHome/Lib/logging/handlers.pyc create mode 100644 PythonHome/Lib/macpath.py delete mode 100644 PythonHome/Lib/macpath.pyc create mode 100644 PythonHome/Lib/macurl2path.py delete mode 100644 PythonHome/Lib/macurl2path.pyc create mode 100644 PythonHome/Lib/mailbox.py delete mode 100644 PythonHome/Lib/mailbox.pyc create mode 100644 PythonHome/Lib/mailcap.py delete mode 100644 PythonHome/Lib/mailcap.pyc create mode 100644 PythonHome/Lib/markupbase.py create mode 100644 PythonHome/Lib/md5.py delete mode 100644 PythonHome/Lib/md5.pyc create mode 100644 PythonHome/Lib/mhlib.py delete mode 100644 PythonHome/Lib/mhlib.pyc create mode 100644 PythonHome/Lib/mimetools.py create mode 100644 PythonHome/Lib/mimetypes.py create mode 100644 PythonHome/Lib/mimify.py delete mode 100644 PythonHome/Lib/mimify.pyc create mode 100644 PythonHome/Lib/modulefinder.py delete mode 100644 PythonHome/Lib/modulefinder.pyc create mode 100644 PythonHome/Lib/msilib/__init__.py delete mode 100644 PythonHome/Lib/msilib/__init__.pyc create mode 100644 PythonHome/Lib/msilib/schema.py delete mode 100644 PythonHome/Lib/msilib/schema.pyc create mode 100644 PythonHome/Lib/msilib/sequence.py delete mode 100644 PythonHome/Lib/msilib/sequence.pyc create mode 100644 PythonHome/Lib/msilib/text.py delete mode 100644 PythonHome/Lib/msilib/text.pyc create mode 100644 PythonHome/Lib/multifile.py delete mode 100644 PythonHome/Lib/multifile.pyc create mode 100644 PythonHome/Lib/multiprocessing/__init__.py delete mode 100644 PythonHome/Lib/multiprocessing/__init__.pyc create mode 100644 PythonHome/Lib/multiprocessing/connection.py delete mode 100644 PythonHome/Lib/multiprocessing/connection.pyc create mode 100644 PythonHome/Lib/multiprocessing/dummy/__init__.py delete mode 100644 PythonHome/Lib/multiprocessing/dummy/__init__.pyc create mode 100644 PythonHome/Lib/multiprocessing/dummy/connection.py delete mode 100644 PythonHome/Lib/multiprocessing/dummy/connection.pyc create mode 100644 PythonHome/Lib/multiprocessing/forking.py delete mode 100644 PythonHome/Lib/multiprocessing/forking.pyc create mode 100644 PythonHome/Lib/multiprocessing/heap.py delete mode 100644 PythonHome/Lib/multiprocessing/heap.pyc create mode 100644 PythonHome/Lib/multiprocessing/managers.py delete mode 100644 PythonHome/Lib/multiprocessing/managers.pyc create mode 100644 PythonHome/Lib/multiprocessing/pool.py delete mode 100644 PythonHome/Lib/multiprocessing/pool.pyc create mode 100644 PythonHome/Lib/multiprocessing/process.py delete mode 100644 PythonHome/Lib/multiprocessing/process.pyc create mode 100644 PythonHome/Lib/multiprocessing/queues.py delete mode 100644 PythonHome/Lib/multiprocessing/queues.pyc create mode 100644 PythonHome/Lib/multiprocessing/reduction.py delete mode 100644 PythonHome/Lib/multiprocessing/reduction.pyc create mode 100644 PythonHome/Lib/multiprocessing/sharedctypes.py delete mode 100644 PythonHome/Lib/multiprocessing/sharedctypes.pyc create mode 100644 PythonHome/Lib/multiprocessing/synchronize.py delete mode 100644 PythonHome/Lib/multiprocessing/synchronize.pyc create mode 100644 PythonHome/Lib/multiprocessing/util.py delete mode 100644 PythonHome/Lib/multiprocessing/util.pyc create mode 100644 PythonHome/Lib/mutex.py delete mode 100644 PythonHome/Lib/mutex.pyc create mode 100644 PythonHome/Lib/netrc.py create mode 100644 PythonHome/Lib/new.py delete mode 100644 PythonHome/Lib/new.pyc create mode 100644 PythonHome/Lib/nntplib.py delete mode 100644 PythonHome/Lib/nntplib.pyc create mode 100644 PythonHome/Lib/ntpath.py create mode 100644 PythonHome/Lib/nturl2path.py create mode 100644 PythonHome/Lib/numbers.py delete mode 100644 PythonHome/Lib/numbers.pyc create mode 100644 PythonHome/Lib/opcode.py create mode 100644 PythonHome/Lib/optparse.py delete mode 100644 PythonHome/Lib/optparse.pyc create mode 100644 PythonHome/Lib/os.py create mode 100644 PythonHome/Lib/os2emxpath.py delete mode 100644 PythonHome/Lib/os2emxpath.pyc create mode 100644 PythonHome/Lib/pdb.py delete mode 100644 PythonHome/Lib/pdb.pyc create mode 100644 PythonHome/Lib/pickle.py delete mode 100644 PythonHome/Lib/pickle.pyc create mode 100644 PythonHome/Lib/pickletools.py delete mode 100644 PythonHome/Lib/pickletools.pyc create mode 100644 PythonHome/Lib/pipes.py delete mode 100644 PythonHome/Lib/pipes.pyc create mode 100644 PythonHome/Lib/pkgutil.py delete mode 100644 PythonHome/Lib/pkgutil.pyc create mode 100644 PythonHome/Lib/platform.py create mode 100644 PythonHome/Lib/plistlib.py delete mode 100644 PythonHome/Lib/plistlib.pyc create mode 100644 PythonHome/Lib/popen2.py delete mode 100644 PythonHome/Lib/popen2.pyc create mode 100644 PythonHome/Lib/poplib.py delete mode 100644 PythonHome/Lib/poplib.pyc create mode 100644 PythonHome/Lib/posixfile.py delete mode 100644 PythonHome/Lib/posixfile.pyc create mode 100644 PythonHome/Lib/posixpath.py create mode 100644 PythonHome/Lib/pprint.py delete mode 100644 PythonHome/Lib/pprint.pyc create mode 100644 PythonHome/Lib/profile.py delete mode 100644 PythonHome/Lib/profile.pyc create mode 100644 PythonHome/Lib/pstats.py delete mode 100644 PythonHome/Lib/pstats.pyc create mode 100644 PythonHome/Lib/pty.py delete mode 100644 PythonHome/Lib/pty.pyc create mode 100644 PythonHome/Lib/py_compile.py delete mode 100644 PythonHome/Lib/py_compile.pyc delete mode 100644 PythonHome/Lib/pyclbr.pyc create mode 100644 PythonHome/Lib/pydoc.py delete mode 100644 PythonHome/Lib/pydoc.pyc create mode 100644 PythonHome/Lib/pydoc_data/__init__.py delete mode 100644 PythonHome/Lib/pydoc_data/__init__.pyc create mode 100644 PythonHome/Lib/pydoc_data/topics.py delete mode 100644 PythonHome/Lib/pydoc_data/topics.pyc create mode 100644 PythonHome/Lib/quopri.py create mode 100644 PythonHome/Lib/random.py create mode 100644 PythonHome/Lib/re.py create mode 100644 PythonHome/Lib/repr.py delete mode 100644 PythonHome/Lib/repr.pyc create mode 100644 PythonHome/Lib/rexec.py delete mode 100644 PythonHome/Lib/rexec.pyc create mode 100644 PythonHome/Lib/rfc822.py create mode 100644 PythonHome/Lib/rlcompleter.py delete mode 100644 PythonHome/Lib/rlcompleter.pyc create mode 100644 PythonHome/Lib/robotparser.py delete mode 100644 PythonHome/Lib/robotparser.pyc create mode 100644 PythonHome/Lib/runpy.py delete mode 100644 PythonHome/Lib/runpy.pyc create mode 100644 PythonHome/Lib/sched.py delete mode 100644 PythonHome/Lib/sched.pyc create mode 100644 PythonHome/Lib/sets.py delete mode 100644 PythonHome/Lib/sets.pyc create mode 100644 PythonHome/Lib/sgmllib.py delete mode 100644 PythonHome/Lib/sgmllib.pyc create mode 100644 PythonHome/Lib/sha.py delete mode 100644 PythonHome/Lib/sha.pyc create mode 100644 PythonHome/Lib/shelve.py delete mode 100644 PythonHome/Lib/shelve.pyc create mode 100644 PythonHome/Lib/shlex.py create mode 100644 PythonHome/Lib/shutil.py delete mode 100644 PythonHome/Lib/shutil.pyc create mode 100644 PythonHome/Lib/site-packages/_markerlib/__init__.py delete mode 100644 PythonHome/Lib/site-packages/_markerlib/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/_markerlib/markers.py delete mode 100644 PythonHome/Lib/site-packages/_markerlib/markers.pyc create mode 100644 PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/PKG-INFO create mode 100644 PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/SOURCES.txt create mode 100644 PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/dependency_links.txt create mode 100644 PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/installed-files.txt create mode 100644 PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/top_level.txt create mode 100644 PythonHome/Lib/site-packages/bs4/__init__.py create mode 100644 PythonHome/Lib/site-packages/bs4/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/bs4/builder/__init__.py create mode 100644 PythonHome/Lib/site-packages/bs4/builder/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/bs4/builder/_html5lib.py create mode 100644 PythonHome/Lib/site-packages/bs4/builder/_html5lib.pyc create mode 100644 PythonHome/Lib/site-packages/bs4/builder/_htmlparser.py create mode 100644 PythonHome/Lib/site-packages/bs4/builder/_htmlparser.pyc create mode 100644 PythonHome/Lib/site-packages/bs4/builder/_lxml.py create mode 100644 PythonHome/Lib/site-packages/bs4/builder/_lxml.pyc create mode 100644 PythonHome/Lib/site-packages/bs4/dammit.py create mode 100644 PythonHome/Lib/site-packages/bs4/dammit.pyc create mode 100644 PythonHome/Lib/site-packages/bs4/diagnose.py create mode 100644 PythonHome/Lib/site-packages/bs4/element.py create mode 100644 PythonHome/Lib/site-packages/bs4/element.pyc create mode 100644 PythonHome/Lib/site-packages/bs4/testing.py create mode 100644 PythonHome/Lib/site-packages/easy_install.py delete mode 100644 PythonHome/Lib/site-packages/easy_install.pyc create mode 100644 PythonHome/Lib/site-packages/pip/__init__.py delete mode 100644 PythonHome/Lib/site-packages/pip/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/__main__.py delete mode 100644 PythonHome/Lib/site-packages/pip/__main__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/__init__.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/_markerlib/__init__.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/_markerlib/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/_markerlib/markers.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/_markerlib/markers.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/colorama/__init__.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/colorama/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/colorama/ansi.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/colorama/ansi.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/colorama/ansitowin32.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/colorama/ansitowin32.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/colorama/initialise.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/colorama/initialise.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/colorama/win32.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/colorama/win32.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/colorama/winterm.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/colorama/winterm.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/__init__.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/_backport/__init__.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/_backport/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/_backport/misc.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/_backport/misc.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/_backport/shutil.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/_backport/shutil.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/_backport/tarfile.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/_backport/tarfile.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/compat.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/compat.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/database.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/database.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/index.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/index.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/locators.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/locators.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/manifest.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/manifest.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/markers.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/markers.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/metadata.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/metadata.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/resources.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/resources.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/scripts.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/scripts.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/util.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/util.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/version.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/version.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/wheel.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/distlib/wheel.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/__init__.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/constants.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/constants.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/filters/__init__.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/filters/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/filters/_base.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/filters/_base.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/filters/lint.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/filters/lint.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/filters/optionaltags.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/filters/optionaltags.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/filters/sanitizer.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/filters/sanitizer.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/filters/whitespace.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/filters/whitespace.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/html5parser.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/html5parser.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/ihatexml.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/ihatexml.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/inputstream.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/inputstream.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/sanitizer.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/sanitizer.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/serializer/__init__.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/serializer/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/serializer/htmlserializer.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/serializer/htmlserializer.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/tokenizer.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/tokenizer.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treeadapters/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treeadapters/sax.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treeadapters/sax.pyc rename PythonHome/Lib/site-packages/pip/_vendor/html5lib/treebuilders/{__init__.pyc => __init__.py} (59%) create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treebuilders/_base.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treebuilders/_base.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treebuilders/dom.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treebuilders/dom.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treebuilders/etree.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treebuilders/etree.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treewalkers/_base.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treewalkers/_base.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treewalkers/dom.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treewalkers/dom.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treewalkers/etree.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treewalkers/etree.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treewalkers/genshistream.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treewalkers/genshistream.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treewalkers/lxmletree.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treewalkers/lxmletree.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treewalkers/pulldom.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/treewalkers/pulldom.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/trie/__init__.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/trie/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/trie/_base.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/trie/_base.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/trie/datrie.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/trie/datrie.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/trie/py.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/trie/py.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/utils.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/html5lib/utils.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/pkg_resources.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/pkg_resources.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/re-vendor.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/re-vendor.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/__init__.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/adapters.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/adapters.pyc rename PythonHome/Lib/site-packages/pip/_vendor/requests/{api.pyc => api.py} (51%) create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/auth.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/auth.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/certs.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/certs.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/compat.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/compat.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/cookies.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/cookies.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/exceptions.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/exceptions.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/hooks.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/hooks.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/models.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/models.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/sessions.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/sessions.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/status_codes.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/status_codes.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/structures.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/structures.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/utils.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/requests/utils.pyc create mode 100644 PythonHome/Lib/site-packages/pip/_vendor/six.py delete mode 100644 PythonHome/Lib/site-packages/pip/_vendor/six.pyc create mode 100644 PythonHome/Lib/site-packages/pip/backwardcompat/__init__.py delete mode 100644 PythonHome/Lib/site-packages/pip/backwardcompat/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/basecommand.py delete mode 100644 PythonHome/Lib/site-packages/pip/basecommand.pyc create mode 100644 PythonHome/Lib/site-packages/pip/baseparser.py delete mode 100644 PythonHome/Lib/site-packages/pip/baseparser.pyc create mode 100644 PythonHome/Lib/site-packages/pip/cmdoptions.py delete mode 100644 PythonHome/Lib/site-packages/pip/cmdoptions.pyc create mode 100644 PythonHome/Lib/site-packages/pip/commands/__init__.py delete mode 100644 PythonHome/Lib/site-packages/pip/commands/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/commands/bundle.py delete mode 100644 PythonHome/Lib/site-packages/pip/commands/bundle.pyc create mode 100644 PythonHome/Lib/site-packages/pip/commands/completion.py delete mode 100644 PythonHome/Lib/site-packages/pip/commands/completion.pyc create mode 100644 PythonHome/Lib/site-packages/pip/commands/freeze.py delete mode 100644 PythonHome/Lib/site-packages/pip/commands/freeze.pyc create mode 100644 PythonHome/Lib/site-packages/pip/commands/help.py delete mode 100644 PythonHome/Lib/site-packages/pip/commands/help.pyc create mode 100644 PythonHome/Lib/site-packages/pip/commands/install.py delete mode 100644 PythonHome/Lib/site-packages/pip/commands/install.pyc create mode 100644 PythonHome/Lib/site-packages/pip/commands/list.py delete mode 100644 PythonHome/Lib/site-packages/pip/commands/list.pyc create mode 100644 PythonHome/Lib/site-packages/pip/commands/search.py delete mode 100644 PythonHome/Lib/site-packages/pip/commands/search.pyc create mode 100644 PythonHome/Lib/site-packages/pip/commands/show.py delete mode 100644 PythonHome/Lib/site-packages/pip/commands/show.pyc create mode 100644 PythonHome/Lib/site-packages/pip/commands/uninstall.py delete mode 100644 PythonHome/Lib/site-packages/pip/commands/uninstall.pyc create mode 100644 PythonHome/Lib/site-packages/pip/commands/unzip.py delete mode 100644 PythonHome/Lib/site-packages/pip/commands/unzip.pyc create mode 100644 PythonHome/Lib/site-packages/pip/commands/wheel.py delete mode 100644 PythonHome/Lib/site-packages/pip/commands/wheel.pyc create mode 100644 PythonHome/Lib/site-packages/pip/commands/zip.py delete mode 100644 PythonHome/Lib/site-packages/pip/commands/zip.pyc create mode 100644 PythonHome/Lib/site-packages/pip/download.py delete mode 100644 PythonHome/Lib/site-packages/pip/download.pyc create mode 100644 PythonHome/Lib/site-packages/pip/exceptions.py delete mode 100644 PythonHome/Lib/site-packages/pip/exceptions.pyc create mode 100644 PythonHome/Lib/site-packages/pip/index.py delete mode 100644 PythonHome/Lib/site-packages/pip/index.pyc create mode 100644 PythonHome/Lib/site-packages/pip/locations.py delete mode 100644 PythonHome/Lib/site-packages/pip/locations.pyc create mode 100644 PythonHome/Lib/site-packages/pip/log.py delete mode 100644 PythonHome/Lib/site-packages/pip/log.pyc create mode 100644 PythonHome/Lib/site-packages/pip/pep425tags.py delete mode 100644 PythonHome/Lib/site-packages/pip/pep425tags.pyc create mode 100644 PythonHome/Lib/site-packages/pip/req.py delete mode 100644 PythonHome/Lib/site-packages/pip/req.pyc create mode 100644 PythonHome/Lib/site-packages/pip/runner.py delete mode 100644 PythonHome/Lib/site-packages/pip/runner.pyc create mode 100644 PythonHome/Lib/site-packages/pip/status_codes.py delete mode 100644 PythonHome/Lib/site-packages/pip/status_codes.pyc create mode 100644 PythonHome/Lib/site-packages/pip/util.py delete mode 100644 PythonHome/Lib/site-packages/pip/util.pyc create mode 100644 PythonHome/Lib/site-packages/pip/vcs/__init__.py delete mode 100644 PythonHome/Lib/site-packages/pip/vcs/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/pip/vcs/bazaar.py delete mode 100644 PythonHome/Lib/site-packages/pip/vcs/bazaar.pyc create mode 100644 PythonHome/Lib/site-packages/pip/vcs/git.py delete mode 100644 PythonHome/Lib/site-packages/pip/vcs/git.pyc create mode 100644 PythonHome/Lib/site-packages/pip/vcs/mercurial.py delete mode 100644 PythonHome/Lib/site-packages/pip/vcs/mercurial.pyc create mode 100644 PythonHome/Lib/site-packages/pip/vcs/subversion.py delete mode 100644 PythonHome/Lib/site-packages/pip/vcs/subversion.pyc create mode 100644 PythonHome/Lib/site-packages/pip/wheel.py delete mode 100644 PythonHome/Lib/site-packages/pip/wheel.pyc create mode 100644 PythonHome/Lib/site-packages/pkg_resources.py delete mode 100644 PythonHome/Lib/site-packages/pkg_resources.pyc create mode 100644 PythonHome/Lib/site-packages/requests/__init__.py create mode 100644 PythonHome/Lib/site-packages/requests/adapters.py create mode 100644 PythonHome/Lib/site-packages/requests/api.py create mode 100644 PythonHome/Lib/site-packages/requests/auth.py create mode 100644 PythonHome/Lib/site-packages/requests/certs.py create mode 100644 PythonHome/Lib/site-packages/requests/compat.py create mode 100644 PythonHome/Lib/site-packages/requests/cookies.py create mode 100644 PythonHome/Lib/site-packages/requests/exceptions.py create mode 100644 PythonHome/Lib/site-packages/requests/hooks.py create mode 100644 PythonHome/Lib/site-packages/requests/models.py create mode 100644 PythonHome/Lib/site-packages/requests/sessions.py create mode 100644 PythonHome/Lib/site-packages/requests/status_codes.py create mode 100644 PythonHome/Lib/site-packages/requests/structures.py create mode 100644 PythonHome/Lib/site-packages/requests/utils.py create mode 100644 PythonHome/Lib/site-packages/setuptools/__init__.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/archive_util.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/archive_util.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/__init__.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/__init__.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/alias.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/alias.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/bdist_egg.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/bdist_egg.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/bdist_rpm.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/bdist_rpm.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/bdist_wininst.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/bdist_wininst.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/build_ext.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/build_ext.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/build_py.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/build_py.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/develop.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/develop.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/easy_install.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/easy_install.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/egg_info.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/egg_info.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/install.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/install.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/install_egg_info.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/install_egg_info.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/install_lib.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/install_lib.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/install_scripts.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/install_scripts.pyc delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/launcher manifest.xml create mode 100644 PythonHome/Lib/site-packages/setuptools/command/register.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/register.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/rotate.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/rotate.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/saveopts.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/saveopts.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/sdist.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/sdist.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/setopt.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/setopt.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/test.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/test.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/command/upload_docs.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/command/upload_docs.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/compat.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/compat.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/depends.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/depends.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/dist.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/dist.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/extension.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/extension.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/lib2to3_ex.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/lib2to3_ex.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/package_index.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/package_index.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/py26compat.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/py26compat.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/py27compat.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/py27compat.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/py31compat.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/py31compat.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/sandbox.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/sandbox.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/site-patch.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/site-patch.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/ssl_support.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/ssl_support.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/svn_utils.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/svn_utils.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/unicode_utils.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/unicode_utils.pyc create mode 100644 PythonHome/Lib/site-packages/setuptools/version.py delete mode 100644 PythonHome/Lib/site-packages/setuptools/version.pyc create mode 100644 PythonHome/Lib/site.py create mode 100644 PythonHome/Lib/smtpd.py delete mode 100644 PythonHome/Lib/smtpd.pyc create mode 100644 PythonHome/Lib/smtplib.py delete mode 100644 PythonHome/Lib/smtplib.pyc create mode 100644 PythonHome/Lib/sndhdr.py delete mode 100644 PythonHome/Lib/sndhdr.pyc create mode 100644 PythonHome/Lib/socket.py create mode 100644 PythonHome/Lib/sqlite3/__init__.py delete mode 100644 PythonHome/Lib/sqlite3/__init__.pyc create mode 100644 PythonHome/Lib/sqlite3/dbapi2.py delete mode 100644 PythonHome/Lib/sqlite3/dbapi2.pyc create mode 100644 PythonHome/Lib/sqlite3/dump.py delete mode 100644 PythonHome/Lib/sqlite3/dump.pyc create mode 100644 PythonHome/Lib/sre.py delete mode 100644 PythonHome/Lib/sre.pyc create mode 100644 PythonHome/Lib/sre_compile.py create mode 100644 PythonHome/Lib/sre_constants.py create mode 100644 PythonHome/Lib/sre_parse.py create mode 100644 PythonHome/Lib/ssl.py create mode 100644 PythonHome/Lib/stat.py create mode 100644 PythonHome/Lib/statvfs.py delete mode 100644 PythonHome/Lib/statvfs.pyc create mode 100644 PythonHome/Lib/string.py create mode 100644 PythonHome/Lib/stringold.py delete mode 100644 PythonHome/Lib/stringold.pyc create mode 100644 PythonHome/Lib/stringprep.py create mode 100644 PythonHome/Lib/struct.py create mode 100644 PythonHome/Lib/subprocess.py create mode 100644 PythonHome/Lib/sunau.py delete mode 100644 PythonHome/Lib/sunau.pyc create mode 100644 PythonHome/Lib/sunaudio.py delete mode 100644 PythonHome/Lib/sunaudio.pyc create mode 100644 PythonHome/Lib/symbol.py delete mode 100644 PythonHome/Lib/symbol.pyc create mode 100644 PythonHome/Lib/symtable.py delete mode 100644 PythonHome/Lib/symtable.pyc create mode 100644 PythonHome/Lib/sysconfig.py create mode 100644 PythonHome/Lib/tabnanny.py delete mode 100644 PythonHome/Lib/tabnanny.pyc create mode 100644 PythonHome/Lib/tarfile.py delete mode 100644 PythonHome/Lib/tarfile.pyc create mode 100644 PythonHome/Lib/telnetlib.py delete mode 100644 PythonHome/Lib/telnetlib.pyc create mode 100644 PythonHome/Lib/tempfile.py create mode 100644 PythonHome/Lib/textwrap.py rename PythonHome/Lib/{this.pyc => this.py} (68%) create mode 100644 PythonHome/Lib/threading.py create mode 100644 PythonHome/Lib/timeit.py delete mode 100644 PythonHome/Lib/timeit.pyc create mode 100644 PythonHome/Lib/toaiff.py delete mode 100644 PythonHome/Lib/toaiff.pyc create mode 100644 PythonHome/Lib/token.py create mode 100644 PythonHome/Lib/tokenize.py create mode 100644 PythonHome/Lib/trace.py delete mode 100644 PythonHome/Lib/trace.pyc create mode 100644 PythonHome/Lib/traceback.py create mode 100644 PythonHome/Lib/tty.py delete mode 100644 PythonHome/Lib/tty.pyc create mode 100644 PythonHome/Lib/types.py rename PythonHome/Lib/unittest/{__init__.pyc => __init__.py} (58%) create mode 100644 PythonHome/Lib/unittest/__main__.py delete mode 100644 PythonHome/Lib/unittest/__main__.pyc create mode 100644 PythonHome/Lib/unittest/case.py delete mode 100644 PythonHome/Lib/unittest/case.pyc create mode 100644 PythonHome/Lib/unittest/loader.py delete mode 100644 PythonHome/Lib/unittest/loader.pyc create mode 100644 PythonHome/Lib/unittest/main.py delete mode 100644 PythonHome/Lib/unittest/main.pyc create mode 100644 PythonHome/Lib/unittest/result.py delete mode 100644 PythonHome/Lib/unittest/result.pyc create mode 100644 PythonHome/Lib/unittest/runner.py delete mode 100644 PythonHome/Lib/unittest/runner.pyc create mode 100644 PythonHome/Lib/unittest/signals.py delete mode 100644 PythonHome/Lib/unittest/signals.pyc create mode 100644 PythonHome/Lib/unittest/suite.py delete mode 100644 PythonHome/Lib/unittest/suite.pyc create mode 100644 PythonHome/Lib/unittest/test/__init__.py create mode 100644 PythonHome/Lib/unittest/test/dummy.py create mode 100644 PythonHome/Lib/unittest/test/support.py create mode 100644 PythonHome/Lib/unittest/test/test_assertions.py create mode 100644 PythonHome/Lib/unittest/test/test_break.py create mode 100644 PythonHome/Lib/unittest/test/test_case.py create mode 100644 PythonHome/Lib/unittest/test/test_discovery.py create mode 100644 PythonHome/Lib/unittest/test/test_functiontestcase.py create mode 100644 PythonHome/Lib/unittest/test/test_loader.py create mode 100644 PythonHome/Lib/unittest/test/test_program.py create mode 100644 PythonHome/Lib/unittest/test/test_result.py create mode 100644 PythonHome/Lib/unittest/test/test_runner.py create mode 100644 PythonHome/Lib/unittest/test/test_setups.py create mode 100644 PythonHome/Lib/unittest/test/test_skipping.py create mode 100644 PythonHome/Lib/unittest/test/test_suite.py create mode 100644 PythonHome/Lib/unittest/util.py delete mode 100644 PythonHome/Lib/unittest/util.pyc create mode 100644 PythonHome/Lib/urllib.py create mode 100644 PythonHome/Lib/urllib2.py create mode 100644 PythonHome/Lib/urlparse.py rename PythonHome/Lib/{user.pyc => user.py} (50%) create mode 100644 PythonHome/Lib/uu.py delete mode 100644 PythonHome/Lib/uu.pyc create mode 100644 PythonHome/Lib/uuid.py create mode 100644 PythonHome/Lib/warnings.py create mode 100644 PythonHome/Lib/wave.py delete mode 100644 PythonHome/Lib/wave.pyc create mode 100644 PythonHome/Lib/weakref.py create mode 100644 PythonHome/Lib/webbrowser.py create mode 100644 PythonHome/Lib/whichdb.py delete mode 100644 PythonHome/Lib/whichdb.pyc create mode 100644 PythonHome/Lib/wox.pyc rename PythonHome/Lib/wsgiref/{__init__.pyc => __init__.py} (74%) create mode 100644 PythonHome/Lib/wsgiref/handlers.py delete mode 100644 PythonHome/Lib/wsgiref/handlers.pyc create mode 100644 PythonHome/Lib/wsgiref/headers.py delete mode 100644 PythonHome/Lib/wsgiref/headers.pyc create mode 100644 PythonHome/Lib/wsgiref/simple_server.py delete mode 100644 PythonHome/Lib/wsgiref/simple_server.pyc create mode 100644 PythonHome/Lib/wsgiref/util.py delete mode 100644 PythonHome/Lib/wsgiref/util.pyc create mode 100644 PythonHome/Lib/wsgiref/validate.py delete mode 100644 PythonHome/Lib/wsgiref/validate.pyc create mode 100644 PythonHome/Lib/xdrlib.py delete mode 100644 PythonHome/Lib/xdrlib.pyc create mode 100644 PythonHome/Lib/xml/__init__.py delete mode 100644 PythonHome/Lib/xml/__init__.pyc create mode 100644 PythonHome/Lib/xml/dom/NodeFilter.py delete mode 100644 PythonHome/Lib/xml/dom/NodeFilter.pyc create mode 100644 PythonHome/Lib/xml/dom/__init__.py delete mode 100644 PythonHome/Lib/xml/dom/__init__.pyc create mode 100644 PythonHome/Lib/xml/dom/domreg.py delete mode 100644 PythonHome/Lib/xml/dom/domreg.pyc create mode 100644 PythonHome/Lib/xml/dom/expatbuilder.py delete mode 100644 PythonHome/Lib/xml/dom/expatbuilder.pyc create mode 100644 PythonHome/Lib/xml/dom/minicompat.py delete mode 100644 PythonHome/Lib/xml/dom/minicompat.pyc create mode 100644 PythonHome/Lib/xml/dom/minidom.py delete mode 100644 PythonHome/Lib/xml/dom/minidom.pyc create mode 100644 PythonHome/Lib/xml/dom/pulldom.py delete mode 100644 PythonHome/Lib/xml/dom/pulldom.pyc create mode 100644 PythonHome/Lib/xml/dom/xmlbuilder.py delete mode 100644 PythonHome/Lib/xml/dom/xmlbuilder.pyc create mode 100644 PythonHome/Lib/xml/etree/ElementInclude.py delete mode 100644 PythonHome/Lib/xml/etree/ElementInclude.pyc create mode 100644 PythonHome/Lib/xml/etree/ElementPath.py delete mode 100644 PythonHome/Lib/xml/etree/ElementPath.pyc create mode 100644 PythonHome/Lib/xml/etree/ElementTree.py delete mode 100644 PythonHome/Lib/xml/etree/ElementTree.pyc create mode 100644 PythonHome/Lib/xml/etree/__init__.py delete mode 100644 PythonHome/Lib/xml/etree/__init__.pyc create mode 100644 PythonHome/Lib/xml/etree/cElementTree.py delete mode 100644 PythonHome/Lib/xml/etree/cElementTree.pyc create mode 100644 PythonHome/Lib/xml/parsers/__init__.py delete mode 100644 PythonHome/Lib/xml/parsers/__init__.pyc create mode 100644 PythonHome/Lib/xml/parsers/expat.py delete mode 100644 PythonHome/Lib/xml/parsers/expat.pyc create mode 100644 PythonHome/Lib/xml/sax/__init__.py delete mode 100644 PythonHome/Lib/xml/sax/__init__.pyc create mode 100644 PythonHome/Lib/xml/sax/_exceptions.py delete mode 100644 PythonHome/Lib/xml/sax/_exceptions.pyc create mode 100644 PythonHome/Lib/xml/sax/expatreader.py delete mode 100644 PythonHome/Lib/xml/sax/expatreader.pyc create mode 100644 PythonHome/Lib/xml/sax/handler.py delete mode 100644 PythonHome/Lib/xml/sax/handler.pyc create mode 100644 PythonHome/Lib/xml/sax/saxutils.py delete mode 100644 PythonHome/Lib/xml/sax/saxutils.pyc create mode 100644 PythonHome/Lib/xml/sax/xmlreader.py delete mode 100644 PythonHome/Lib/xml/sax/xmlreader.pyc create mode 100644 PythonHome/Lib/xmllib.py delete mode 100644 PythonHome/Lib/xmllib.pyc create mode 100644 PythonHome/Lib/xmlrpclib.py delete mode 100644 PythonHome/Lib/xmlrpclib.pyc create mode 100644 PythonHome/Lib/zipfile.py delete mode 100644 PythonHome/Lib/zipfile.pyc create mode 100644 PythonHome/install_requirements.bat create mode 100644 PythonHome/requirements.txt diff --git a/Plugins/Wox.Plugin.HackerNews/main.py b/Plugins/Wox.Plugin.HackerNews/main.py index faf4be9231..4a41993ddc 100644 --- a/Plugins/Wox.Plugin.HackerNews/main.py +++ b/Plugins/Wox.Plugin.HackerNews/main.py @@ -1,11 +1,9 @@ #encoding=utf8 -from __future__ import unicode_literals import requests from bs4 import BeautifulSoup -import json import webbrowser -from wox import Wox +from wox import Wox,WoxAPI class HackerNews(Wox): @@ -16,12 +14,16 @@ class HackerNews(Wox): for i in bs.select(".comhead"): title = i.previous_sibling.text url = i.previous_sibling["href"] - results.append({"Title": title ,"IcoPath":"Images/app.ico","JsonRPCAction":{"method": "openUrl", "parameters": url}}) + #results.append({"Title": title ,"IcoPath":"Images/app.ico","JsonRPCAction":{"method": "Wox.ChangeQuery","parameters":[url,True]}}) + results.append({"Title": title ,"IcoPath":"Images/app.ico","JsonRPCAction":{"method": "openUrl","parameters":[url],"dontHideAfterAction":True}}) + #results.append({"Title": title ,"IcoPath":"Images/app.ico","JsonRPCAction":{"method": "Wox.ShowApp"}}) return results def openUrl(self,url): webbrowser.open(url) + #todo:doesn't work when move this line up + WoxAPI.change_query(url) if __name__ == "__main__": HackerNews() diff --git a/Plugins/Wox.Plugin.HackerNews/run.bat b/Plugins/Wox.Plugin.HackerNews/run.bat index 8f795eb291..c5355024bb 100644 --- a/Plugins/Wox.Plugin.HackerNews/run.bat +++ b/Plugins/Wox.Plugin.HackerNews/run.bat @@ -1 +1,2 @@ -d:\Personal\wox.jsonrpc\Output\Debug\PythonHome\python.exe main.py "{\"jsonrpc\": \"2.0\", \"method\": \"query\", \"params\": \"l\", \"id\": 1} +..\..\PythonHome\python.exe main.py "{\"jsonrpc\": \"2.0\", \"method\": \"query\", \"params\": \"l\", \"id\": 1} +REM ..\..\PythonHome\python.exe main.py "{\"method\":\"openUrl\",\"parameters\":[\"https://blog.pinboard.in/2014/07/pinboard_turns_five/\",2]}" diff --git a/PythonHome/DLLs/pyc.ico b/PythonHome/DLLs/pyc.ico deleted file mode 100644 index f7bd2b1cc238c09301af80da5b8085ce13150b97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19790 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 diff --git a/PythonHome/Lib/BaseHTTPServer.py b/PythonHome/Lib/BaseHTTPServer.py new file mode 100644 index 0000000000..deaf2f960b --- /dev/null +++ b/PythonHome/Lib/BaseHTTPServer.py @@ -0,0 +1,603 @@ +"""HTTP server base class. + +Note: the class in this module doesn't implement any HTTP request; see +SimpleHTTPServer for simple implementations of GET, HEAD and POST +(including CGI scripts). It does, however, optionally implement HTTP/1.1 +persistent connections, as of version 0.3. + +Contents: + +- BaseHTTPRequestHandler: HTTP request handler base class +- test: test function + +XXX To do: + +- log requests even later (to capture byte count) +- log user-agent header and other interesting goodies +- send error log to separate file +""" + + +# See also: +# +# HTTP Working Group T. Berners-Lee +# INTERNET-DRAFT R. T. Fielding +# H. Frystyk Nielsen +# Expires September 8, 1995 March 8, 1995 +# +# URL: http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-v10-spec-00.txt +# +# and +# +# Network Working Group R. Fielding +# Request for Comments: 2616 et al +# Obsoletes: 2068 June 1999 +# Category: Standards Track +# +# URL: http://www.faqs.org/rfcs/rfc2616.html + +# Log files +# --------- +# +# Here's a quote from the NCSA httpd docs about log file format. +# +# | The logfile format is as follows. Each line consists of: +# | +# | host rfc931 authuser [DD/Mon/YYYY:hh:mm:ss] "request" ddd bbbb +# | +# | host: Either the DNS name or the IP number of the remote client +# | rfc931: Any information returned by identd for this person, +# | - otherwise. +# | authuser: If user sent a userid for authentication, the user name, +# | - otherwise. +# | DD: Day +# | Mon: Month (calendar name) +# | YYYY: Year +# | hh: hour (24-hour format, the machine's timezone) +# | mm: minutes +# | ss: seconds +# | request: The first line of the HTTP request as sent by the client. +# | ddd: the status code returned by the server, - if not available. +# | bbbb: the total number of bytes sent, +# | *not including the HTTP/1.0 header*, - if not available +# | +# | You can determine the name of the file accessed through request. +# +# (Actually, the latter is only true if you know the server configuration +# at the time the request was made!) + +__version__ = "0.3" + +__all__ = ["HTTPServer", "BaseHTTPRequestHandler"] + +import sys +import time +import socket # For gethostbyaddr() +from warnings import filterwarnings, catch_warnings +with catch_warnings(): + if sys.py3kwarning: + filterwarnings("ignore", ".*mimetools has been removed", + DeprecationWarning) + import mimetools +import SocketServer + +# Default error message template +DEFAULT_ERROR_MESSAGE = """\ + +Error response + + +

Error response

+

Error code %(code)d. +

Message: %(message)s. +

Error code explanation: %(code)s = %(explain)s. + +""" + +DEFAULT_ERROR_CONTENT_TYPE = "text/html" + +def _quote_html(html): + return html.replace("&", "&").replace("<", "<").replace(">", ">") + +class HTTPServer(SocketServer.TCPServer): + + allow_reuse_address = 1 # Seems to make sense in testing environment + + def server_bind(self): + """Override server_bind to store the server name.""" + SocketServer.TCPServer.server_bind(self) + host, port = self.socket.getsockname()[:2] + self.server_name = socket.getfqdn(host) + self.server_port = port + + +class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler): + + """HTTP request handler base class. + + The following explanation of HTTP serves to guide you through the + code as well as to expose any misunderstandings I may have about + HTTP (so you don't need to read the code to figure out I'm wrong + :-). + + HTTP (HyperText Transfer Protocol) is an extensible protocol on + top of a reliable stream transport (e.g. TCP/IP). The protocol + recognizes three parts to a request: + + 1. One line identifying the request type and path + 2. An optional set of RFC-822-style headers + 3. An optional data part + + The headers and data are separated by a blank line. + + The first line of the request has the form + + + + where is a (case-sensitive) keyword such as GET or POST, + is a string containing path information for the request, + and should be the string "HTTP/1.0" or "HTTP/1.1". + is encoded using the URL encoding scheme (using %xx to signify + the ASCII character with hex code xx). + + The specification specifies that lines are separated by CRLF but + for compatibility with the widest range of clients recommends + servers also handle LF. Similarly, whitespace in the request line + is treated sensibly (allowing multiple spaces between components + and allowing trailing whitespace). + + Similarly, for output, lines ought to be separated by CRLF pairs + but most clients grok LF characters just fine. + + If the first line of the request has the form + + + + (i.e. is left out) then this is assumed to be an HTTP + 0.9 request; this form has no optional headers and data part and + the reply consists of just the data. + + The reply form of the HTTP 1.x protocol again has three parts: + + 1. One line giving the response code + 2. An optional set of RFC-822-style headers + 3. The data + + Again, the headers and data are separated by a blank line. + + The response code line has the form + + + + where is the protocol version ("HTTP/1.0" or "HTTP/1.1"), + is a 3-digit response code indicating success or + failure of the request, and is an optional + human-readable string explaining what the response code means. + + This server parses the request and the headers, and then calls a + function specific to the request type (). Specifically, + a request SPAM will be handled by a method do_SPAM(). If no + such method exists the server sends an error response to the + client. If it exists, it is called with no arguments: + + do_SPAM() + + Note that the request name is case sensitive (i.e. SPAM and spam + are different requests). + + The various request details are stored in instance variables: + + - client_address is the client IP address in the form (host, + port); + + - command, path and version are the broken-down request line; + + - headers is an instance of mimetools.Message (or a derived + class) containing the header information; + + - rfile is a file object open for reading positioned at the + start of the optional input data part; + + - wfile is a file object open for writing. + + IT IS IMPORTANT TO ADHERE TO THE PROTOCOL FOR WRITING! + + The first thing to be written must be the response line. Then + follow 0 or more header lines, then a blank line, and then the + actual data (if any). The meaning of the header lines depends on + the command executed by the server; in most cases, when data is + returned, there should be at least one header line of the form + + Content-type: / + + where and should be registered MIME types, + e.g. "text/html" or "text/plain". + + """ + + # The Python system version, truncated to its first component. + sys_version = "Python/" + sys.version.split()[0] + + # The server software version. You may want to override this. + # The format is multiple whitespace-separated strings, + # where each string is of the form name[/version]. + server_version = "BaseHTTP/" + __version__ + + # The default request version. This only affects responses up until + # the point where the request line is parsed, so it mainly decides what + # the client gets back when sending a malformed request line. + # Most web servers default to HTTP 0.9, i.e. don't send a status line. + default_request_version = "HTTP/0.9" + + def parse_request(self): + """Parse a request (internal). + + The request should be stored in self.raw_requestline; the results + are in self.command, self.path, self.request_version and + self.headers. + + Return True for success, False for failure; on failure, an + error is sent back. + + """ + self.command = None # set in case of error on the first line + self.request_version = version = self.default_request_version + self.close_connection = 1 + requestline = self.raw_requestline + requestline = requestline.rstrip('\r\n') + self.requestline = requestline + words = requestline.split() + if len(words) == 3: + command, path, version = words + if version[:5] != 'HTTP/': + self.send_error(400, "Bad request version (%r)" % version) + return False + try: + base_version_number = version.split('/', 1)[1] + version_number = base_version_number.split(".") + # RFC 2145 section 3.1 says there can be only one "." and + # - major and minor numbers MUST be treated as + # separate integers; + # - HTTP/2.4 is a lower version than HTTP/2.13, which in + # turn is lower than HTTP/12.3; + # - Leading zeros MUST be ignored by recipients. + if len(version_number) != 2: + raise ValueError + version_number = int(version_number[0]), int(version_number[1]) + except (ValueError, IndexError): + self.send_error(400, "Bad request version (%r)" % version) + return False + if version_number >= (1, 1) and self.protocol_version >= "HTTP/1.1": + self.close_connection = 0 + if version_number >= (2, 0): + self.send_error(505, + "Invalid HTTP Version (%s)" % base_version_number) + return False + elif len(words) == 2: + command, path = words + self.close_connection = 1 + if command != 'GET': + self.send_error(400, + "Bad HTTP/0.9 request type (%r)" % command) + return False + elif not words: + return False + else: + self.send_error(400, "Bad request syntax (%r)" % requestline) + return False + self.command, self.path, self.request_version = command, path, version + + # Examine the headers and look for a Connection directive + self.headers = self.MessageClass(self.rfile, 0) + + conntype = self.headers.get('Connection', "") + if conntype.lower() == 'close': + self.close_connection = 1 + elif (conntype.lower() == 'keep-alive' and + self.protocol_version >= "HTTP/1.1"): + self.close_connection = 0 + return True + + def handle_one_request(self): + """Handle a single HTTP request. + + You normally don't need to override this method; see the class + __doc__ string for information on how to handle specific HTTP + commands such as GET and POST. + + """ + try: + self.raw_requestline = self.rfile.readline(65537) + if len(self.raw_requestline) > 65536: + self.requestline = '' + self.request_version = '' + self.command = '' + self.send_error(414) + return + if not self.raw_requestline: + self.close_connection = 1 + return + if not self.parse_request(): + # An error code has been sent, just exit + return + mname = 'do_' + self.command + if not hasattr(self, mname): + self.send_error(501, "Unsupported method (%r)" % self.command) + return + method = getattr(self, mname) + method() + self.wfile.flush() #actually send the response if not already done. + except socket.timeout, e: + #a read or a write timed out. Discard this connection + self.log_error("Request timed out: %r", e) + self.close_connection = 1 + return + + def handle(self): + """Handle multiple requests if necessary.""" + self.close_connection = 1 + + self.handle_one_request() + while not self.close_connection: + self.handle_one_request() + + def send_error(self, code, message=None): + """Send and log an error reply. + + Arguments are the error code, and a detailed message. + The detailed message defaults to the short entry matching the + response code. + + This sends an error response (so it must be called before any + output has been generated), logs the error, and finally sends + a piece of HTML explaining the error to the user. + + """ + + try: + short, long = self.responses[code] + except KeyError: + short, long = '???', '???' + if message is None: + message = short + explain = long + self.log_error("code %d, message %s", code, message) + # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201) + content = (self.error_message_format % + {'code': code, 'message': _quote_html(message), 'explain': explain}) + self.send_response(code, message) + self.send_header("Content-Type", self.error_content_type) + self.send_header('Connection', 'close') + self.end_headers() + if self.command != 'HEAD' and code >= 200 and code not in (204, 304): + self.wfile.write(content) + + error_message_format = DEFAULT_ERROR_MESSAGE + error_content_type = DEFAULT_ERROR_CONTENT_TYPE + + def send_response(self, code, message=None): + """Send the response header and log the response code. + + Also send two standard headers with the server software + version and the current date. + + """ + self.log_request(code) + if message is None: + if code in self.responses: + message = self.responses[code][0] + else: + message = '' + if self.request_version != 'HTTP/0.9': + self.wfile.write("%s %d %s\r\n" % + (self.protocol_version, code, message)) + # print (self.protocol_version, code, message) + self.send_header('Server', self.version_string()) + self.send_header('Date', self.date_time_string()) + + def send_header(self, keyword, value): + """Send a MIME header.""" + if self.request_version != 'HTTP/0.9': + self.wfile.write("%s: %s\r\n" % (keyword, value)) + + if keyword.lower() == 'connection': + if value.lower() == 'close': + self.close_connection = 1 + elif value.lower() == 'keep-alive': + self.close_connection = 0 + + def end_headers(self): + """Send the blank line ending the MIME headers.""" + if self.request_version != 'HTTP/0.9': + self.wfile.write("\r\n") + + def log_request(self, code='-', size='-'): + """Log an accepted request. + + This is called by send_response(). + + """ + + self.log_message('"%s" %s %s', + self.requestline, str(code), str(size)) + + def log_error(self, format, *args): + """Log an error. + + This is called when a request cannot be fulfilled. By + default it passes the message on to log_message(). + + Arguments are the same as for log_message(). + + XXX This should go to the separate error log. + + """ + + self.log_message(format, *args) + + def log_message(self, format, *args): + """Log an arbitrary message. + + This is used by all other logging functions. Override + it if you have specific logging wishes. + + The first argument, FORMAT, is a format string for the + message to be logged. If the format string contains + any % escapes requiring parameters, they should be + specified as subsequent arguments (it's just like + printf!). + + The client ip address and current date/time are prefixed to every + message. + + """ + + sys.stderr.write("%s - - [%s] %s\n" % + (self.client_address[0], + self.log_date_time_string(), + format%args)) + + def version_string(self): + """Return the server software version string.""" + return self.server_version + ' ' + self.sys_version + + def date_time_string(self, timestamp=None): + """Return the current date and time formatted for a message header.""" + if timestamp is None: + timestamp = time.time() + year, month, day, hh, mm, ss, wd, y, z = time.gmtime(timestamp) + s = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % ( + self.weekdayname[wd], + day, self.monthname[month], year, + hh, mm, ss) + return s + + def log_date_time_string(self): + """Return the current time formatted for logging.""" + now = time.time() + year, month, day, hh, mm, ss, x, y, z = time.localtime(now) + s = "%02d/%3s/%04d %02d:%02d:%02d" % ( + day, self.monthname[month], year, hh, mm, ss) + return s + + weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] + + monthname = [None, + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] + + def address_string(self): + """Return the client address formatted for logging. + + This version looks up the full hostname using gethostbyaddr(), + and tries to find a name that contains at least one dot. + + """ + + host, port = self.client_address[:2] + return socket.getfqdn(host) + + # Essentially static class variables + + # The version of the HTTP protocol we support. + # Set this to HTTP/1.1 to enable automatic keepalive + protocol_version = "HTTP/1.0" + + # The Message-like class used to parse headers + MessageClass = mimetools.Message + + # Table mapping response codes to messages; entries have the + # form {code: (shortmessage, longmessage)}. + # See RFC 2616. + responses = { + 100: ('Continue', 'Request received, please continue'), + 101: ('Switching Protocols', + 'Switching to new protocol; obey Upgrade header'), + + 200: ('OK', 'Request fulfilled, document follows'), + 201: ('Created', 'Document created, URL follows'), + 202: ('Accepted', + 'Request accepted, processing continues off-line'), + 203: ('Non-Authoritative Information', 'Request fulfilled from cache'), + 204: ('No Content', 'Request fulfilled, nothing follows'), + 205: ('Reset Content', 'Clear input form for further input.'), + 206: ('Partial Content', 'Partial content follows.'), + + 300: ('Multiple Choices', + 'Object has several resources -- see URI list'), + 301: ('Moved Permanently', 'Object moved permanently -- see URI list'), + 302: ('Found', 'Object moved temporarily -- see URI list'), + 303: ('See Other', 'Object moved -- see Method and URL list'), + 304: ('Not Modified', + 'Document has not changed since given time'), + 305: ('Use Proxy', + 'You must use proxy specified in Location to access this ' + 'resource.'), + 307: ('Temporary Redirect', + 'Object moved temporarily -- see URI list'), + + 400: ('Bad Request', + 'Bad request syntax or unsupported method'), + 401: ('Unauthorized', + 'No permission -- see authorization schemes'), + 402: ('Payment Required', + 'No payment -- see charging schemes'), + 403: ('Forbidden', + 'Request forbidden -- authorization will not help'), + 404: ('Not Found', 'Nothing matches the given URI'), + 405: ('Method Not Allowed', + 'Specified method is invalid for this resource.'), + 406: ('Not Acceptable', 'URI not available in preferred format.'), + 407: ('Proxy Authentication Required', 'You must authenticate with ' + 'this proxy before proceeding.'), + 408: ('Request Timeout', 'Request timed out; try again later.'), + 409: ('Conflict', 'Request conflict.'), + 410: ('Gone', + 'URI no longer exists and has been permanently removed.'), + 411: ('Length Required', 'Client must specify Content-Length.'), + 412: ('Precondition Failed', 'Precondition in headers is false.'), + 413: ('Request Entity Too Large', 'Entity is too large.'), + 414: ('Request-URI Too Long', 'URI is too long.'), + 415: ('Unsupported Media Type', 'Entity body in unsupported format.'), + 416: ('Requested Range Not Satisfiable', + 'Cannot satisfy request range.'), + 417: ('Expectation Failed', + 'Expect condition could not be satisfied.'), + + 500: ('Internal Server Error', 'Server got itself in trouble'), + 501: ('Not Implemented', + 'Server does not support this operation'), + 502: ('Bad Gateway', 'Invalid responses from another server/proxy.'), + 503: ('Service Unavailable', + 'The server cannot process the request due to a high load'), + 504: ('Gateway Timeout', + 'The gateway server did not receive a timely response'), + 505: ('HTTP Version Not Supported', 'Cannot fulfill request.'), + } + + +def test(HandlerClass = BaseHTTPRequestHandler, + ServerClass = HTTPServer, protocol="HTTP/1.0"): + """Test the HTTP request handler class. + + This runs an HTTP server on port 8000 (or the first command line + argument). + + """ + + if sys.argv[1:]: + port = int(sys.argv[1]) + else: + port = 8000 + server_address = ('', port) + + HandlerClass.protocol_version = protocol + httpd = ServerClass(server_address, HandlerClass) + + sa = httpd.socket.getsockname() + print "Serving HTTP on", sa[0], "port", sa[1], "..." + httpd.serve_forever() + + +if __name__ == '__main__': + test() diff --git a/PythonHome/Lib/BaseHTTPServer.pyc b/PythonHome/Lib/BaseHTTPServer.pyc deleted file mode 100644 index 47fc35c4e0c9be79739b05947f6298d4cbf3b398..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21389 zcmcJ1>vvpNR_Cdbte553u^l_6JLJY`cS>1O*-3h3HHk?_QDj@R^~hDFlL#|4S9Ncd zu2ogHa_=om6=GiL1&g&psq7pL6!vue0~Q8vE;GGr#%9Kiq5>`!j|6%lOTvOU8u8Y~flmTO|{g zO*m#+WwV8caT6Xf?J=`8=AOsR77Dfeh}k+K&l9FSVLFp$YtnS4%+{1CMN{TIV}5J_ zPh;lhv`P0(G-*QopEA*md2h^=x)@R695q`<%^Mi$wKr|atl641;k4O0X2Kb>^^ggV zn$KdA$2q-d*4#W{nwaV=3o*`HTMu*6tT-tZ$BK$mCc=MI1IBUlSuEwWi5@ZG3A0-^ z>5)=&ngC=nN6cpBVWMQFY|OPf$riXJ&d)n#Ebp$u^R1H)_bR^IjlB13-q(-lghuSpHJd zWy9=+nVALe6(EL7@O5R^Ft>J;zHnf<-j0@zU=clYAOcv#)ob>Q8-tW`ioCVvPQfWg3fLE6R0nG`jGys=X+iYCx1ZgmsP?xT3DKHZ5sQJy624Cu?e z?Fg$+qfT-w3bWrqgUejoOEZ`AIB!QUEz9K5w+Cv8E??BrnadY#tL-Elpz+Q#ceF&& z%;lafZX{vkU8wLj7gkxm8f6)9`2tEi`Zxy`IM^ZD@3n)jP%7I=@67vlJW5U6l`a=` z4%sv&pGW)o#htv@0YW2zPEFIeMw(i`HK~{&e<`IFzrU91#Ha;ad;z_>@1$DH?GIqH{2d8 zpH_Q={3z<`Z}%Yx>aq;HX54I3YVgV*j`IqB1x^IX1!;vVL~2O{*_iP+g+OAq6hsgS zgd&KzhKC%8D4CmOV&uJ&DG@OcrsEV?0OQ>#o7*LGyKHil9x?Bh*b0s66Xsp%REM}F zq6j&w;<652PGjt{3by)o4ALjT=b${1XYuZ8G)ITo-=7KRjnxJ8=(sF@!otp?2dMmIwIDB=_P3{6VJIhS=4UI!%mXr@*wr7 z`R3c@A44lpl*zafQ$A5TS2|g$5NytpdYxm}>%!mly2^39o=ZcT`an>1&k zUqh(jY3k+LOU?%n(%QGdM13rgy&88qzOM}!V9K#%xt0d;{p(Eo-$jHo5(XapDyCKD~6PMr0-P{UacJxulIt$3YafJxm# zgYBfB3lJHtk|i=in9zdiMv(}o6sk^SlMDpt&A3I~kFMUzQyp(FO}Z@s^1{NLU73Qr zHh^VQgSPQ%Y0%A@Fab8wBu^Sid(MN&7IZOFSTk9?4a==(tGuKu(DI~5JOog@?KohI zEXQ0rUQS??KVBuOwyGY);Kh{<8eT-G10yifsFAd~@jDUFvXe%r4bogtM6hBG!q(wl zJX7`7yOGz9aRH{gdE6XuSAb>L(#x?PF=u)~z9YS!t$K^y!n%W4&pBoP%F@CopM7>A z%LkaXnn9Vgf9_!WFvtU$(vTi(YZ*qW1EAU&L?H|=AY>Z~e^;hDN=PyGSm%!^j82;t z4Buhlc66Z2jil27J-p;y=2CF8M&?UezXxkA@`kOrS6-z7YjXkCS{CQ=t!U2MjRt#3 z8hTm3u|vXxjqJgQqj5YhtF^$TH};O`gngR_G3_v{JKupx$XSW?!ugHPTVc?8EN16r zJ4wF{ELdf!Fwc|PU`Ss&&*9zMGv}*^CJ}W>!68gkx3RDL*F7m^LDty8fx)Y2^@aU? z(af+4K?wqhI9%LZT3PWLJFrh1G=}$LEMh0x$HKs#`}>XoYG|AFqDI_|VQSKRw{Jp; zfo>GAdU$h}{Oeb|ZOfEI2zCmHinrr-oDXz3&SMWWitPp`w7`i?oQ`6i3P7sdT3FOd zZ>r2OP8+PP2LbQ;6>tiUKXE%q+k<&;Zzsk%pa)}2&r(BrCo{;(v4dp29LSUX-^Mwn zBD$G~>-5`sjMEmD2q3hU^F12OoO;sbv;+uuvgiXI#){B+IJ!gK$kd1ch?!nLpBKu; zc?gm(=f;2p4seAat`~p_WH6u*CqiJzA*PikyIA^g>oV_VpQj(J(Q?s>vQ6^=7)jZu z5?7<@2-O08?WhUS(9h>c;r7HzzR0qEN5w1_1bIkOmIYj@ew&j!FQO0Hl2NdSnb%E* z66X$aK>2H73Ir_1ksiVVkUTV?FL6w-gE4-K(E<_AB(Xr_xAPO@u>8cVs?flrV0>D#JhyJMdrW5H+mrR*=R?pGrjs z2qWlj?hCaRkE|gzM%<-s3GKn=q!s$6IOzo|eBH^7b0f+W5#Gv%XODDF?}+HB@QA5< zMjLPL#R8bxEc0qOa4C+RI3EJuhK!H83t_THZ;j5GI;;TUgasLDWa5x^g}CEGXQ+k@~1g`+j*7>N52 z#yU(Ys7feEVJRiJoTA)HV#k^o2ij01w-}DaSbN`Oti2RNbX!i<)x4EWZ)J63-LEaK z)x6rexA^L{Wq+AZwQI}XhQD50Us}KJU0L_NH~f{_%G%W@hLoW?5^4z|L6tG#!<2_H z0Htc}Gbd%#R2B1FO?y4`c$a9eb?ExANaSW^BG0ZKMqy(=fqZbPJ7bU>m9D^$QKL^22R1f0Ryq4c5~o@cFn=*Q*v4HQHda$3 zjo=E!-pRbl8HJ5XGcO8&4{Yt|65Y&5F^W^`)m`8T;|1?BZ!cZEob|WmN!wVXTuM}m zyZVtK)2KyHGFfwVWp!C(W2W3BXQlIn^G}Usd4(q~?!sJFvZHryV*p9my%^&W5ei(K z6Yiooam3(;g(7}4R@2|K#I`>GPYS#b^n!^m4BoSGzKqdT2B#UH$9aWk1)ekb$!@~0 z0!O1b(h9d3%O!$wd(6Pq_3juOgkusj7?kjO0|3X(Z2$pGRE--C-k9AnlYT*{O3^*wR&IrW6r2Fj$N(KRw{Fr$c zPQ9b%9Oh$R00S>gI0Glm8{K&`j@IxoqhNQ&q)(Ud!}Z>6MsE_>S+je@q`ovld}Y?Y zVh}|ZhGnxyrTniPECgmA;>3&9b$cV2!o(3>`9r}JCMK8~VtJF zd&;~!Wo|wquC~)M^ViD7Y`Y61wU0>c_i(tI1+KoQJc=vC1vV?^NQ+OwwYx#91G2=a z0|afr9f-s@Jx4`V1Gl>dL+%}FIC?*;X+TG$C>7BuA|oK-aQIOKJDcxUU)dslF>(;{o{y$E6B*=LGP;c0?U z!vvZSmH{Mm(AXV;FJ5r*p&y%x$AG+;4t??J3$Mrj2)N81McFHG202{01ynAibK>{E zC|7k{tL&hIS0EtH75_g1;nu8lZw2i*R3F!8Y<#P7A)A9I-5B^0vTwCRIZ0EDN%7}# zK=JvG&L$f`FYim8xRN1LZ728fYn6Q*8un|;{TDUW#R1ijTtx!Gq^yNzjOEUh)S->5k2PyMC zJoy({#+KXAv~DW(Zojh)cyOv3+u0S7wunfQgoFX)@_w-ZNNlbPBEjv~|3X3b4{$L@ zr%NYF)A)BBzq5!?9LM|V(s*gCbf$EC@+3+>Ryu`}Bc+d^eirXXOOt5FC-*i{8ZWcY zV`Gn&ACWr3nJqOy`G!d4l0{KIjFQ3s5NQZmCb|(?gd$SnNfdCR6`>n<$4&YcwI6FC zyY&HaIDLTrLStwM1f~$Bf*Rb^-dV!H1Uo_B*;42@Eckono$3)iC(KzWQIG{*7{e-? z>}w7rIzszOBa!+91ClISstN~4QA-H_A0zzI8{JD#gAY+gQwPqLO3>rdL02RI^*@0l4P|=)Lh{`fjA+UMCj&<0)?4t0BWl~h>1lvN(x}@Sv09C_X?B1d z?IiSX&mbV?LN?axVbZAA>0qYeNZWkGo~J}bB%g+^b)h-W-q2k`32VgyBdOBZJCH$y_5AaE@_3o!}P!chGl|&NZQ_g4Sjzkz~DC#;yRopAzo-c*rENiLj4$KULLgc?K8-hDFV9`WtLnEPpFmHnTL}J1U+N->7Ximtm;NFeidCM z0xoE}M;S&GDlRs-{wchg@^pEIVrC4_wBHLcGleDtw+L|exf`&z#CCq8`xtn%Bn-X&+N0V%}KEW`(LQ`(a>Y6Y5fqP)s-(aoWIBI>M)m&Iu!C9gl>fVZrBNq$kn< z=SjLmggGTuLt_q<1~e)U*P=kI1^7YKg#~L9XM8B}6p=cnq{xBV9&rh!I6`yKk-63A z5vJC^o70JLJh+wIQQZ2Lwj;&n0>naE`XQ zF5ZPq%m|i?n6c&ZYzN7h7~xLOH5dZ^M^WI@e3ZUS*^2)NZ}Hc8xrEJE1}sJ<%U}j- z^%adOv=l_1xgE$vo_;zSh}q;nj(UHIjZWhtgi*KitMgnRlM*$a za>_RC4`YV8U3D5X(u`J}HL+A!zf6!Kis5dFBm+l8hrfaf|2tf*kd>^zjo7UJX_iwg z*a7ZM(1>PulOo1LS95F(V)PhnBHB6=rBmgJ(s{g{!tYG!DHT1$Wg&Wg6))s&wJMlD z1A#Ir0%chQ2kKzlOqletv=eD^PLAYd^Y${ui(pEAvVDOAeljays zrpoPBs6YgvtN0N{p&B!5QQ*s-H5?%$6wTjRrtt_f(tEH5dR|!r%)rXUM=e_(n-8>lDgw)mg4WL!K8H>jro5@z<>qqP%KdzF*kikmh_HZY7deLl8kyv6M96FuKX0KJqRfl)y6D)fY zmm$`L%WYg<+R|qkoh;@DSUVkCz@RpR{L~28t!8j>lrbJ*}PtxQD|C z%qIDAz`awuV?Yr13-;3pb8Qz14A6bz0w=kP!_qR#A4^I(1S$!LG34h6R>`o z%jCScOtC~4#C94(3GFLc;v61|CFSJg+moFYRCNuq%Js66DqTBpoztSsI`&B99p=z z(ucmeM$qjh5g&UJrv5sCQVoj~#-5MdcPvqOj!<2kCpb|D(YQG}XSY>tOmXs$2KA{eYg ze*hEbE_hLfGd}5UOi31xgjeAA3lrDu)(*XJAq-5Cky)njanvS?A9E z%;gbECHR9i|dL73=G%b#~KJRm>=PC zk5Y)N^EFaDb*6cE7B=SHj_tIa3lV)*W%OAqhn_~A^_x?>95T8JV@v6$DoVf`elwuW zoflG#_Ce;}Kd{pIPE6+O1qYXfgL!nJ@j&j*ZsEf7EG%N2xIbbrA1KrJ3Lt|Na}z`clcHz+SIMYa&~~F-RTLWL4=q&Z6#^0 z?zCV4Weu0fj@&vOxxtgo!o5)TeIVC&gyUCuP;_hd>V2#G_^Fr$O_izyu@B0J3 zzr)LS<8qHOAx6``B*tkv6XV3USCU;`1$l4+wSFY`H=^2MIsS3y0}&b3FZN9y}6xo^V8F5bbfdi@y$_++?P%b=-fN}! z@XZRvm`YD%&HATBKDrqcHtswE7Y)hwf>h(oI4K1Aan7-_~ z{5K9mWw~h29T~%EZZLNk!E)1t?r7R;ZplmvZ7wiM5dU}dk--q_Tv+UbFu*rRYQnby zE5igQ5g872u@0}9CLNqGZDmlPFojRxvWe3@Gw|XrX35g?hKe)%Z`?ou&;U|9OlIAqRlLYgfjV(u9);_gw?#K;Mzab~aaK$EDH?bS{DLvUUaTO^3Ewu(lNui;D1I&I zZA9<|G6}jp5Y1v?$)|)KK96vfcfetALsZ!nd|nye**A}nT@713M&#@89IBiHh4m(8 zwode9PYu_hW7|Hfn)66rCppOyF0wnd7xE0fReYz}jPc#$9102=BrbSZLnb^j(2-S$ zk6|MZS-Xt+|>2g3O8Q&@PfL58fit zBA*rHK^t80U5%gNfHNvMDYbdQqI`?E%&45OpCMP{pK&w3 z9(7w-Ux5b|mHZw=Sxp&i;3VOKwy(xtBmg=tH~7^E{BXi}S0tV#%JM)tcE&lfvEfbT z9aZC>B?wAZx6Wnk3%*mSC5d+(L>-B*$QGg-KB>l6Q^2+i)xPqDzvcY1I_KX%&(^~A}TX}rHM4E?J zLV-fIR^y*1AX-5yHb2c%*S)vQ+#ON4wxET+an3w3t}n;8fJnKH|2O-Se7S}d_qPwg zv1BvblYbgPhPEjM$`Qy$M#vBI)}#X`J+H#EzZVQd|G9K6=b*&)Q`HAp1~so9l`jfw zRpbB5nW#HFy#*EOL6SQ5&d8#*;bFX?$Q3>mNk7cP3z6wY9pLT6_|~zVAXEBp+#2oN zJjbG+uuxk%XLr;OkzqzmTU!sX$iGmRZXNO865_X@x1^VR#wMZ>g_|zxLb5O{5m>9m z5kXZF+H5@k#{uQuEKKn+e25mN!1I5CEk3yMIuFQhR+U2Bm^}aD!6d_&>#sq+~i^hrW+3sl(s5Evelf z%$6KZ;X}4174Y3{$@@T(6P=a=Kak-mQ}MsR-T7d~rmo=uj7=T+r#bQ^Tnh1Vk2a=` z{{d}G?ewA9m zkX@-D?#r&!t{=#*)GiNfS1Onf#jaFPAA((}fbQR})cy}Cy4qtS4^kE;LoI`@5`pf)}Rr`iv0! z*LV@)q#q|INxZszW%2dvwfeH}ulx1Y<;~5-tIPg6t2y_B)l2JZwdJ*1z4q1y+N0Xv z;N>-5HhJ0NWr>%77Y4k1#z_2_mxPxdFQ4OuegtuF6yIISB3Cu)?295=MH^ZwBbWEf z?e}5Jn-ssM2ZmBdpv!Tp5)@4pPeBJ*p(0H@PLp$;zRrp4dEihia->Sj;ldH z!boCnBB7qi(Kf^qy@5O{_{L2$K z`5j2gx2f^?gBAAg^f7`^6W1Ni;5aL4YdtG6qh9`i%O@{gx+GuP5}Zc+-RGF}M@v-Q zMb2GdT(YF%mqE*#14rq^6E0oaa*o4M7DXCVkTlO~wYsLclH?wjd~wUCZ&!2NXgl}> zWb-xgX9t?aZ za~HBf" % self._name_ + + def __getattr__(self, name): + """Get an as-yet undefined attribute value. + + This calls the get() function that was passed to the + constructor. The result is stored as an instance variable so + that the next time the same attribute is requested, + __getattr__() won't be invoked. + + If the get() function raises an exception, this is simply + passed on -- exceptions are not cached. + + """ + attribute = self._get_(name) + self.__dict__[name] = attribute + return attribute + + +def Bastion(object, filter = lambda name: name[:1] != '_', + name=None, bastionclass=BastionClass): + """Create a bastion for an object, using an optional filter. + + See the Bastion module's documentation for background. + + Arguments: + + object - the original object + filter - a predicate that decides whether a function name is OK; + by default all names are OK that don't start with '_' + name - the name of the object; default repr(object) + bastionclass - class used to create the bastion; default BastionClass + + """ + + raise RuntimeError, "This code is not secure in Python 2.2 and later" + + # Note: we define *two* ad-hoc functions here, get1 and get2. + # Both are intended to be called in the same way: get(name). + # It is clear that the real work (getting the attribute + # from the object and calling the filter) is done in get1. + # Why can't we pass get1 to the bastion? Because the user + # would be able to override the filter argument! With get2, + # overriding the default argument is no security loophole: + # all it does is call it. + # Also notice that we can't place the object and filter as + # instance variables on the bastion object itself, since + # the user has full access to all instance variables! + + def get1(name, object=object, filter=filter): + """Internal function for Bastion(). See source comments.""" + if filter(name): + attribute = getattr(object, name) + if type(attribute) == MethodType: + return attribute + raise AttributeError, name + + def get2(name, get1=get1): + """Internal function for Bastion(). See source comments.""" + return get1(name) + + if name is None: + name = repr(object) + return bastionclass(get2, name) + + +def _test(): + """Test the Bastion() function.""" + class Original: + def __init__(self): + self.sum = 0 + def add(self, n): + self._add(n) + def _add(self, n): + self.sum = self.sum + n + def total(self): + return self.sum + o = Original() + b = Bastion(o) + testcode = """if 1: + b.add(81) + b.add(18) + print "b.total() =", b.total() + try: + print "b.sum =", b.sum, + except: + print "inaccessible" + else: + print "accessible" + try: + print "b._add =", b._add, + except: + print "inaccessible" + else: + print "accessible" + try: + print "b._get_.func_defaults =", map(type, b._get_.func_defaults), + except: + print "inaccessible" + else: + print "accessible" + \n""" + exec testcode + print '='*20, "Using rexec:", '='*20 + import rexec + r = rexec.RExec() + m = r.add_module('__main__') + m.b = b + r.r_exec(testcode) + + +if __name__ == '__main__': + _test() diff --git a/PythonHome/Lib/Bastion.pyc b/PythonHome/Lib/Bastion.pyc deleted file mode 100644 index 8cbbb535b1e80fd37085e2db87624c79c80a1eff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6435 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 ITdTo;0ESgpB>(^b diff --git a/PythonHome/Lib/CGIHTTPServer.py b/PythonHome/Lib/CGIHTTPServer.py new file mode 100644 index 0000000000..2acf913155 --- /dev/null +++ b/PythonHome/Lib/CGIHTTPServer.py @@ -0,0 +1,377 @@ +"""CGI-savvy HTTP Server. + +This module builds on SimpleHTTPServer by implementing GET and POST +requests to cgi-bin scripts. + +If the os.fork() function is not present (e.g. on Windows), +os.popen2() is used as a fallback, with slightly altered semantics; if +that function is not present either (e.g. on Macintosh), only Python +scripts are supported, and they are executed by the current process. + +In all cases, the implementation is intentionally naive -- all +requests are executed sychronously. + +SECURITY WARNING: DON'T USE THIS CODE UNLESS YOU ARE INSIDE A FIREWALL +-- it may execute arbitrary Python code or external programs. + +Note that status code 200 is sent prior to execution of a CGI script, so +scripts cannot send other status codes such as 302 (redirect). +""" + + +__version__ = "0.4" + +__all__ = ["CGIHTTPRequestHandler"] + +import os +import sys +import urllib +import BaseHTTPServer +import SimpleHTTPServer +import select +import copy + + +class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): + + """Complete HTTP server with GET, HEAD and POST commands. + + GET and HEAD also support running CGI scripts. + + The POST command is *only* implemented for CGI scripts. + + """ + + # Determine platform specifics + have_fork = hasattr(os, 'fork') + have_popen2 = hasattr(os, 'popen2') + have_popen3 = hasattr(os, 'popen3') + + # Make rfile unbuffered -- we need to read one line and then pass + # the rest to a subprocess, so we can't use buffered input. + rbufsize = 0 + + def do_POST(self): + """Serve a POST request. + + This is only implemented for CGI scripts. + + """ + + if self.is_cgi(): + self.run_cgi() + else: + self.send_error(501, "Can only POST to CGI scripts") + + def send_head(self): + """Version of send_head that support CGI scripts""" + if self.is_cgi(): + return self.run_cgi() + else: + return SimpleHTTPServer.SimpleHTTPRequestHandler.send_head(self) + + def is_cgi(self): + """Test whether self.path corresponds to a CGI script. + + Returns True and updates the cgi_info attribute to the tuple + (dir, rest) if self.path requires running a CGI script. + Returns False otherwise. + + If any exception is raised, the caller should assume that + self.path was rejected as invalid and act accordingly. + + The default implementation tests whether the normalized url + path begins with one of the strings in self.cgi_directories + (and the next character is a '/' or the end of the string). + """ + collapsed_path = _url_collapse_path(urllib.unquote(self.path)) + dir_sep = collapsed_path.find('/', 1) + head, tail = collapsed_path[:dir_sep], collapsed_path[dir_sep+1:] + if head in self.cgi_directories: + self.cgi_info = head, tail + return True + return False + + cgi_directories = ['/cgi-bin', '/htbin'] + + def is_executable(self, path): + """Test whether argument path is an executable file.""" + return executable(path) + + def is_python(self, path): + """Test whether argument path is a Python script.""" + head, tail = os.path.splitext(path) + return tail.lower() in (".py", ".pyw") + + def run_cgi(self): + """Execute a CGI script.""" + dir, rest = self.cgi_info + + i = rest.find('/') + while i >= 0: + nextdir = rest[:i] + nextrest = rest[i+1:] + + scriptdir = self.translate_path(nextdir) + if os.path.isdir(scriptdir): + dir, rest = nextdir, nextrest + i = rest.find('/') + else: + break + + # find an explicit query string, if present. + i = rest.rfind('?') + if i >= 0: + rest, query = rest[:i], rest[i+1:] + else: + query = '' + + # dissect the part after the directory name into a script name & + # a possible additional path, to be stored in PATH_INFO. + i = rest.find('/') + if i >= 0: + script, rest = rest[:i], rest[i:] + else: + script, rest = rest, '' + + scriptname = dir + '/' + script + scriptfile = self.translate_path(scriptname) + if not os.path.exists(scriptfile): + self.send_error(404, "No such CGI script (%r)" % scriptname) + return + if not os.path.isfile(scriptfile): + self.send_error(403, "CGI script is not a plain file (%r)" % + scriptname) + return + ispy = self.is_python(scriptname) + if not ispy: + if not (self.have_fork or self.have_popen2 or self.have_popen3): + self.send_error(403, "CGI script is not a Python script (%r)" % + scriptname) + return + if not self.is_executable(scriptfile): + self.send_error(403, "CGI script is not executable (%r)" % + scriptname) + return + + # Reference: http://hoohoo.ncsa.uiuc.edu/cgi/env.html + # XXX Much of the following could be prepared ahead of time! + env = copy.deepcopy(os.environ) + env['SERVER_SOFTWARE'] = self.version_string() + env['SERVER_NAME'] = self.server.server_name + env['GATEWAY_INTERFACE'] = 'CGI/1.1' + env['SERVER_PROTOCOL'] = self.protocol_version + env['SERVER_PORT'] = str(self.server.server_port) + env['REQUEST_METHOD'] = self.command + uqrest = urllib.unquote(rest) + env['PATH_INFO'] = uqrest + env['PATH_TRANSLATED'] = self.translate_path(uqrest) + env['SCRIPT_NAME'] = scriptname + if query: + env['QUERY_STRING'] = query + host = self.address_string() + if host != self.client_address[0]: + env['REMOTE_HOST'] = host + env['REMOTE_ADDR'] = self.client_address[0] + authorization = self.headers.getheader("authorization") + if authorization: + authorization = authorization.split() + if len(authorization) == 2: + import base64, binascii + env['AUTH_TYPE'] = authorization[0] + if authorization[0].lower() == "basic": + try: + authorization = base64.decodestring(authorization[1]) + except binascii.Error: + pass + else: + authorization = authorization.split(':') + if len(authorization) == 2: + env['REMOTE_USER'] = authorization[0] + # XXX REMOTE_IDENT + if self.headers.typeheader is None: + env['CONTENT_TYPE'] = self.headers.type + else: + env['CONTENT_TYPE'] = self.headers.typeheader + length = self.headers.getheader('content-length') + if length: + env['CONTENT_LENGTH'] = length + referer = self.headers.getheader('referer') + if referer: + env['HTTP_REFERER'] = referer + accept = [] + for line in self.headers.getallmatchingheaders('accept'): + if line[:1] in "\t\n\r ": + accept.append(line.strip()) + else: + accept = accept + line[7:].split(',') + env['HTTP_ACCEPT'] = ','.join(accept) + ua = self.headers.getheader('user-agent') + if ua: + env['HTTP_USER_AGENT'] = ua + co = filter(None, self.headers.getheaders('cookie')) + if co: + env['HTTP_COOKIE'] = ', '.join(co) + # XXX Other HTTP_* headers + # Since we're setting the env in the parent, provide empty + # values to override previously set values + for k in ('QUERY_STRING', 'REMOTE_HOST', 'CONTENT_LENGTH', + 'HTTP_USER_AGENT', 'HTTP_COOKIE', 'HTTP_REFERER'): + env.setdefault(k, "") + + self.send_response(200, "Script output follows") + + decoded_query = query.replace('+', ' ') + + if self.have_fork: + # Unix -- fork as we should + args = [script] + if '=' not in decoded_query: + args.append(decoded_query) + nobody = nobody_uid() + self.wfile.flush() # Always flush before forking + pid = os.fork() + if pid != 0: + # Parent + pid, sts = os.waitpid(pid, 0) + # throw away additional data [see bug #427345] + while select.select([self.rfile], [], [], 0)[0]: + if not self.rfile.read(1): + break + if sts: + self.log_error("CGI script exit status %#x", sts) + return + # Child + try: + try: + os.setuid(nobody) + except os.error: + pass + os.dup2(self.rfile.fileno(), 0) + os.dup2(self.wfile.fileno(), 1) + os.execve(scriptfile, args, env) + except: + self.server.handle_error(self.request, self.client_address) + os._exit(127) + + else: + # Non Unix - use subprocess + import subprocess + cmdline = [scriptfile] + if self.is_python(scriptfile): + interp = sys.executable + if interp.lower().endswith("w.exe"): + # On Windows, use python.exe, not pythonw.exe + interp = interp[:-5] + interp[-4:] + cmdline = [interp, '-u'] + cmdline + if '=' not in query: + cmdline.append(query) + + self.log_message("command: %s", subprocess.list2cmdline(cmdline)) + try: + nbytes = int(length) + except (TypeError, ValueError): + nbytes = 0 + p = subprocess.Popen(cmdline, + stdin = subprocess.PIPE, + stdout = subprocess.PIPE, + stderr = subprocess.PIPE, + env = env + ) + if self.command.lower() == "post" and nbytes > 0: + data = self.rfile.read(nbytes) + else: + data = None + # throw away additional data [see bug #427345] + while select.select([self.rfile._sock], [], [], 0)[0]: + if not self.rfile._sock.recv(1): + break + stdout, stderr = p.communicate(data) + self.wfile.write(stdout) + if stderr: + self.log_error('%s', stderr) + p.stderr.close() + p.stdout.close() + status = p.returncode + if status: + self.log_error("CGI script exit status %#x", status) + else: + self.log_message("CGI script exited OK") + + +def _url_collapse_path(path): + """ + Given a URL path, remove extra '/'s and '.' path elements and collapse + any '..' references and returns a colllapsed path. + + Implements something akin to RFC-2396 5.2 step 6 to parse relative paths. + The utility of this function is limited to is_cgi method and helps + preventing some security attacks. + + Returns: A tuple of (head, tail) where tail is everything after the final / + and head is everything before it. Head will always start with a '/' and, + if it contains anything else, never have a trailing '/'. + + Raises: IndexError if too many '..' occur within the path. + + """ + # Similar to os.path.split(os.path.normpath(path)) but specific to URL + # path semantics rather than local operating system semantics. + path_parts = path.split('/') + head_parts = [] + for part in path_parts[:-1]: + if part == '..': + head_parts.pop() # IndexError if more '..' than prior parts + elif part and part != '.': + head_parts.append( part ) + if path_parts: + tail_part = path_parts.pop() + if tail_part: + if tail_part == '..': + head_parts.pop() + tail_part = '' + elif tail_part == '.': + tail_part = '' + else: + tail_part = '' + + splitpath = ('/' + '/'.join(head_parts), tail_part) + collapsed_path = "/".join(splitpath) + + return collapsed_path + + +nobody = None + +def nobody_uid(): + """Internal routine to get nobody's uid""" + global nobody + if nobody: + return nobody + try: + import pwd + except ImportError: + return -1 + try: + nobody = pwd.getpwnam('nobody')[2] + except KeyError: + nobody = 1 + max(map(lambda x: x[2], pwd.getpwall())) + return nobody + + +def executable(path): + """Test for executable file.""" + try: + st = os.stat(path) + except os.error: + return False + return st.st_mode & 0111 != 0 + + +def test(HandlerClass = CGIHTTPRequestHandler, + ServerClass = BaseHTTPServer.HTTPServer): + SimpleHTTPServer.test(HandlerClass, ServerClass) + + +if __name__ == '__main__': + test() diff --git a/PythonHome/Lib/CGIHTTPServer.pyc b/PythonHome/Lib/CGIHTTPServer.pyc deleted file mode 100644 index 120ff20c81e03a9d9f58a312a7870d0e5c4abfdd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10868 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 diff --git a/PythonHome/Lib/ConfigParser.py b/PythonHome/Lib/ConfigParser.py new file mode 100644 index 0000000000..7e6cdbc30a --- /dev/null +++ b/PythonHome/Lib/ConfigParser.py @@ -0,0 +1,753 @@ +"""Configuration file parser. + +A setup file consists of sections, lead by a "[section]" header, +and followed by "name: value" entries, with continuations and such in +the style of RFC 822. + +The option values can contain format strings which refer to other values in +the same section, or values in a special [DEFAULT] section. + +For example: + + something: %(dir)s/whatever + +would resolve the "%(dir)s" to the value of dir. All reference +expansions are done late, on demand. + +Intrinsic defaults can be specified by passing them into the +ConfigParser constructor as a dictionary. + +class: + +ConfigParser -- responsible for parsing a list of + configuration files, and managing the parsed database. + + methods: + + __init__(defaults=None) + create the parser and specify a dictionary of intrinsic defaults. The + keys must be strings, the values must be appropriate for %()s string + interpolation. Note that `__name__' is always an intrinsic default; + its value is the section's name. + + sections() + return all the configuration section names, sans DEFAULT + + has_section(section) + return whether the given section exists + + has_option(section, option) + return whether the given option exists in the given section + + options(section) + return list of configuration options for the named section + + read(filenames) + read and parse the list of named configuration files, given by + name. A single filename is also allowed. Non-existing files + are ignored. Return list of successfully read files. + + readfp(fp, filename=None) + read and parse one configuration file, given as a file object. + The filename defaults to fp.name; it is only used in error + messages (if fp has no `name' attribute, the string `' is used). + + get(section, option, raw=False, vars=None) + return a string value for the named option. All % interpolations are + expanded in the return values, based on the defaults passed into the + constructor and the DEFAULT section. Additional substitutions may be + provided using the `vars' argument, which must be a dictionary whose + contents override any pre-existing defaults. + + getint(section, options) + like get(), but convert value to an integer + + getfloat(section, options) + like get(), but convert value to a float + + getboolean(section, options) + like get(), but convert value to a boolean (currently case + insensitively defined as 0, false, no, off for False, and 1, true, + yes, on for True). Returns False or True. + + items(section, raw=False, vars=None) + return a list of tuples with (name, value) for each option + in the section. + + remove_section(section) + remove the given file section and all its options + + remove_option(section, option) + remove the given option from the given section + + set(section, option, value) + set the given option + + write(fp) + write the configuration state in .ini format +""" + +try: + from collections import OrderedDict as _default_dict +except ImportError: + # fallback for setup.py which hasn't yet built _collections + _default_dict = dict + +import re + +__all__ = ["NoSectionError", "DuplicateSectionError", "NoOptionError", + "InterpolationError", "InterpolationDepthError", + "InterpolationSyntaxError", "ParsingError", + "MissingSectionHeaderError", + "ConfigParser", "SafeConfigParser", "RawConfigParser", + "DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"] + +DEFAULTSECT = "DEFAULT" + +MAX_INTERPOLATION_DEPTH = 10 + + + +# exception classes +class Error(Exception): + """Base class for ConfigParser exceptions.""" + + def _get_message(self): + """Getter for 'message'; needed only to override deprecation in + BaseException.""" + return self.__message + + def _set_message(self, value): + """Setter for 'message'; needed only to override deprecation in + BaseException.""" + self.__message = value + + # BaseException.message has been deprecated since Python 2.6. To prevent + # DeprecationWarning from popping up over this pre-existing attribute, use + # a new property that takes lookup precedence. + message = property(_get_message, _set_message) + + def __init__(self, msg=''): + self.message = msg + Exception.__init__(self, msg) + + def __repr__(self): + return self.message + + __str__ = __repr__ + +class NoSectionError(Error): + """Raised when no section matches a requested option.""" + + def __init__(self, section): + Error.__init__(self, 'No section: %r' % (section,)) + self.section = section + self.args = (section, ) + +class DuplicateSectionError(Error): + """Raised when a section is multiply-created.""" + + def __init__(self, section): + Error.__init__(self, "Section %r already exists" % section) + self.section = section + self.args = (section, ) + +class NoOptionError(Error): + """A requested option was not found.""" + + def __init__(self, option, section): + Error.__init__(self, "No option %r in section: %r" % + (option, section)) + self.option = option + self.section = section + self.args = (option, section) + +class InterpolationError(Error): + """Base class for interpolation-related exceptions.""" + + def __init__(self, option, section, msg): + Error.__init__(self, msg) + self.option = option + self.section = section + self.args = (option, section, msg) + +class InterpolationMissingOptionError(InterpolationError): + """A string substitution required a setting which was not available.""" + + def __init__(self, option, section, rawval, reference): + msg = ("Bad value substitution:\n" + "\tsection: [%s]\n" + "\toption : %s\n" + "\tkey : %s\n" + "\trawval : %s\n" + % (section, option, reference, rawval)) + InterpolationError.__init__(self, option, section, msg) + self.reference = reference + self.args = (option, section, rawval, reference) + +class InterpolationSyntaxError(InterpolationError): + """Raised when the source text into which substitutions are made + does not conform to the required syntax.""" + +class InterpolationDepthError(InterpolationError): + """Raised when substitutions are nested too deeply.""" + + def __init__(self, option, section, rawval): + msg = ("Value interpolation too deeply recursive:\n" + "\tsection: [%s]\n" + "\toption : %s\n" + "\trawval : %s\n" + % (section, option, rawval)) + InterpolationError.__init__(self, option, section, msg) + self.args = (option, section, rawval) + +class ParsingError(Error): + """Raised when a configuration file does not follow legal syntax.""" + + def __init__(self, filename): + Error.__init__(self, 'File contains parsing errors: %s' % filename) + self.filename = filename + self.errors = [] + self.args = (filename, ) + + def append(self, lineno, line): + self.errors.append((lineno, line)) + self.message += '\n\t[line %2d]: %s' % (lineno, line) + +class MissingSectionHeaderError(ParsingError): + """Raised when a key-value pair is found before any section header.""" + + def __init__(self, filename, lineno, line): + Error.__init__( + self, + 'File contains no section headers.\nfile: %s, line: %d\n%r' % + (filename, lineno, line)) + self.filename = filename + self.lineno = lineno + self.line = line + self.args = (filename, lineno, line) + + +class RawConfigParser: + def __init__(self, defaults=None, dict_type=_default_dict, + allow_no_value=False): + self._dict = dict_type + self._sections = self._dict() + self._defaults = self._dict() + if allow_no_value: + self._optcre = self.OPTCRE_NV + else: + self._optcre = self.OPTCRE + if defaults: + for key, value in defaults.items(): + self._defaults[self.optionxform(key)] = value + + def defaults(self): + return self._defaults + + def sections(self): + """Return a list of section names, excluding [DEFAULT]""" + # self._sections will never have [DEFAULT] in it + return self._sections.keys() + + def add_section(self, section): + """Create a new section in the configuration. + + Raise DuplicateSectionError if a section by the specified name + already exists. Raise ValueError if name is DEFAULT or any of it's + case-insensitive variants. + """ + if section.lower() == "default": + raise ValueError, 'Invalid section name: %s' % section + + if section in self._sections: + raise DuplicateSectionError(section) + self._sections[section] = self._dict() + + def has_section(self, section): + """Indicate whether the named section is present in the configuration. + + The DEFAULT section is not acknowledged. + """ + return section in self._sections + + def options(self, section): + """Return a list of option names for the given section name.""" + try: + opts = self._sections[section].copy() + except KeyError: + raise NoSectionError(section) + opts.update(self._defaults) + if '__name__' in opts: + del opts['__name__'] + return opts.keys() + + def read(self, filenames): + """Read and parse a filename or a list of filenames. + + Files that cannot be opened are silently ignored; this is + designed so that you can specify a list of potential + configuration file locations (e.g. current directory, user's + home directory, systemwide directory), and all existing + configuration files in the list will be read. A single + filename may also be given. + + Return list of successfully read files. + """ + if isinstance(filenames, basestring): + filenames = [filenames] + read_ok = [] + for filename in filenames: + try: + fp = open(filename) + except IOError: + continue + self._read(fp, filename) + fp.close() + read_ok.append(filename) + return read_ok + + def readfp(self, fp, filename=None): + """Like read() but the argument must be a file-like object. + + The `fp' argument must have a `readline' method. Optional + second argument is the `filename', which if not given, is + taken from fp.name. If fp has no `name' attribute, `' is + used. + + """ + if filename is None: + try: + filename = fp.name + except AttributeError: + filename = '' + self._read(fp, filename) + + def get(self, section, option): + opt = self.optionxform(option) + if section not in self._sections: + if section != DEFAULTSECT: + raise NoSectionError(section) + if opt in self._defaults: + return self._defaults[opt] + else: + raise NoOptionError(option, section) + elif opt in self._sections[section]: + return self._sections[section][opt] + elif opt in self._defaults: + return self._defaults[opt] + else: + raise NoOptionError(option, section) + + def items(self, section): + try: + d2 = self._sections[section] + except KeyError: + if section != DEFAULTSECT: + raise NoSectionError(section) + d2 = self._dict() + d = self._defaults.copy() + d.update(d2) + if "__name__" in d: + del d["__name__"] + return d.items() + + def _get(self, section, conv, option): + return conv(self.get(section, option)) + + def getint(self, section, option): + return self._get(section, int, option) + + def getfloat(self, section, option): + return self._get(section, float, option) + + _boolean_states = {'1': True, 'yes': True, 'true': True, 'on': True, + '0': False, 'no': False, 'false': False, 'off': False} + + def getboolean(self, section, option): + v = self.get(section, option) + if v.lower() not in self._boolean_states: + raise ValueError, 'Not a boolean: %s' % v + return self._boolean_states[v.lower()] + + def optionxform(self, optionstr): + return optionstr.lower() + + def has_option(self, section, option): + """Check for the existence of a given option in a given section.""" + if not section or section == DEFAULTSECT: + option = self.optionxform(option) + return option in self._defaults + elif section not in self._sections: + return False + else: + option = self.optionxform(option) + return (option in self._sections[section] + or option in self._defaults) + + def set(self, section, option, value=None): + """Set an option.""" + if not section or section == DEFAULTSECT: + sectdict = self._defaults + else: + try: + sectdict = self._sections[section] + except KeyError: + raise NoSectionError(section) + sectdict[self.optionxform(option)] = value + + def write(self, fp): + """Write an .ini-format representation of the configuration state.""" + if self._defaults: + fp.write("[%s]\n" % DEFAULTSECT) + for (key, value) in self._defaults.items(): + fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t'))) + fp.write("\n") + for section in self._sections: + fp.write("[%s]\n" % section) + for (key, value) in self._sections[section].items(): + if key == "__name__": + continue + if (value is not None) or (self._optcre == self.OPTCRE): + key = " = ".join((key, str(value).replace('\n', '\n\t'))) + fp.write("%s\n" % (key)) + fp.write("\n") + + def remove_option(self, section, option): + """Remove an option.""" + if not section or section == DEFAULTSECT: + sectdict = self._defaults + else: + try: + sectdict = self._sections[section] + except KeyError: + raise NoSectionError(section) + option = self.optionxform(option) + existed = option in sectdict + if existed: + del sectdict[option] + return existed + + def remove_section(self, section): + """Remove a file section.""" + existed = section in self._sections + if existed: + del self._sections[section] + return existed + + # + # Regular expressions for parsing section headers and options. + # + SECTCRE = re.compile( + r'\[' # [ + r'(?P

[^]]+)' # very permissive! + r'\]' # ] + ) + OPTCRE = re.compile( + r'(?P%s' % (url, url)) + elif rfc: + url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc) + results.append('%s' % (url, escape(all))) + elif pep: + url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep) + results.append('%s' % (url, escape(all))) + elif text[end:end+1] == '(': + results.append(self.namelink(name, methods, funcs, classes)) + elif selfdot: + results.append('self.%s' % name) + else: + results.append(self.namelink(name, classes)) + here = end + results.append(escape(text[here:])) + return ''.join(results) + + def docroutine(self, object, name, mod=None, + funcs={}, classes={}, methods={}, cl=None): + """Produce HTML documentation for a function or method object.""" + + anchor = (cl and cl.__name__ or '') + '-' + name + note = '' + + title = '%s' % ( + self.escape(anchor), self.escape(name)) + + if inspect.ismethod(object): + args, varargs, varkw, defaults = inspect.getargspec(object.im_func) + # exclude the argument bound to the instance, it will be + # confusing to the non-Python user + argspec = inspect.formatargspec ( + args[1:], + varargs, + varkw, + defaults, + formatvalue=self.formatvalue + ) + elif inspect.isfunction(object): + args, varargs, varkw, defaults = inspect.getargspec(object) + argspec = inspect.formatargspec( + args, varargs, varkw, defaults, formatvalue=self.formatvalue) + else: + argspec = '(...)' + + if isinstance(object, tuple): + argspec = object[0] or argspec + docstring = object[1] or "" + else: + docstring = pydoc.getdoc(object) + + decl = title + argspec + (note and self.grey( + '%s' % note)) + + doc = self.markup( + docstring, self.preformat, funcs, classes, methods) + doc = doc and '
%s
' % doc + return '
%s
%s
\n' % (decl, doc) + + def docserver(self, server_name, package_documentation, methods): + """Produce HTML documentation for an XML-RPC server.""" + + fdict = {} + for key, value in methods.items(): + fdict[key] = '#-' + key + fdict[value] = fdict[key] + + server_name = self.escape(server_name) + head = '%s' % server_name + result = self.heading(head, '#ffffff', '#7799ee') + + doc = self.markup(package_documentation, self.preformat, fdict) + doc = doc and '%s' % doc + result = result + '

%s

\n' % doc + + contents = [] + method_items = sorted(methods.items()) + for key, value in method_items: + contents.append(self.docroutine(value, key, funcs=fdict)) + result = result + self.bigsection( + 'Methods', '#ffffff', '#eeaa77', pydoc.join(contents)) + + return result + +class XMLRPCDocGenerator: + """Generates documentation for an XML-RPC server. + + This class is designed as mix-in and should not + be constructed directly. + """ + + def __init__(self): + # setup variables used for HTML documentation + self.server_name = 'XML-RPC Server Documentation' + self.server_documentation = \ + "This server exports the following methods through the XML-RPC "\ + "protocol." + self.server_title = 'XML-RPC Server Documentation' + + def set_server_title(self, server_title): + """Set the HTML title of the generated server documentation""" + + self.server_title = server_title + + def set_server_name(self, server_name): + """Set the name of the generated HTML server documentation""" + + self.server_name = server_name + + def set_server_documentation(self, server_documentation): + """Set the documentation string for the entire server.""" + + self.server_documentation = server_documentation + + def generate_html_documentation(self): + """generate_html_documentation() => html documentation for the server + + Generates HTML documentation for the server using introspection for + installed functions and instances that do not implement the + _dispatch method. Alternatively, instances can choose to implement + the _get_method_argstring(method_name) method to provide the + argument string used in the documentation and the + _methodHelp(method_name) method to provide the help text used + in the documentation.""" + + methods = {} + + for method_name in self.system_listMethods(): + if method_name in self.funcs: + method = self.funcs[method_name] + elif self.instance is not None: + method_info = [None, None] # argspec, documentation + if hasattr(self.instance, '_get_method_argstring'): + method_info[0] = self.instance._get_method_argstring(method_name) + if hasattr(self.instance, '_methodHelp'): + method_info[1] = self.instance._methodHelp(method_name) + + method_info = tuple(method_info) + if method_info != (None, None): + method = method_info + elif not hasattr(self.instance, '_dispatch'): + try: + method = resolve_dotted_attribute( + self.instance, + method_name + ) + except AttributeError: + method = method_info + else: + method = method_info + else: + assert 0, "Could not find method in self.functions and no "\ + "instance installed" + + methods[method_name] = method + + documenter = ServerHTMLDoc() + documentation = documenter.docserver( + self.server_name, + self.server_documentation, + methods + ) + + return documenter.page(self.server_title, documentation) + +class DocXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): + """XML-RPC and documentation request handler class. + + Handles all HTTP POST requests and attempts to decode them as + XML-RPC requests. + + Handles all HTTP GET requests and interprets them as requests + for documentation. + """ + + def do_GET(self): + """Handles the HTTP GET request. + + Interpret all HTTP GET requests as requests for server + documentation. + """ + # Check that the path is legal + if not self.is_rpc_path_valid(): + self.report_404() + return + + response = self.server.generate_html_documentation() + self.send_response(200) + self.send_header("Content-type", "text/html") + self.send_header("Content-length", str(len(response))) + self.end_headers() + self.wfile.write(response) + +class DocXMLRPCServer( SimpleXMLRPCServer, + XMLRPCDocGenerator): + """XML-RPC and HTML documentation server. + + Adds the ability to serve server documentation to the capabilities + of SimpleXMLRPCServer. + """ + + def __init__(self, addr, requestHandler=DocXMLRPCRequestHandler, + logRequests=1, allow_none=False, encoding=None, + bind_and_activate=True): + SimpleXMLRPCServer.__init__(self, addr, requestHandler, logRequests, + allow_none, encoding, bind_and_activate) + XMLRPCDocGenerator.__init__(self) + +class DocCGIXMLRPCRequestHandler( CGIXMLRPCRequestHandler, + XMLRPCDocGenerator): + """Handler for XML-RPC data and documentation requests passed through + CGI""" + + def handle_get(self): + """Handles the HTTP GET request. + + Interpret all HTTP GET requests as requests for server + documentation. + """ + + response = self.generate_html_documentation() + + print 'Content-Type: text/html' + print 'Content-Length: %d' % len(response) + print + sys.stdout.write(response) + + def __init__(self): + CGIXMLRPCRequestHandler.__init__(self) + XMLRPCDocGenerator.__init__(self) diff --git a/PythonHome/Lib/DocXMLRPCServer.pyc b/PythonHome/Lib/DocXMLRPCServer.pyc deleted file mode 100644 index 432e4a0561af48be0edce098251bb930a2e845d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9564 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') +commentclose = re.compile(r'--\s*>') + +# see http://www.w3.org/TR/html5/tokenization.html#tag-open-state +# and http://www.w3.org/TR/html5/tokenization.html#tag-name-state +# note: if you change tagfind/attrfind remember to update locatestarttagend too +tagfind = re.compile('([a-zA-Z][^\t\n\r\f />\x00]*)(?:\s|/(?!>))*') +# this regex is currently unused, but left for backward compatibility +tagfind_tolerant = re.compile('[a-zA-Z][^\t\n\r\f />\x00]*') + +attrfind = re.compile( + r'((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*' + r'(\'[^\']*\'|"[^"]*"|(?![\'"])[^>\s]*))?(?:\s|/(?!>))*') + +locatestarttagend = re.compile(r""" + <[a-zA-Z][^\t\n\r\f />\x00]* # tag name + (?:[\s/]* # optional whitespace before attribute name + (?:(?<=['"\s/])[^\s/>][^\s/=>]* # attribute name + (?:\s*=+\s* # value indicator + (?:'[^']*' # LITA-enclosed value + |"[^"]*" # LIT-enclosed value + |(?!['"])[^>\s]* # bare value + ) + )?(?:\s|/(?!>))* + )* + )? + \s* # trailing whitespace +""", re.VERBOSE) +endendtag = re.compile('>') +# the HTML 5 spec, section 8.1.2.2, doesn't allow spaces between +# ') + + +class HTMLParseError(Exception): + """Exception raised for all parse errors.""" + + def __init__(self, msg, position=(None, None)): + assert msg + self.msg = msg + self.lineno = position[0] + self.offset = position[1] + + def __str__(self): + result = self.msg + if self.lineno is not None: + result = result + ", at line %d" % self.lineno + if self.offset is not None: + result = result + ", column %d" % (self.offset + 1) + return result + + +class HTMLParser(markupbase.ParserBase): + """Find tags and other markup and call handler functions. + + Usage: + p = HTMLParser() + p.feed(data) + ... + p.close() + + Start tags are handled by calling self.handle_starttag() or + self.handle_startendtag(); end tags by self.handle_endtag(). The + data between tags is passed from the parser to the derived class + by calling self.handle_data() with the data as argument (the data + may be split up in arbitrary chunks). Entity references are + passed by calling self.handle_entityref() with the entity + reference as the argument. Numeric character references are + passed to self.handle_charref() with the string containing the + reference as the argument. + """ + + CDATA_CONTENT_ELEMENTS = ("script", "style") + + + def __init__(self): + """Initialize and reset this instance.""" + self.reset() + + def reset(self): + """Reset this instance. Loses all unprocessed data.""" + self.rawdata = '' + self.lasttag = '???' + self.interesting = interesting_normal + self.cdata_elem = None + markupbase.ParserBase.reset(self) + + def feed(self, data): + r"""Feed data to the parser. + + Call this as often as you want, with as little or as much text + as you want (may include '\n'). + """ + self.rawdata = self.rawdata + data + self.goahead(0) + + def close(self): + """Handle any buffered data.""" + self.goahead(1) + + def error(self, message): + raise HTMLParseError(message, self.getpos()) + + __starttag_text = None + + def get_starttag_text(self): + """Return full source of start tag: '<...>'.""" + return self.__starttag_text + + def set_cdata_mode(self, elem): + self.cdata_elem = elem.lower() + self.interesting = re.compile(r'' % self.cdata_elem, re.I) + + def clear_cdata_mode(self): + self.interesting = interesting_normal + self.cdata_elem = None + + # Internal -- handle data as far as reasonable. May leave state + # and data to be processed by a subsequent call. If 'end' is + # true, force handling all data as if followed by EOF marker. + def goahead(self, end): + rawdata = self.rawdata + i = 0 + n = len(rawdata) + while i < n: + match = self.interesting.search(rawdata, i) # < or & + if match: + j = match.start() + else: + if self.cdata_elem: + break + j = n + if i < j: self.handle_data(rawdata[i:j]) + i = self.updatepos(i, j) + if i == n: break + startswith = rawdata.startswith + if startswith('<', i): + if starttagopen.match(rawdata, i): # < + letter + k = self.parse_starttag(i) + elif startswith("', i + 1) + if k < 0: + k = rawdata.find('<', i + 1) + if k < 0: + k = i + 1 + else: + k += 1 + self.handle_data(rawdata[i:k]) + i = self.updatepos(i, k) + elif startswith("&#", i): + match = charref.match(rawdata, i) + if match: + name = match.group()[2:-1] + self.handle_charref(name) + k = match.end() + if not startswith(';', k-1): + k = k - 1 + i = self.updatepos(i, k) + continue + else: + if ";" in rawdata[i:]: # bail by consuming '&#' + self.handle_data(rawdata[i:i+2]) + i = self.updatepos(i, i+2) + break + elif startswith('&', i): + match = entityref.match(rawdata, i) + if match: + name = match.group(1) + self.handle_entityref(name) + k = match.end() + if not startswith(';', k-1): + k = k - 1 + i = self.updatepos(i, k) + continue + match = incomplete.match(rawdata, i) + if match: + # match.group() will contain at least 2 chars + if end and match.group() == rawdata[i:]: + self.error("EOF in middle of entity or char ref") + # incomplete + break + elif (i + 1) < n: + # not the end of the buffer, and can't be confused + # with some other construct + self.handle_data("&") + i = self.updatepos(i, i + 1) + else: + break + else: + assert 0, "interesting.search() lied" + # end while + if end and i < n and not self.cdata_elem: + self.handle_data(rawdata[i:n]) + i = self.updatepos(i, n) + self.rawdata = rawdata[i:] + + # Internal -- parse html declarations, return length or -1 if not terminated + # See w3.org/TR/html5/tokenization.html#markup-declaration-open-state + # See also parse_declaration in _markupbase + def parse_html_declaration(self, i): + rawdata = self.rawdata + if rawdata[i:i+2] != ' + gtpos = rawdata.find('>', i+9) + if gtpos == -1: + return -1 + self.handle_decl(rawdata[i+2:gtpos]) + return gtpos+1 + else: + return self.parse_bogus_comment(i) + + # Internal -- parse bogus comment, return length or -1 if not terminated + # see http://www.w3.org/TR/html5/tokenization.html#bogus-comment-state + def parse_bogus_comment(self, i, report=1): + rawdata = self.rawdata + if rawdata[i:i+2] not in ('', i+2) + if pos == -1: + return -1 + if report: + self.handle_comment(rawdata[i+2:pos]) + return pos + 1 + + # Internal -- parse processing instr, return end or -1 if not terminated + def parse_pi(self, i): + rawdata = self.rawdata + assert rawdata[i:i+2] == ' + if not match: + return -1 + j = match.start() + self.handle_pi(rawdata[i+2: j]) + j = match.end() + return j + + # Internal -- handle starttag, return end or -1 if not terminated + def parse_starttag(self, i): + self.__starttag_text = None + endpos = self.check_for_whole_start_tag(i) + if endpos < 0: + return endpos + rawdata = self.rawdata + self.__starttag_text = rawdata[i:endpos] + + # Now parse the data between i+1 and j into a tag and attrs + attrs = [] + match = tagfind.match(rawdata, i+1) + assert match, 'unexpected call to parse_starttag()' + k = match.end() + self.lasttag = tag = match.group(1).lower() + + while k < endpos: + m = attrfind.match(rawdata, k) + if not m: + break + attrname, rest, attrvalue = m.group(1, 2, 3) + if not rest: + attrvalue = None + elif attrvalue[:1] == '\'' == attrvalue[-1:] or \ + attrvalue[:1] == '"' == attrvalue[-1:]: + attrvalue = attrvalue[1:-1] + if attrvalue: + attrvalue = self.unescape(attrvalue) + attrs.append((attrname.lower(), attrvalue)) + k = m.end() + + end = rawdata[k:endpos].strip() + if end not in (">", "/>"): + lineno, offset = self.getpos() + if "\n" in self.__starttag_text: + lineno = lineno + self.__starttag_text.count("\n") + offset = len(self.__starttag_text) \ + - self.__starttag_text.rfind("\n") + else: + offset = offset + len(self.__starttag_text) + self.handle_data(rawdata[i:endpos]) + return endpos + if end.endswith('/>'): + # XHTML-style empty tag: + self.handle_startendtag(tag, attrs) + else: + self.handle_starttag(tag, attrs) + if tag in self.CDATA_CONTENT_ELEMENTS: + self.set_cdata_mode(tag) + return endpos + + # Internal -- check to see if we have a complete starttag; return end + # or -1 if incomplete. + def check_for_whole_start_tag(self, i): + rawdata = self.rawdata + m = locatestarttagend.match(rawdata, i) + if m: + j = m.end() + next = rawdata[j:j+1] + if next == ">": + return j + 1 + if next == "/": + if rawdata.startswith("/>", j): + return j + 2 + if rawdata.startswith("/", j): + # buffer boundary + return -1 + # else bogus input + self.updatepos(i, j + 1) + self.error("malformed empty start tag") + if next == "": + # end of input + return -1 + if next in ("abcdefghijklmnopqrstuvwxyz=/" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"): + # end of input in or before attribute value, or we have the + # '/' from a '/>' ending + return -1 + if j > i: + return j + else: + return i + 1 + raise AssertionError("we should not get here!") + + # Internal -- parse endtag, return end or -1 if incomplete + def parse_endtag(self, i): + rawdata = self.rawdata + assert rawdata[i:i+2] == " + if not match: + return -1 + gtpos = match.end() + match = endtagfind.match(rawdata, i) # + if not match: + if self.cdata_elem is not None: + self.handle_data(rawdata[i:gtpos]) + return gtpos + # find the name: w3.org/TR/html5/tokenization.html#tag-name-state + namematch = tagfind.match(rawdata, i+2) + if not namematch: + # w3.org/TR/html5/tokenization.html#end-tag-open-state + if rawdata[i:i+3] == '': + return i+3 + else: + return self.parse_bogus_comment(i) + tagname = namematch.group(1).lower() + # consume and ignore other stuff between the name and the > + # Note: this is not 100% correct, since we might have things like + # , but looking for > after tha name should cover + # most of the cases and is much simpler + gtpos = rawdata.find('>', namematch.end()) + self.handle_endtag(tagname) + return gtpos+1 + + elem = match.group(1).lower() # script or style + if self.cdata_elem is not None: + if elem != self.cdata_elem: + self.handle_data(rawdata[i:gtpos]) + return gtpos + + self.handle_endtag(elem) + self.clear_cdata_mode() + return gtpos + + # Overridable -- finish processing of start+end tag: + def handle_startendtag(self, tag, attrs): + self.handle_starttag(tag, attrs) + self.handle_endtag(tag) + + # Overridable -- handle start tag + def handle_starttag(self, tag, attrs): + pass + + # Overridable -- handle end tag + def handle_endtag(self, tag): + pass + + # Overridable -- handle character reference + def handle_charref(self, name): + pass + + # Overridable -- handle entity reference + def handle_entityref(self, name): + pass + + # Overridable -- handle data + def handle_data(self, data): + pass + + # Overridable -- handle comment + def handle_comment(self, data): + pass + + # Overridable -- handle declaration + def handle_decl(self, decl): + pass + + # Overridable -- handle processing instruction + def handle_pi(self, data): + pass + + def unknown_decl(self, data): + pass + + # Internal -- helper to remove special character quoting + entitydefs = None + def unescape(self, s): + if '&' not in s: + return s + def replaceEntities(s): + s = s.groups()[0] + try: + if s[0] == "#": + s = s[1:] + if s[0] in ['x','X']: + c = int(s[1:], 16) + else: + c = int(s) + return unichr(c) + except ValueError: + return '&#'+s+';' + else: + # Cannot use name2codepoint directly, because HTMLParser supports apos, + # which is not part of HTML 4 + import htmlentitydefs + if HTMLParser.entitydefs is None: + entitydefs = HTMLParser.entitydefs = {'apos':u"'"} + for k, v in htmlentitydefs.name2codepoint.iteritems(): + entitydefs[k] = unichr(v) + try: + return self.entitydefs[s] + except KeyError: + return '&'+s+';' + + return re.sub(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));", replaceEntities, s) diff --git a/PythonHome/Lib/HTMLParser.pyc b/PythonHome/Lib/HTMLParser.pyc index c0243f6407e4492669a96b07abd801c7bc0cd24c..89e9876de69bc3c8ecc07e75c1213d813f5fbdd0 100644 GIT binary patch delta 1843 zcmZq6I##sd538X)0|P^On82Uo>#EHUr>N^jDKlKL1{^hOKMVSdQ3oN zNk)F2M}BVVW^Oh%M$)xSR$y-@L)S%K;ms%67qXD4wTH)y47YB+$V-m4$zuG|$#7?^ zfcWIg{MBUX+(3pd8Nr8S=;9HYM24=lLbi--n_mm4Zet=->jIfNGU9$R z$W{kAe=@aB-YBmD^zkkEc5;(!vr03$KGsnGK&IBoR$AmFC16-h=Ftu%FM=jFYx|L@ z^E25xlXb|o^D@~wops5zbF*#`nIWXEN3NaI$cC%qf zf!vlLy^RU0M3h_|rlUbRWEA|dN=#m_sKLmx`G#UUM$k+K>07MUjNPUz%@0^5CePEs z^fu6>$&++Lu{n9Nww@nW@x3_2{q?b{e~3f8*Z{kFR>L5y_RcoMu3py&LwxfZqqCTS cu*!5ZR)ZIsy}~Mf-uwrKxGtOcWPVF?0NymqYybcN diff --git a/PythonHome/Lib/MimeWriter.pyc b/PythonHome/Lib/MimeWriter.py similarity index 58% rename from PythonHome/Lib/MimeWriter.pyc rename to PythonHome/Lib/MimeWriter.py index e75342cbcc4b89091dcfab109f717adad0ece44f..e898f9ff231793672ae281c770666be8953be6ec 100644 GIT binary patch delta 1807 zcma)7!EVz)5LMetWhxM&65_U6sfwc}ChZ9Y5LqQ;<9+GI~#Or2@v$l3OwBeE; z;8w(UfO_D>PjKKrxN&4=ZLjULNX;Q@uV-f8yf-uZ^U1HnElTP4FJCv_!RmRQm}jXn zWG?31q-ml(kFhXG7$XBRq{py*qJ-g!j-Bm!sHBjmU|K!}_~6saqs?b8XvZUKzayS0 zJ`IgXOh{oE^EFT64vDjN-yMWo z0gE%h9A|60Gag1Ceu~4U4Hv zFAz{oJp*v$>pp2c z9Z9mM2P3+tN3=!uh+hk`mPgeN^m!@`?@H5s5145ukLM8Qy|Lzf`F88U3e#xPx7G`a zn}w3jrV`1rHD4q~WKG)iVv-X#Nf$B-)pGDUmH**!$JH6OYHwF<-XLrl2WWDSK&~5p z!E~0UnzQm_tr6(Hm=5x{WHTDj34Lm;c~^+DQ|cRnhL1@O3^Ivy;4-%{Yi_EeJCn(bU0g z+dQz|e?R*C309}w?ZI@rcF@A5gjWMrHeOi+(qe2L3dvY2Z;#@BGhCYh|5$b1c>e$z C5(CBn delta 2588 zcmb7GO>Y}j6uoc8-$|N~G)X_AVg-sURS5zKglGe(%_57`mBy7KLds;~87JdT#?HKF znn;cYDP4AhBJ~e+$p*-p4L^Ye`~p@i*>nfz-m#q^(TYZ$>-#?DzH`q#_f3EO@aIob z`>%=0PaE5fCJp{_`27Npj$nMEO;|;~MUkRSI5zFVv4)d2ZQ2yr)XtHgqaaUyo=$91 z*yoqXFVIt>6QVCS3ltQ|FVbU+lD*;ErCHi6Q;Z`lYShYn>~lr*qy1c63;)Jn-Bd7n zKim&ClF$T+zKh}MpXzQJTJZjbnwPW-696@k!U{|v07jeuOizJbkn&`nc5yNw1Eobk z=vRg_MS6x1eC{!dIhekpJ`wQX5OxGn zqlWaTUgO=yhH+b6gFxi&1)h)mvXvZWbP%-+?`w5yup~y$z+2v04|ldkq@>Am_b3bE zhH+?IcMF>|#~@W!A^$dcRK&x-0`WIEeT&*s-V;T~IXYaRevXnQwxH|k_{d#3n5K=v z^13YByqvkIO)CcNQY(Rv%ka zsbn1@fJe0{Oi~|k!5JzJ3`1MtnqI1W1 zzMpAl8v}g>hRT!bGL6Zzpcd5HjJl)>YR+o%0sJs(Q9%_B6N`T$*S5uVQv=CL`!qz7 z`XzRrZeMzt)@z)T!(pU3pKxOeej!5yE@}S{{No7Hih6o)p#C1lnQ%)pN~$EnWm35= z3^~<1u!l7k@9Lu}ZCNZ`NQ^au97JU;i{|E!6&)05BTEl@<_(Yz^k*r>vk)lgU=MwO z8$vWY7&mGngzu526PR8S>#A36g;8+&$Mo&9TT?qw6<YED(ulxi}7;ltGG&tX7ocaqGI9==!lYuF(r%6Q{m)4d&L&bbcX;XdH-X-3xTxtiv;nX3^_ zCha?(Ey2*lteOC6qxP{eCxqRC!(0ekOb;B~Szu_M+X%yX@RsesL_=CfLwI!d)m$4A z;z*UHrHd+IZ8-b^ac;n5X}itH)7o|4sJR$=92^?v{RRB2u`1Wk^Z0m_$lF+dO(H1o zps>%d@pS#lvvcSiV`-^!;aWIH|HgQcrr`a7@$xN2g}Qui2j4et0oTR7lR}s7e#h@c zJm&JduHR|8uEUDH&}u9c>7IHg4xB14F0y$CMpSWbUe!wuwh~uFPr(#c3syOoj?b3I zCf}N#E>8@g?R#O23h~|=-we)sY!+Y!@VqDjRIbVsFNwo=R|_s47*^nFfDb~`Ghrv* z$TrBq&bu7qG8=p%mf5)X!>@<`Ba#?Ad7g)OuS!M$+{u{xjB#d3+2dB(!lNqI%!_gL E580s8TL1t6 diff --git a/PythonHome/Lib/Queue.py b/PythonHome/Lib/Queue.py new file mode 100644 index 0000000000..00364b39be --- /dev/null +++ b/PythonHome/Lib/Queue.py @@ -0,0 +1,244 @@ +"""A multi-producer, multi-consumer queue.""" + +from time import time as _time +try: + import threading as _threading +except ImportError: + import dummy_threading as _threading +from collections import deque +import heapq + +__all__ = ['Empty', 'Full', 'Queue', 'PriorityQueue', 'LifoQueue'] + +class Empty(Exception): + "Exception raised by Queue.get(block=0)/get_nowait()." + pass + +class Full(Exception): + "Exception raised by Queue.put(block=0)/put_nowait()." + pass + +class Queue: + """Create a queue object with a given maximum size. + + If maxsize is <= 0, the queue size is infinite. + """ + def __init__(self, maxsize=0): + self.maxsize = maxsize + self._init(maxsize) + # mutex must be held whenever the queue is mutating. All methods + # that acquire mutex must release it before returning. mutex + # is shared between the three conditions, so acquiring and + # releasing the conditions also acquires and releases mutex. + self.mutex = _threading.Lock() + # Notify not_empty whenever an item is added to the queue; a + # thread waiting to get is notified then. + self.not_empty = _threading.Condition(self.mutex) + # Notify not_full whenever an item is removed from the queue; + # a thread waiting to put is notified then. + self.not_full = _threading.Condition(self.mutex) + # Notify all_tasks_done whenever the number of unfinished tasks + # drops to zero; thread waiting to join() is notified to resume + self.all_tasks_done = _threading.Condition(self.mutex) + self.unfinished_tasks = 0 + + def task_done(self): + """Indicate that a formerly enqueued task is complete. + + Used by Queue consumer threads. For each get() used to fetch a task, + a subsequent call to task_done() tells the queue that the processing + on the task is complete. + + If a join() is currently blocking, it will resume when all items + have been processed (meaning that a task_done() call was received + for every item that had been put() into the queue). + + Raises a ValueError if called more times than there were items + placed in the queue. + """ + self.all_tasks_done.acquire() + try: + unfinished = self.unfinished_tasks - 1 + if unfinished <= 0: + if unfinished < 0: + raise ValueError('task_done() called too many times') + self.all_tasks_done.notify_all() + self.unfinished_tasks = unfinished + finally: + self.all_tasks_done.release() + + def join(self): + """Blocks until all items in the Queue have been gotten and processed. + + The count of unfinished tasks goes up whenever an item is added to the + queue. The count goes down whenever a consumer thread calls task_done() + to indicate the item was retrieved and all work on it is complete. + + When the count of unfinished tasks drops to zero, join() unblocks. + """ + self.all_tasks_done.acquire() + try: + while self.unfinished_tasks: + self.all_tasks_done.wait() + finally: + self.all_tasks_done.release() + + def qsize(self): + """Return the approximate size of the queue (not reliable!).""" + self.mutex.acquire() + n = self._qsize() + self.mutex.release() + return n + + def empty(self): + """Return True if the queue is empty, False otherwise (not reliable!).""" + self.mutex.acquire() + n = not self._qsize() + self.mutex.release() + return n + + def full(self): + """Return True if the queue is full, False otherwise (not reliable!).""" + self.mutex.acquire() + n = 0 < self.maxsize == self._qsize() + self.mutex.release() + return n + + def put(self, item, block=True, timeout=None): + """Put an item into the queue. + + If optional args 'block' is true and 'timeout' is None (the default), + block if necessary until a free slot is available. If 'timeout' is + a non-negative number, it blocks at most 'timeout' seconds and raises + the Full exception if no free slot was available within that time. + Otherwise ('block' is false), put an item on the queue if a free slot + is immediately available, else raise the Full exception ('timeout' + is ignored in that case). + """ + self.not_full.acquire() + try: + if self.maxsize > 0: + if not block: + if self._qsize() == self.maxsize: + raise Full + elif timeout is None: + while self._qsize() == self.maxsize: + self.not_full.wait() + elif timeout < 0: + raise ValueError("'timeout' must be a non-negative number") + else: + endtime = _time() + timeout + while self._qsize() == self.maxsize: + remaining = endtime - _time() + if remaining <= 0.0: + raise Full + self.not_full.wait(remaining) + self._put(item) + self.unfinished_tasks += 1 + self.not_empty.notify() + finally: + self.not_full.release() + + def put_nowait(self, item): + """Put an item into the queue without blocking. + + Only enqueue the item if a free slot is immediately available. + Otherwise raise the Full exception. + """ + return self.put(item, False) + + def get(self, block=True, timeout=None): + """Remove and return an item from the queue. + + If optional args 'block' is true and 'timeout' is None (the default), + block if necessary until an item is available. If 'timeout' is + a non-negative number, it blocks at most 'timeout' seconds and raises + the Empty exception if no item was available within that time. + Otherwise ('block' is false), return an item if one is immediately + available, else raise the Empty exception ('timeout' is ignored + in that case). + """ + self.not_empty.acquire() + try: + if not block: + if not self._qsize(): + raise Empty + elif timeout is None: + while not self._qsize(): + self.not_empty.wait() + elif timeout < 0: + raise ValueError("'timeout' must be a non-negative number") + else: + endtime = _time() + timeout + while not self._qsize(): + remaining = endtime - _time() + if remaining <= 0.0: + raise Empty + self.not_empty.wait(remaining) + item = self._get() + self.not_full.notify() + return item + finally: + self.not_empty.release() + + def get_nowait(self): + """Remove and return an item from the queue without blocking. + + Only get an item if one is immediately available. Otherwise + raise the Empty exception. + """ + return self.get(False) + + # Override these methods to implement other queue organizations + # (e.g. stack or priority queue). + # These will only be called with appropriate locks held + + # Initialize the queue representation + def _init(self, maxsize): + self.queue = deque() + + def _qsize(self, len=len): + return len(self.queue) + + # Put a new item in the queue + def _put(self, item): + self.queue.append(item) + + # Get an item from the queue + def _get(self): + return self.queue.popleft() + + +class PriorityQueue(Queue): + '''Variant of Queue that retrieves open entries in priority order (lowest first). + + Entries are typically tuples of the form: (priority number, data). + ''' + + def _init(self, maxsize): + self.queue = [] + + def _qsize(self, len=len): + return len(self.queue) + + def _put(self, item, heappush=heapq.heappush): + heappush(self.queue, item) + + def _get(self, heappop=heapq.heappop): + return heappop(self.queue) + + +class LifoQueue(Queue): + '''Variant of Queue that retrieves most recently added entries first.''' + + def _init(self, maxsize): + self.queue = [] + + def _qsize(self, len=len): + return len(self.queue) + + def _put(self, item): + self.queue.append(item) + + def _get(self): + return self.queue.pop() diff --git a/PythonHome/Lib/Queue.pyc b/PythonHome/Lib/Queue.pyc index f6b46ceb4833c7d58444a8157eff7795d4c2bf08..2969ba64ee155635c58188074de957e520eb1f0f 100644 GIT binary patch delta 1529 zcmX@&@yCCI36r4}0|P^On82Uo>#EHUr>N^jDKlKL1{^hOKMVSdQ3oN zNk)F2M}BVVWM`(Or0d%JovDiq%QjD7?O`UvHf_!jGHjdN$Nh|S%O*GTyd+)M=4xIp zMl!Tb;j3mLLz|qiKRLG5i2Nic_**2L$gpklRmn!uy*4>jDwhmh52b3z(3K-yNQSOA z(z8j|wRxIMGdY2%A(utEWs?`m)sdk~PoA9MSSO!Hx?P*K6*$QW4rfJjf@6i{42!_hZ z7Cg_;6;Af&eTgo%Ig^iz5kqhZe>Dq+V1S4}rpgPVKQSHjOVSBL<>XxHMsy=5%gf|q zi0zfB!4S)mEyNJxk(-S!w)uu!Gp5Bo3R&n1C#x&gVTfH*#I&SBDGy!UW^rXsOiKb) fFfDnbQiiU1@?=#^9~-JgVW``qb_qjlzq%~|*&v{$ diff --git a/PythonHome/Lib/SimpleHTTPServer.py b/PythonHome/Lib/SimpleHTTPServer.py new file mode 100644 index 0000000000..d497e1e8cc --- /dev/null +++ b/PythonHome/Lib/SimpleHTTPServer.py @@ -0,0 +1,230 @@ +"""Simple HTTP Server. + +This module builds on BaseHTTPServer by implementing the standard GET +and HEAD requests in a fairly straightforward manner. + +""" + + +__version__ = "0.6" + +__all__ = ["SimpleHTTPRequestHandler"] + +import os +import posixpath +import BaseHTTPServer +import urllib +import cgi +import sys +import shutil +import mimetypes +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + + +class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): + + """Simple HTTP request handler with GET and HEAD commands. + + This serves files from the current directory and any of its + subdirectories. The MIME type for files is determined by + calling the .guess_type() method. + + The GET and HEAD requests are identical except that the HEAD + request omits the actual contents of the file. + + """ + + server_version = "SimpleHTTP/" + __version__ + + def do_GET(self): + """Serve a GET request.""" + f = self.send_head() + if f: + try: + self.copyfile(f, self.wfile) + finally: + f.close() + + def do_HEAD(self): + """Serve a HEAD request.""" + f = self.send_head() + if f: + f.close() + + def send_head(self): + """Common code for GET and HEAD commands. + + This sends the response code and MIME headers. + + Return value is either a file object (which has to be copied + to the outputfile by the caller unless the command was HEAD, + and must be closed by the caller under all circumstances), or + None, in which case the caller has nothing further to do. + + """ + path = self.translate_path(self.path) + f = None + if os.path.isdir(path): + if not self.path.endswith('/'): + # redirect browser - doing basically what apache does + self.send_response(301) + self.send_header("Location", self.path + "/") + self.end_headers() + return None + for index in "index.html", "index.htm": + index = os.path.join(path, index) + if os.path.exists(index): + path = index + break + else: + return self.list_directory(path) + ctype = self.guess_type(path) + try: + # Always read in binary mode. Opening files in text mode may cause + # newline translations, making the actual size of the content + # transmitted *less* than the content-length! + f = open(path, 'rb') + except IOError: + self.send_error(404, "File not found") + return None + try: + self.send_response(200) + self.send_header("Content-type", ctype) + fs = os.fstat(f.fileno()) + self.send_header("Content-Length", str(fs[6])) + self.send_header("Last-Modified", self.date_time_string(fs.st_mtime)) + self.end_headers() + return f + except: + f.close() + raise + + def list_directory(self, path): + """Helper to produce a directory listing (absent index.html). + + Return value is either a file object, or None (indicating an + error). In either case, the headers are sent, making the + interface the same as for send_head(). + + """ + try: + list = os.listdir(path) + except os.error: + self.send_error(404, "No permission to list directory") + return None + list.sort(key=lambda a: a.lower()) + f = StringIO() + displaypath = cgi.escape(urllib.unquote(self.path)) + f.write('') + f.write("\nDirectory listing for %s\n" % displaypath) + f.write("\n

Directory listing for %s

\n" % displaypath) + f.write("
\n
    \n") + for name in list: + fullname = os.path.join(path, name) + displayname = linkname = name + # Append / for directories or @ for symbolic links + if os.path.isdir(fullname): + displayname = name + "/" + linkname = name + "/" + if os.path.islink(fullname): + displayname = name + "@" + # Note: a link to a directory displays with @ and links with / + f.write('
  • %s\n' + % (urllib.quote(linkname), cgi.escape(displayname))) + f.write("
\n
\n\n\n") + length = f.tell() + f.seek(0) + self.send_response(200) + encoding = sys.getfilesystemencoding() + self.send_header("Content-type", "text/html; charset=%s" % encoding) + self.send_header("Content-Length", str(length)) + self.end_headers() + return f + + def translate_path(self, path): + """Translate a /-separated PATH to the local filename syntax. + + Components that mean special things to the local file system + (e.g. drive or directory names) are ignored. (XXX They should + probably be diagnosed.) + + """ + # abandon query parameters + path = path.split('?',1)[0] + path = path.split('#',1)[0] + # Don't forget explicit trailing slash when normalizing. Issue17324 + trailing_slash = path.rstrip().endswith('/') + path = posixpath.normpath(urllib.unquote(path)) + words = path.split('/') + words = filter(None, words) + path = os.getcwd() + for word in words: + drive, word = os.path.splitdrive(word) + head, word = os.path.split(word) + if word in (os.curdir, os.pardir): continue + path = os.path.join(path, word) + if trailing_slash: + path += '/' + return path + + def copyfile(self, source, outputfile): + """Copy all data between two file objects. + + The SOURCE argument is a file object open for reading + (or anything with a read() method) and the DESTINATION + argument is a file object open for writing (or + anything with a write() method). + + The only reason for overriding this would be to change + the block size or perhaps to replace newlines by CRLF + -- note however that this the default server uses this + to copy binary data as well. + + """ + shutil.copyfileobj(source, outputfile) + + def guess_type(self, path): + """Guess the type of a file. + + Argument is a PATH (a filename). + + Return value is a string of the form type/subtype, + usable for a MIME Content-type header. + + The default implementation looks the file's extension + up in the table self.extensions_map, using application/octet-stream + as a default; however it would be permissible (if + slow) to look inside the data to make a better guess. + + """ + + base, ext = posixpath.splitext(path) + if ext in self.extensions_map: + return self.extensions_map[ext] + ext = ext.lower() + if ext in self.extensions_map: + return self.extensions_map[ext] + else: + return self.extensions_map[''] + + if not mimetypes.inited: + mimetypes.init() # try to read system mime.types + extensions_map = mimetypes.types_map.copy() + extensions_map.update({ + '': 'application/octet-stream', # Default + '.py': 'text/plain', + '.c': 'text/plain', + '.h': 'text/plain', + }) + + +def test(HandlerClass = SimpleHTTPRequestHandler, + ServerClass = BaseHTTPServer.HTTPServer): + BaseHTTPServer.test(HandlerClass, ServerClass) + + +if __name__ == '__main__': + test() diff --git a/PythonHome/Lib/SimpleHTTPServer.pyc b/PythonHome/Lib/SimpleHTTPServer.pyc deleted file mode 100644 index 39f179b1efe8bf529709e74c1baa343f56b37d1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7701 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 5" + elif method == 'pow': + return "pow(x, y[, z]) => number" + else: + # By convention, return empty + # string if no help is available + return "" + def _dispatch(self, method, params): + if method == 'pow': + return pow(*params) + elif method == 'add': + return params[0] + params[1] + else: + raise 'bad method' + +server = SimpleXMLRPCServer(("localhost", 8000)) +server.register_introspection_functions() +server.register_instance(Math()) +server.serve_forever() + +4. Subclass SimpleXMLRPCServer: + +class MathServer(SimpleXMLRPCServer): + def _dispatch(self, method, params): + try: + # We are forcing the 'export_' prefix on methods that are + # callable through XML-RPC to prevent potential security + # problems + func = getattr(self, 'export_' + method) + except AttributeError: + raise Exception('method "%s" is not supported' % method) + else: + return func(*params) + + def export_add(self, x, y): + return x + y + +server = MathServer(("localhost", 8000)) +server.serve_forever() + +5. CGI script: + +server = CGIXMLRPCRequestHandler() +server.register_function(pow) +server.handle_request() +""" + +# Written by Brian Quinlan (brian@sweetapp.com). +# Based on code written by Fredrik Lundh. + +import xmlrpclib +from xmlrpclib import Fault +import SocketServer +import BaseHTTPServer +import sys +import os +import traceback +import re +try: + import fcntl +except ImportError: + fcntl = None + +def resolve_dotted_attribute(obj, attr, allow_dotted_names=True): + """resolve_dotted_attribute(a, 'b.c.d') => a.b.c.d + + Resolves a dotted attribute name to an object. Raises + an AttributeError if any attribute in the chain starts with a '_'. + + If the optional allow_dotted_names argument is false, dots are not + supported and this function operates similar to getattr(obj, attr). + """ + + if allow_dotted_names: + attrs = attr.split('.') + else: + attrs = [attr] + + for i in attrs: + if i.startswith('_'): + raise AttributeError( + 'attempt to access private attribute "%s"' % i + ) + else: + obj = getattr(obj,i) + return obj + +def list_public_methods(obj): + """Returns a list of attribute strings, found in the specified + object, which represent callable attributes""" + + return [member for member in dir(obj) + if not member.startswith('_') and + hasattr(getattr(obj, member), '__call__')] + +def remove_duplicates(lst): + """remove_duplicates([2,2,2,1,3,3]) => [3,1,2] + + Returns a copy of a list without duplicates. Every list + item must be hashable and the order of the items in the + resulting list is not defined. + """ + u = {} + for x in lst: + u[x] = 1 + + return u.keys() + +class SimpleXMLRPCDispatcher: + """Mix-in class that dispatches XML-RPC requests. + + This class is used to register XML-RPC method handlers + and then to dispatch them. This class doesn't need to be + instanced directly when used by SimpleXMLRPCServer but it + can be instanced when used by the MultiPathXMLRPCServer. + """ + + def __init__(self, allow_none=False, encoding=None): + self.funcs = {} + self.instance = None + self.allow_none = allow_none + self.encoding = encoding + + def register_instance(self, instance, allow_dotted_names=False): + """Registers an instance to respond to XML-RPC requests. + + Only one instance can be installed at a time. + + If the registered instance has a _dispatch method then that + method will be called with the name of the XML-RPC method and + its parameters as a tuple + e.g. instance._dispatch('add',(2,3)) + + If the registered instance does not have a _dispatch method + then the instance will be searched to find a matching method + and, if found, will be called. Methods beginning with an '_' + are considered private and will not be called by + SimpleXMLRPCServer. + + If a registered function matches a XML-RPC request, then it + will be called instead of the registered instance. + + If the optional allow_dotted_names argument is true and the + instance does not have a _dispatch method, method names + containing dots are supported and resolved, as long as none of + the name segments start with an '_'. + + *** SECURITY WARNING: *** + + Enabling the allow_dotted_names options allows intruders + to access your module's global variables and may allow + intruders to execute arbitrary code on your machine. Only + use this option on a secure, closed network. + + """ + + self.instance = instance + self.allow_dotted_names = allow_dotted_names + + def register_function(self, function, name = None): + """Registers a function to respond to XML-RPC requests. + + The optional name argument can be used to set a Unicode name + for the function. + """ + + if name is None: + name = function.__name__ + self.funcs[name] = function + + def register_introspection_functions(self): + """Registers the XML-RPC introspection methods in the system + namespace. + + see http://xmlrpc.usefulinc.com/doc/reserved.html + """ + + self.funcs.update({'system.listMethods' : self.system_listMethods, + 'system.methodSignature' : self.system_methodSignature, + 'system.methodHelp' : self.system_methodHelp}) + + def register_multicall_functions(self): + """Registers the XML-RPC multicall method in the system + namespace. + + see http://www.xmlrpc.com/discuss/msgReader$1208""" + + self.funcs.update({'system.multicall' : self.system_multicall}) + + def _marshaled_dispatch(self, data, dispatch_method = None, path = None): + """Dispatches an XML-RPC method from marshalled (XML) data. + + XML-RPC methods are dispatched from the marshalled (XML) data + using the _dispatch method and the result is returned as + marshalled data. For backwards compatibility, a dispatch + function can be provided as an argument (see comment in + SimpleXMLRPCRequestHandler.do_POST) but overriding the + existing method through subclassing is the preferred means + of changing method dispatch behavior. + """ + + try: + params, method = xmlrpclib.loads(data) + + # generate response + if dispatch_method is not None: + response = dispatch_method(method, params) + else: + response = self._dispatch(method, params) + # wrap response in a singleton tuple + response = (response,) + response = xmlrpclib.dumps(response, methodresponse=1, + allow_none=self.allow_none, encoding=self.encoding) + except Fault, fault: + response = xmlrpclib.dumps(fault, allow_none=self.allow_none, + encoding=self.encoding) + except: + # report exception back to server + exc_type, exc_value, exc_tb = sys.exc_info() + response = xmlrpclib.dumps( + xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value)), + encoding=self.encoding, allow_none=self.allow_none, + ) + + return response + + def system_listMethods(self): + """system.listMethods() => ['add', 'subtract', 'multiple'] + + Returns a list of the methods supported by the server.""" + + methods = self.funcs.keys() + if self.instance is not None: + # Instance can implement _listMethod to return a list of + # methods + if hasattr(self.instance, '_listMethods'): + methods = remove_duplicates( + methods + self.instance._listMethods() + ) + # if the instance has a _dispatch method then we + # don't have enough information to provide a list + # of methods + elif not hasattr(self.instance, '_dispatch'): + methods = remove_duplicates( + methods + list_public_methods(self.instance) + ) + methods.sort() + return methods + + def system_methodSignature(self, method_name): + """system.methodSignature('add') => [double, int, int] + + Returns a list describing the signature of the method. In the + above example, the add method takes two integers as arguments + and returns a double result. + + This server does NOT support system.methodSignature.""" + + # See http://xmlrpc.usefulinc.com/doc/sysmethodsig.html + + return 'signatures not supported' + + def system_methodHelp(self, method_name): + """system.methodHelp('add') => "Adds two integers together" + + Returns a string containing documentation for the specified method.""" + + method = None + if method_name in self.funcs: + method = self.funcs[method_name] + elif self.instance is not None: + # Instance can implement _methodHelp to return help for a method + if hasattr(self.instance, '_methodHelp'): + return self.instance._methodHelp(method_name) + # if the instance has a _dispatch method then we + # don't have enough information to provide help + elif not hasattr(self.instance, '_dispatch'): + try: + method = resolve_dotted_attribute( + self.instance, + method_name, + self.allow_dotted_names + ) + except AttributeError: + pass + + # Note that we aren't checking that the method actually + # be a callable object of some kind + if method is None: + return "" + else: + import pydoc + return pydoc.getdoc(method) + + def system_multicall(self, call_list): + """system.multicall([{'methodName': 'add', 'params': [2, 2]}, ...]) => \ +[[4], ...] + + Allows the caller to package multiple XML-RPC calls into a single + request. + + See http://www.xmlrpc.com/discuss/msgReader$1208 + """ + + results = [] + for call in call_list: + method_name = call['methodName'] + params = call['params'] + + try: + # XXX A marshalling error in any response will fail the entire + # multicall. If someone cares they should fix this. + results.append([self._dispatch(method_name, params)]) + except Fault, fault: + results.append( + {'faultCode' : fault.faultCode, + 'faultString' : fault.faultString} + ) + except: + exc_type, exc_value, exc_tb = sys.exc_info() + results.append( + {'faultCode' : 1, + 'faultString' : "%s:%s" % (exc_type, exc_value)} + ) + return results + + def _dispatch(self, method, params): + """Dispatches the XML-RPC method. + + XML-RPC calls are forwarded to a registered function that + matches the called XML-RPC method name. If no such function + exists then the call is forwarded to the registered instance, + if available. + + If the registered instance has a _dispatch method then that + method will be called with the name of the XML-RPC method and + its parameters as a tuple + e.g. instance._dispatch('add',(2,3)) + + If the registered instance does not have a _dispatch method + then the instance will be searched to find a matching method + and, if found, will be called. + + Methods beginning with an '_' are considered private and will + not be called. + """ + + func = None + try: + # check to see if a matching function has been registered + func = self.funcs[method] + except KeyError: + if self.instance is not None: + # check for a _dispatch method + if hasattr(self.instance, '_dispatch'): + return self.instance._dispatch(method, params) + else: + # call instance method directly + try: + func = resolve_dotted_attribute( + self.instance, + method, + self.allow_dotted_names + ) + except AttributeError: + pass + + if func is not None: + return func(*params) + else: + raise Exception('method "%s" is not supported' % method) + +class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): + """Simple XML-RPC request handler class. + + Handles all HTTP POST requests and attempts to decode them as + XML-RPC requests. + """ + + # Class attribute listing the accessible path components; + # paths not on this list will result in a 404 error. + rpc_paths = ('/', '/RPC2') + + #if not None, encode responses larger than this, if possible + encode_threshold = 1400 #a common MTU + + #Override form StreamRequestHandler: full buffering of output + #and no Nagle. + wbufsize = -1 + disable_nagle_algorithm = True + + # a re to match a gzip Accept-Encoding + aepattern = re.compile(r""" + \s* ([^\s;]+) \s* #content-coding + (;\s* q \s*=\s* ([0-9\.]+))? #q + """, re.VERBOSE | re.IGNORECASE) + + def accept_encodings(self): + r = {} + ae = self.headers.get("Accept-Encoding", "") + for e in ae.split(","): + match = self.aepattern.match(e) + if match: + v = match.group(3) + v = float(v) if v else 1.0 + r[match.group(1)] = v + return r + + def is_rpc_path_valid(self): + if self.rpc_paths: + return self.path in self.rpc_paths + else: + # If .rpc_paths is empty, just assume all paths are legal + return True + + def do_POST(self): + """Handles the HTTP POST request. + + Attempts to interpret all HTTP POST requests as XML-RPC calls, + which are forwarded to the server's _dispatch method for handling. + """ + + # Check that the path is legal + if not self.is_rpc_path_valid(): + self.report_404() + return + + try: + # Get arguments by reading body of request. + # We read this in chunks to avoid straining + # socket.read(); around the 10 or 15Mb mark, some platforms + # begin to have problems (bug #792570). + max_chunk_size = 10*1024*1024 + size_remaining = int(self.headers["content-length"]) + L = [] + while size_remaining: + chunk_size = min(size_remaining, max_chunk_size) + chunk = self.rfile.read(chunk_size) + if not chunk: + break + L.append(chunk) + size_remaining -= len(L[-1]) + data = ''.join(L) + + data = self.decode_request_content(data) + if data is None: + return #response has been sent + + # In previous versions of SimpleXMLRPCServer, _dispatch + # could be overridden in this class, instead of in + # SimpleXMLRPCDispatcher. To maintain backwards compatibility, + # check to see if a subclass implements _dispatch and dispatch + # using that method if present. + response = self.server._marshaled_dispatch( + data, getattr(self, '_dispatch', None), self.path + ) + except Exception, e: # This should only happen if the module is buggy + # internal error, report as HTTP server error + self.send_response(500) + + # Send information about the exception if requested + if hasattr(self.server, '_send_traceback_header') and \ + self.server._send_traceback_header: + self.send_header("X-exception", str(e)) + self.send_header("X-traceback", traceback.format_exc()) + + self.send_header("Content-length", "0") + self.end_headers() + else: + # got a valid XML RPC response + self.send_response(200) + self.send_header("Content-type", "text/xml") + if self.encode_threshold is not None: + if len(response) > self.encode_threshold: + q = self.accept_encodings().get("gzip", 0) + if q: + try: + response = xmlrpclib.gzip_encode(response) + self.send_header("Content-Encoding", "gzip") + except NotImplementedError: + pass + self.send_header("Content-length", str(len(response))) + self.end_headers() + self.wfile.write(response) + + def decode_request_content(self, data): + #support gzip encoding of request + encoding = self.headers.get("content-encoding", "identity").lower() + if encoding == "identity": + return data + if encoding == "gzip": + try: + return xmlrpclib.gzip_decode(data) + except NotImplementedError: + self.send_response(501, "encoding %r not supported" % encoding) + except ValueError: + self.send_response(400, "error decoding gzip content") + else: + self.send_response(501, "encoding %r not supported" % encoding) + self.send_header("Content-length", "0") + self.end_headers() + + def report_404 (self): + # Report a 404 error + self.send_response(404) + response = 'No such page' + self.send_header("Content-type", "text/plain") + self.send_header("Content-length", str(len(response))) + self.end_headers() + self.wfile.write(response) + + def log_request(self, code='-', size='-'): + """Selectively log an accepted request.""" + + if self.server.logRequests: + BaseHTTPServer.BaseHTTPRequestHandler.log_request(self, code, size) + +class SimpleXMLRPCServer(SocketServer.TCPServer, + SimpleXMLRPCDispatcher): + """Simple XML-RPC server. + + Simple XML-RPC server that allows functions and a single instance + to be installed to handle requests. The default implementation + attempts to dispatch XML-RPC calls to the functions or instance + installed in the server. Override the _dispatch method inhereted + from SimpleXMLRPCDispatcher to change this behavior. + """ + + allow_reuse_address = True + + # Warning: this is for debugging purposes only! Never set this to True in + # production code, as will be sending out sensitive information (exception + # and stack trace details) when exceptions are raised inside + # SimpleXMLRPCRequestHandler.do_POST + _send_traceback_header = False + + def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler, + logRequests=True, allow_none=False, encoding=None, bind_and_activate=True): + self.logRequests = logRequests + + SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding) + SocketServer.TCPServer.__init__(self, addr, requestHandler, bind_and_activate) + + # [Bug #1222790] If possible, set close-on-exec flag; if a + # method spawns a subprocess, the subprocess shouldn't have + # the listening socket open. + if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'): + flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD) + flags |= fcntl.FD_CLOEXEC + fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags) + +class MultiPathXMLRPCServer(SimpleXMLRPCServer): + """Multipath XML-RPC Server + This specialization of SimpleXMLRPCServer allows the user to create + multiple Dispatcher instances and assign them to different + HTTP request paths. This makes it possible to run two or more + 'virtual XML-RPC servers' at the same port. + Make sure that the requestHandler accepts the paths in question. + """ + def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler, + logRequests=True, allow_none=False, encoding=None, bind_and_activate=True): + + SimpleXMLRPCServer.__init__(self, addr, requestHandler, logRequests, allow_none, + encoding, bind_and_activate) + self.dispatchers = {} + self.allow_none = allow_none + self.encoding = encoding + + def add_dispatcher(self, path, dispatcher): + self.dispatchers[path] = dispatcher + return dispatcher + + def get_dispatcher(self, path): + return self.dispatchers[path] + + def _marshaled_dispatch(self, data, dispatch_method = None, path = None): + try: + response = self.dispatchers[path]._marshaled_dispatch( + data, dispatch_method, path) + except: + # report low level exception back to server + # (each dispatcher should have handled their own + # exceptions) + exc_type, exc_value = sys.exc_info()[:2] + response = xmlrpclib.dumps( + xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value)), + encoding=self.encoding, allow_none=self.allow_none) + return response + +class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher): + """Simple handler for XML-RPC data passed through CGI.""" + + def __init__(self, allow_none=False, encoding=None): + SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding) + + def handle_xmlrpc(self, request_text): + """Handle a single XML-RPC request""" + + response = self._marshaled_dispatch(request_text) + + print 'Content-Type: text/xml' + print 'Content-Length: %d' % len(response) + print + sys.stdout.write(response) + + def handle_get(self): + """Handle a single HTTP GET request. + + Default implementation indicates an error because + XML-RPC uses the POST method. + """ + + code = 400 + message, explain = \ + BaseHTTPServer.BaseHTTPRequestHandler.responses[code] + + response = BaseHTTPServer.DEFAULT_ERROR_MESSAGE % \ + { + 'code' : code, + 'message' : message, + 'explain' : explain + } + print 'Status: %d %s' % (code, message) + print 'Content-Type: %s' % BaseHTTPServer.DEFAULT_ERROR_CONTENT_TYPE + print 'Content-Length: %d' % len(response) + print + sys.stdout.write(response) + + def handle_request(self, request_text = None): + """Handle a single XML-RPC request passed through a CGI post method. + + If no XML data is given then it is read from stdin. The resulting + XML-RPC response is printed to stdout along with the correct HTTP + headers. + """ + + if request_text is None and \ + os.environ.get('REQUEST_METHOD', None) == 'GET': + self.handle_get() + else: + # POST data is normally available through stdin + try: + length = int(os.environ.get('CONTENT_LENGTH', None)) + except (TypeError, ValueError): + length = -1 + if request_text is None: + request_text = sys.stdin.read(length) + + self.handle_xmlrpc(request_text) + +if __name__ == '__main__': + print 'Running XML-RPC server on port 8000' + server = SimpleXMLRPCServer(("localhost", 8000)) + server.register_function(pow) + server.register_function(lambda x,y: x+y, 'add') + server.register_multicall_functions() + server.serve_forever() diff --git a/PythonHome/Lib/SimpleXMLRPCServer.pyc b/PythonHome/Lib/SimpleXMLRPCServer.pyc deleted file mode 100644 index 30fe3a90274eef0cde7fcea5abbec7a4d784bfb8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22322 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 diff --git a/PythonHome/Lib/SocketServer.py b/PythonHome/Lib/SocketServer.py new file mode 100644 index 0000000000..afb8686f73 --- /dev/null +++ b/PythonHome/Lib/SocketServer.py @@ -0,0 +1,733 @@ +"""Generic socket server classes. + +This module tries to capture the various aspects of defining a server: + +For socket-based servers: + +- address family: + - AF_INET{,6}: IP (Internet Protocol) sockets (default) + - AF_UNIX: Unix domain sockets + - others, e.g. AF_DECNET are conceivable (see +- socket type: + - SOCK_STREAM (reliable stream, e.g. TCP) + - SOCK_DGRAM (datagrams, e.g. UDP) + +For request-based servers (including socket-based): + +- client address verification before further looking at the request + (This is actually a hook for any processing that needs to look + at the request before anything else, e.g. logging) +- how to handle multiple requests: + - synchronous (one request is handled at a time) + - forking (each request is handled by a new process) + - threading (each request is handled by a new thread) + +The classes in this module favor the server type that is simplest to +write: a synchronous TCP/IP server. This is bad class design, but +save some typing. (There's also the issue that a deep class hierarchy +slows down method lookups.) + +There are five classes in an inheritance diagram, four of which represent +synchronous servers of four types: + + +------------+ + | BaseServer | + +------------+ + | + v + +-----------+ +------------------+ + | TCPServer |------->| UnixStreamServer | + +-----------+ +------------------+ + | + v + +-----------+ +--------------------+ + | UDPServer |------->| UnixDatagramServer | + +-----------+ +--------------------+ + +Note that UnixDatagramServer derives from UDPServer, not from +UnixStreamServer -- the only difference between an IP and a Unix +stream server is the address family, which is simply repeated in both +unix server classes. + +Forking and threading versions of each type of server can be created +using the ForkingMixIn and ThreadingMixIn mix-in classes. For +instance, a threading UDP server class is created as follows: + + class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass + +The Mix-in class must come first, since it overrides a method defined +in UDPServer! Setting the various member variables also changes +the behavior of the underlying server mechanism. + +To implement a service, you must derive a class from +BaseRequestHandler and redefine its handle() method. You can then run +various versions of the service by combining one of the server classes +with your request handler class. + +The request handler class must be different for datagram or stream +services. This can be hidden by using the request handler +subclasses StreamRequestHandler or DatagramRequestHandler. + +Of course, you still have to use your head! + +For instance, it makes no sense to use a forking server if the service +contains state in memory that can be modified by requests (since the +modifications in the child process would never reach the initial state +kept in the parent process and passed to each child). In this case, +you can use a threading server, but you will probably have to use +locks to avoid two requests that come in nearly simultaneous to apply +conflicting changes to the server state. + +On the other hand, if you are building e.g. an HTTP server, where all +data is stored externally (e.g. in the file system), a synchronous +class will essentially render the service "deaf" while one request is +being handled -- which may be for a very long time if a client is slow +to read all the data it has requested. Here a threading or forking +server is appropriate. + +In some cases, it may be appropriate to process part of a request +synchronously, but to finish processing in a forked child depending on +the request data. This can be implemented by using a synchronous +server and doing an explicit fork in the request handler class +handle() method. + +Another approach to handling multiple simultaneous requests in an +environment that supports neither threads nor fork (or where these are +too expensive or inappropriate for the service) is to maintain an +explicit table of partially finished requests and to use select() to +decide which request to work on next (or whether to handle a new +incoming request). This is particularly important for stream services +where each client can potentially be connected for a long time (if +threads or subprocesses cannot be used). + +Future work: +- Standard classes for Sun RPC (which uses either UDP or TCP) +- Standard mix-in classes to implement various authentication + and encryption schemes +- Standard framework for select-based multiplexing + +XXX Open problems: +- What to do with out-of-band data? + +BaseServer: +- split generic "request" functionality out into BaseServer class. + Copyright (C) 2000 Luke Kenneth Casson Leighton + + example: read entries from a SQL database (requires overriding + get_request() to return a table entry from the database). + entry is processed by a RequestHandlerClass. + +""" + +# Author of the BaseServer patch: Luke Kenneth Casson Leighton + +# XXX Warning! +# There is a test suite for this module, but it cannot be run by the +# standard regression test. +# To run it manually, run Lib/test/test_socketserver.py. + +__version__ = "0.4" + + +import socket +import select +import sys +import os +import errno +try: + import threading +except ImportError: + import dummy_threading as threading + +__all__ = ["TCPServer","UDPServer","ForkingUDPServer","ForkingTCPServer", + "ThreadingUDPServer","ThreadingTCPServer","BaseRequestHandler", + "StreamRequestHandler","DatagramRequestHandler", + "ThreadingMixIn", "ForkingMixIn"] +if hasattr(socket, "AF_UNIX"): + __all__.extend(["UnixStreamServer","UnixDatagramServer", + "ThreadingUnixStreamServer", + "ThreadingUnixDatagramServer"]) + +def _eintr_retry(func, *args): + """restart a system call interrupted by EINTR""" + while True: + try: + return func(*args) + except (OSError, select.error) as e: + if e.args[0] != errno.EINTR: + raise + +class BaseServer: + + """Base class for server classes. + + Methods for the caller: + + - __init__(server_address, RequestHandlerClass) + - serve_forever(poll_interval=0.5) + - shutdown() + - handle_request() # if you do not use serve_forever() + - fileno() -> int # for select() + + Methods that may be overridden: + + - server_bind() + - server_activate() + - get_request() -> request, client_address + - handle_timeout() + - verify_request(request, client_address) + - server_close() + - process_request(request, client_address) + - shutdown_request(request) + - close_request(request) + - handle_error() + + Methods for derived classes: + + - finish_request(request, client_address) + + Class variables that may be overridden by derived classes or + instances: + + - timeout + - address_family + - socket_type + - allow_reuse_address + + Instance variables: + + - RequestHandlerClass + - socket + + """ + + timeout = None + + def __init__(self, server_address, RequestHandlerClass): + """Constructor. May be extended, do not override.""" + self.server_address = server_address + self.RequestHandlerClass = RequestHandlerClass + self.__is_shut_down = threading.Event() + self.__shutdown_request = False + + def server_activate(self): + """Called by constructor to activate the server. + + May be overridden. + + """ + pass + + def serve_forever(self, poll_interval=0.5): + """Handle one request at a time until shutdown. + + Polls for shutdown every poll_interval seconds. Ignores + self.timeout. If you need to do periodic tasks, do them in + another thread. + """ + self.__is_shut_down.clear() + try: + while not self.__shutdown_request: + # XXX: Consider using another file descriptor or + # connecting to the socket to wake this up instead of + # polling. Polling reduces our responsiveness to a + # shutdown request and wastes cpu at all other times. + r, w, e = _eintr_retry(select.select, [self], [], [], + poll_interval) + if self in r: + self._handle_request_noblock() + finally: + self.__shutdown_request = False + self.__is_shut_down.set() + + def shutdown(self): + """Stops the serve_forever loop. + + Blocks until the loop has finished. This must be called while + serve_forever() is running in another thread, or it will + deadlock. + """ + self.__shutdown_request = True + self.__is_shut_down.wait() + + # The distinction between handling, getting, processing and + # finishing a request is fairly arbitrary. Remember: + # + # - handle_request() is the top-level call. It calls + # select, get_request(), verify_request() and process_request() + # - get_request() is different for stream or datagram sockets + # - process_request() is the place that may fork a new process + # or create a new thread to finish the request + # - finish_request() instantiates the request handler class; + # this constructor will handle the request all by itself + + def handle_request(self): + """Handle one request, possibly blocking. + + Respects self.timeout. + """ + # Support people who used socket.settimeout() to escape + # handle_request before self.timeout was available. + timeout = self.socket.gettimeout() + if timeout is None: + timeout = self.timeout + elif self.timeout is not None: + timeout = min(timeout, self.timeout) + fd_sets = _eintr_retry(select.select, [self], [], [], timeout) + if not fd_sets[0]: + self.handle_timeout() + return + self._handle_request_noblock() + + def _handle_request_noblock(self): + """Handle one request, without blocking. + + I assume that select.select has returned that the socket is + readable before this function was called, so there should be + no risk of blocking in get_request(). + """ + try: + request, client_address = self.get_request() + except socket.error: + return + if self.verify_request(request, client_address): + try: + self.process_request(request, client_address) + except: + self.handle_error(request, client_address) + self.shutdown_request(request) + + def handle_timeout(self): + """Called if no new request arrives within self.timeout. + + Overridden by ForkingMixIn. + """ + pass + + def verify_request(self, request, client_address): + """Verify the request. May be overridden. + + Return True if we should proceed with this request. + + """ + return True + + def process_request(self, request, client_address): + """Call finish_request. + + Overridden by ForkingMixIn and ThreadingMixIn. + + """ + self.finish_request(request, client_address) + self.shutdown_request(request) + + def server_close(self): + """Called to clean-up the server. + + May be overridden. + + """ + pass + + def finish_request(self, request, client_address): + """Finish one request by instantiating RequestHandlerClass.""" + self.RequestHandlerClass(request, client_address, self) + + def shutdown_request(self, request): + """Called to shutdown and close an individual request.""" + self.close_request(request) + + def close_request(self, request): + """Called to clean up an individual request.""" + pass + + def handle_error(self, request, client_address): + """Handle an error gracefully. May be overridden. + + The default is to print a traceback and continue. + + """ + print '-'*40 + print 'Exception happened during processing of request from', + print client_address + import traceback + traceback.print_exc() # XXX But this goes to stderr! + print '-'*40 + + +class TCPServer(BaseServer): + + """Base class for various socket-based server classes. + + Defaults to synchronous IP stream (i.e., TCP). + + Methods for the caller: + + - __init__(server_address, RequestHandlerClass, bind_and_activate=True) + - serve_forever(poll_interval=0.5) + - shutdown() + - handle_request() # if you don't use serve_forever() + - fileno() -> int # for select() + + Methods that may be overridden: + + - server_bind() + - server_activate() + - get_request() -> request, client_address + - handle_timeout() + - verify_request(request, client_address) + - process_request(request, client_address) + - shutdown_request(request) + - close_request(request) + - handle_error() + + Methods for derived classes: + + - finish_request(request, client_address) + + Class variables that may be overridden by derived classes or + instances: + + - timeout + - address_family + - socket_type + - request_queue_size (only for stream sockets) + - allow_reuse_address + + Instance variables: + + - server_address + - RequestHandlerClass + - socket + + """ + + address_family = socket.AF_INET + + socket_type = socket.SOCK_STREAM + + request_queue_size = 5 + + allow_reuse_address = False + + def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True): + """Constructor. May be extended, do not override.""" + BaseServer.__init__(self, server_address, RequestHandlerClass) + self.socket = socket.socket(self.address_family, + self.socket_type) + if bind_and_activate: + self.server_bind() + self.server_activate() + + def server_bind(self): + """Called by constructor to bind the socket. + + May be overridden. + + """ + if self.allow_reuse_address: + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.socket.bind(self.server_address) + self.server_address = self.socket.getsockname() + + def server_activate(self): + """Called by constructor to activate the server. + + May be overridden. + + """ + self.socket.listen(self.request_queue_size) + + def server_close(self): + """Called to clean-up the server. + + May be overridden. + + """ + self.socket.close() + + def fileno(self): + """Return socket file number. + + Interface required by select(). + + """ + return self.socket.fileno() + + def get_request(self): + """Get the request and client address from the socket. + + May be overridden. + + """ + return self.socket.accept() + + def shutdown_request(self, request): + """Called to shutdown and close an individual request.""" + try: + #explicitly shutdown. socket.close() merely releases + #the socket and waits for GC to perform the actual close. + request.shutdown(socket.SHUT_WR) + except socket.error: + pass #some platforms may raise ENOTCONN here + self.close_request(request) + + def close_request(self, request): + """Called to clean up an individual request.""" + request.close() + + +class UDPServer(TCPServer): + + """UDP server class.""" + + allow_reuse_address = False + + socket_type = socket.SOCK_DGRAM + + max_packet_size = 8192 + + def get_request(self): + data, client_addr = self.socket.recvfrom(self.max_packet_size) + return (data, self.socket), client_addr + + def server_activate(self): + # No need to call listen() for UDP. + pass + + def shutdown_request(self, request): + # No need to shutdown anything. + self.close_request(request) + + def close_request(self, request): + # No need to close anything. + pass + +class ForkingMixIn: + + """Mix-in class to handle each request in a new process.""" + + timeout = 300 + active_children = None + max_children = 40 + + def collect_children(self): + """Internal routine to wait for children that have exited.""" + if self.active_children is None: + return + + # If we're above the max number of children, wait and reap them until + # we go back below threshold. Note that we use waitpid(-1) below to be + # able to collect children in size() syscalls instead + # of size(): the downside is that this might reap children + # which we didn't spawn, which is why we only resort to this when we're + # above max_children. + while len(self.active_children) >= self.max_children: + try: + pid, _ = os.waitpid(-1, 0) + self.active_children.discard(pid) + except OSError as e: + if e.errno == errno.ECHILD: + # we don't have any children, we're done + self.active_children.clear() + elif e.errno != errno.EINTR: + break + + # Now reap all defunct children. + for pid in self.active_children.copy(): + try: + pid, _ = os.waitpid(pid, os.WNOHANG) + # if the child hasn't exited yet, pid will be 0 and ignored by + # discard() below + self.active_children.discard(pid) + except OSError as e: + if e.errno == errno.ECHILD: + # someone else reaped it + self.active_children.discard(pid) + + def handle_timeout(self): + """Wait for zombies after self.timeout seconds of inactivity. + + May be extended, do not override. + """ + self.collect_children() + + def process_request(self, request, client_address): + """Fork a new subprocess to process the request.""" + self.collect_children() + pid = os.fork() + if pid: + # Parent process + if self.active_children is None: + self.active_children = set() + self.active_children.add(pid) + self.close_request(request) #close handle in parent process + return + else: + # Child process. + # This must never return, hence os._exit()! + try: + self.finish_request(request, client_address) + self.shutdown_request(request) + os._exit(0) + except: + try: + self.handle_error(request, client_address) + self.shutdown_request(request) + finally: + os._exit(1) + + +class ThreadingMixIn: + """Mix-in class to handle each request in a new thread.""" + + # Decides how threads will act upon termination of the + # main process + daemon_threads = False + + def process_request_thread(self, request, client_address): + """Same as in BaseServer but as a thread. + + In addition, exception handling is done here. + + """ + try: + self.finish_request(request, client_address) + self.shutdown_request(request) + except: + self.handle_error(request, client_address) + self.shutdown_request(request) + + def process_request(self, request, client_address): + """Start a new thread to process the request.""" + t = threading.Thread(target = self.process_request_thread, + args = (request, client_address)) + t.daemon = self.daemon_threads + t.start() + + +class ForkingUDPServer(ForkingMixIn, UDPServer): pass +class ForkingTCPServer(ForkingMixIn, TCPServer): pass + +class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass +class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass + +if hasattr(socket, 'AF_UNIX'): + + class UnixStreamServer(TCPServer): + address_family = socket.AF_UNIX + + class UnixDatagramServer(UDPServer): + address_family = socket.AF_UNIX + + class ThreadingUnixStreamServer(ThreadingMixIn, UnixStreamServer): pass + + class ThreadingUnixDatagramServer(ThreadingMixIn, UnixDatagramServer): pass + +class BaseRequestHandler: + + """Base class for request handler classes. + + This class is instantiated for each request to be handled. The + constructor sets the instance variables request, client_address + and server, and then calls the handle() method. To implement a + specific service, all you need to do is to derive a class which + defines a handle() method. + + The handle() method can find the request as self.request, the + client address as self.client_address, and the server (in case it + needs access to per-server information) as self.server. Since a + separate instance is created for each request, the handle() method + can define arbitrary other instance variariables. + + """ + + def __init__(self, request, client_address, server): + self.request = request + self.client_address = client_address + self.server = server + self.setup() + try: + self.handle() + finally: + self.finish() + + def setup(self): + pass + + def handle(self): + pass + + def finish(self): + pass + + +# The following two classes make it possible to use the same service +# class for stream or datagram servers. +# Each class sets up these instance variables: +# - rfile: a file object from which receives the request is read +# - wfile: a file object to which the reply is written +# When the handle() method returns, wfile is flushed properly + + +class StreamRequestHandler(BaseRequestHandler): + + """Define self.rfile and self.wfile for stream sockets.""" + + # Default buffer sizes for rfile, wfile. + # We default rfile to buffered because otherwise it could be + # really slow for large data (a getc() call per byte); we make + # wfile unbuffered because (a) often after a write() we want to + # read and we need to flush the line; (b) big writes to unbuffered + # files are typically optimized by stdio even when big reads + # aren't. + rbufsize = -1 + wbufsize = 0 + + # A timeout to apply to the request socket, if not None. + timeout = None + + # Disable nagle algorithm for this socket, if True. + # Use only when wbufsize != 0, to avoid small packets. + disable_nagle_algorithm = False + + def setup(self): + self.connection = self.request + if self.timeout is not None: + self.connection.settimeout(self.timeout) + if self.disable_nagle_algorithm: + self.connection.setsockopt(socket.IPPROTO_TCP, + socket.TCP_NODELAY, True) + self.rfile = self.connection.makefile('rb', self.rbufsize) + self.wfile = self.connection.makefile('wb', self.wbufsize) + + def finish(self): + if not self.wfile.closed: + try: + self.wfile.flush() + except socket.error: + # An final socket error may have occurred here, such as + # the local error ECONNABORTED. + pass + self.wfile.close() + self.rfile.close() + + +class DatagramRequestHandler(BaseRequestHandler): + + # XXX Regrettably, I cannot get this working on Linux; + # s.recvfrom() doesn't return a meaningful client address. + + """Define self.rfile and self.wfile for datagram sockets.""" + + def setup(self): + try: + from cStringIO import StringIO + except ImportError: + from StringIO import StringIO + self.packet, self.socket = self.request + self.rfile = StringIO(self.packet) + self.wfile = StringIO() + + def finish(self): + self.socket.sendto(self.wfile.getvalue(), self.client_address) diff --git a/PythonHome/Lib/SocketServer.pyc b/PythonHome/Lib/SocketServer.pyc deleted file mode 100644 index 679a5ca1f0ac45631207a205b0145ba9924a1db0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23733 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 diff --git a/PythonHome/Lib/StringIO.py b/PythonHome/Lib/StringIO.py new file mode 100644 index 0000000000..b63525b9bf --- /dev/null +++ b/PythonHome/Lib/StringIO.py @@ -0,0 +1,324 @@ +r"""File-like objects that read from or write to a string buffer. + +This implements (nearly) all stdio methods. + +f = StringIO() # ready for writing +f = StringIO(buf) # ready for reading +f.close() # explicitly release resources held +flag = f.isatty() # always false +pos = f.tell() # get current position +f.seek(pos) # set current position +f.seek(pos, mode) # mode 0: absolute; 1: relative; 2: relative to EOF +buf = f.read() # read until EOF +buf = f.read(n) # read up to n bytes +buf = f.readline() # read until end of line ('\n') or EOF +list = f.readlines()# list of f.readline() results until EOF +f.truncate([size]) # truncate file at to at most size (default: current pos) +f.write(buf) # write at current position +f.writelines(list) # for line in list: f.write(line) +f.getvalue() # return whole file's contents as a string + +Notes: +- Using a real file is often faster (but less convenient). +- There's also a much faster implementation in C, called cStringIO, but + it's not subclassable. +- fileno() is left unimplemented so that code which uses it triggers + an exception early. +- Seeking far beyond EOF and then writing will insert real null + bytes that occupy space in the buffer. +- There's a simple test set (see end of this file). +""" +try: + from errno import EINVAL +except ImportError: + EINVAL = 22 + +__all__ = ["StringIO"] + +def _complain_ifclosed(closed): + if closed: + raise ValueError, "I/O operation on closed file" + +class StringIO: + """class StringIO([buffer]) + + When a StringIO object is created, it can be initialized to an existing + string by passing the string to the constructor. If no string is given, + the StringIO will start empty. + + The StringIO object can accept either Unicode or 8-bit strings, but + mixing the two may take some care. If both are used, 8-bit strings that + cannot be interpreted as 7-bit ASCII (that use the 8th bit) will cause + a UnicodeError to be raised when getvalue() is called. + """ + def __init__(self, buf = ''): + # Force self.buf to be a string or unicode + if not isinstance(buf, basestring): + buf = str(buf) + self.buf = buf + self.len = len(buf) + self.buflist = [] + self.pos = 0 + self.closed = False + self.softspace = 0 + + def __iter__(self): + return self + + def next(self): + """A file object is its own iterator, for example iter(f) returns f + (unless f is closed). When a file is used as an iterator, typically + in a for loop (for example, for line in f: print line), the next() + method is called repeatedly. This method returns the next input line, + or raises StopIteration when EOF is hit. + """ + _complain_ifclosed(self.closed) + r = self.readline() + if not r: + raise StopIteration + return r + + def close(self): + """Free the memory buffer. + """ + if not self.closed: + self.closed = True + del self.buf, self.pos + + def isatty(self): + """Returns False because StringIO objects are not connected to a + tty-like device. + """ + _complain_ifclosed(self.closed) + return False + + def seek(self, pos, mode = 0): + """Set the file's current position. + + The mode argument is optional and defaults to 0 (absolute file + positioning); other values are 1 (seek relative to the current + position) and 2 (seek relative to the file's end). + + There is no return value. + """ + _complain_ifclosed(self.closed) + if self.buflist: + self.buf += ''.join(self.buflist) + self.buflist = [] + if mode == 1: + pos += self.pos + elif mode == 2: + pos += self.len + self.pos = max(0, pos) + + def tell(self): + """Return the file's current position.""" + _complain_ifclosed(self.closed) + return self.pos + + def read(self, n = -1): + """Read at most size bytes from the file + (less if the read hits EOF before obtaining size bytes). + + If the size argument is negative or omitted, read all data until EOF + is reached. The bytes are returned as a string object. An empty + string is returned when EOF is encountered immediately. + """ + _complain_ifclosed(self.closed) + if self.buflist: + self.buf += ''.join(self.buflist) + self.buflist = [] + if n is None or n < 0: + newpos = self.len + else: + newpos = min(self.pos+n, self.len) + r = self.buf[self.pos:newpos] + self.pos = newpos + return r + + def readline(self, length=None): + r"""Read one entire line from the file. + + A trailing newline character is kept in the string (but may be absent + when a file ends with an incomplete line). If the size argument is + present and non-negative, it is a maximum byte count (including the + trailing newline) and an incomplete line may be returned. + + An empty string is returned only when EOF is encountered immediately. + + Note: Unlike stdio's fgets(), the returned string contains null + characters ('\0') if they occurred in the input. + """ + _complain_ifclosed(self.closed) + if self.buflist: + self.buf += ''.join(self.buflist) + self.buflist = [] + i = self.buf.find('\n', self.pos) + if i < 0: + newpos = self.len + else: + newpos = i+1 + if length is not None and length >= 0: + if self.pos + length < newpos: + newpos = self.pos + length + r = self.buf[self.pos:newpos] + self.pos = newpos + return r + + def readlines(self, sizehint = 0): + """Read until EOF using readline() and return a list containing the + lines thus read. + + If the optional sizehint argument is present, instead of reading up + to EOF, whole lines totalling approximately sizehint bytes (or more + to accommodate a final whole line). + """ + total = 0 + lines = [] + line = self.readline() + while line: + lines.append(line) + total += len(line) + if 0 < sizehint <= total: + break + line = self.readline() + return lines + + def truncate(self, size=None): + """Truncate the file's size. + + If the optional size argument is present, the file is truncated to + (at most) that size. The size defaults to the current position. + The current file position is not changed unless the position + is beyond the new file size. + + If the specified size exceeds the file's current size, the + file remains unchanged. + """ + _complain_ifclosed(self.closed) + if size is None: + size = self.pos + elif size < 0: + raise IOError(EINVAL, "Negative size not allowed") + elif size < self.pos: + self.pos = size + self.buf = self.getvalue()[:size] + self.len = size + + def write(self, s): + """Write a string to the file. + + There is no return value. + """ + _complain_ifclosed(self.closed) + if not s: return + # Force s to be a string or unicode + if not isinstance(s, basestring): + s = str(s) + spos = self.pos + slen = self.len + if spos == slen: + self.buflist.append(s) + self.len = self.pos = spos + len(s) + return + if spos > slen: + self.buflist.append('\0'*(spos - slen)) + slen = spos + newpos = spos + len(s) + if spos < slen: + if self.buflist: + self.buf += ''.join(self.buflist) + self.buflist = [self.buf[:spos], s, self.buf[newpos:]] + self.buf = '' + if newpos > slen: + slen = newpos + else: + self.buflist.append(s) + slen = newpos + self.len = slen + self.pos = newpos + + def writelines(self, iterable): + """Write a sequence of strings to the file. The sequence can be any + iterable object producing strings, typically a list of strings. There + is no return value. + + (The name is intended to match readlines(); writelines() does not add + line separators.) + """ + write = self.write + for line in iterable: + write(line) + + def flush(self): + """Flush the internal buffer + """ + _complain_ifclosed(self.closed) + + def getvalue(self): + """ + Retrieve the entire contents of the "file" at any time before + the StringIO object's close() method is called. + + The StringIO object can accept either Unicode or 8-bit strings, + but mixing the two may take some care. If both are used, 8-bit + strings that cannot be interpreted as 7-bit ASCII (that use the + 8th bit) will cause a UnicodeError to be raised when getvalue() + is called. + """ + _complain_ifclosed(self.closed) + if self.buflist: + self.buf += ''.join(self.buflist) + self.buflist = [] + return self.buf + + +# A little test suite + +def test(): + import sys + if sys.argv[1:]: + file = sys.argv[1] + else: + file = '/etc/passwd' + lines = open(file, 'r').readlines() + text = open(file, 'r').read() + f = StringIO() + for line in lines[:-2]: + f.write(line) + f.writelines(lines[-2:]) + if f.getvalue() != text: + raise RuntimeError, 'write failed' + length = f.tell() + print 'File length =', length + f.seek(len(lines[0])) + f.write(lines[1]) + f.seek(0) + print 'First line =', repr(f.readline()) + print 'Position =', f.tell() + line = f.readline() + print 'Second line =', repr(line) + f.seek(-len(line), 1) + line2 = f.read(len(line)) + if line != line2: + raise RuntimeError, 'bad result after seek back' + f.seek(len(line2), 1) + list = f.readlines() + line = list[-1] + f.seek(f.tell() - len(line)) + line2 = f.read() + if line != line2: + raise RuntimeError, 'bad result after seek back from EOF' + print 'Read', len(list), 'more lines' + print 'File length =', f.tell() + if f.tell() != length: + raise RuntimeError, 'bad length' + f.truncate(length/2) + f.seek(0, 2) + print 'Truncated length =', f.tell() + if f.tell() != length/2: + raise RuntimeError, 'truncate did not adjust length' + f.close() + +if __name__ == '__main__': + test() diff --git a/PythonHome/Lib/StringIO.pyc b/PythonHome/Lib/StringIO.pyc index 971a003f4a0fe60f088b317bbfeaa6f3212632d2..862085d8b908e4fe0e64edd40ef53474e27a9c81 100644 GIT binary patch delta 1068 zcmewv@jrG$IGdp@0|P^On82Uo>#EHUr>N^jDKlKL1{^hOKMVSdQ3oN zNk)F2M}BVV<}|jy%%p3Z{E4VY3yH-DB*B1h|cUeV2! x3U?XF2-Q@jWn}0AS*Wj^MvhyTsBRX- delta 398 zcmew#`!ixgI2*q-0|SGzRZKu-Nk)F2k@@Bhw!h5if|Iv#6`+f44(FC(LKmF8g!c%B z*i61h=wh4K@JC^4HW%80p-@J6CWgYz&qU8)xN-Ai$v{k%sWJ~R1 1: + raise TypeError, "pop expected at most 2 arguments, got "\ + + repr(1 + len(args)) + try: + value = self[key] + except KeyError: + if args: + return args[0] + raise + del self[key] + return value + def popitem(self): + try: + k, v = self.iteritems().next() + except StopIteration: + raise KeyError, 'container is empty' + del self[k] + return (k, v) + def update(self, other=None, **kwargs): + # Make progressively weaker assumptions about "other" + if other is None: + pass + elif hasattr(other, 'iteritems'): # iteritems saves memory and lookups + for k, v in other.iteritems(): + self[k] = v + elif hasattr(other, 'keys'): + for k in other.keys(): + self[k] = other[k] + else: + for k, v in other: + self[k] = v + if kwargs: + self.update(kwargs) + def get(self, key, default=None): + try: + return self[key] + except KeyError: + return default + def __repr__(self): + return repr(dict(self.iteritems())) + def __cmp__(self, other): + if other is None: + return 1 + if isinstance(other, DictMixin): + other = dict(other.iteritems()) + return cmp(dict(self.iteritems()), other) + def __len__(self): + return len(self.keys()) diff --git a/PythonHome/Lib/UserDict.pyc b/PythonHome/Lib/UserDict.pyc index 0c71743ea32984181b9e095952cd66b164185104..a50306050000e3a1c7b90a5014b2f00e41a8bc03 100644 GIT binary patch delta 2477 zcmbR2-0Qz#F_WP!0|SGrRZMzjNk(Z>On82Uo>#EHUr>N^jDKlKL1{^hOKMVSdQ3oN zNk)F2M}BVVIGV}Ob&I2b3|*0&C1mId5EGsJku#1AopD^HWavs17oGf_D~1f6N!;0F z=$gO+^dGk*BkN{v9z8}f4DjHcNQSN#yd7lds^^> z3|)!hU1aF`B~C^Po?I)@M21~_l5~ZOl6`#PV4xu!xCI)@QwgA#TIg ziy`)ltsFya5qmv`SP;i|46!QCW(+Yst^y1(Mp@CxPq^YS#7nq~F~lTzN-@M1N{ddu z%oBqlp1_-pA(qb~I$4lUl96SzHlH3NhIAMIL<}(>fes8YR>4UaVh`m-C*Kvs^hT~w zE{0le;q@3|uZ6#2hzW{5!Vpst^FbHeyihC>(=*xp+Bg_D&Qpevl5 fqTGlfCZ=*4Lrh2&Gq>zk#SFzZwPhH3W7Q1+#j6F} diff --git a/PythonHome/Lib/UserList.py b/PythonHome/Lib/UserList.py new file mode 100644 index 0000000000..b445985707 --- /dev/null +++ b/PythonHome/Lib/UserList.py @@ -0,0 +1,88 @@ +"""A more or less complete user-defined wrapper around list objects.""" + +import collections + +class UserList(collections.MutableSequence): + def __init__(self, initlist=None): + self.data = [] + if initlist is not None: + # XXX should this accept an arbitrary sequence? + if type(initlist) == type(self.data): + self.data[:] = initlist + elif isinstance(initlist, UserList): + self.data[:] = initlist.data[:] + else: + self.data = list(initlist) + def __repr__(self): return repr(self.data) + def __lt__(self, other): return self.data < self.__cast(other) + def __le__(self, other): return self.data <= self.__cast(other) + def __eq__(self, other): return self.data == self.__cast(other) + def __ne__(self, other): return self.data != self.__cast(other) + def __gt__(self, other): return self.data > self.__cast(other) + def __ge__(self, other): return self.data >= self.__cast(other) + def __cast(self, other): + if isinstance(other, UserList): return other.data + else: return other + def __cmp__(self, other): + return cmp(self.data, self.__cast(other)) + __hash__ = None # Mutable sequence, so not hashable + def __contains__(self, item): return item in self.data + def __len__(self): return len(self.data) + def __getitem__(self, i): return self.data[i] + def __setitem__(self, i, item): self.data[i] = item + def __delitem__(self, i): del self.data[i] + def __getslice__(self, i, j): + i = max(i, 0); j = max(j, 0) + return self.__class__(self.data[i:j]) + def __setslice__(self, i, j, other): + i = max(i, 0); j = max(j, 0) + if isinstance(other, UserList): + self.data[i:j] = other.data + elif isinstance(other, type(self.data)): + self.data[i:j] = other + else: + self.data[i:j] = list(other) + def __delslice__(self, i, j): + i = max(i, 0); j = max(j, 0) + del self.data[i:j] + def __add__(self, other): + if isinstance(other, UserList): + return self.__class__(self.data + other.data) + elif isinstance(other, type(self.data)): + return self.__class__(self.data + other) + else: + return self.__class__(self.data + list(other)) + def __radd__(self, other): + if isinstance(other, UserList): + return self.__class__(other.data + self.data) + elif isinstance(other, type(self.data)): + return self.__class__(other + self.data) + else: + return self.__class__(list(other) + self.data) + def __iadd__(self, other): + if isinstance(other, UserList): + self.data += other.data + elif isinstance(other, type(self.data)): + self.data += other + else: + self.data += list(other) + return self + def __mul__(self, n): + return self.__class__(self.data*n) + __rmul__ = __mul__ + def __imul__(self, n): + self.data *= n + return self + def append(self, item): self.data.append(item) + def insert(self, i, item): self.data.insert(i, item) + def pop(self, i=-1): return self.data.pop(i) + def remove(self, item): self.data.remove(item) + def count(self, item): return self.data.count(item) + def index(self, item, *args): return self.data.index(item, *args) + def reverse(self): self.data.reverse() + def sort(self, *args, **kwds): self.data.sort(*args, **kwds) + def extend(self, other): + if isinstance(other, UserList): + self.data.extend(other.data) + else: + self.data.extend(other) diff --git a/PythonHome/Lib/UserList.pyc b/PythonHome/Lib/UserList.pyc deleted file mode 100644 index 1e398aca2a25455eaec41faba712813b6a2cc3fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6067 zcmcIoYjYb#7QHj_OO72S@hi?#2?+=S0k)Q+*y0sJ?bcQW?=ps>aAm7kQFjvA(ny&Z zL#WDr3Lp4D?T^{Nwm)Dw=l0BKBF2rUKDuXW|6N`F&o}?v?MVJp!~aiF z(zj7rkv-Ib*id?b>_MoB3uHf(hmhywN0H|u-|p2oVz)KViFZ)lY4!(+YYviT&!uUz zGw2U{E_2Pp)Fp3O_plo~+x$Lh4~H&kwv)kOY@5Aqnl%Rx_FX4SZ+HKPpPg(8YkiG5 z_s~~D4AJ-*cluKx;s6m)t`X~xfCwZ3VeQQk5`}q!rm&DB-dhwquPsYr7gVT=T~uLN z?2-zn#MV_<;o^I%Vwd&twAfQBG{ml`a7OH^3TMThR^go3h6-z9¢_N)pUV$Z3t zDRxbTEwSq=oEN*H!nU|=*}EWiQy(vi-BRI_*z+n}7P~F>g6exk>_u(7D)y2JO|h3% z04G;exGwgp3a^N5s>1-PUz**dduLwEJC@G)47DXHm33;FmwP(frL zrVr#Gl;k6}V?0_~PcW{==WI@%qwgP-(Q&2HKcBDTw}{ovc3ZHe?6ek8V=CI(SzCpj zLF`n>ei*uJ8C~798>d-2?zjj~emI?{MLl$A>Us~=ce-&m(=HBdu}aUPx_$p%_rd+b zv2G84(80!VxG}_#p61}79;}2HgVmrBoDDlf$ii)us#OS?Qnjzd6iSph5;sgDPEqY5 zF03G?BjHSA&R_!VafF#R(ds#64gM9ufglP!lLVoAXAMZEP}Z1EJEuzVWQ^HC_Shv; zkrBQzJupNLPlhY_HLmCsR#BTNkZ6UEC@-{Aj=>po4kJ&7ff;Ioo8N%JJuznO#29KX z6+;Xj)=!LK?xkXQ1b^5#F^2h)UBRE|O7C1mz=(*VAP(&nm>h@lDOf-gmFzzDd&df!5It^sI*!L*C+18!9 zE7vpTk;_PtF;~l-Y0IK0=gg(gV0k@1LH>soe;n=4DLzfofDxU2Mht0zp@})iXwSp0 z1n|+30Lat`z>Ira*Yo;cEB7vRFQec+bot=K#SNbSFGQ&_l0SNCyi;m`fUIlk8-%pe zMI|k+st(d`Kh5fRfW!6LDZI_Q%Q$_=0$_Wp4&HHL!?f4!Aj4e8tTLb*L5C_7bRc_@;AA;TH!(B6JT;_&i_>OsK3EGo+^Q%_7T+&k zOcr&5X7~%`y-A(aA5|wBQypLe|BUv9kLJ+dBJ?6*!@k^th1@9QAp{ROKSy3w-o1ya z1!2c6`er_A!i3S}a2-oEizR4Jy~t^g>P+?gy|`jM<`aJ$kkd#_sEnwoXEL16i*0L- zc?WBxyjkO<3btUc_3$LhdT)bEETl=zckjOPPk?qheSGT4vYC|VfiYH@AHn#I{en^r7NH>kwx361Ub?W(>X zQ(w9Wt-S$jp9?oe&Q5<)XJ3avbNE{0aGkDQy+W66IJ(AbZjGnLp7*}~Vb7R9W24C% zNr__3qnIO%Kt2fhPCDX9NzwQp@$njFOx-@`L-+qH_h*cgkJ9hC-~6e zGKL;MXvB8J#!Lrw^af_$L-D6GbuWq{;6>6~qD+T45RM0dTb4_*$&@(Dl_9!?t-dIb z=r@>O6T+9$Dx68DP%@~%a4@Ve!F$UzyF_nd&<@Hm_mq)O&R~ng^#|X%3WAv!;34q0 z;}OiHJVUpGZ(9C~gg=&M+Wa;q{(Wro!V&($);t&x3#B9cJQ0yfKKJj&);+EG0Qc8B zdpmiQPPGFM=P$V>igdVWQPd;#&Z@ZqK%S%X$bevsC+<6!q;B@_AJMy*#n-RV)&&P@ zmLr1U-^T%9P^W{jP~cIgG#q?yr_=BUjNUD=Fw|LyM``!~!q|P_rUpisU*~WvAU1;d z%vdX%Ds&O!M4H!3;+|&XnPiqjJ^CY7`wFGF#sr(;PU|LN`ivL1`?$#JS2Sb#1AExR zW28BZ1EOVC{Hzu6l^|-cqRU6Lc*IXG`u-X5g+E{NaXWpCHE5TJZ?w@xR+m`uO)t8} z>N=}eSlwVnMA56P=!yA4iDu*Ibv832YBJJ{5HTnt21i84^e#f%sJ-e}=`K{H%h4JU5dab^Q-zDv-aqLQEgkG65e~#Hf2dwg)uQTZN@BzC! nz!yrg_r+n>e$aEf?#ZDmK3L8KSV{TNo9JT(pB_;Q;Y#=mE6{iV diff --git a/PythonHome/Lib/UserString.py b/PythonHome/Lib/UserString.py new file mode 100644 index 0000000000..726b3f7d3c --- /dev/null +++ b/PythonHome/Lib/UserString.py @@ -0,0 +1,228 @@ +#!/usr/bin/env python +## vim:ts=4:et:nowrap +"""A user-defined wrapper around string objects + +Note: string objects have grown methods in Python 1.6 +This module requires Python 1.6 or later. +""" +import sys +import collections + +__all__ = ["UserString","MutableString"] + +class UserString(collections.Sequence): + def __init__(self, seq): + if isinstance(seq, basestring): + self.data = seq + elif isinstance(seq, UserString): + self.data = seq.data[:] + else: + self.data = str(seq) + def __str__(self): return str(self.data) + def __repr__(self): return repr(self.data) + def __int__(self): return int(self.data) + def __long__(self): return long(self.data) + def __float__(self): return float(self.data) + def __complex__(self): return complex(self.data) + def __hash__(self): return hash(self.data) + + def __cmp__(self, string): + if isinstance(string, UserString): + return cmp(self.data, string.data) + else: + return cmp(self.data, string) + def __contains__(self, char): + return char in self.data + + def __len__(self): return len(self.data) + def __getitem__(self, index): return self.__class__(self.data[index]) + def __getslice__(self, start, end): + start = max(start, 0); end = max(end, 0) + return self.__class__(self.data[start:end]) + + def __add__(self, other): + if isinstance(other, UserString): + return self.__class__(self.data + other.data) + elif isinstance(other, basestring): + return self.__class__(self.data + other) + else: + return self.__class__(self.data + str(other)) + def __radd__(self, other): + if isinstance(other, basestring): + return self.__class__(other + self.data) + else: + return self.__class__(str(other) + self.data) + def __mul__(self, n): + return self.__class__(self.data*n) + __rmul__ = __mul__ + def __mod__(self, args): + return self.__class__(self.data % args) + + # the following methods are defined in alphabetical order: + def capitalize(self): return self.__class__(self.data.capitalize()) + def center(self, width, *args): + return self.__class__(self.data.center(width, *args)) + def count(self, sub, start=0, end=sys.maxint): + return self.data.count(sub, start, end) + def decode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.decode(encoding, errors)) + else: + return self.__class__(self.data.decode(encoding)) + else: + return self.__class__(self.data.decode()) + def encode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.encode(encoding, errors)) + else: + return self.__class__(self.data.encode(encoding)) + else: + return self.__class__(self.data.encode()) + def endswith(self, suffix, start=0, end=sys.maxint): + return self.data.endswith(suffix, start, end) + def expandtabs(self, tabsize=8): + return self.__class__(self.data.expandtabs(tabsize)) + def find(self, sub, start=0, end=sys.maxint): + return self.data.find(sub, start, end) + def index(self, sub, start=0, end=sys.maxint): + return self.data.index(sub, start, end) + def isalpha(self): return self.data.isalpha() + def isalnum(self): return self.data.isalnum() + def isdecimal(self): return self.data.isdecimal() + def isdigit(self): return self.data.isdigit() + def islower(self): return self.data.islower() + def isnumeric(self): return self.data.isnumeric() + def isspace(self): return self.data.isspace() + def istitle(self): return self.data.istitle() + def isupper(self): return self.data.isupper() + def join(self, seq): return self.data.join(seq) + def ljust(self, width, *args): + return self.__class__(self.data.ljust(width, *args)) + def lower(self): return self.__class__(self.data.lower()) + def lstrip(self, chars=None): return self.__class__(self.data.lstrip(chars)) + def partition(self, sep): + return self.data.partition(sep) + def replace(self, old, new, maxsplit=-1): + return self.__class__(self.data.replace(old, new, maxsplit)) + def rfind(self, sub, start=0, end=sys.maxint): + return self.data.rfind(sub, start, end) + def rindex(self, sub, start=0, end=sys.maxint): + return self.data.rindex(sub, start, end) + def rjust(self, width, *args): + return self.__class__(self.data.rjust(width, *args)) + def rpartition(self, sep): + return self.data.rpartition(sep) + def rstrip(self, chars=None): return self.__class__(self.data.rstrip(chars)) + def split(self, sep=None, maxsplit=-1): + return self.data.split(sep, maxsplit) + def rsplit(self, sep=None, maxsplit=-1): + return self.data.rsplit(sep, maxsplit) + def splitlines(self, keepends=0): return self.data.splitlines(keepends) + def startswith(self, prefix, start=0, end=sys.maxint): + return self.data.startswith(prefix, start, end) + def strip(self, chars=None): return self.__class__(self.data.strip(chars)) + def swapcase(self): return self.__class__(self.data.swapcase()) + def title(self): return self.__class__(self.data.title()) + def translate(self, *args): + return self.__class__(self.data.translate(*args)) + def upper(self): return self.__class__(self.data.upper()) + def zfill(self, width): return self.__class__(self.data.zfill(width)) + +class MutableString(UserString, collections.MutableSequence): + """mutable string objects + + Python strings are immutable objects. This has the advantage, that + strings may be used as dictionary keys. If this property isn't needed + and you insist on changing string values in place instead, you may cheat + and use MutableString. + + But the purpose of this class is an educational one: to prevent + people from inventing their own mutable string class derived + from UserString and than forget thereby to remove (override) the + __hash__ method inherited from UserString. This would lead to + errors that would be very hard to track down. + + A faster and better solution is to rewrite your program using lists.""" + def __init__(self, string=""): + from warnings import warnpy3k + warnpy3k('the class UserString.MutableString has been removed in ' + 'Python 3.0', stacklevel=2) + self.data = string + + # We inherit object.__hash__, so we must deny this explicitly + __hash__ = None + + def __setitem__(self, index, sub): + if isinstance(index, slice): + if isinstance(sub, UserString): + sub = sub.data + elif not isinstance(sub, basestring): + sub = str(sub) + start, stop, step = index.indices(len(self.data)) + if step == -1: + start, stop = stop+1, start+1 + sub = sub[::-1] + elif step != 1: + # XXX(twouters): I guess we should be reimplementing + # the extended slice assignment/deletion algorithm here... + raise TypeError, "invalid step in slicing assignment" + start = min(start, stop) + self.data = self.data[:start] + sub + self.data[stop:] + else: + if index < 0: + index += len(self.data) + if index < 0 or index >= len(self.data): raise IndexError + self.data = self.data[:index] + sub + self.data[index+1:] + def __delitem__(self, index): + if isinstance(index, slice): + start, stop, step = index.indices(len(self.data)) + if step == -1: + start, stop = stop+1, start+1 + elif step != 1: + # XXX(twouters): see same block in __setitem__ + raise TypeError, "invalid step in slicing deletion" + start = min(start, stop) + self.data = self.data[:start] + self.data[stop:] + else: + if index < 0: + index += len(self.data) + if index < 0 or index >= len(self.data): raise IndexError + self.data = self.data[:index] + self.data[index+1:] + def __setslice__(self, start, end, sub): + start = max(start, 0); end = max(end, 0) + if isinstance(sub, UserString): + self.data = self.data[:start]+sub.data+self.data[end:] + elif isinstance(sub, basestring): + self.data = self.data[:start]+sub+self.data[end:] + else: + self.data = self.data[:start]+str(sub)+self.data[end:] + def __delslice__(self, start, end): + start = max(start, 0); end = max(end, 0) + self.data = self.data[:start] + self.data[end:] + def immutable(self): + return UserString(self.data) + def __iadd__(self, other): + if isinstance(other, UserString): + self.data += other.data + elif isinstance(other, basestring): + self.data += other + else: + self.data += str(other) + return self + def __imul__(self, n): + self.data *= n + return self + def insert(self, index, value): + self[index:index] = value + +if __name__ == "__main__": + # execute the regression test to stdout, if called as a script: + import os + called_in_dir, called_as = os.path.split(sys.argv[0]) + called_as, py = os.path.splitext(called_as) + if '-q' in sys.argv: + from test import test_support + test_support.verbose = 0 + __import__('test.test_' + called_as.lower()) diff --git a/PythonHome/Lib/UserString.pyc b/PythonHome/Lib/UserString.pyc deleted file mode 100644 index b90fbcdde79846ea6953ed4495382e5552c248ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13844 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 D_zsOE delta 335 zcmdm_v`le>B`3cu0|SGzRZKu-Nk)F2k@@5U0^*Y!IUk{mZ=S+s$cQdD`5X5N3^9-a z&v;@m#EW?=IEz_;wk4&OBu@UoE6G*N3gji`6l5e$_UA+4>hReh%PR7t$aeEd@*wnP jGEUCt6Gv8#A@9hKB5#js9GdBPWj9yzi(m%B0f8a_so__( diff --git a/PythonHome/Lib/__phello__.foo.py b/PythonHome/Lib/__phello__.foo.py new file mode 100644 index 0000000000..8e8623ee1d --- /dev/null +++ b/PythonHome/Lib/__phello__.foo.py @@ -0,0 +1 @@ +# This file exists as a helper for the test.test_frozen module. diff --git a/PythonHome/Lib/__phello__.foo.pyc b/PythonHome/Lib/__phello__.foo.pyc deleted file mode 100644 index 982d1f9b086268ea9d0fd825949fe213d49be5b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 110 zcmZSn%*(YYJRvxl0SXv_v;z len(other): + return False + for elem in self: + if elem not in other: + return False + return True + + def __lt__(self, other): + if not isinstance(other, Set): + return NotImplemented + return len(self) < len(other) and self.__le__(other) + + def __gt__(self, other): + if not isinstance(other, Set): + return NotImplemented + return len(self) > len(other) and self.__ge__(other) + + def __ge__(self, other): + if not isinstance(other, Set): + return NotImplemented + if len(self) < len(other): + return False + for elem in other: + if elem not in self: + return False + return True + + def __eq__(self, other): + if not isinstance(other, Set): + return NotImplemented + return len(self) == len(other) and self.__le__(other) + + def __ne__(self, other): + return not (self == other) + + @classmethod + def _from_iterable(cls, it): + '''Construct an instance of the class from any iterable input. + + Must override this method if the class constructor signature + does not accept an iterable for an input. + ''' + return cls(it) + + def __and__(self, other): + if not isinstance(other, Iterable): + return NotImplemented + return self._from_iterable(value for value in other if value in self) + + __rand__ = __and__ + + def isdisjoint(self, other): + 'Return True if two sets have a null intersection.' + for value in other: + if value in self: + return False + return True + + def __or__(self, other): + if not isinstance(other, Iterable): + return NotImplemented + chain = (e for s in (self, other) for e in s) + return self._from_iterable(chain) + + __ror__ = __or__ + + def __sub__(self, other): + if not isinstance(other, Set): + if not isinstance(other, Iterable): + return NotImplemented + other = self._from_iterable(other) + return self._from_iterable(value for value in self + if value not in other) + + def __rsub__(self, other): + if not isinstance(other, Set): + if not isinstance(other, Iterable): + return NotImplemented + other = self._from_iterable(other) + return self._from_iterable(value for value in other + if value not in self) + + def __xor__(self, other): + if not isinstance(other, Set): + if not isinstance(other, Iterable): + return NotImplemented + other = self._from_iterable(other) + return (self - other) | (other - self) + + __rxor__ = __xor__ + + # Sets are not hashable by default, but subclasses can change this + __hash__ = None + + def _hash(self): + """Compute the hash value of a set. + + Note that we don't define __hash__: not all sets are hashable. + But if you define a hashable set type, its __hash__ should + call this function. + + This must be compatible __eq__. + + All sets ought to compare equal if they contain the same + elements, regardless of how they are implemented, and + regardless of the order of the elements; so there's not much + freedom for __eq__ or __hash__. We match the algorithm used + by the built-in frozenset type. + """ + MAX = sys.maxint + MASK = 2 * MAX + 1 + n = len(self) + h = 1927868237 * (n + 1) + h &= MASK + for x in self: + hx = hash(x) + h ^= (hx ^ (hx << 16) ^ 89869747) * 3644798167 + h &= MASK + h = h * 69069 + 907133923 + h &= MASK + if h > MAX: + h -= MASK + 1 + if h == -1: + h = 590923713 + return h + +Set.register(frozenset) + + +class MutableSet(Set): + """A mutable set is a finite, iterable container. + + This class provides concrete generic implementations of all + methods except for __contains__, __iter__, __len__, + add(), and discard(). + + To override the comparisons (presumably for speed, as the + semantics are fixed), all you have to do is redefine __le__ and + then the other operations will automatically follow suit. + """ + + @abstractmethod + def add(self, value): + """Add an element.""" + raise NotImplementedError + + @abstractmethod + def discard(self, value): + """Remove an element. Do not raise an exception if absent.""" + raise NotImplementedError + + def remove(self, value): + """Remove an element. If not a member, raise a KeyError.""" + if value not in self: + raise KeyError(value) + self.discard(value) + + def pop(self): + """Return the popped value. Raise KeyError if empty.""" + it = iter(self) + try: + value = next(it) + except StopIteration: + raise KeyError + self.discard(value) + return value + + def clear(self): + """This is slow (creates N new iterators!) but effective.""" + try: + while True: + self.pop() + except KeyError: + pass + + def __ior__(self, it): + for value in it: + self.add(value) + return self + + def __iand__(self, it): + for value in (self - it): + self.discard(value) + return self + + def __ixor__(self, it): + if it is self: + self.clear() + else: + if not isinstance(it, Set): + it = self._from_iterable(it) + for value in it: + if value in self: + self.discard(value) + else: + self.add(value) + return self + + def __isub__(self, it): + if it is self: + self.clear() + else: + for value in it: + self.discard(value) + return self + +MutableSet.register(set) + + +### MAPPINGS ### + + +class Mapping(Sized, Iterable, Container): + + """A Mapping is a generic container for associating key/value + pairs. + + This class provides concrete generic implementations of all + methods except for __getitem__, __iter__, and __len__. + + """ + + @abstractmethod + def __getitem__(self, key): + raise KeyError + + def get(self, key, default=None): + 'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.' + try: + return self[key] + except KeyError: + return default + + def __contains__(self, key): + try: + self[key] + except KeyError: + return False + else: + return True + + def iterkeys(self): + 'D.iterkeys() -> an iterator over the keys of D' + return iter(self) + + def itervalues(self): + 'D.itervalues() -> an iterator over the values of D' + for key in self: + yield self[key] + + def iteritems(self): + 'D.iteritems() -> an iterator over the (key, value) items of D' + for key in self: + yield (key, self[key]) + + def keys(self): + "D.keys() -> list of D's keys" + return list(self) + + def items(self): + "D.items() -> list of D's (key, value) pairs, as 2-tuples" + return [(key, self[key]) for key in self] + + def values(self): + "D.values() -> list of D's values" + return [self[key] for key in self] + + # Mappings are not hashable by default, but subclasses can change this + __hash__ = None + + def __eq__(self, other): + if not isinstance(other, Mapping): + return NotImplemented + return dict(self.items()) == dict(other.items()) + + def __ne__(self, other): + return not (self == other) + +class MappingView(Sized): + + def __init__(self, mapping): + self._mapping = mapping + + def __len__(self): + return len(self._mapping) + + def __repr__(self): + return '{0.__class__.__name__}({0._mapping!r})'.format(self) + + +class KeysView(MappingView, Set): + + @classmethod + def _from_iterable(self, it): + return set(it) + + def __contains__(self, key): + return key in self._mapping + + def __iter__(self): + for key in self._mapping: + yield key + + +class ItemsView(MappingView, Set): + + @classmethod + def _from_iterable(self, it): + return set(it) + + def __contains__(self, item): + key, value = item + try: + v = self._mapping[key] + except KeyError: + return False + else: + return v == value + + def __iter__(self): + for key in self._mapping: + yield (key, self._mapping[key]) + + +class ValuesView(MappingView): + + def __contains__(self, value): + for key in self._mapping: + if value == self._mapping[key]: + return True + return False + + def __iter__(self): + for key in self._mapping: + yield self._mapping[key] + + +class MutableMapping(Mapping): + + """A MutableMapping is a generic container for associating + key/value pairs. + + This class provides concrete generic implementations of all + methods except for __getitem__, __setitem__, __delitem__, + __iter__, and __len__. + + """ + + @abstractmethod + def __setitem__(self, key, value): + raise KeyError + + @abstractmethod + def __delitem__(self, key): + raise KeyError + + __marker = object() + + def pop(self, key, default=__marker): + '''D.pop(k[,d]) -> v, remove specified key and return the corresponding value. + If key is not found, d is returned if given, otherwise KeyError is raised. + ''' + try: + value = self[key] + except KeyError: + if default is self.__marker: + raise + return default + else: + del self[key] + return value + + def popitem(self): + '''D.popitem() -> (k, v), remove and return some (key, value) pair + as a 2-tuple; but raise KeyError if D is empty. + ''' + try: + key = next(iter(self)) + except StopIteration: + raise KeyError + value = self[key] + del self[key] + return key, value + + def clear(self): + 'D.clear() -> None. Remove all items from D.' + try: + while True: + self.popitem() + except KeyError: + pass + + def update(*args, **kwds): + ''' D.update([E, ]**F) -> None. Update D from mapping/iterable E and F. + If E present and has a .keys() method, does: for k in E: D[k] = E[k] + If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v + In either case, this is followed by: for k, v in F.items(): D[k] = v + ''' + if len(args) > 2: + raise TypeError("update() takes at most 2 positional " + "arguments ({} given)".format(len(args))) + elif not args: + raise TypeError("update() takes at least 1 argument (0 given)") + self = args[0] + other = args[1] if len(args) >= 2 else () + + if isinstance(other, Mapping): + for key in other: + self[key] = other[key] + elif hasattr(other, "keys"): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + for key, value in kwds.items(): + self[key] = value + + def setdefault(self, key, default=None): + 'D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D' + try: + return self[key] + except KeyError: + self[key] = default + return default + +MutableMapping.register(dict) + + +### SEQUENCES ### + + +class Sequence(Sized, Iterable, Container): + """All the operations on a read-only sequence. + + Concrete subclasses must override __new__ or __init__, + __getitem__, and __len__. + """ + + @abstractmethod + def __getitem__(self, index): + raise IndexError + + def __iter__(self): + i = 0 + try: + while True: + v = self[i] + yield v + i += 1 + except IndexError: + return + + def __contains__(self, value): + for v in self: + if v == value: + return True + return False + + def __reversed__(self): + for i in reversed(range(len(self))): + yield self[i] + + def index(self, value): + '''S.index(value) -> integer -- return first index of value. + Raises ValueError if the value is not present. + ''' + for i, v in enumerate(self): + if v == value: + return i + raise ValueError + + def count(self, value): + 'S.count(value) -> integer -- return number of occurrences of value' + return sum(1 for v in self if v == value) + +Sequence.register(tuple) +Sequence.register(basestring) +Sequence.register(buffer) +Sequence.register(xrange) + + +class MutableSequence(Sequence): + + """All the operations on a read-only sequence. + + Concrete subclasses must provide __new__ or __init__, + __getitem__, __setitem__, __delitem__, __len__, and insert(). + + """ + + @abstractmethod + def __setitem__(self, index, value): + raise IndexError + + @abstractmethod + def __delitem__(self, index): + raise IndexError + + @abstractmethod + def insert(self, index, value): + 'S.insert(index, object) -- insert object before index' + raise IndexError + + def append(self, value): + 'S.append(object) -- append object to the end of the sequence' + self.insert(len(self), value) + + def reverse(self): + 'S.reverse() -- reverse *IN PLACE*' + n = len(self) + for i in range(n//2): + self[i], self[n-i-1] = self[n-i-1], self[i] + + def extend(self, values): + 'S.extend(iterable) -- extend sequence by appending elements from the iterable' + for v in values: + self.append(v) + + def pop(self, index=-1): + '''S.pop([index]) -> item -- remove and return item at index (default last). + Raise IndexError if list is empty or index is out of range. + ''' + v = self[index] + del self[index] + return v + + def remove(self, value): + '''S.remove(value) -- remove first occurrence of value. + Raise ValueError if the value is not present. + ''' + del self[self.index(value)] + + def __iadd__(self, values): + self.extend(values) + return self + +MutableSequence.register(list) diff --git a/PythonHome/Lib/_abcoll.pyc b/PythonHome/Lib/_abcoll.pyc index 28e92e8fe696970fec333b864dd26dd74243d403..04f0ef2de6164399a022b5796bb0e458fd308581 100644 GIT binary patch delta 5788 zcmbW)-%pZJ7zc34L_-j92xdazMH(eiX2pMr9AgLLsK{Iugn88*Xo6Ff;<>u;i z;mR6Czo@p9YQFzUA^1pcSXWIk+9$19*lJO-N(Y6p>9X$P&=7k zts>EkeSoxb`6OL<1(FK-Qm7OF^k?QRKqa!C0?NuM$+;CnfaF9${))y#Qe;aWWw-DT zBU*8(U^(%M2LSs`j3m}e5Djf)m8RSH-xD867@&+j1DxU-Ldch>1*c$s+`Y@R+EI=-al2x-n z9(x=%71;pE+IFPqJ|F|C6rfn8y=n&_+1L1}#xgsAJhn5wHS>UEYYb_efMm`8Niz<} zrD|!i_!ZL1Lu(iK2hxF(XUq6A(yYZEml+_7ofyf6AArm*`vRzcWdu;{oQ>;_^Ow}h z36LwsvvG=l7-2(JMR_-WNyo}lNSRkFKJX7C!<#Pv%20U;P*zS({#M2T8Bpbu$6M|J za&Rkh#@6YPQDjk%>`Kg#1lAQWb^&U}cnVOxRnvfC4bWvm2I_aF5hzbV&YCTN{A`{8 zRD9b(K&dTJKqV}@041(QUdGqe4}q)^E7E7i8f0A;Yu*DD_S;SZs?ZM1CG?1W4!Oej z*M|9*NEd2PAYqzTIX&aBAe249i#vfI3;MztM@B9-nGDwXfC+A&#z_ymUqsZP+ z57It;^`rbtBwFts{)(o&JAj4Js)kH}5l_*yVUG0En9=4*|IHGx^m{0mMpeG%Udl{=QYj9NU}jenx8r; zK@pgR-Mp-0h-Q6I%0NP*i0C##g%Tk#x_t0MJ73TL{rY=<&;Q(>bKZf7bb3tM@0O|b z5{blND|DZ2D6g$CTS-WE0a)0gABjHCS-#bP zK0BOOhA{Zi9Qu6I1Rlol<{!LF-)(uhgok9pB;JNYX?SngF^p~d2^mx7Z@_+UC&1XM zU#EwFv-{YwV^)NZh%g;_Vy)ph_3oU(HmIv!+L@!00J?nUm;3c^^wvRZ-lI^FsYjIWqGq~{Gd+YLocX&Uxu`Tx*c*Z>3&$&Fzt2^)>Y8wx>05j*qwW2-w)7Uhl z?gqY?mL0kTA{9IyfTYv=395U1U3f!7{zYCSy+>fpw7#GTM_E^d8>TG234tGrAMuP1 zmN+4hnvTT)jQ*4baxq}#6Ubbkl4tbt@evF-eFA$|ReFyvCam`tOR+B)UnrXbpFJe{ o;3V*ProductUserVisibleVersion\s*' + r'(.*?)', f.read()) + finally: + f.close() + if m is not None: + _SYSTEM_VERSION = '.'.join(m.group(1).split('.')[:2]) + # else: fall back to the default behaviour + + return _SYSTEM_VERSION + +def _remove_original_values(_config_vars): + """Remove original unmodified values for testing""" + # This is needed for higher-level cross-platform tests of get_platform. + for k in list(_config_vars): + if k.startswith(_INITPRE): + del _config_vars[k] + +def _save_modified_value(_config_vars, cv, newvalue): + """Save modified and original unmodified value of configuration var""" + + oldvalue = _config_vars.get(cv, '') + if (oldvalue != newvalue) and (_INITPRE + cv not in _config_vars): + _config_vars[_INITPRE + cv] = oldvalue + _config_vars[cv] = newvalue + +def _supports_universal_builds(): + """Returns True if universal builds are supported on this system""" + # As an approximation, we assume that if we are running on 10.4 or above, + # then we are running with an Xcode environment that supports universal + # builds, in particular -isysroot and -arch arguments to the compiler. This + # is in support of allowing 10.4 universal builds to run on 10.3.x systems. + + osx_version = _get_system_version() + if osx_version: + try: + osx_version = tuple(int(i) for i in osx_version.split('.')) + except ValueError: + osx_version = '' + return bool(osx_version >= (10, 4)) if osx_version else False + + +def _find_appropriate_compiler(_config_vars): + """Find appropriate C compiler for extension module builds""" + + # Issue #13590: + # The OSX location for the compiler varies between OSX + # (or rather Xcode) releases. With older releases (up-to 10.5) + # the compiler is in /usr/bin, with newer releases the compiler + # can only be found inside Xcode.app if the "Command Line Tools" + # are not installed. + # + # Futhermore, the compiler that can be used varies between + # Xcode releases. Up to Xcode 4 it was possible to use 'gcc-4.2' + # as the compiler, after that 'clang' should be used because + # gcc-4.2 is either not present, or a copy of 'llvm-gcc' that + # miscompiles Python. + + # skip checks if the compiler was overriden with a CC env variable + if 'CC' in os.environ: + return _config_vars + + # The CC config var might contain additional arguments. + # Ignore them while searching. + cc = oldcc = _config_vars['CC'].split()[0] + if not _find_executable(cc): + # Compiler is not found on the shell search PATH. + # Now search for clang, first on PATH (if the Command LIne + # Tools have been installed in / or if the user has provided + # another location via CC). If not found, try using xcrun + # to find an uninstalled clang (within a selected Xcode). + + # NOTE: Cannot use subprocess here because of bootstrap + # issues when building Python itself (and os.popen is + # implemented on top of subprocess and is therefore not + # usable as well) + + cc = _find_build_tool('clang') + + elif os.path.basename(cc).startswith('gcc'): + # Compiler is GCC, check if it is LLVM-GCC + data = _read_output("'%s' --version" + % (cc.replace("'", "'\"'\"'"),)) + if data and 'llvm-gcc' in data: + # Found LLVM-GCC, fall back to clang + cc = _find_build_tool('clang') + + if not cc: + raise SystemError( + "Cannot locate working compiler") + + if cc != oldcc: + # Found a replacement compiler. + # Modify config vars using new compiler, if not already explicitly + # overriden by an env variable, preserving additional arguments. + for cv in _COMPILER_CONFIG_VARS: + if cv in _config_vars and cv not in os.environ: + cv_split = _config_vars[cv].split() + cv_split[0] = cc if cv != 'CXX' else cc + '++' + _save_modified_value(_config_vars, cv, ' '.join(cv_split)) + + return _config_vars + + +def _remove_universal_flags(_config_vars): + """Remove all universal build arguments from config vars""" + + for cv in _UNIVERSAL_CONFIG_VARS: + # Do not alter a config var explicitly overriden by env var + if cv in _config_vars and cv not in os.environ: + flags = _config_vars[cv] + flags = re.sub('-arch\s+\w+\s', ' ', flags) + flags = re.sub('-isysroot [^ \t]*', ' ', flags) + _save_modified_value(_config_vars, cv, flags) + + return _config_vars + + +def _remove_unsupported_archs(_config_vars): + """Remove any unsupported archs from config vars""" + # Different Xcode releases support different sets for '-arch' + # flags. In particular, Xcode 4.x no longer supports the + # PPC architectures. + # + # This code automatically removes '-arch ppc' and '-arch ppc64' + # when these are not supported. That makes it possible to + # build extensions on OSX 10.7 and later with the prebuilt + # 32-bit installer on the python.org website. + + # skip checks if the compiler was overriden with a CC env variable + if 'CC' in os.environ: + return _config_vars + + if re.search('-arch\s+ppc', _config_vars['CFLAGS']) is not None: + # NOTE: Cannot use subprocess here because of bootstrap + # issues when building Python itself + status = os.system( + """echo 'int main{};' | """ + """'%s' -c -arch ppc -x c -o /dev/null /dev/null 2>/dev/null""" + %(_config_vars['CC'].replace("'", "'\"'\"'"),)) + if status: + # The compile failed for some reason. Because of differences + # across Xcode and compiler versions, there is no reliable way + # to be sure why it failed. Assume here it was due to lack of + # PPC support and remove the related '-arch' flags from each + # config variables not explicitly overriden by an environment + # variable. If the error was for some other reason, we hope the + # failure will show up again when trying to compile an extension + # module. + for cv in _UNIVERSAL_CONFIG_VARS: + if cv in _config_vars and cv not in os.environ: + flags = _config_vars[cv] + flags = re.sub('-arch\s+ppc\w*\s', ' ', flags) + _save_modified_value(_config_vars, cv, flags) + + return _config_vars + + +def _override_all_archs(_config_vars): + """Allow override of all archs with ARCHFLAGS env var""" + # NOTE: This name was introduced by Apple in OSX 10.5 and + # is used by several scripting languages distributed with + # that OS release. + if 'ARCHFLAGS' in os.environ: + arch = os.environ['ARCHFLAGS'] + for cv in _UNIVERSAL_CONFIG_VARS: + if cv in _config_vars and '-arch' in _config_vars[cv]: + flags = _config_vars[cv] + flags = re.sub('-arch\s+\w+\s', ' ', flags) + flags = flags + ' ' + arch + _save_modified_value(_config_vars, cv, flags) + + return _config_vars + + +def _check_for_unavailable_sdk(_config_vars): + """Remove references to any SDKs not available""" + # If we're on OSX 10.5 or later and the user tries to + # compile an extension using an SDK that is not present + # on the current machine it is better to not use an SDK + # than to fail. This is particularly important with + # the standalone Command Line Tools alternative to a + # full-blown Xcode install since the CLT packages do not + # provide SDKs. If the SDK is not present, it is assumed + # that the header files and dev libs have been installed + # to /usr and /System/Library by either a standalone CLT + # package or the CLT component within Xcode. + cflags = _config_vars.get('CFLAGS', '') + m = re.search(r'-isysroot\s+(\S+)', cflags) + if m is not None: + sdk = m.group(1) + if not os.path.exists(sdk): + for cv in _UNIVERSAL_CONFIG_VARS: + # Do not alter a config var explicitly overriden by env var + if cv in _config_vars and cv not in os.environ: + flags = _config_vars[cv] + flags = re.sub(r'-isysroot\s+\S+(?:\s|$)', ' ', flags) + _save_modified_value(_config_vars, cv, flags) + + return _config_vars + + +def compiler_fixup(compiler_so, cc_args): + """ + This function will strip '-isysroot PATH' and '-arch ARCH' from the + compile flags if the user has specified one them in extra_compile_flags. + + This is needed because '-arch ARCH' adds another architecture to the + build, without a way to remove an architecture. Furthermore GCC will + barf if multiple '-isysroot' arguments are present. + """ + stripArch = stripSysroot = False + + compiler_so = list(compiler_so) + + if not _supports_universal_builds(): + # OSX before 10.4.0, these don't support -arch and -isysroot at + # all. + stripArch = stripSysroot = True + else: + stripArch = '-arch' in cc_args + stripSysroot = '-isysroot' in cc_args + + if stripArch or 'ARCHFLAGS' in os.environ: + while True: + try: + index = compiler_so.index('-arch') + # Strip this argument and the next one: + del compiler_so[index:index+2] + except ValueError: + break + + if 'ARCHFLAGS' in os.environ and not stripArch: + # User specified different -arch flags in the environ, + # see also distutils.sysconfig + compiler_so = compiler_so + os.environ['ARCHFLAGS'].split() + + if stripSysroot: + while True: + try: + index = compiler_so.index('-isysroot') + # Strip this argument and the next one: + del compiler_so[index:index+2] + except ValueError: + break + + # Check if the SDK that is used during compilation actually exists, + # the universal build requires the usage of a universal SDK and not all + # users have that installed by default. + sysroot = None + if '-isysroot' in cc_args: + idx = cc_args.index('-isysroot') + sysroot = cc_args[idx+1] + elif '-isysroot' in compiler_so: + idx = compiler_so.index('-isysroot') + sysroot = compiler_so[idx+1] + + if sysroot and not os.path.isdir(sysroot): + from distutils import log + log.warn("Compiling with an SDK that doesn't seem to exist: %s", + sysroot) + log.warn("Please check your Xcode installation") + + return compiler_so + + +def customize_config_vars(_config_vars): + """Customize Python build configuration variables. + + Called internally from sysconfig with a mutable mapping + containing name/value pairs parsed from the configured + makefile used to build this interpreter. Returns + the mapping updated as needed to reflect the environment + in which the interpreter is running; in the case of + a Python from a binary installer, the installed + environment may be very different from the build + environment, i.e. different OS levels, different + built tools, different available CPU architectures. + + This customization is performed whenever + distutils.sysconfig.get_config_vars() is first + called. It may be used in environments where no + compilers are present, i.e. when installing pure + Python dists. Customization of compiler paths + and detection of unavailable archs is deferred + until the first extension module build is + requested (in distutils.sysconfig.customize_compiler). + + Currently called from distutils.sysconfig + """ + + if not _supports_universal_builds(): + # On Mac OS X before 10.4, check if -arch and -isysroot + # are in CFLAGS or LDFLAGS and remove them if they are. + # This is needed when building extensions on a 10.3 system + # using a universal build of python. + _remove_universal_flags(_config_vars) + + # Allow user to override all archs with ARCHFLAGS env var + _override_all_archs(_config_vars) + + # Remove references to sdks that are not found + _check_for_unavailable_sdk(_config_vars) + + return _config_vars + + +def customize_compiler(_config_vars): + """Customize compiler path and configuration variables. + + This customization is performed when the first + extension module build is requested + in distutils.sysconfig.customize_compiler). + """ + + # Find a compiler to use for extension module builds + _find_appropriate_compiler(_config_vars) + + # Remove ppc arch flags if not supported here + _remove_unsupported_archs(_config_vars) + + # Allow user to override all archs with ARCHFLAGS env var + _override_all_archs(_config_vars) + + return _config_vars + + +def get_platform_osx(_config_vars, osname, release, machine): + """Filter values for get_platform()""" + # called from get_platform() in sysconfig and distutils.util + # + # For our purposes, we'll assume that the system version from + # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set + # to. This makes the compatibility story a bit more sane because the + # machine is going to compile and link as if it were + # MACOSX_DEPLOYMENT_TARGET. + + macver = _config_vars.get('MACOSX_DEPLOYMENT_TARGET', '') + macrelease = _get_system_version() or macver + macver = macver or macrelease + + if macver: + release = macver + osname = "macosx" + + # Use the original CFLAGS value, if available, so that we + # return the same machine type for the platform string. + # Otherwise, distutils may consider this a cross-compiling + # case and disallow installs. + cflags = _config_vars.get(_INITPRE+'CFLAGS', + _config_vars.get('CFLAGS', '')) + if macrelease: + try: + macrelease = tuple(int(i) for i in macrelease.split('.')[0:2]) + except ValueError: + macrelease = (10, 0) + else: + # assume no universal support + macrelease = (10, 0) + + if (macrelease >= (10, 4)) and '-arch' in cflags.strip(): + # The universal build will build fat binaries, but not on + # systems before 10.4 + + machine = 'fat' + + archs = re.findall('-arch\s+(\S+)', cflags) + archs = tuple(sorted(set(archs))) + + if len(archs) == 1: + machine = archs[0] + elif archs == ('i386', 'ppc'): + machine = 'fat' + elif archs == ('i386', 'x86_64'): + machine = 'intel' + elif archs == ('i386', 'ppc', 'x86_64'): + machine = 'fat3' + elif archs == ('ppc64', 'x86_64'): + machine = 'fat64' + elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'): + machine = 'universal' + else: + raise ValueError( + "Don't know machine value for archs=%r" % (archs,)) + + elif machine == 'i386': + # On OSX the machine type returned by uname is always the + # 32-bit variant, even if the executable architecture is + # the 64-bit variant + if sys.maxint >= 2**32: + machine = 'x86_64' + + elif machine in ('PowerPC', 'Power_Macintosh'): + # Pick a sane name for the PPC architecture. + # See 'i386' case + if sys.maxint >= 2**32: + machine = 'ppc64' + else: + machine = 'ppc' + + return (osname, release, machine) diff --git a/PythonHome/Lib/_osx_support.pyc b/PythonHome/Lib/_osx_support.pyc deleted file mode 100644 index 590edb4723a494b55a47d69608683d9e0d5a48c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11527 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 B3^o7& diff --git a/PythonHome/Lib/_pyio.py b/PythonHome/Lib/_pyio.py new file mode 100644 index 0000000000..3acbc65224 --- /dev/null +++ b/PythonHome/Lib/_pyio.py @@ -0,0 +1,2030 @@ +""" +Python implementation of the io module. +""" + +from __future__ import (print_function, unicode_literals) + +import os +import abc +import codecs +import warnings +import errno +# Import thread instead of threading to reduce startup cost +try: + from thread import allocate_lock as Lock +except ImportError: + from dummy_thread import allocate_lock as Lock + +import io +from io import (__all__, SEEK_SET, SEEK_CUR, SEEK_END) +from errno import EINTR + +__metaclass__ = type + +# open() uses st_blksize whenever we can +DEFAULT_BUFFER_SIZE = 8 * 1024 # bytes + +# NOTE: Base classes defined here are registered with the "official" ABCs +# defined in io.py. We don't use real inheritance though, because we don't +# want to inherit the C implementations. + + +class BlockingIOError(IOError): + + """Exception raised when I/O would block on a non-blocking I/O stream.""" + + def __init__(self, errno, strerror, characters_written=0): + super(IOError, self).__init__(errno, strerror) + if not isinstance(characters_written, (int, long)): + raise TypeError("characters_written must be a integer") + self.characters_written = characters_written + + +def open(file, mode="r", buffering=-1, + encoding=None, errors=None, + newline=None, closefd=True): + + r"""Open file and return a stream. Raise IOError upon failure. + + file is either a text or byte string giving the name (and the path + if the file isn't in the current working directory) of the file to + be opened or an integer file descriptor of the file to be + wrapped. (If a file descriptor is given, it is closed when the + returned I/O object is closed, unless closefd is set to False.) + + mode is an optional string that specifies the mode in which the file + is opened. It defaults to 'r' which means open for reading in text + mode. Other common values are 'w' for writing (truncating the file if + it already exists), and 'a' for appending (which on some Unix systems, + means that all writes append to the end of the file regardless of the + current seek position). In text mode, if encoding is not specified the + encoding used is platform dependent. (For reading and writing raw + bytes use binary mode and leave encoding unspecified.) The available + modes are: + + ========= =============================================================== + Character Meaning + --------- --------------------------------------------------------------- + 'r' open for reading (default) + 'w' open for writing, truncating the file first + 'a' open for writing, appending to the end of the file if it exists + 'b' binary mode + 't' text mode (default) + '+' open a disk file for updating (reading and writing) + 'U' universal newline mode (for backwards compatibility; unneeded + for new code) + ========= =============================================================== + + The default mode is 'rt' (open for reading text). For binary random + access, the mode 'w+b' opens and truncates the file to 0 bytes, while + 'r+b' opens the file without truncation. + + Python distinguishes between files opened in binary and text modes, + even when the underlying operating system doesn't. Files opened in + binary mode (appending 'b' to the mode argument) return contents as + bytes objects without any decoding. In text mode (the default, or when + 't' is appended to the mode argument), the contents of the file are + returned as strings, the bytes having been first decoded using a + platform-dependent encoding or using the specified encoding if given. + + buffering is an optional integer used to set the buffering policy. + Pass 0 to switch buffering off (only allowed in binary mode), 1 to select + line buffering (only usable in text mode), and an integer > 1 to indicate + the size of a fixed-size chunk buffer. When no buffering argument is + given, the default buffering policy works as follows: + + * Binary files are buffered in fixed-size chunks; the size of the buffer + is chosen using a heuristic trying to determine the underlying device's + "block size" and falling back on `io.DEFAULT_BUFFER_SIZE`. + On many systems, the buffer will typically be 4096 or 8192 bytes long. + + * "Interactive" text files (files for which isatty() returns True) + use line buffering. Other text files use the policy described above + for binary files. + + encoding is the name of the encoding used to decode or encode the + file. This should only be used in text mode. The default encoding is + platform dependent, but any encoding supported by Python can be + passed. See the codecs module for the list of supported encodings. + + errors is an optional string that specifies how encoding errors are to + be handled---this argument should not be used in binary mode. Pass + 'strict' to raise a ValueError exception if there is an encoding error + (the default of None has the same effect), or pass 'ignore' to ignore + errors. (Note that ignoring encoding errors can lead to data loss.) + See the documentation for codecs.register for a list of the permitted + encoding error strings. + + newline controls how universal newlines works (it only applies to text + mode). It can be None, '', '\n', '\r', and '\r\n'. It works as + follows: + + * On input, if newline is None, universal newlines mode is + enabled. Lines in the input can end in '\n', '\r', or '\r\n', and + these are translated into '\n' before being returned to the + caller. If it is '', universal newline mode is enabled, but line + endings are returned to the caller untranslated. If it has any of + the other legal values, input lines are only terminated by the given + string, and the line ending is returned to the caller untranslated. + + * On output, if newline is None, any '\n' characters written are + translated to the system default line separator, os.linesep. If + newline is '', no translation takes place. If newline is any of the + other legal values, any '\n' characters written are translated to + the given string. + + If closefd is False, the underlying file descriptor will be kept open + when the file is closed. This does not work when a file name is given + and must be True in that case. + + open() returns a file object whose type depends on the mode, and + through which the standard file operations such as reading and writing + are performed. When open() is used to open a file in a text mode ('w', + 'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open + a file in a binary mode, the returned class varies: in read binary + mode, it returns a BufferedReader; in write binary and append binary + modes, it returns a BufferedWriter, and in read/write mode, it returns + a BufferedRandom. + + It is also possible to use a string or bytearray as a file for both + reading and writing. For strings StringIO can be used like a file + opened in a text mode, and for bytes a BytesIO can be used like a file + opened in a binary mode. + """ + if not isinstance(file, (basestring, int, long)): + raise TypeError("invalid file: %r" % file) + if not isinstance(mode, basestring): + raise TypeError("invalid mode: %r" % mode) + if not isinstance(buffering, (int, long)): + raise TypeError("invalid buffering: %r" % buffering) + if encoding is not None and not isinstance(encoding, basestring): + raise TypeError("invalid encoding: %r" % encoding) + if errors is not None and not isinstance(errors, basestring): + raise TypeError("invalid errors: %r" % errors) + modes = set(mode) + if modes - set("arwb+tU") or len(mode) > len(modes): + raise ValueError("invalid mode: %r" % mode) + reading = "r" in modes + writing = "w" in modes + appending = "a" in modes + updating = "+" in modes + text = "t" in modes + binary = "b" in modes + if "U" in modes: + if writing or appending: + raise ValueError("can't use U and writing mode at once") + reading = True + if text and binary: + raise ValueError("can't have text and binary mode at once") + if reading + writing + appending > 1: + raise ValueError("can't have read/write/append mode at once") + if not (reading or writing or appending): + raise ValueError("must have exactly one of read/write/append mode") + if binary and encoding is not None: + raise ValueError("binary mode doesn't take an encoding argument") + if binary and errors is not None: + raise ValueError("binary mode doesn't take an errors argument") + if binary and newline is not None: + raise ValueError("binary mode doesn't take a newline argument") + raw = FileIO(file, + (reading and "r" or "") + + (writing and "w" or "") + + (appending and "a" or "") + + (updating and "+" or ""), + closefd) + result = raw + try: + line_buffering = False + if buffering == 1 or buffering < 0 and raw.isatty(): + buffering = -1 + line_buffering = True + if buffering < 0: + buffering = DEFAULT_BUFFER_SIZE + try: + bs = os.fstat(raw.fileno()).st_blksize + except (os.error, AttributeError): + pass + else: + if bs > 1: + buffering = bs + if buffering < 0: + raise ValueError("invalid buffering size") + if buffering == 0: + if binary: + return result + raise ValueError("can't have unbuffered text I/O") + if updating: + buffer = BufferedRandom(raw, buffering) + elif writing or appending: + buffer = BufferedWriter(raw, buffering) + elif reading: + buffer = BufferedReader(raw, buffering) + else: + raise ValueError("unknown mode: %r" % mode) + result = buffer + if binary: + return result + text = TextIOWrapper(buffer, encoding, errors, newline, line_buffering) + result = text + text.mode = mode + return result + except: + result.close() + raise + + +class DocDescriptor: + """Helper for builtins.open.__doc__ + """ + def __get__(self, obj, typ): + return ( + "open(file, mode='r', buffering=-1, encoding=None, " + "errors=None, newline=None, closefd=True)\n\n" + + open.__doc__) + +class OpenWrapper: + """Wrapper for builtins.open + + Trick so that open won't become a bound method when stored + as a class variable (as dbm.dumb does). + + See initstdio() in Python/pythonrun.c. + """ + __doc__ = DocDescriptor() + + def __new__(cls, *args, **kwargs): + return open(*args, **kwargs) + + +class UnsupportedOperation(ValueError, IOError): + pass + + +class IOBase: + __metaclass__ = abc.ABCMeta + + """The abstract base class for all I/O classes, acting on streams of + bytes. There is no public constructor. + + This class provides dummy implementations for many methods that + derived classes can override selectively; the default implementations + represent a file that cannot be read, written or seeked. + + Even though IOBase does not declare read, readinto, or write because + their signatures will vary, implementations and clients should + consider those methods part of the interface. Also, implementations + may raise a IOError when operations they do not support are called. + + The basic type used for binary data read from or written to a file is + bytes. bytearrays are accepted too, and in some cases (such as + readinto) needed. Text I/O classes work with str data. + + Note that calling any method (even inquiries) on a closed stream is + undefined. Implementations may raise IOError in this case. + + IOBase (and its subclasses) support the iterator protocol, meaning + that an IOBase object can be iterated over yielding the lines in a + stream. + + IOBase also supports the :keyword:`with` statement. In this example, + fp is closed after the suite of the with statement is complete: + + with open('spam.txt', 'r') as fp: + fp.write('Spam and eggs!') + """ + + ### Internal ### + + def _unsupported(self, name): + """Internal: raise an exception for unsupported operations.""" + raise UnsupportedOperation("%s.%s() not supported" % + (self.__class__.__name__, name)) + + ### Positioning ### + + def seek(self, pos, whence=0): + """Change stream position. + + Change the stream position to byte offset pos. Argument pos is + interpreted relative to the position indicated by whence. Values + for whence are: + + * 0 -- start of stream (the default); offset should be zero or positive + * 1 -- current stream position; offset may be negative + * 2 -- end of stream; offset is usually negative + + Return the new absolute position. + """ + self._unsupported("seek") + + def tell(self): + """Return current stream position.""" + return self.seek(0, 1) + + def truncate(self, pos=None): + """Truncate file to size bytes. + + Size defaults to the current IO position as reported by tell(). Return + the new size. + """ + self._unsupported("truncate") + + ### Flush and close ### + + def flush(self): + """Flush write buffers, if applicable. + + This is not implemented for read-only and non-blocking streams. + """ + self._checkClosed() + # XXX Should this return the number of bytes written??? + + __closed = False + + def close(self): + """Flush and close the IO object. + + This method has no effect if the file is already closed. + """ + if not self.__closed: + try: + self.flush() + finally: + self.__closed = True + + def __del__(self): + """Destructor. Calls close().""" + # The try/except block is in case this is called at program + # exit time, when it's possible that globals have already been + # deleted, and then the close() call might fail. Since + # there's nothing we can do about such failures and they annoy + # the end users, we suppress the traceback. + try: + self.close() + except: + pass + + ### Inquiries ### + + def seekable(self): + """Return whether object supports random access. + + If False, seek(), tell() and truncate() will raise IOError. + This method may need to do a test seek(). + """ + return False + + def _checkSeekable(self, msg=None): + """Internal: raise an IOError if file is not seekable + """ + if not self.seekable(): + raise IOError("File or stream is not seekable." + if msg is None else msg) + + + def readable(self): + """Return whether object was opened for reading. + + If False, read() will raise IOError. + """ + return False + + def _checkReadable(self, msg=None): + """Internal: raise an IOError if file is not readable + """ + if not self.readable(): + raise IOError("File or stream is not readable." + if msg is None else msg) + + def writable(self): + """Return whether object was opened for writing. + + If False, write() and truncate() will raise IOError. + """ + return False + + def _checkWritable(self, msg=None): + """Internal: raise an IOError if file is not writable + """ + if not self.writable(): + raise IOError("File or stream is not writable." + if msg is None else msg) + + @property + def closed(self): + """closed: bool. True iff the file has been closed. + + For backwards compatibility, this is a property, not a predicate. + """ + return self.__closed + + def _checkClosed(self, msg=None): + """Internal: raise an ValueError if file is closed + """ + if self.closed: + raise ValueError("I/O operation on closed file." + if msg is None else msg) + + ### Context manager ### + + def __enter__(self): + """Context management protocol. Returns self.""" + self._checkClosed() + return self + + def __exit__(self, *args): + """Context management protocol. Calls close()""" + self.close() + + ### Lower-level APIs ### + + # XXX Should these be present even if unimplemented? + + def fileno(self): + """Returns underlying file descriptor if one exists. + + An IOError is raised if the IO object does not use a file descriptor. + """ + self._unsupported("fileno") + + def isatty(self): + """Return whether this is an 'interactive' stream. + + Return False if it can't be determined. + """ + self._checkClosed() + return False + + ### Readline[s] and writelines ### + + def readline(self, limit=-1): + r"""Read and return a line from the stream. + + If limit is specified, at most limit bytes will be read. + + The line terminator is always b'\n' for binary files; for text + files, the newlines argument to open can be used to select the line + terminator(s) recognized. + """ + # For backwards compatibility, a (slowish) readline(). + if hasattr(self, "peek"): + def nreadahead(): + readahead = self.peek(1) + if not readahead: + return 1 + n = (readahead.find(b"\n") + 1) or len(readahead) + if limit >= 0: + n = min(n, limit) + return n + else: + def nreadahead(): + return 1 + if limit is None: + limit = -1 + elif not isinstance(limit, (int, long)): + raise TypeError("limit must be an integer") + res = bytearray() + while limit < 0 or len(res) < limit: + b = self.read(nreadahead()) + if not b: + break + res += b + if res.endswith(b"\n"): + break + return bytes(res) + + def __iter__(self): + self._checkClosed() + return self + + def next(self): + line = self.readline() + if not line: + raise StopIteration + return line + + def readlines(self, hint=None): + """Return a list of lines from the stream. + + hint can be specified to control the number of lines read: no more + lines will be read if the total size (in bytes/characters) of all + lines so far exceeds hint. + """ + if hint is not None and not isinstance(hint, (int, long)): + raise TypeError("integer or None expected") + if hint is None or hint <= 0: + return list(self) + n = 0 + lines = [] + for line in self: + lines.append(line) + n += len(line) + if n >= hint: + break + return lines + + def writelines(self, lines): + self._checkClosed() + for line in lines: + self.write(line) + +io.IOBase.register(IOBase) + + +class RawIOBase(IOBase): + + """Base class for raw binary I/O.""" + + # The read() method is implemented by calling readinto(); derived + # classes that want to support read() only need to implement + # readinto() as a primitive operation. In general, readinto() can be + # more efficient than read(). + + # (It would be tempting to also provide an implementation of + # readinto() in terms of read(), in case the latter is a more suitable + # primitive operation, but that would lead to nasty recursion in case + # a subclass doesn't implement either.) + + def read(self, n=-1): + """Read and return up to n bytes. + + Returns an empty bytes object on EOF, or None if the object is + set not to block and has no data to read. + """ + if n is None: + n = -1 + if n < 0: + return self.readall() + b = bytearray(n.__index__()) + n = self.readinto(b) + if n is None: + return None + del b[n:] + return bytes(b) + + def readall(self): + """Read until EOF, using multiple read() call.""" + res = bytearray() + while True: + data = self.read(DEFAULT_BUFFER_SIZE) + if not data: + break + res += data + if res: + return bytes(res) + else: + # b'' or None + return data + + def readinto(self, b): + """Read up to len(b) bytes into b. + + Returns number of bytes read (0 for EOF), or None if the object + is set not to block and has no data to read. + """ + self._unsupported("readinto") + + def write(self, b): + """Write the given buffer to the IO stream. + + Returns the number of bytes written, which may be less than len(b). + """ + self._unsupported("write") + +io.RawIOBase.register(RawIOBase) +from _io import FileIO +RawIOBase.register(FileIO) + + +class BufferedIOBase(IOBase): + + """Base class for buffered IO objects. + + The main difference with RawIOBase is that the read() method + supports omitting the size argument, and does not have a default + implementation that defers to readinto(). + + In addition, read(), readinto() and write() may raise + BlockingIOError if the underlying raw stream is in non-blocking + mode and not ready; unlike their raw counterparts, they will never + return None. + + A typical implementation should not inherit from a RawIOBase + implementation, but wrap one. + """ + + def read(self, n=None): + """Read and return up to n bytes. + + If the argument is omitted, None, or negative, reads and + returns all data until EOF. + + If the argument is positive, and the underlying raw stream is + not 'interactive', multiple raw reads may be issued to satisfy + the byte count (unless EOF is reached first). But for + interactive raw streams (XXX and for pipes?), at most one raw + read will be issued, and a short result does not imply that + EOF is imminent. + + Returns an empty bytes array on EOF. + + Raises BlockingIOError if the underlying raw stream has no + data at the moment. + """ + self._unsupported("read") + + def read1(self, n=None): + """Read up to n bytes with at most one read() system call.""" + self._unsupported("read1") + + def readinto(self, b): + """Read up to len(b) bytes into b. + + Like read(), this may issue multiple reads to the underlying raw + stream, unless the latter is 'interactive'. + + Returns the number of bytes read (0 for EOF). + + Raises BlockingIOError if the underlying raw stream has no + data at the moment. + """ + # XXX This ought to work with anything that supports the buffer API + data = self.read(len(b)) + n = len(data) + try: + b[:n] = data + except TypeError as err: + import array + if not isinstance(b, array.array): + raise err + b[:n] = array.array(b'b', data) + return n + + def write(self, b): + """Write the given buffer to the IO stream. + + Return the number of bytes written, which is never less than + len(b). + + Raises BlockingIOError if the buffer is full and the + underlying raw stream cannot accept more data at the moment. + """ + self._unsupported("write") + + def detach(self): + """ + Separate the underlying raw stream from the buffer and return it. + + After the raw stream has been detached, the buffer is in an unusable + state. + """ + self._unsupported("detach") + +io.BufferedIOBase.register(BufferedIOBase) + + +class _BufferedIOMixin(BufferedIOBase): + + """A mixin implementation of BufferedIOBase with an underlying raw stream. + + This passes most requests on to the underlying raw stream. It + does *not* provide implementations of read(), readinto() or + write(). + """ + + def __init__(self, raw): + self._raw = raw + + ### Positioning ### + + def seek(self, pos, whence=0): + new_position = self.raw.seek(pos, whence) + if new_position < 0: + raise IOError("seek() returned an invalid position") + return new_position + + def tell(self): + pos = self.raw.tell() + if pos < 0: + raise IOError("tell() returned an invalid position") + return pos + + def truncate(self, pos=None): + # Flush the stream. We're mixing buffered I/O with lower-level I/O, + # and a flush may be necessary to synch both views of the current + # file state. + self.flush() + + if pos is None: + pos = self.tell() + # XXX: Should seek() be used, instead of passing the position + # XXX directly to truncate? + return self.raw.truncate(pos) + + ### Flush and close ### + + def flush(self): + if self.closed: + raise ValueError("flush of closed file") + self.raw.flush() + + def close(self): + if self.raw is not None and not self.closed: + try: + # may raise BlockingIOError or BrokenPipeError etc + self.flush() + finally: + self.raw.close() + + def detach(self): + if self.raw is None: + raise ValueError("raw stream already detached") + self.flush() + raw = self._raw + self._raw = None + return raw + + ### Inquiries ### + + def seekable(self): + return self.raw.seekable() + + def readable(self): + return self.raw.readable() + + def writable(self): + return self.raw.writable() + + @property + def raw(self): + return self._raw + + @property + def closed(self): + return self.raw.closed + + @property + def name(self): + return self.raw.name + + @property + def mode(self): + return self.raw.mode + + def __repr__(self): + clsname = self.__class__.__name__ + try: + name = self.name + except AttributeError: + return "<_pyio.{0}>".format(clsname) + else: + return "<_pyio.{0} name={1!r}>".format(clsname, name) + + ### Lower-level APIs ### + + def fileno(self): + return self.raw.fileno() + + def isatty(self): + return self.raw.isatty() + + +class BytesIO(BufferedIOBase): + + """Buffered I/O implementation using an in-memory bytes buffer.""" + + def __init__(self, initial_bytes=None): + buf = bytearray() + if initial_bytes is not None: + buf.extend(initial_bytes) + self._buffer = buf + self._pos = 0 + + def __getstate__(self): + if self.closed: + raise ValueError("__getstate__ on closed file") + return self.__dict__.copy() + + def getvalue(self): + """Return the bytes value (contents) of the buffer + """ + if self.closed: + raise ValueError("getvalue on closed file") + return bytes(self._buffer) + + def read(self, n=None): + if self.closed: + raise ValueError("read from closed file") + if n is None: + n = -1 + if not isinstance(n, (int, long)): + raise TypeError("integer argument expected, got {0!r}".format( + type(n))) + if n < 0: + n = len(self._buffer) + if len(self._buffer) <= self._pos: + return b"" + newpos = min(len(self._buffer), self._pos + n) + b = self._buffer[self._pos : newpos] + self._pos = newpos + return bytes(b) + + def read1(self, n): + """This is the same as read. + """ + return self.read(n) + + def write(self, b): + if self.closed: + raise ValueError("write to closed file") + if isinstance(b, unicode): + raise TypeError("can't write unicode to binary stream") + n = len(b) + if n == 0: + return 0 + pos = self._pos + if pos > len(self._buffer): + # Inserts null bytes between the current end of the file + # and the new write position. + padding = b'\x00' * (pos - len(self._buffer)) + self._buffer += padding + self._buffer[pos:pos + n] = b + self._pos += n + return n + + def seek(self, pos, whence=0): + if self.closed: + raise ValueError("seek on closed file") + try: + pos.__index__ + except AttributeError: + raise TypeError("an integer is required") + if whence == 0: + if pos < 0: + raise ValueError("negative seek position %r" % (pos,)) + self._pos = pos + elif whence == 1: + self._pos = max(0, self._pos + pos) + elif whence == 2: + self._pos = max(0, len(self._buffer) + pos) + else: + raise ValueError("invalid whence value") + return self._pos + + def tell(self): + if self.closed: + raise ValueError("tell on closed file") + return self._pos + + def truncate(self, pos=None): + if self.closed: + raise ValueError("truncate on closed file") + if pos is None: + pos = self._pos + else: + try: + pos.__index__ + except AttributeError: + raise TypeError("an integer is required") + if pos < 0: + raise ValueError("negative truncate position %r" % (pos,)) + del self._buffer[pos:] + return pos + + def readable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") + return True + + def writable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") + return True + + def seekable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") + return True + + +class BufferedReader(_BufferedIOMixin): + + """BufferedReader(raw[, buffer_size]) + + A buffer for a readable, sequential BaseRawIO object. + + The constructor creates a BufferedReader for the given readable raw + stream and buffer_size. If buffer_size is omitted, DEFAULT_BUFFER_SIZE + is used. + """ + + def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): + """Create a new buffered reader using the given readable raw IO object. + """ + if not raw.readable(): + raise IOError('"raw" argument must be readable.') + + _BufferedIOMixin.__init__(self, raw) + if buffer_size <= 0: + raise ValueError("invalid buffer size") + self.buffer_size = buffer_size + self._reset_read_buf() + self._read_lock = Lock() + + def _reset_read_buf(self): + self._read_buf = b"" + self._read_pos = 0 + + def read(self, n=None): + """Read n bytes. + + Returns exactly n bytes of data unless the underlying raw IO + stream reaches EOF or if the call would block in non-blocking + mode. If n is negative, read until EOF or until read() would + block. + """ + if n is not None and n < -1: + raise ValueError("invalid number of bytes to read") + with self._read_lock: + return self._read_unlocked(n) + + def _read_unlocked(self, n=None): + nodata_val = b"" + empty_values = (b"", None) + buf = self._read_buf + pos = self._read_pos + + # Special case for when the number of bytes to read is unspecified. + if n is None or n == -1: + self._reset_read_buf() + chunks = [buf[pos:]] # Strip the consumed bytes. + current_size = 0 + while True: + # Read until EOF or until read() would block. + try: + chunk = self.raw.read() + except IOError as e: + if e.errno != EINTR: + raise + continue + if chunk in empty_values: + nodata_val = chunk + break + current_size += len(chunk) + chunks.append(chunk) + return b"".join(chunks) or nodata_val + + # The number of bytes to read is specified, return at most n bytes. + avail = len(buf) - pos # Length of the available buffered data. + if n <= avail: + # Fast path: the data to read is fully buffered. + self._read_pos += n + return buf[pos:pos+n] + # Slow path: read from the stream until enough bytes are read, + # or until an EOF occurs or until read() would block. + chunks = [buf[pos:]] + wanted = max(self.buffer_size, n) + while avail < n: + try: + chunk = self.raw.read(wanted) + except IOError as e: + if e.errno != EINTR: + raise + continue + if chunk in empty_values: + nodata_val = chunk + break + avail += len(chunk) + chunks.append(chunk) + # n is more then avail only when an EOF occurred or when + # read() would have blocked. + n = min(n, avail) + out = b"".join(chunks) + self._read_buf = out[n:] # Save the extra data in the buffer. + self._read_pos = 0 + return out[:n] if out else nodata_val + + def peek(self, n=0): + """Returns buffered bytes without advancing the position. + + The argument indicates a desired minimal number of bytes; we + do at most one raw read to satisfy it. We never return more + than self.buffer_size. + """ + with self._read_lock: + return self._peek_unlocked(n) + + def _peek_unlocked(self, n=0): + want = min(n, self.buffer_size) + have = len(self._read_buf) - self._read_pos + if have < want or have <= 0: + to_read = self.buffer_size - have + while True: + try: + current = self.raw.read(to_read) + except IOError as e: + if e.errno != EINTR: + raise + continue + break + if current: + self._read_buf = self._read_buf[self._read_pos:] + current + self._read_pos = 0 + return self._read_buf[self._read_pos:] + + def read1(self, n): + """Reads up to n bytes, with at most one read() system call.""" + # Returns up to n bytes. If at least one byte is buffered, we + # only return buffered bytes. Otherwise, we do one raw read. + if n < 0: + raise ValueError("number of bytes to read must be positive") + if n == 0: + return b"" + with self._read_lock: + self._peek_unlocked(1) + return self._read_unlocked( + min(n, len(self._read_buf) - self._read_pos)) + + def tell(self): + return _BufferedIOMixin.tell(self) - len(self._read_buf) + self._read_pos + + def seek(self, pos, whence=0): + if not (0 <= whence <= 2): + raise ValueError("invalid whence value") + with self._read_lock: + if whence == 1: + pos -= len(self._read_buf) - self._read_pos + pos = _BufferedIOMixin.seek(self, pos, whence) + self._reset_read_buf() + return pos + +class BufferedWriter(_BufferedIOMixin): + + """A buffer for a writeable sequential RawIO object. + + The constructor creates a BufferedWriter for the given writeable raw + stream. If the buffer_size is not given, it defaults to + DEFAULT_BUFFER_SIZE. + """ + + _warning_stack_offset = 2 + + def __init__(self, raw, + buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): + if not raw.writable(): + raise IOError('"raw" argument must be writable.') + + _BufferedIOMixin.__init__(self, raw) + if buffer_size <= 0: + raise ValueError("invalid buffer size") + if max_buffer_size is not None: + warnings.warn("max_buffer_size is deprecated", DeprecationWarning, + self._warning_stack_offset) + self.buffer_size = buffer_size + self._write_buf = bytearray() + self._write_lock = Lock() + + def write(self, b): + if self.closed: + raise ValueError("write to closed file") + if isinstance(b, unicode): + raise TypeError("can't write unicode to binary stream") + with self._write_lock: + # XXX we can implement some more tricks to try and avoid + # partial writes + if len(self._write_buf) > self.buffer_size: + # We're full, so let's pre-flush the buffer. (This may + # raise BlockingIOError with characters_written == 0.) + self._flush_unlocked() + before = len(self._write_buf) + self._write_buf.extend(b) + written = len(self._write_buf) - before + if len(self._write_buf) > self.buffer_size: + try: + self._flush_unlocked() + except BlockingIOError as e: + if len(self._write_buf) > self.buffer_size: + # We've hit the buffer_size. We have to accept a partial + # write and cut back our buffer. + overage = len(self._write_buf) - self.buffer_size + written -= overage + self._write_buf = self._write_buf[:self.buffer_size] + raise BlockingIOError(e.errno, e.strerror, written) + return written + + def truncate(self, pos=None): + with self._write_lock: + self._flush_unlocked() + if pos is None: + pos = self.raw.tell() + return self.raw.truncate(pos) + + def flush(self): + with self._write_lock: + self._flush_unlocked() + + def _flush_unlocked(self): + if self.closed: + raise ValueError("flush of closed file") + while self._write_buf: + try: + n = self.raw.write(self._write_buf) + except BlockingIOError: + raise RuntimeError("self.raw should implement RawIOBase: it " + "should not raise BlockingIOError") + except IOError as e: + if e.errno != EINTR: + raise + continue + if n is None: + raise BlockingIOError( + errno.EAGAIN, + "write could not complete without blocking", 0) + if n > len(self._write_buf) or n < 0: + raise IOError("write() returned incorrect number of bytes") + del self._write_buf[:n] + + def tell(self): + return _BufferedIOMixin.tell(self) + len(self._write_buf) + + def seek(self, pos, whence=0): + if not (0 <= whence <= 2): + raise ValueError("invalid whence") + with self._write_lock: + self._flush_unlocked() + return _BufferedIOMixin.seek(self, pos, whence) + + +class BufferedRWPair(BufferedIOBase): + + """A buffered reader and writer object together. + + A buffered reader object and buffered writer object put together to + form a sequential IO object that can read and write. This is typically + used with a socket or two-way pipe. + + reader and writer are RawIOBase objects that are readable and + writeable respectively. If the buffer_size is omitted it defaults to + DEFAULT_BUFFER_SIZE. + """ + + # XXX The usefulness of this (compared to having two separate IO + # objects) is questionable. + + def __init__(self, reader, writer, + buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): + """Constructor. + + The arguments are two RawIO instances. + """ + if max_buffer_size is not None: + warnings.warn("max_buffer_size is deprecated", DeprecationWarning, 2) + + if not reader.readable(): + raise IOError('"reader" argument must be readable.') + + if not writer.writable(): + raise IOError('"writer" argument must be writable.') + + self.reader = BufferedReader(reader, buffer_size) + self.writer = BufferedWriter(writer, buffer_size) + + def read(self, n=None): + if n is None: + n = -1 + return self.reader.read(n) + + def readinto(self, b): + return self.reader.readinto(b) + + def write(self, b): + return self.writer.write(b) + + def peek(self, n=0): + return self.reader.peek(n) + + def read1(self, n): + return self.reader.read1(n) + + def readable(self): + return self.reader.readable() + + def writable(self): + return self.writer.writable() + + def flush(self): + return self.writer.flush() + + def close(self): + self.writer.close() + self.reader.close() + + def isatty(self): + return self.reader.isatty() or self.writer.isatty() + + @property + def closed(self): + return self.writer.closed + + +class BufferedRandom(BufferedWriter, BufferedReader): + + """A buffered interface to random access streams. + + The constructor creates a reader and writer for a seekable stream, + raw, given in the first argument. If the buffer_size is omitted it + defaults to DEFAULT_BUFFER_SIZE. + """ + + _warning_stack_offset = 3 + + def __init__(self, raw, + buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): + raw._checkSeekable() + BufferedReader.__init__(self, raw, buffer_size) + BufferedWriter.__init__(self, raw, buffer_size, max_buffer_size) + + def seek(self, pos, whence=0): + if not (0 <= whence <= 2): + raise ValueError("invalid whence") + self.flush() + if self._read_buf: + # Undo read ahead. + with self._read_lock: + self.raw.seek(self._read_pos - len(self._read_buf), 1) + # First do the raw seek, then empty the read buffer, so that + # if the raw seek fails, we don't lose buffered data forever. + pos = self.raw.seek(pos, whence) + with self._read_lock: + self._reset_read_buf() + if pos < 0: + raise IOError("seek() returned invalid position") + return pos + + def tell(self): + if self._write_buf: + return BufferedWriter.tell(self) + else: + return BufferedReader.tell(self) + + def truncate(self, pos=None): + if pos is None: + pos = self.tell() + # Use seek to flush the read buffer. + return BufferedWriter.truncate(self, pos) + + def read(self, n=None): + if n is None: + n = -1 + self.flush() + return BufferedReader.read(self, n) + + def readinto(self, b): + self.flush() + return BufferedReader.readinto(self, b) + + def peek(self, n=0): + self.flush() + return BufferedReader.peek(self, n) + + def read1(self, n): + self.flush() + return BufferedReader.read1(self, n) + + def write(self, b): + if self._read_buf: + # Undo readahead + with self._read_lock: + self.raw.seek(self._read_pos - len(self._read_buf), 1) + self._reset_read_buf() + return BufferedWriter.write(self, b) + + +class TextIOBase(IOBase): + + """Base class for text I/O. + + This class provides a character and line based interface to stream + I/O. There is no readinto method because Python's character strings + are immutable. There is no public constructor. + """ + + def read(self, n=-1): + """Read at most n characters from stream. + + Read from underlying buffer until we have n characters or we hit EOF. + If n is negative or omitted, read until EOF. + """ + self._unsupported("read") + + def write(self, s): + """Write string s to stream.""" + self._unsupported("write") + + def truncate(self, pos=None): + """Truncate size to pos.""" + self._unsupported("truncate") + + def readline(self): + """Read until newline or EOF. + + Returns an empty string if EOF is hit immediately. + """ + self._unsupported("readline") + + def detach(self): + """ + Separate the underlying buffer from the TextIOBase and return it. + + After the underlying buffer has been detached, the TextIO is in an + unusable state. + """ + self._unsupported("detach") + + @property + def encoding(self): + """Subclasses should override.""" + return None + + @property + def newlines(self): + """Line endings translated so far. + + Only line endings translated during reading are considered. + + Subclasses should override. + """ + return None + + @property + def errors(self): + """Error setting of the decoder or encoder. + + Subclasses should override.""" + return None + +io.TextIOBase.register(TextIOBase) + + +class IncrementalNewlineDecoder(codecs.IncrementalDecoder): + r"""Codec used when reading a file in universal newlines mode. It wraps + another incremental decoder, translating \r\n and \r into \n. It also + records the types of newlines encountered. When used with + translate=False, it ensures that the newline sequence is returned in + one piece. + """ + def __init__(self, decoder, translate, errors='strict'): + codecs.IncrementalDecoder.__init__(self, errors=errors) + self.translate = translate + self.decoder = decoder + self.seennl = 0 + self.pendingcr = False + + def decode(self, input, final=False): + # decode input (with the eventual \r from a previous pass) + if self.decoder is None: + output = input + else: + output = self.decoder.decode(input, final=final) + if self.pendingcr and (output or final): + output = "\r" + output + self.pendingcr = False + + # retain last \r even when not translating data: + # then readline() is sure to get \r\n in one pass + if output.endswith("\r") and not final: + output = output[:-1] + self.pendingcr = True + + # Record which newlines are read + crlf = output.count('\r\n') + cr = output.count('\r') - crlf + lf = output.count('\n') - crlf + self.seennl |= (lf and self._LF) | (cr and self._CR) \ + | (crlf and self._CRLF) + + if self.translate: + if crlf: + output = output.replace("\r\n", "\n") + if cr: + output = output.replace("\r", "\n") + + return output + + def getstate(self): + if self.decoder is None: + buf = b"" + flag = 0 + else: + buf, flag = self.decoder.getstate() + flag <<= 1 + if self.pendingcr: + flag |= 1 + return buf, flag + + def setstate(self, state): + buf, flag = state + self.pendingcr = bool(flag & 1) + if self.decoder is not None: + self.decoder.setstate((buf, flag >> 1)) + + def reset(self): + self.seennl = 0 + self.pendingcr = False + if self.decoder is not None: + self.decoder.reset() + + _LF = 1 + _CR = 2 + _CRLF = 4 + + @property + def newlines(self): + return (None, + "\n", + "\r", + ("\r", "\n"), + "\r\n", + ("\n", "\r\n"), + ("\r", "\r\n"), + ("\r", "\n", "\r\n") + )[self.seennl] + + +class TextIOWrapper(TextIOBase): + + r"""Character and line based layer over a BufferedIOBase object, buffer. + + encoding gives the name of the encoding that the stream will be + decoded or encoded with. It defaults to locale.getpreferredencoding. + + errors determines the strictness of encoding and decoding (see the + codecs.register) and defaults to "strict". + + newline can be None, '', '\n', '\r', or '\r\n'. It controls the + handling of line endings. If it is None, universal newlines is + enabled. With this enabled, on input, the lines endings '\n', '\r', + or '\r\n' are translated to '\n' before being returned to the + caller. Conversely, on output, '\n' is translated to the system + default line separator, os.linesep. If newline is any other of its + legal values, that newline becomes the newline when the file is read + and it is returned untranslated. On output, '\n' is converted to the + newline. + + If line_buffering is True, a call to flush is implied when a call to + write contains a newline character. + """ + + _CHUNK_SIZE = 2048 + + def __init__(self, buffer, encoding=None, errors=None, newline=None, + line_buffering=False): + if newline is not None and not isinstance(newline, basestring): + raise TypeError("illegal newline type: %r" % (type(newline),)) + if newline not in (None, "", "\n", "\r", "\r\n"): + raise ValueError("illegal newline value: %r" % (newline,)) + if encoding is None: + try: + import locale + except ImportError: + # Importing locale may fail if Python is being built + encoding = "ascii" + else: + encoding = locale.getpreferredencoding() + + if not isinstance(encoding, basestring): + raise ValueError("invalid encoding: %r" % encoding) + + if errors is None: + errors = "strict" + else: + if not isinstance(errors, basestring): + raise ValueError("invalid errors: %r" % errors) + + self._buffer = buffer + self._line_buffering = line_buffering + self._encoding = encoding + self._errors = errors + self._readuniversal = not newline + self._readtranslate = newline is None + self._readnl = newline + self._writetranslate = newline != '' + self._writenl = newline or os.linesep + self._encoder = None + self._decoder = None + self._decoded_chars = '' # buffer for text returned from decoder + self._decoded_chars_used = 0 # offset into _decoded_chars for read() + self._snapshot = None # info for reconstructing decoder state + self._seekable = self._telling = self.buffer.seekable() + + if self._seekable and self.writable(): + position = self.buffer.tell() + if position != 0: + try: + self._get_encoder().setstate(0) + except LookupError: + # Sometimes the encoder doesn't exist + pass + + # self._snapshot is either None, or a tuple (dec_flags, next_input) + # where dec_flags is the second (integer) item of the decoder state + # and next_input is the chunk of input bytes that comes next after the + # snapshot point. We use this to reconstruct decoder states in tell(). + + # Naming convention: + # - "bytes_..." for integer variables that count input bytes + # - "chars_..." for integer variables that count decoded characters + + def __repr__(self): + try: + name = self.name + except AttributeError: + return "<_pyio.TextIOWrapper encoding='{0}'>".format(self.encoding) + else: + return "<_pyio.TextIOWrapper name={0!r} encoding='{1}'>".format( + name, self.encoding) + + @property + def encoding(self): + return self._encoding + + @property + def errors(self): + return self._errors + + @property + def line_buffering(self): + return self._line_buffering + + @property + def buffer(self): + return self._buffer + + def seekable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") + return self._seekable + + def readable(self): + return self.buffer.readable() + + def writable(self): + return self.buffer.writable() + + def flush(self): + self.buffer.flush() + self._telling = self._seekable + + def close(self): + if self.buffer is not None and not self.closed: + try: + self.flush() + finally: + self.buffer.close() + + @property + def closed(self): + return self.buffer.closed + + @property + def name(self): + return self.buffer.name + + def fileno(self): + return self.buffer.fileno() + + def isatty(self): + return self.buffer.isatty() + + def write(self, s): + if self.closed: + raise ValueError("write to closed file") + if not isinstance(s, unicode): + raise TypeError("can't write %s to text stream" % + s.__class__.__name__) + length = len(s) + haslf = (self._writetranslate or self._line_buffering) and "\n" in s + if haslf and self._writetranslate and self._writenl != "\n": + s = s.replace("\n", self._writenl) + encoder = self._encoder or self._get_encoder() + # XXX What if we were just reading? + b = encoder.encode(s) + self.buffer.write(b) + if self._line_buffering and (haslf or "\r" in s): + self.flush() + self._snapshot = None + if self._decoder: + self._decoder.reset() + return length + + def _get_encoder(self): + make_encoder = codecs.getincrementalencoder(self._encoding) + self._encoder = make_encoder(self._errors) + return self._encoder + + def _get_decoder(self): + make_decoder = codecs.getincrementaldecoder(self._encoding) + decoder = make_decoder(self._errors) + if self._readuniversal: + decoder = IncrementalNewlineDecoder(decoder, self._readtranslate) + self._decoder = decoder + return decoder + + # The following three methods implement an ADT for _decoded_chars. + # Text returned from the decoder is buffered here until the client + # requests it by calling our read() or readline() method. + def _set_decoded_chars(self, chars): + """Set the _decoded_chars buffer.""" + self._decoded_chars = chars + self._decoded_chars_used = 0 + + def _get_decoded_chars(self, n=None): + """Advance into the _decoded_chars buffer.""" + offset = self._decoded_chars_used + if n is None: + chars = self._decoded_chars[offset:] + else: + chars = self._decoded_chars[offset:offset + n] + self._decoded_chars_used += len(chars) + return chars + + def _rewind_decoded_chars(self, n): + """Rewind the _decoded_chars buffer.""" + if self._decoded_chars_used < n: + raise AssertionError("rewind decoded_chars out of bounds") + self._decoded_chars_used -= n + + def _read_chunk(self): + """ + Read and decode the next chunk of data from the BufferedReader. + """ + + # The return value is True unless EOF was reached. The decoded + # string is placed in self._decoded_chars (replacing its previous + # value). The entire input chunk is sent to the decoder, though + # some of it may remain buffered in the decoder, yet to be + # converted. + + if self._decoder is None: + raise ValueError("no decoder") + + if self._telling: + # To prepare for tell(), we need to snapshot a point in the + # file where the decoder's input buffer is empty. + + dec_buffer, dec_flags = self._decoder.getstate() + # Given this, we know there was a valid snapshot point + # len(dec_buffer) bytes ago with decoder state (b'', dec_flags). + + # Read a chunk, decode it, and put the result in self._decoded_chars. + input_chunk = self.buffer.read1(self._CHUNK_SIZE) + eof = not input_chunk + self._set_decoded_chars(self._decoder.decode(input_chunk, eof)) + + if self._telling: + # At the snapshot point, len(dec_buffer) bytes before the read, + # the next input to be decoded is dec_buffer + input_chunk. + self._snapshot = (dec_flags, dec_buffer + input_chunk) + + return not eof + + def _pack_cookie(self, position, dec_flags=0, + bytes_to_feed=0, need_eof=0, chars_to_skip=0): + # The meaning of a tell() cookie is: seek to position, set the + # decoder flags to dec_flags, read bytes_to_feed bytes, feed them + # into the decoder with need_eof as the EOF flag, then skip + # chars_to_skip characters of the decoded result. For most simple + # decoders, tell() will often just give a byte offset in the file. + return (position | (dec_flags<<64) | (bytes_to_feed<<128) | + (chars_to_skip<<192) | bool(need_eof)<<256) + + def _unpack_cookie(self, bigint): + rest, position = divmod(bigint, 1<<64) + rest, dec_flags = divmod(rest, 1<<64) + rest, bytes_to_feed = divmod(rest, 1<<64) + need_eof, chars_to_skip = divmod(rest, 1<<64) + return position, dec_flags, bytes_to_feed, need_eof, chars_to_skip + + def tell(self): + if not self._seekable: + raise IOError("underlying stream is not seekable") + if not self._telling: + raise IOError("telling position disabled by next() call") + self.flush() + position = self.buffer.tell() + decoder = self._decoder + if decoder is None or self._snapshot is None: + if self._decoded_chars: + # This should never happen. + raise AssertionError("pending decoded text") + return position + + # Skip backward to the snapshot point (see _read_chunk). + dec_flags, next_input = self._snapshot + position -= len(next_input) + + # How many decoded characters have been used up since the snapshot? + chars_to_skip = self._decoded_chars_used + if chars_to_skip == 0: + # We haven't moved from the snapshot point. + return self._pack_cookie(position, dec_flags) + + # Starting from the snapshot position, we will walk the decoder + # forward until it gives us enough decoded characters. + saved_state = decoder.getstate() + try: + # Note our initial start point. + decoder.setstate((b'', dec_flags)) + start_pos = position + start_flags, bytes_fed, chars_decoded = dec_flags, 0, 0 + need_eof = 0 + + # Feed the decoder one byte at a time. As we go, note the + # nearest "safe start point" before the current location + # (a point where the decoder has nothing buffered, so seek() + # can safely start from there and advance to this location). + for next_byte in next_input: + bytes_fed += 1 + chars_decoded += len(decoder.decode(next_byte)) + dec_buffer, dec_flags = decoder.getstate() + if not dec_buffer and chars_decoded <= chars_to_skip: + # Decoder buffer is empty, so this is a safe start point. + start_pos += bytes_fed + chars_to_skip -= chars_decoded + start_flags, bytes_fed, chars_decoded = dec_flags, 0, 0 + if chars_decoded >= chars_to_skip: + break + else: + # We didn't get enough decoded data; signal EOF to get more. + chars_decoded += len(decoder.decode(b'', final=True)) + need_eof = 1 + if chars_decoded < chars_to_skip: + raise IOError("can't reconstruct logical file position") + + # The returned cookie corresponds to the last safe start point. + return self._pack_cookie( + start_pos, start_flags, bytes_fed, need_eof, chars_to_skip) + finally: + decoder.setstate(saved_state) + + def truncate(self, pos=None): + self.flush() + if pos is None: + pos = self.tell() + return self.buffer.truncate(pos) + + def detach(self): + if self.buffer is None: + raise ValueError("buffer is already detached") + self.flush() + buffer = self._buffer + self._buffer = None + return buffer + + def seek(self, cookie, whence=0): + if self.closed: + raise ValueError("tell on closed file") + if not self._seekable: + raise IOError("underlying stream is not seekable") + if whence == 1: # seek relative to current position + if cookie != 0: + raise IOError("can't do nonzero cur-relative seeks") + # Seeking to the current position should attempt to + # sync the underlying buffer with the current position. + whence = 0 + cookie = self.tell() + if whence == 2: # seek relative to end of file + if cookie != 0: + raise IOError("can't do nonzero end-relative seeks") + self.flush() + position = self.buffer.seek(0, 2) + self._set_decoded_chars('') + self._snapshot = None + if self._decoder: + self._decoder.reset() + return position + if whence != 0: + raise ValueError("invalid whence (%r, should be 0, 1 or 2)" % + (whence,)) + if cookie < 0: + raise ValueError("negative seek position %r" % (cookie,)) + self.flush() + + # The strategy of seek() is to go back to the safe start point + # and replay the effect of read(chars_to_skip) from there. + start_pos, dec_flags, bytes_to_feed, need_eof, chars_to_skip = \ + self._unpack_cookie(cookie) + + # Seek back to the safe start point. + self.buffer.seek(start_pos) + self._set_decoded_chars('') + self._snapshot = None + + # Restore the decoder to its state from the safe start point. + if cookie == 0 and self._decoder: + self._decoder.reset() + elif self._decoder or dec_flags or chars_to_skip: + self._decoder = self._decoder or self._get_decoder() + self._decoder.setstate((b'', dec_flags)) + self._snapshot = (dec_flags, b'') + + if chars_to_skip: + # Just like _read_chunk, feed the decoder and save a snapshot. + input_chunk = self.buffer.read(bytes_to_feed) + self._set_decoded_chars( + self._decoder.decode(input_chunk, need_eof)) + self._snapshot = (dec_flags, input_chunk) + + # Skip chars_to_skip of the decoded characters. + if len(self._decoded_chars) < chars_to_skip: + raise IOError("can't restore logical file position") + self._decoded_chars_used = chars_to_skip + + # Finally, reset the encoder (merely useful for proper BOM handling) + try: + encoder = self._encoder or self._get_encoder() + except LookupError: + # Sometimes the encoder doesn't exist + pass + else: + if cookie != 0: + encoder.setstate(0) + else: + encoder.reset() + return cookie + + def read(self, n=None): + self._checkReadable() + if n is None: + n = -1 + decoder = self._decoder or self._get_decoder() + try: + n.__index__ + except AttributeError: + raise TypeError("an integer is required") + if n < 0: + # Read everything. + result = (self._get_decoded_chars() + + decoder.decode(self.buffer.read(), final=True)) + self._set_decoded_chars('') + self._snapshot = None + return result + else: + # Keep reading chunks until we have n characters to return. + eof = False + result = self._get_decoded_chars(n) + while len(result) < n and not eof: + eof = not self._read_chunk() + result += self._get_decoded_chars(n - len(result)) + return result + + def next(self): + self._telling = False + line = self.readline() + if not line: + self._snapshot = None + self._telling = self._seekable + raise StopIteration + return line + + def readline(self, limit=None): + if self.closed: + raise ValueError("read from closed file") + if limit is None: + limit = -1 + elif not isinstance(limit, (int, long)): + raise TypeError("limit must be an integer") + + # Grab all the decoded text (we will rewind any extra bits later). + line = self._get_decoded_chars() + + start = 0 + # Make the decoder if it doesn't already exist. + if not self._decoder: + self._get_decoder() + + pos = endpos = None + while True: + if self._readtranslate: + # Newlines are already translated, only search for \n + pos = line.find('\n', start) + if pos >= 0: + endpos = pos + 1 + break + else: + start = len(line) + + elif self._readuniversal: + # Universal newline search. Find any of \r, \r\n, \n + # The decoder ensures that \r\n are not split in two pieces + + # In C we'd look for these in parallel of course. + nlpos = line.find("\n", start) + crpos = line.find("\r", start) + if crpos == -1: + if nlpos == -1: + # Nothing found + start = len(line) + else: + # Found \n + endpos = nlpos + 1 + break + elif nlpos == -1: + # Found lone \r + endpos = crpos + 1 + break + elif nlpos < crpos: + # Found \n + endpos = nlpos + 1 + break + elif nlpos == crpos + 1: + # Found \r\n + endpos = crpos + 2 + break + else: + # Found \r + endpos = crpos + 1 + break + else: + # non-universal + pos = line.find(self._readnl) + if pos >= 0: + endpos = pos + len(self._readnl) + break + + if limit >= 0 and len(line) >= limit: + endpos = limit # reached length limit + break + + # No line ending seen yet - get more data' + while self._read_chunk(): + if self._decoded_chars: + break + if self._decoded_chars: + line += self._get_decoded_chars() + else: + # end of file + self._set_decoded_chars('') + self._snapshot = None + return line + + if limit >= 0 and endpos > limit: + endpos = limit # don't exceed limit + + # Rewind _decoded_chars to just after the line ending we found. + self._rewind_decoded_chars(len(line) - endpos) + return line[:endpos] + + @property + def newlines(self): + return self._decoder.newlines if self._decoder else None + + +class StringIO(TextIOWrapper): + """Text I/O implementation using an in-memory buffer. + + The initial_value argument sets the value of object. The newline + argument is like the one of TextIOWrapper's constructor. + """ + + def __init__(self, initial_value="", newline="\n"): + super(StringIO, self).__init__(BytesIO(), + encoding="utf-8", + errors="strict", + newline=newline) + # Issue #5645: make universal newlines semantics the same as in the + # C version, even under Windows. + if newline is None: + self._writetranslate = False + if initial_value: + if not isinstance(initial_value, unicode): + initial_value = unicode(initial_value) + self.write(initial_value) + self.seek(0) + + def getvalue(self): + self.flush() + decoder = self._decoder or self._get_decoder() + old_state = decoder.getstate() + decoder.reset() + try: + return decoder.decode(self.buffer.getvalue(), final=True) + finally: + decoder.setstate(old_state) + + def __repr__(self): + # TextIOWrapper tells the encoding in its repr. In StringIO, + # that's a implementation detail. + return object.__repr__(self) + + @property + def errors(self): + return None + + @property + def encoding(self): + return None + + def detach(self): + # This doesn't make sense on StringIO. + self._unsupported("detach") diff --git a/PythonHome/Lib/_pyio.pyc b/PythonHome/Lib/_pyio.pyc deleted file mode 100644 index cfaad1f8bd5836e07e09f2f98c772db46e7c9b24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61784 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 Ze{27HZ$7^N-Mi{Hzp(!c*%z`s|1T+;y%Ycd diff --git a/PythonHome/Lib/_strptime.py b/PythonHome/Lib/_strptime.py new file mode 100644 index 0000000000..042db6f4f0 --- /dev/null +++ b/PythonHome/Lib/_strptime.py @@ -0,0 +1,467 @@ +"""Strptime-related classes and functions. + +CLASSES: + LocaleTime -- Discovers and stores locale-specific time information + TimeRE -- Creates regexes for pattern matching a string of text containing + time information + +FUNCTIONS: + _getlang -- Figure out what language is being used for the locale + strptime -- Calculates the time struct represented by the passed-in string + +""" +import time +import locale +import calendar +from re import compile as re_compile +from re import IGNORECASE +from re import escape as re_escape +from datetime import date as datetime_date +try: + from thread import allocate_lock as _thread_allocate_lock +except: + from dummy_thread import allocate_lock as _thread_allocate_lock + +__all__ = [] + +def _getlang(): + # Figure out what the current language is set to. + return locale.getlocale(locale.LC_TIME) + +class LocaleTime(object): + """Stores and handles locale-specific information related to time. + + ATTRIBUTES: + f_weekday -- full weekday names (7-item list) + a_weekday -- abbreviated weekday names (7-item list) + f_month -- full month names (13-item list; dummy value in [0], which + is added by code) + a_month -- abbreviated month names (13-item list, dummy value in + [0], which is added by code) + am_pm -- AM/PM representation (2-item list) + LC_date_time -- format string for date/time representation (string) + LC_date -- format string for date representation (string) + LC_time -- format string for time representation (string) + timezone -- daylight- and non-daylight-savings timezone representation + (2-item list of sets) + lang -- Language used by instance (2-item tuple) + """ + + def __init__(self): + """Set all attributes. + + Order of methods called matters for dependency reasons. + + The locale language is set at the offset and then checked again before + exiting. This is to make sure that the attributes were not set with a + mix of information from more than one locale. This would most likely + happen when using threads where one thread calls a locale-dependent + function while another thread changes the locale while the function in + the other thread is still running. Proper coding would call for + locks to prevent changing the locale while locale-dependent code is + running. The check here is done in case someone does not think about + doing this. + + Only other possible issue is if someone changed the timezone and did + not call tz.tzset . That is an issue for the programmer, though, + since changing the timezone is worthless without that call. + + """ + self.lang = _getlang() + self.__calc_weekday() + self.__calc_month() + self.__calc_am_pm() + self.__calc_timezone() + self.__calc_date_time() + if _getlang() != self.lang: + raise ValueError("locale changed during initialization") + + def __pad(self, seq, front): + # Add '' to seq to either the front (is True), else the back. + seq = list(seq) + if front: + seq.insert(0, '') + else: + seq.append('') + return seq + + def __calc_weekday(self): + # Set self.a_weekday and self.f_weekday using the calendar + # module. + a_weekday = [calendar.day_abbr[i].lower() for i in range(7)] + f_weekday = [calendar.day_name[i].lower() for i in range(7)] + self.a_weekday = a_weekday + self.f_weekday = f_weekday + + def __calc_month(self): + # Set self.f_month and self.a_month using the calendar module. + a_month = [calendar.month_abbr[i].lower() for i in range(13)] + f_month = [calendar.month_name[i].lower() for i in range(13)] + self.a_month = a_month + self.f_month = f_month + + def __calc_am_pm(self): + # Set self.am_pm by using time.strftime(). + + # The magic date (1999,3,17,hour,44,55,2,76,0) is not really that + # magical; just happened to have used it everywhere else where a + # static date was needed. + am_pm = [] + for hour in (01,22): + time_tuple = time.struct_time((1999,3,17,hour,44,55,2,76,0)) + am_pm.append(time.strftime("%p", time_tuple).lower()) + self.am_pm = am_pm + + def __calc_date_time(self): + # Set self.date_time, self.date, & self.time by using + # time.strftime(). + + # Use (1999,3,17,22,44,55,2,76,0) for magic date because the amount of + # overloaded numbers is minimized. The order in which searches for + # values within the format string is very important; it eliminates + # possible ambiguity for what something represents. + time_tuple = time.struct_time((1999,3,17,22,44,55,2,76,0)) + date_time = [None, None, None] + date_time[0] = time.strftime("%c", time_tuple).lower() + date_time[1] = time.strftime("%x", time_tuple).lower() + date_time[2] = time.strftime("%X", time_tuple).lower() + replacement_pairs = [('%', '%%'), (self.f_weekday[2], '%A'), + (self.f_month[3], '%B'), (self.a_weekday[2], '%a'), + (self.a_month[3], '%b'), (self.am_pm[1], '%p'), + ('1999', '%Y'), ('99', '%y'), ('22', '%H'), + ('44', '%M'), ('55', '%S'), ('76', '%j'), + ('17', '%d'), ('03', '%m'), ('3', '%m'), + # '3' needed for when no leading zero. + ('2', '%w'), ('10', '%I')] + replacement_pairs.extend([(tz, "%Z") for tz_values in self.timezone + for tz in tz_values]) + for offset,directive in ((0,'%c'), (1,'%x'), (2,'%X')): + current_format = date_time[offset] + for old, new in replacement_pairs: + # Must deal with possible lack of locale info + # manifesting itself as the empty string (e.g., Swedish's + # lack of AM/PM info) or a platform returning a tuple of empty + # strings (e.g., MacOS 9 having timezone as ('','')). + if old: + current_format = current_format.replace(old, new) + # If %W is used, then Sunday, 2005-01-03 will fall on week 0 since + # 2005-01-03 occurs before the first Monday of the year. Otherwise + # %U is used. + time_tuple = time.struct_time((1999,1,3,1,1,1,6,3,0)) + if '00' in time.strftime(directive, time_tuple): + U_W = '%W' + else: + U_W = '%U' + date_time[offset] = current_format.replace('11', U_W) + self.LC_date_time = date_time[0] + self.LC_date = date_time[1] + self.LC_time = date_time[2] + + def __calc_timezone(self): + # Set self.timezone by using time.tzname. + # Do not worry about possibility of time.tzname[0] == timetzname[1] + # and time.daylight; handle that in strptime . + try: + time.tzset() + except AttributeError: + pass + no_saving = frozenset(["utc", "gmt", time.tzname[0].lower()]) + if time.daylight: + has_saving = frozenset([time.tzname[1].lower()]) + else: + has_saving = frozenset() + self.timezone = (no_saving, has_saving) + + +class TimeRE(dict): + """Handle conversion from format directives to regexes.""" + + def __init__(self, locale_time=None): + """Create keys/values. + + Order of execution is important for dependency reasons. + + """ + if locale_time: + self.locale_time = locale_time + else: + self.locale_time = LocaleTime() + base = super(TimeRE, self) + base.__init__({ + # The " \d" part of the regex is to make %c from ANSI C work + 'd': r"(?P3[0-1]|[1-2]\d|0[1-9]|[1-9]| [1-9])", + 'f': r"(?P[0-9]{1,6})", + 'H': r"(?P2[0-3]|[0-1]\d|\d)", + 'I': r"(?P1[0-2]|0[1-9]|[1-9])", + 'j': r"(?P36[0-6]|3[0-5]\d|[1-2]\d\d|0[1-9]\d|00[1-9]|[1-9]\d|0[1-9]|[1-9])", + 'm': r"(?P1[0-2]|0[1-9]|[1-9])", + 'M': r"(?P[0-5]\d|\d)", + 'S': r"(?P6[0-1]|[0-5]\d|\d)", + 'U': r"(?P5[0-3]|[0-4]\d|\d)", + 'w': r"(?P[0-6])", + # W is set below by using 'U' + 'y': r"(?P\d\d)", + #XXX: Does 'Y' need to worry about having less or more than + # 4 digits? + 'Y': r"(?P\d\d\d\d)", + 'A': self.__seqToRE(self.locale_time.f_weekday, 'A'), + 'a': self.__seqToRE(self.locale_time.a_weekday, 'a'), + 'B': self.__seqToRE(self.locale_time.f_month[1:], 'B'), + 'b': self.__seqToRE(self.locale_time.a_month[1:], 'b'), + 'p': self.__seqToRE(self.locale_time.am_pm, 'p'), + 'Z': self.__seqToRE((tz for tz_names in self.locale_time.timezone + for tz in tz_names), + 'Z'), + '%': '%'}) + base.__setitem__('W', base.__getitem__('U').replace('U', 'W')) + base.__setitem__('c', self.pattern(self.locale_time.LC_date_time)) + base.__setitem__('x', self.pattern(self.locale_time.LC_date)) + base.__setitem__('X', self.pattern(self.locale_time.LC_time)) + + def __seqToRE(self, to_convert, directive): + """Convert a list to a regex string for matching a directive. + + Want possible matching values to be from longest to shortest. This + prevents the possibility of a match occurring for a value that also + a substring of a larger value that should have matched (e.g., 'abc' + matching when 'abcdef' should have been the match). + + """ + to_convert = sorted(to_convert, key=len, reverse=True) + for value in to_convert: + if value != '': + break + else: + return '' + regex = '|'.join(re_escape(stuff) for stuff in to_convert) + regex = '(?P<%s>%s' % (directive, regex) + return '%s)' % regex + + def pattern(self, format): + """Return regex pattern for the format string. + + Need to make sure that any characters that might be interpreted as + regex syntax are escaped. + + """ + processed_format = '' + # The sub() call escapes all characters that might be misconstrued + # as regex syntax. Cannot use re.escape since we have to deal with + # format directives (%m, etc.). + regex_chars = re_compile(r"([\\.^$*+?\(\){}\[\]|])") + format = regex_chars.sub(r"\\\1", format) + whitespace_replacement = re_compile('\s+') + format = whitespace_replacement.sub('\s+', format) + while '%' in format: + directive_index = format.index('%')+1 + processed_format = "%s%s%s" % (processed_format, + format[:directive_index-1], + self[format[directive_index]]) + format = format[directive_index+1:] + return "%s%s" % (processed_format, format) + + def compile(self, format): + """Return a compiled re object for the format string.""" + return re_compile(self.pattern(format), IGNORECASE) + +_cache_lock = _thread_allocate_lock() +# DO NOT modify _TimeRE_cache or _regex_cache without acquiring the cache lock +# first! +_TimeRE_cache = TimeRE() +_CACHE_MAX_SIZE = 5 # Max number of regexes stored in _regex_cache +_regex_cache = {} + +def _calc_julian_from_U_or_W(year, week_of_year, day_of_week, week_starts_Mon): + """Calculate the Julian day based on the year, week of the year, and day of + the week, with week_start_day representing whether the week of the year + assumes the week starts on Sunday or Monday (6 or 0).""" + first_weekday = datetime_date(year, 1, 1).weekday() + # If we are dealing with the %U directive (week starts on Sunday), it's + # easier to just shift the view to Sunday being the first day of the + # week. + if not week_starts_Mon: + first_weekday = (first_weekday + 1) % 7 + day_of_week = (day_of_week + 1) % 7 + # Need to watch out for a week 0 (when the first day of the year is not + # the same as that specified by %U or %W). + week_0_length = (7 - first_weekday) % 7 + if week_of_year == 0: + return 1 + day_of_week - first_weekday + else: + days_to_week = week_0_length + (7 * (week_of_year - 1)) + return 1 + days_to_week + day_of_week + + +def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"): + """Return a time struct based on the input string and the format string.""" + global _TimeRE_cache, _regex_cache + with _cache_lock: + if _getlang() != _TimeRE_cache.locale_time.lang: + _TimeRE_cache = TimeRE() + _regex_cache.clear() + if len(_regex_cache) > _CACHE_MAX_SIZE: + _regex_cache.clear() + locale_time = _TimeRE_cache.locale_time + format_regex = _regex_cache.get(format) + if not format_regex: + try: + format_regex = _TimeRE_cache.compile(format) + # KeyError raised when a bad format is found; can be specified as + # \\, in which case it was a stray % but with a space after it + except KeyError, err: + bad_directive = err.args[0] + if bad_directive == "\\": + bad_directive = "%" + del err + raise ValueError("'%s' is a bad directive in format '%s'" % + (bad_directive, format)) + # IndexError only occurs when the format string is "%" + except IndexError: + raise ValueError("stray %% in format '%s'" % format) + _regex_cache[format] = format_regex + found = format_regex.match(data_string) + if not found: + raise ValueError("time data %r does not match format %r" % + (data_string, format)) + if len(data_string) != found.end(): + raise ValueError("unconverted data remains: %s" % + data_string[found.end():]) + + year = None + month = day = 1 + hour = minute = second = fraction = 0 + tz = -1 + # Default to -1 to signify that values not known; not critical to have, + # though + week_of_year = -1 + week_of_year_start = -1 + # weekday and julian defaulted to -1 so as to signal need to calculate + # values + weekday = julian = -1 + found_dict = found.groupdict() + for group_key in found_dict.iterkeys(): + # Directives not explicitly handled below: + # c, x, X + # handled by making out of other directives + # U, W + # worthless without day of the week + if group_key == 'y': + year = int(found_dict['y']) + # Open Group specification for strptime() states that a %y + #value in the range of [00, 68] is in the century 2000, while + #[69,99] is in the century 1900 + if year <= 68: + year += 2000 + else: + year += 1900 + elif group_key == 'Y': + year = int(found_dict['Y']) + elif group_key == 'm': + month = int(found_dict['m']) + elif group_key == 'B': + month = locale_time.f_month.index(found_dict['B'].lower()) + elif group_key == 'b': + month = locale_time.a_month.index(found_dict['b'].lower()) + elif group_key == 'd': + day = int(found_dict['d']) + elif group_key == 'H': + hour = int(found_dict['H']) + elif group_key == 'I': + hour = int(found_dict['I']) + ampm = found_dict.get('p', '').lower() + # If there was no AM/PM indicator, we'll treat this like AM + if ampm in ('', locale_time.am_pm[0]): + # We're in AM so the hour is correct unless we're + # looking at 12 midnight. + # 12 midnight == 12 AM == hour 0 + if hour == 12: + hour = 0 + elif ampm == locale_time.am_pm[1]: + # We're in PM so we need to add 12 to the hour unless + # we're looking at 12 noon. + # 12 noon == 12 PM == hour 12 + if hour != 12: + hour += 12 + elif group_key == 'M': + minute = int(found_dict['M']) + elif group_key == 'S': + second = int(found_dict['S']) + elif group_key == 'f': + s = found_dict['f'] + # Pad to always return microseconds. + s += "0" * (6 - len(s)) + fraction = int(s) + elif group_key == 'A': + weekday = locale_time.f_weekday.index(found_dict['A'].lower()) + elif group_key == 'a': + weekday = locale_time.a_weekday.index(found_dict['a'].lower()) + elif group_key == 'w': + weekday = int(found_dict['w']) + if weekday == 0: + weekday = 6 + else: + weekday -= 1 + elif group_key == 'j': + julian = int(found_dict['j']) + elif group_key in ('U', 'W'): + week_of_year = int(found_dict[group_key]) + if group_key == 'U': + # U starts week on Sunday. + week_of_year_start = 6 + else: + # W starts week on Monday. + week_of_year_start = 0 + elif group_key == 'Z': + # Since -1 is default value only need to worry about setting tz if + # it can be something other than -1. + found_zone = found_dict['Z'].lower() + for value, tz_values in enumerate(locale_time.timezone): + if found_zone in tz_values: + # Deal with bad locale setup where timezone names are the + # same and yet time.daylight is true; too ambiguous to + # be able to tell what timezone has daylight savings + if (time.tzname[0] == time.tzname[1] and + time.daylight and found_zone not in ("utc", "gmt")): + break + else: + tz = value + break + leap_year_fix = False + if year is None and month == 2 and day == 29: + year = 1904 # 1904 is first leap year of 20th century + leap_year_fix = True + elif year is None: + year = 1900 + # If we know the week of the year and what day of that week, we can figure + # out the Julian day of the year. + if julian == -1 and week_of_year != -1 and weekday != -1: + week_starts_Mon = True if week_of_year_start == 0 else False + julian = _calc_julian_from_U_or_W(year, week_of_year, weekday, + week_starts_Mon) + # Cannot pre-calculate datetime_date() since can change in Julian + # calculation and thus could have different value for the day of the week + # calculation. + if julian == -1: + # Need to add 1 to result since first day of the year is 1, not 0. + julian = datetime_date(year, month, day).toordinal() - \ + datetime_date(year, 1, 1).toordinal() + 1 + else: # Assume that if they bothered to include Julian day it will + # be accurate. + datetime_result = datetime_date.fromordinal((julian - 1) + datetime_date(year, 1, 1).toordinal()) + year = datetime_result.year + month = datetime_result.month + day = datetime_result.day + if weekday == -1: + weekday = datetime_date(year, month, day).weekday() + if leap_year_fix: + # the caller didn't supply a year but asked for Feb 29th. We couldn't + # use the default of 1900 for computations. We set it back to ensure + # that February 29th is smaller than March 1st. + year = 1900 + + return (time.struct_time((year, month, day, + hour, minute, second, + weekday, julian, tz)), fraction) + +def _strptime_time(data_string, format="%a %b %d %H:%M:%S %Y"): + return _strptime(data_string, format)[0] diff --git a/PythonHome/Lib/_strptime.pyc b/PythonHome/Lib/_strptime.pyc deleted file mode 100644 index 9413c8a2f81a36625e1a8fb9152dfc1b951ad2ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14575 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 diff --git a/PythonHome/Lib/_threading_local.py b/PythonHome/Lib/_threading_local.py new file mode 100644 index 0000000000..09a3515bdb --- /dev/null +++ b/PythonHome/Lib/_threading_local.py @@ -0,0 +1,251 @@ +"""Thread-local objects. + +(Note that this module provides a Python version of the threading.local + class. Depending on the version of Python you're using, there may be a + faster one available. You should always import the `local` class from + `threading`.) + +Thread-local objects support the management of thread-local data. +If you have data that you want to be local to a thread, simply create +a thread-local object and use its attributes: + + >>> mydata = local() + >>> mydata.number = 42 + >>> mydata.number + 42 + +You can also access the local-object's dictionary: + + >>> mydata.__dict__ + {'number': 42} + >>> mydata.__dict__.setdefault('widgets', []) + [] + >>> mydata.widgets + [] + +What's important about thread-local objects is that their data are +local to a thread. If we access the data in a different thread: + + >>> log = [] + >>> def f(): + ... items = mydata.__dict__.items() + ... items.sort() + ... log.append(items) + ... mydata.number = 11 + ... log.append(mydata.number) + + >>> import threading + >>> thread = threading.Thread(target=f) + >>> thread.start() + >>> thread.join() + >>> log + [[], 11] + +we get different data. Furthermore, changes made in the other thread +don't affect data seen in this thread: + + >>> mydata.number + 42 + +Of course, values you get from a local object, including a __dict__ +attribute, are for whatever thread was current at the time the +attribute was read. For that reason, you generally don't want to save +these values across threads, as they apply only to the thread they +came from. + +You can create custom local objects by subclassing the local class: + + >>> class MyLocal(local): + ... number = 2 + ... initialized = False + ... def __init__(self, **kw): + ... if self.initialized: + ... raise SystemError('__init__ called too many times') + ... self.initialized = True + ... self.__dict__.update(kw) + ... def squared(self): + ... return self.number ** 2 + +This can be useful to support default values, methods and +initialization. Note that if you define an __init__ method, it will be +called each time the local object is used in a separate thread. This +is necessary to initialize each thread's dictionary. + +Now if we create a local object: + + >>> mydata = MyLocal(color='red') + +Now we have a default number: + + >>> mydata.number + 2 + +an initial color: + + >>> mydata.color + 'red' + >>> del mydata.color + +And a method that operates on the data: + + >>> mydata.squared() + 4 + +As before, we can access the data in a separate thread: + + >>> log = [] + >>> thread = threading.Thread(target=f) + >>> thread.start() + >>> thread.join() + >>> log + [[('color', 'red'), ('initialized', True)], 11] + +without affecting this thread's data: + + >>> mydata.number + 2 + >>> mydata.color + Traceback (most recent call last): + ... + AttributeError: 'MyLocal' object has no attribute 'color' + +Note that subclasses can define slots, but they are not thread +local. They are shared across threads: + + >>> class MyLocal(local): + ... __slots__ = 'number' + + >>> mydata = MyLocal() + >>> mydata.number = 42 + >>> mydata.color = 'red' + +So, the separate thread: + + >>> thread = threading.Thread(target=f) + >>> thread.start() + >>> thread.join() + +affects what we see: + + >>> mydata.number + 11 + +>>> del mydata +""" + +__all__ = ["local"] + +# We need to use objects from the threading module, but the threading +# module may also want to use our `local` class, if support for locals +# isn't compiled in to the `thread` module. This creates potential problems +# with circular imports. For that reason, we don't import `threading` +# until the bottom of this file (a hack sufficient to worm around the +# potential problems). Note that almost all platforms do have support for +# locals in the `thread` module, and there is no circular import problem +# then, so problems introduced by fiddling the order of imports here won't +# manifest on most boxes. + +class _localbase(object): + __slots__ = '_local__key', '_local__args', '_local__lock' + + def __new__(cls, *args, **kw): + self = object.__new__(cls) + key = '_local__key', 'thread.local.' + str(id(self)) + object.__setattr__(self, '_local__key', key) + object.__setattr__(self, '_local__args', (args, kw)) + object.__setattr__(self, '_local__lock', RLock()) + + if (args or kw) and (cls.__init__ is object.__init__): + raise TypeError("Initialization arguments are not supported") + + # We need to create the thread dict in anticipation of + # __init__ being called, to make sure we don't call it + # again ourselves. + dict = object.__getattribute__(self, '__dict__') + current_thread().__dict__[key] = dict + + return self + +def _patch(self): + key = object.__getattribute__(self, '_local__key') + d = current_thread().__dict__.get(key) + if d is None: + d = {} + current_thread().__dict__[key] = d + object.__setattr__(self, '__dict__', d) + + # we have a new instance dict, so call out __init__ if we have + # one + cls = type(self) + if cls.__init__ is not object.__init__: + args, kw = object.__getattribute__(self, '_local__args') + cls.__init__(self, *args, **kw) + else: + object.__setattr__(self, '__dict__', d) + +class local(_localbase): + + def __getattribute__(self, name): + lock = object.__getattribute__(self, '_local__lock') + lock.acquire() + try: + _patch(self) + return object.__getattribute__(self, name) + finally: + lock.release() + + def __setattr__(self, name, value): + if name == '__dict__': + raise AttributeError( + "%r object attribute '__dict__' is read-only" + % self.__class__.__name__) + lock = object.__getattribute__(self, '_local__lock') + lock.acquire() + try: + _patch(self) + return object.__setattr__(self, name, value) + finally: + lock.release() + + def __delattr__(self, name): + if name == '__dict__': + raise AttributeError( + "%r object attribute '__dict__' is read-only" + % self.__class__.__name__) + lock = object.__getattribute__(self, '_local__lock') + lock.acquire() + try: + _patch(self) + return object.__delattr__(self, name) + finally: + lock.release() + + def __del__(self): + import threading + + key = object.__getattribute__(self, '_local__key') + + try: + # We use the non-locking API since we might already hold the lock + # (__del__ can be called at any point by the cyclic GC). + threads = threading._enumerate() + except: + # If enumerating the current threads fails, as it seems to do + # during shutdown, we'll skip cleanup under the assumption + # that there is nothing to clean up. + return + + for thread in threads: + try: + __dict__ = thread.__dict__ + except AttributeError: + # Thread is dying, rest in peace. + continue + + if key in __dict__: + try: + del __dict__[key] + except KeyError: + pass # didn't have anything in this thread + +from threading import current_thread, RLock diff --git a/PythonHome/Lib/_threading_local.pyc b/PythonHome/Lib/_threading_local.pyc deleted file mode 100644 index 68c5c980f4e0f41f1dd4850452ef6b20a6f8b365..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6469 zcmcIo&yUMcg?<1CR;b`njrOoyYQB(s&=V~BH!z5W+}25xVaA{j9R?wBJWjZ<*JM_P=#H1 z%_QX7cJi5EvOiPjC;ugSoY5{%ad z{+RWKmi-C%vCq6tbWZB505>&$=QsJ2$pfk^U6zt#M{&)n)sxHi4SeZT^14s!k?3E>z z%8bk0PFQ*F+BFF%Z&P(9{zj2Or5KDeig8`QDx$3b(vw4lqMe|Yl?t)*soQ|jk^sU}<1sF>qP&gmMuMQS8tC8> z4%WBTNm@TI=%}hHVh88LGnJj-6DVAi z-Oe=F3EC-zt~Mnj1!7U;E!|tfX-J;n@EX_Hz;TFX_ep*oj_opvRX>W4WOrC-BTE1e zHJ*Shv0XKF_CdqFnx>f`ZpuytpiZ?{24(`ui;a#UUVfY`ziiY2*-VE*kz3F8vqWj1Y&8c#hMZBVOQe$EQBy3eytLThxfZivw4@SYpv7YK74A zCGoN)92#w#AdXg?7Ttvoj9aFoBZ)&qPe`i#ElqjYW}R(uv`Q^zMI;b)#4j9?Tgz5? zy0&-;1D3_}WntDx*P%xS+=3}v-4!fiGjM4=8?+v#Y-zbTzr82 z{V^S}P?@SMs4AFB%qqm|>e(e%8}gjpo54=%%+*O4!c9pM^OpSgM%L(3};?guz z+iAOT4R~sJpL+g^TLXBYm|*1y#O@_9)nX_!;9s}|(gZFAF#jM@A#6({2_WAhMQwsH zK9fM2(_v+rNdV{JD$lkmj@Cr^`OM5nELS|{q#{_eBoqPDfcUQ+;T(T1@^e*k%*_Cs zw%C;x@(c+^Ie%OU2pj<+Cpb+vCJKrdu*Fc=#FvbK{LXI%2n;B4465K94WY0ba$FJ+ zEQ7b`b{4m3F#a=wI8nk;Wa5M0W0<~xn{duLZ#(Nw+d1Q$TUy84H=RpvOg;3Y>E6So zd$=h}dV)VPAqWmXfOK4bz-K4^7`3}hOh}Q93H!9jCd?1;vKVHL(IH3Ld3KrUjX94g zj0q4iMO3zS;9`Umv<6T(582@~!zS|xbMMs6Oa)PVJWfj$e4D1F{3%t2qm<%IVXv~c z3HAKI=>V}e%0~+3pK)iOU@y^_lr&%t-_#Bi`MmUw0Ih4QB{j)U2-wep6q6H4k6G*uUfY5)T91HFXoAy-$+A!wtwrI%Z&FkTzr5 zawGf$ex9765P-%3Oh9@k$7g59!GNuYKieaOfAHiXZDS@IM6}3nQ14EDUMvA8N1iBC z5-FTB0>)`fdt0D8M*DF6Tf diff --git a/PythonHome/Lib/_weakrefset.py b/PythonHome/Lib/_weakrefset.py new file mode 100644 index 0000000000..627959b624 --- /dev/null +++ b/PythonHome/Lib/_weakrefset.py @@ -0,0 +1,204 @@ +# Access WeakSet through the weakref module. +# This code is separated-out because it is needed +# by abc.py to load everything else at startup. + +from _weakref import ref + +__all__ = ['WeakSet'] + + +class _IterationGuard(object): + # This context manager registers itself in the current iterators of the + # weak container, such as to delay all removals until the context manager + # exits. + # This technique should be relatively thread-safe (since sets are). + + def __init__(self, weakcontainer): + # Don't create cycles + self.weakcontainer = ref(weakcontainer) + + def __enter__(self): + w = self.weakcontainer() + if w is not None: + w._iterating.add(self) + return self + + def __exit__(self, e, t, b): + w = self.weakcontainer() + if w is not None: + s = w._iterating + s.remove(self) + if not s: + w._commit_removals() + + +class WeakSet(object): + def __init__(self, data=None): + self.data = set() + def _remove(item, selfref=ref(self)): + self = selfref() + if self is not None: + if self._iterating: + self._pending_removals.append(item) + else: + self.data.discard(item) + self._remove = _remove + # A list of keys to be removed + self._pending_removals = [] + self._iterating = set() + if data is not None: + self.update(data) + + def _commit_removals(self): + l = self._pending_removals + discard = self.data.discard + while l: + discard(l.pop()) + + def __iter__(self): + with _IterationGuard(self): + for itemref in self.data: + item = itemref() + if item is not None: + # Caveat: the iterator will keep a strong reference to + # `item` until it is resumed or closed. + yield item + + def __len__(self): + return len(self.data) - len(self._pending_removals) + + def __contains__(self, item): + try: + wr = ref(item) + except TypeError: + return False + return wr in self.data + + def __reduce__(self): + return (self.__class__, (list(self),), + getattr(self, '__dict__', None)) + + __hash__ = None + + def add(self, item): + if self._pending_removals: + self._commit_removals() + self.data.add(ref(item, self._remove)) + + def clear(self): + if self._pending_removals: + self._commit_removals() + self.data.clear() + + def copy(self): + return self.__class__(self) + + def pop(self): + if self._pending_removals: + self._commit_removals() + while True: + try: + itemref = self.data.pop() + except KeyError: + raise KeyError('pop from empty WeakSet') + item = itemref() + if item is not None: + return item + + def remove(self, item): + if self._pending_removals: + self._commit_removals() + self.data.remove(ref(item)) + + def discard(self, item): + if self._pending_removals: + self._commit_removals() + self.data.discard(ref(item)) + + def update(self, other): + if self._pending_removals: + self._commit_removals() + for element in other: + self.add(element) + + def __ior__(self, other): + self.update(other) + return self + + def difference(self, other): + newset = self.copy() + newset.difference_update(other) + return newset + __sub__ = difference + + def difference_update(self, other): + self.__isub__(other) + def __isub__(self, other): + if self._pending_removals: + self._commit_removals() + if self is other: + self.data.clear() + else: + self.data.difference_update(ref(item) for item in other) + return self + + def intersection(self, other): + return self.__class__(item for item in other if item in self) + __and__ = intersection + + def intersection_update(self, other): + self.__iand__(other) + def __iand__(self, other): + if self._pending_removals: + self._commit_removals() + self.data.intersection_update(ref(item) for item in other) + return self + + def issubset(self, other): + return self.data.issubset(ref(item) for item in other) + __le__ = issubset + + def __lt__(self, other): + return self.data < set(ref(item) for item in other) + + def issuperset(self, other): + return self.data.issuperset(ref(item) for item in other) + __ge__ = issuperset + + def __gt__(self, other): + return self.data > set(ref(item) for item in other) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.data == set(ref(item) for item in other) + + def __ne__(self, other): + opposite = self.__eq__(other) + if opposite is NotImplemented: + return NotImplemented + return not opposite + + def symmetric_difference(self, other): + newset = self.copy() + newset.symmetric_difference_update(other) + return newset + __xor__ = symmetric_difference + + def symmetric_difference_update(self, other): + self.__ixor__(other) + def __ixor__(self, other): + if self._pending_removals: + self._commit_removals() + if self is other: + self.data.clear() + else: + self.data.symmetric_difference_update(ref(item, self._remove) for item in other) + return self + + def union(self, other): + return self.__class__(e for s in (self, other) for e in s) + __or__ = union + + def isdisjoint(self, other): + return len(self.intersection(other)) == 0 diff --git a/PythonHome/Lib/_weakrefset.pyc b/PythonHome/Lib/_weakrefset.pyc index f87566afc25d4b0a11b66e698bc17cf2571856e4..7a4ff24222c3143b91d894d00c758ae87ee7197c 100644 GIT binary patch delta 2794 zcmbW(JxfAS7zc1)qI{{;&Q;T!skgSkD4L=qNWor6$*7>aD2XJOG^zE z1rZ_K5?V?qT%s|erD%v+T-|~=U*Z1&e*Dk#oaf=3kE#2`N>o2Iq0{N2qjGjl$*F01 zsjw58PR8fv6O(dWRW?*bj%3nmR!)?ZTp=GTtY@fb7AU8`0OhdZ7nI}16eO8eGu90d z_0V-|9+Hg0ZI__5m~J2`(3fc!k~K&Pv|!OdS&>>OWIcy8qo#Ealqc;nBn2(lVaK+G zQL+;)RJ0vJ$7S?t!#0%Bu{{fAdMV^MfTTct9KIc!kY-fsdIw~RtpciOX7t051x>La zJqsgHra+QY0p*?Z1(5u-RaY30yhAQGGJQO=;T{7sXS&Y-$us>P^j5Y!$Y%4*Sufh# zD=%7SSw!o66Cc3d)_Ya}$^RG;-##dtz9Udpd&`hywCryHl23vfhyjvs*=OJukUaA# bI0#67D=ujplUhX@Kp)V*zEdoe9{a_A94g8( delta 1158 zcmdlNcF%KzD> file, "Class: %s.%s" % (cls.__module__, cls.__name__) + print >> file, "Inv.counter: %s" % ABCMeta._abc_invalidation_counter + for name in sorted(cls.__dict__.keys()): + if name.startswith("_abc_"): + value = getattr(cls, name) + print >> file, "%s: %r" % (name, value) + + def __instancecheck__(cls, instance): + """Override for isinstance(instance, cls).""" + # Inline the cache checking when it's simple. + subclass = getattr(instance, '__class__', None) + if subclass is not None and subclass in cls._abc_cache: + return True + subtype = type(instance) + # Old-style instances + if subtype is _InstanceType: + subtype = subclass + if subtype is subclass or subclass is None: + if (cls._abc_negative_cache_version == + ABCMeta._abc_invalidation_counter and + subtype in cls._abc_negative_cache): + return False + # Fall back to the subclass check. + return cls.__subclasscheck__(subtype) + return (cls.__subclasscheck__(subclass) or + cls.__subclasscheck__(subtype)) + + def __subclasscheck__(cls, subclass): + """Override for issubclass(subclass, cls).""" + # Check cache + if subclass in cls._abc_cache: + return True + # Check negative cache; may have to invalidate + if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter: + # Invalidate the negative cache + cls._abc_negative_cache = WeakSet() + cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter + elif subclass in cls._abc_negative_cache: + return False + # Check the subclass hook + ok = cls.__subclasshook__(subclass) + if ok is not NotImplemented: + assert isinstance(ok, bool) + if ok: + cls._abc_cache.add(subclass) + else: + cls._abc_negative_cache.add(subclass) + return ok + # Check if it's a direct subclass + if cls in getattr(subclass, '__mro__', ()): + cls._abc_cache.add(subclass) + return True + # Check if it's a subclass of a registered class (recursive) + for rcls in cls._abc_registry: + if issubclass(subclass, rcls): + cls._abc_cache.add(subclass) + return True + # Check if it's a subclass of a subclass (recursive) + for scls in cls.__subclasses__(): + if issubclass(subclass, scls): + cls._abc_cache.add(subclass) + return True + # No dice; update negative cache + cls._abc_negative_cache.add(subclass) + return False diff --git a/PythonHome/Lib/abc.pyc b/PythonHome/Lib/abc.pyc index 67b792e35b3553d352bd3f8f7fc43b75f4c967fa..70bb2aee9e11ca3db180e46874ff044fb558384d 100644 GIT binary patch delta 615 zcmX@1zt3oc7o(vC0|SGrRZMzjNk(Z>On82Uo>#EHUr>N^jDKlKL1{^hOKMVSdQ3oN zNk)F2M}BVV=19gWCNi`=V!pvlhPIRJ{VZf?OXsO1$8Ya>?~|kLF8^9Gv`wBVXv4_1 i`I_J~GBj_l7Cui#G)#^Zn@)OgPW~^}O@^+S;`#uDde~_I delta 241 zcmdmIbV7fF7bCwI0|SGzRZKu-Nk)F2k@@Co#wsQZK{b{e%ou|D9Q`a9g70}MG0mLG wcOO%5rNCMY!O87HHjFHrj|fe}klNfWavsBBle@*IqdQ@8utYb87{8=G0Jw2OF#rGn diff --git a/PythonHome/Lib/aifc.py b/PythonHome/Lib/aifc.py new file mode 100644 index 0000000000..9ac710fbde --- /dev/null +++ b/PythonHome/Lib/aifc.py @@ -0,0 +1,986 @@ +"""Stuff to parse AIFF-C and AIFF files. + +Unless explicitly stated otherwise, the description below is true +both for AIFF-C files and AIFF files. + +An AIFF-C file has the following structure. + + +-----------------+ + | FORM | + +-----------------+ + | | + +----+------------+ + | | AIFC | + | +------------+ + | | | + | | . | + | | . | + | | . | + +----+------------+ + +An AIFF file has the string "AIFF" instead of "AIFC". + +A chunk consists of an identifier (4 bytes) followed by a size (4 bytes, +big endian order), followed by the data. The size field does not include +the size of the 8 byte header. + +The following chunk types are recognized. + + FVER + (AIFF-C only). + MARK + <# of markers> (2 bytes) + list of markers: + (2 bytes, must be > 0) + (4 bytes) + ("pstring") + COMM + <# of channels> (2 bytes) + <# of sound frames> (4 bytes) + (2 bytes) + (10 bytes, IEEE 80-bit extended + floating point) + in AIFF-C files only: + (4 bytes) + ("pstring") + SSND + (4 bytes, not used by this program) + (4 bytes, not used by this program) + + +A pstring consists of 1 byte length, a string of characters, and 0 or 1 +byte pad to make the total length even. + +Usage. + +Reading AIFF files: + f = aifc.open(file, 'r') +where file is either the name of a file or an open file pointer. +The open file pointer must have methods read(), seek(), and close(). +In some types of audio files, if the setpos() method is not used, +the seek() method is not necessary. + +This returns an instance of a class with the following public methods: + getnchannels() -- returns number of audio channels (1 for + mono, 2 for stereo) + getsampwidth() -- returns sample width in bytes + getframerate() -- returns sampling frequency + getnframes() -- returns number of audio frames + getcomptype() -- returns compression type ('NONE' for AIFF files) + getcompname() -- returns human-readable version of + compression type ('not compressed' for AIFF files) + getparams() -- returns a tuple consisting of all of the + above in the above order + getmarkers() -- get the list of marks in the audio file or None + if there are no marks + getmark(id) -- get mark with the specified id (raises an error + if the mark does not exist) + readframes(n) -- returns at most n frames of audio + rewind() -- rewind to the beginning of the audio stream + setpos(pos) -- seek to the specified position + tell() -- return the current position + close() -- close the instance (make it unusable) +The position returned by tell(), the position given to setpos() and +the position of marks are all compatible and have nothing to do with +the actual position in the file. +The close() method is called automatically when the class instance +is destroyed. + +Writing AIFF files: + f = aifc.open(file, 'w') +where file is either the name of a file or an open file pointer. +The open file pointer must have methods write(), tell(), seek(), and +close(). + +This returns an instance of a class with the following public methods: + aiff() -- create an AIFF file (AIFF-C default) + aifc() -- create an AIFF-C file + setnchannels(n) -- set the number of channels + setsampwidth(n) -- set the sample width + setframerate(n) -- set the frame rate + setnframes(n) -- set the number of frames + setcomptype(type, name) + -- set the compression type and the + human-readable compression type + setparams(tuple) + -- set all parameters at once + setmark(id, pos, name) + -- add specified mark to the list of marks + tell() -- return current position in output file (useful + in combination with setmark()) + writeframesraw(data) + -- write audio frames without pathing up the + file header + writeframes(data) + -- write audio frames and patch up the file header + close() -- patch up the file header and close the + output file +You should set the parameters before the first writeframesraw or +writeframes. The total number of frames does not need to be set, +but when it is set to the correct value, the header does not have to +be patched up. +It is best to first set all parameters, perhaps possibly the +compression type, and then write audio frames using writeframesraw. +When all frames have been written, either call writeframes('') or +close() to patch up the sizes in the header. +Marks can be added anytime. If there are any marks, you must call +close() after all frames have been written. +The close() method is called automatically when the class instance +is destroyed. + +When a file is opened with the extension '.aiff', an AIFF file is +written, otherwise an AIFF-C file is written. This default can be +changed by calling aiff() or aifc() before the first writeframes or +writeframesraw. +""" + +import struct +import __builtin__ + +__all__ = ["Error","open","openfp"] + +class Error(Exception): + pass + +_AIFC_version = 0xA2805140L # Version 1 of AIFF-C + +def _read_long(file): + try: + return struct.unpack('>l', file.read(4))[0] + except struct.error: + raise EOFError + +def _read_ulong(file): + try: + return struct.unpack('>L', file.read(4))[0] + except struct.error: + raise EOFError + +def _read_short(file): + try: + return struct.unpack('>h', file.read(2))[0] + except struct.error: + raise EOFError + +def _read_ushort(file): + try: + return struct.unpack('>H', file.read(2))[0] + except struct.error: + raise EOFError + +def _read_string(file): + length = ord(file.read(1)) + if length == 0: + data = '' + else: + data = file.read(length) + if length & 1 == 0: + dummy = file.read(1) + return data + +_HUGE_VAL = 1.79769313486231e+308 # See + +def _read_float(f): # 10 bytes + expon = _read_short(f) # 2 bytes + sign = 1 + if expon < 0: + sign = -1 + expon = expon + 0x8000 + himant = _read_ulong(f) # 4 bytes + lomant = _read_ulong(f) # 4 bytes + if expon == himant == lomant == 0: + f = 0.0 + elif expon == 0x7FFF: + f = _HUGE_VAL + else: + expon = expon - 16383 + f = (himant * 0x100000000L + lomant) * pow(2.0, expon - 63) + return sign * f + +def _write_short(f, x): + f.write(struct.pack('>h', x)) + +def _write_ushort(f, x): + f.write(struct.pack('>H', x)) + +def _write_long(f, x): + f.write(struct.pack('>l', x)) + +def _write_ulong(f, x): + f.write(struct.pack('>L', x)) + +def _write_string(f, s): + if len(s) > 255: + raise ValueError("string exceeds maximum pstring length") + f.write(struct.pack('B', len(s))) + f.write(s) + if len(s) & 1 == 0: + f.write(chr(0)) + +def _write_float(f, x): + import math + if x < 0: + sign = 0x8000 + x = x * -1 + else: + sign = 0 + if x == 0: + expon = 0 + himant = 0 + lomant = 0 + else: + fmant, expon = math.frexp(x) + if expon > 16384 or fmant >= 1 or fmant != fmant: # Infinity or NaN + expon = sign|0x7FFF + himant = 0 + lomant = 0 + else: # Finite + expon = expon + 16382 + if expon < 0: # denormalized + fmant = math.ldexp(fmant, expon) + expon = 0 + expon = expon | sign + fmant = math.ldexp(fmant, 32) + fsmant = math.floor(fmant) + himant = long(fsmant) + fmant = math.ldexp(fmant - fsmant, 32) + fsmant = math.floor(fmant) + lomant = long(fsmant) + _write_ushort(f, expon) + _write_ulong(f, himant) + _write_ulong(f, lomant) + +from chunk import Chunk + +class Aifc_read: + # Variables used in this class: + # + # These variables are available to the user though appropriate + # methods of this class: + # _file -- the open file with methods read(), close(), and seek() + # set through the __init__() method + # _nchannels -- the number of audio channels + # available through the getnchannels() method + # _nframes -- the number of audio frames + # available through the getnframes() method + # _sampwidth -- the number of bytes per audio sample + # available through the getsampwidth() method + # _framerate -- the sampling frequency + # available through the getframerate() method + # _comptype -- the AIFF-C compression type ('NONE' if AIFF) + # available through the getcomptype() method + # _compname -- the human-readable AIFF-C compression type + # available through the getcomptype() method + # _markers -- the marks in the audio file + # available through the getmarkers() and getmark() + # methods + # _soundpos -- the position in the audio stream + # available through the tell() method, set through the + # setpos() method + # + # These variables are used internally only: + # _version -- the AIFF-C version number + # _decomp -- the decompressor from builtin module cl + # _comm_chunk_read -- 1 iff the COMM chunk has been read + # _aifc -- 1 iff reading an AIFF-C file + # _ssnd_seek_needed -- 1 iff positioned correctly in audio + # file for readframes() + # _ssnd_chunk -- instantiation of a chunk class for the SSND chunk + # _framesize -- size of one frame in the file + + def initfp(self, file): + self._version = 0 + self._decomp = None + self._convert = None + self._markers = [] + self._soundpos = 0 + self._file = file + chunk = Chunk(file) + if chunk.getname() != 'FORM': + raise Error, 'file does not start with FORM id' + formdata = chunk.read(4) + if formdata == 'AIFF': + self._aifc = 0 + elif formdata == 'AIFC': + self._aifc = 1 + else: + raise Error, 'not an AIFF or AIFF-C file' + self._comm_chunk_read = 0 + while 1: + self._ssnd_seek_needed = 1 + try: + chunk = Chunk(self._file) + except EOFError: + break + chunkname = chunk.getname() + if chunkname == 'COMM': + self._read_comm_chunk(chunk) + self._comm_chunk_read = 1 + elif chunkname == 'SSND': + self._ssnd_chunk = chunk + dummy = chunk.read(8) + self._ssnd_seek_needed = 0 + elif chunkname == 'FVER': + self._version = _read_ulong(chunk) + elif chunkname == 'MARK': + self._readmark(chunk) + chunk.skip() + if not self._comm_chunk_read or not self._ssnd_chunk: + raise Error, 'COMM chunk and/or SSND chunk missing' + if self._aifc and self._decomp: + import cl + params = [cl.ORIGINAL_FORMAT, 0, + cl.BITS_PER_COMPONENT, self._sampwidth * 8, + cl.FRAME_RATE, self._framerate] + if self._nchannels == 1: + params[1] = cl.MONO + elif self._nchannels == 2: + params[1] = cl.STEREO_INTERLEAVED + else: + raise Error, 'cannot compress more than 2 channels' + self._decomp.SetParams(params) + + def __init__(self, f): + if type(f) == type(''): + f = __builtin__.open(f, 'rb') + # else, assume it is an open file object already + self.initfp(f) + + # + # User visible methods. + # + def getfp(self): + return self._file + + def rewind(self): + self._ssnd_seek_needed = 1 + self._soundpos = 0 + + def close(self): + if self._decomp: + self._decomp.CloseDecompressor() + self._decomp = None + self._file.close() + + def tell(self): + return self._soundpos + + def getnchannels(self): + return self._nchannels + + def getnframes(self): + return self._nframes + + def getsampwidth(self): + return self._sampwidth + + def getframerate(self): + return self._framerate + + def getcomptype(self): + return self._comptype + + def getcompname(self): + return self._compname + +## def getversion(self): +## return self._version + + def getparams(self): + return self.getnchannels(), self.getsampwidth(), \ + self.getframerate(), self.getnframes(), \ + self.getcomptype(), self.getcompname() + + def getmarkers(self): + if len(self._markers) == 0: + return None + return self._markers + + def getmark(self, id): + for marker in self._markers: + if id == marker[0]: + return marker + raise Error, 'marker %r does not exist' % (id,) + + def setpos(self, pos): + if pos < 0 or pos > self._nframes: + raise Error, 'position not in range' + self._soundpos = pos + self._ssnd_seek_needed = 1 + + def readframes(self, nframes): + if self._ssnd_seek_needed: + self._ssnd_chunk.seek(0) + dummy = self._ssnd_chunk.read(8) + pos = self._soundpos * self._framesize + if pos: + self._ssnd_chunk.seek(pos + 8) + self._ssnd_seek_needed = 0 + if nframes == 0: + return '' + data = self._ssnd_chunk.read(nframes * self._framesize) + if self._convert and data: + data = self._convert(data) + self._soundpos = self._soundpos + len(data) // (self._nchannels * self._sampwidth) + return data + + # + # Internal methods. + # + + def _decomp_data(self, data): + import cl + dummy = self._decomp.SetParam(cl.FRAME_BUFFER_SIZE, + len(data) * 2) + return self._decomp.Decompress(len(data) // self._nchannels, + data) + + def _ulaw2lin(self, data): + import audioop + return audioop.ulaw2lin(data, 2) + + def _adpcm2lin(self, data): + import audioop + if not hasattr(self, '_adpcmstate'): + # first time + self._adpcmstate = None + data, self._adpcmstate = audioop.adpcm2lin(data, 2, + self._adpcmstate) + return data + + def _read_comm_chunk(self, chunk): + self._nchannels = _read_short(chunk) + self._nframes = _read_long(chunk) + self._sampwidth = (_read_short(chunk) + 7) // 8 + self._framerate = int(_read_float(chunk)) + self._framesize = self._nchannels * self._sampwidth + if self._aifc: + #DEBUG: SGI's soundeditor produces a bad size :-( + kludge = 0 + if chunk.chunksize == 18: + kludge = 1 + print 'Warning: bad COMM chunk size' + chunk.chunksize = 23 + #DEBUG end + self._comptype = chunk.read(4) + #DEBUG start + if kludge: + length = ord(chunk.file.read(1)) + if length & 1 == 0: + length = length + 1 + chunk.chunksize = chunk.chunksize + length + chunk.file.seek(-1, 1) + #DEBUG end + self._compname = _read_string(chunk) + if self._comptype != 'NONE': + if self._comptype == 'G722': + try: + import audioop + except ImportError: + pass + else: + self._convert = self._adpcm2lin + self._sampwidth = 2 + return + # for ULAW and ALAW try Compression Library + try: + import cl + except ImportError: + if self._comptype in ('ULAW', 'ulaw'): + try: + import audioop + self._convert = self._ulaw2lin + self._sampwidth = 2 + return + except ImportError: + pass + raise Error, 'cannot read compressed AIFF-C files' + if self._comptype in ('ULAW', 'ulaw'): + scheme = cl.G711_ULAW + elif self._comptype in ('ALAW', 'alaw'): + scheme = cl.G711_ALAW + else: + raise Error, 'unsupported compression type' + self._decomp = cl.OpenDecompressor(scheme) + self._convert = self._decomp_data + self._sampwidth = 2 + else: + self._comptype = 'NONE' + self._compname = 'not compressed' + + def _readmark(self, chunk): + nmarkers = _read_short(chunk) + # Some files appear to contain invalid counts. + # Cope with this by testing for EOF. + try: + for i in range(nmarkers): + id = _read_short(chunk) + pos = _read_long(chunk) + name = _read_string(chunk) + if pos or name: + # some files appear to have + # dummy markers consisting of + # a position 0 and name '' + self._markers.append((id, pos, name)) + except EOFError: + print 'Warning: MARK chunk contains only', + print len(self._markers), + if len(self._markers) == 1: print 'marker', + else: print 'markers', + print 'instead of', nmarkers + +class Aifc_write: + # Variables used in this class: + # + # These variables are user settable through appropriate methods + # of this class: + # _file -- the open file with methods write(), close(), tell(), seek() + # set through the __init__() method + # _comptype -- the AIFF-C compression type ('NONE' in AIFF) + # set through the setcomptype() or setparams() method + # _compname -- the human-readable AIFF-C compression type + # set through the setcomptype() or setparams() method + # _nchannels -- the number of audio channels + # set through the setnchannels() or setparams() method + # _sampwidth -- the number of bytes per audio sample + # set through the setsampwidth() or setparams() method + # _framerate -- the sampling frequency + # set through the setframerate() or setparams() method + # _nframes -- the number of audio frames written to the header + # set through the setnframes() or setparams() method + # _aifc -- whether we're writing an AIFF-C file or an AIFF file + # set through the aifc() method, reset through the + # aiff() method + # + # These variables are used internally only: + # _version -- the AIFF-C version number + # _comp -- the compressor from builtin module cl + # _nframeswritten -- the number of audio frames actually written + # _datalength -- the size of the audio samples written to the header + # _datawritten -- the size of the audio samples actually written + + def __init__(self, f): + if type(f) == type(''): + filename = f + f = __builtin__.open(f, 'wb') + else: + # else, assume it is an open file object already + filename = '???' + self.initfp(f) + if filename[-5:] == '.aiff': + self._aifc = 0 + else: + self._aifc = 1 + + def initfp(self, file): + self._file = file + self._version = _AIFC_version + self._comptype = 'NONE' + self._compname = 'not compressed' + self._comp = None + self._convert = None + self._nchannels = 0 + self._sampwidth = 0 + self._framerate = 0 + self._nframes = 0 + self._nframeswritten = 0 + self._datawritten = 0 + self._datalength = 0 + self._markers = [] + self._marklength = 0 + self._aifc = 1 # AIFF-C is default + + def __del__(self): + if self._file: + self.close() + + # + # User visible methods. + # + def aiff(self): + if self._nframeswritten: + raise Error, 'cannot change parameters after starting to write' + self._aifc = 0 + + def aifc(self): + if self._nframeswritten: + raise Error, 'cannot change parameters after starting to write' + self._aifc = 1 + + def setnchannels(self, nchannels): + if self._nframeswritten: + raise Error, 'cannot change parameters after starting to write' + if nchannels < 1: + raise Error, 'bad # of channels' + self._nchannels = nchannels + + def getnchannels(self): + if not self._nchannels: + raise Error, 'number of channels not set' + return self._nchannels + + def setsampwidth(self, sampwidth): + if self._nframeswritten: + raise Error, 'cannot change parameters after starting to write' + if sampwidth < 1 or sampwidth > 4: + raise Error, 'bad sample width' + self._sampwidth = sampwidth + + def getsampwidth(self): + if not self._sampwidth: + raise Error, 'sample width not set' + return self._sampwidth + + def setframerate(self, framerate): + if self._nframeswritten: + raise Error, 'cannot change parameters after starting to write' + if framerate <= 0: + raise Error, 'bad frame rate' + self._framerate = framerate + + def getframerate(self): + if not self._framerate: + raise Error, 'frame rate not set' + return self._framerate + + def setnframes(self, nframes): + if self._nframeswritten: + raise Error, 'cannot change parameters after starting to write' + self._nframes = nframes + + def getnframes(self): + return self._nframeswritten + + def setcomptype(self, comptype, compname): + if self._nframeswritten: + raise Error, 'cannot change parameters after starting to write' + if comptype not in ('NONE', 'ULAW', 'ulaw', 'ALAW', 'alaw', 'G722'): + raise Error, 'unsupported compression type' + self._comptype = comptype + self._compname = compname + + def getcomptype(self): + return self._comptype + + def getcompname(self): + return self._compname + +## def setversion(self, version): +## if self._nframeswritten: +## raise Error, 'cannot change parameters after starting to write' +## self._version = version + + def setparams(self, info): + nchannels, sampwidth, framerate, nframes, comptype, compname = info + if self._nframeswritten: + raise Error, 'cannot change parameters after starting to write' + if comptype not in ('NONE', 'ULAW', 'ulaw', 'ALAW', 'alaw', 'G722'): + raise Error, 'unsupported compression type' + self.setnchannels(nchannels) + self.setsampwidth(sampwidth) + self.setframerate(framerate) + self.setnframes(nframes) + self.setcomptype(comptype, compname) + + def getparams(self): + if not self._nchannels or not self._sampwidth or not self._framerate: + raise Error, 'not all parameters set' + return self._nchannels, self._sampwidth, self._framerate, \ + self._nframes, self._comptype, self._compname + + def setmark(self, id, pos, name): + if id <= 0: + raise Error, 'marker ID must be > 0' + if pos < 0: + raise Error, 'marker position must be >= 0' + if type(name) != type(''): + raise Error, 'marker name must be a string' + for i in range(len(self._markers)): + if id == self._markers[i][0]: + self._markers[i] = id, pos, name + return + self._markers.append((id, pos, name)) + + def getmark(self, id): + for marker in self._markers: + if id == marker[0]: + return marker + raise Error, 'marker %r does not exist' % (id,) + + def getmarkers(self): + if len(self._markers) == 0: + return None + return self._markers + + def tell(self): + return self._nframeswritten + + def writeframesraw(self, data): + self._ensure_header_written(len(data)) + nframes = len(data) // (self._sampwidth * self._nchannels) + if self._convert: + data = self._convert(data) + self._file.write(data) + self._nframeswritten = self._nframeswritten + nframes + self._datawritten = self._datawritten + len(data) + + def writeframes(self, data): + self.writeframesraw(data) + if self._nframeswritten != self._nframes or \ + self._datalength != self._datawritten: + self._patchheader() + + def close(self): + if self._file is None: + return + try: + self._ensure_header_written(0) + if self._datawritten & 1: + # quick pad to even size + self._file.write(chr(0)) + self._datawritten = self._datawritten + 1 + self._writemarkers() + if self._nframeswritten != self._nframes or \ + self._datalength != self._datawritten or \ + self._marklength: + self._patchheader() + if self._comp: + self._comp.CloseCompressor() + self._comp = None + finally: + # Prevent ref cycles + self._convert = None + f = self._file + self._file = None + f.close() + + # + # Internal methods. + # + + def _comp_data(self, data): + import cl + dummy = self._comp.SetParam(cl.FRAME_BUFFER_SIZE, len(data)) + dummy = self._comp.SetParam(cl.COMPRESSED_BUFFER_SIZE, len(data)) + return self._comp.Compress(self._nframes, data) + + def _lin2ulaw(self, data): + import audioop + return audioop.lin2ulaw(data, 2) + + def _lin2adpcm(self, data): + import audioop + if not hasattr(self, '_adpcmstate'): + self._adpcmstate = None + data, self._adpcmstate = audioop.lin2adpcm(data, 2, + self._adpcmstate) + return data + + def _ensure_header_written(self, datasize): + if not self._nframeswritten: + if self._comptype in ('ULAW', 'ulaw', 'ALAW', 'alaw'): + if not self._sampwidth: + self._sampwidth = 2 + if self._sampwidth != 2: + raise Error, 'sample width must be 2 when compressing with ULAW or ALAW' + if self._comptype == 'G722': + if not self._sampwidth: + self._sampwidth = 2 + if self._sampwidth != 2: + raise Error, 'sample width must be 2 when compressing with G7.22 (ADPCM)' + if not self._nchannels: + raise Error, '# channels not specified' + if not self._sampwidth: + raise Error, 'sample width not specified' + if not self._framerate: + raise Error, 'sampling rate not specified' + self._write_header(datasize) + + def _init_compression(self): + if self._comptype == 'G722': + self._convert = self._lin2adpcm + return + try: + import cl + except ImportError: + if self._comptype in ('ULAW', 'ulaw'): + try: + import audioop + self._convert = self._lin2ulaw + return + except ImportError: + pass + raise Error, 'cannot write compressed AIFF-C files' + if self._comptype in ('ULAW', 'ulaw'): + scheme = cl.G711_ULAW + elif self._comptype in ('ALAW', 'alaw'): + scheme = cl.G711_ALAW + else: + raise Error, 'unsupported compression type' + self._comp = cl.OpenCompressor(scheme) + params = [cl.ORIGINAL_FORMAT, 0, + cl.BITS_PER_COMPONENT, self._sampwidth * 8, + cl.FRAME_RATE, self._framerate, + cl.FRAME_BUFFER_SIZE, 100, + cl.COMPRESSED_BUFFER_SIZE, 100] + if self._nchannels == 1: + params[1] = cl.MONO + elif self._nchannels == 2: + params[1] = cl.STEREO_INTERLEAVED + else: + raise Error, 'cannot compress more than 2 channels' + self._comp.SetParams(params) + # the compressor produces a header which we ignore + dummy = self._comp.Compress(0, '') + self._convert = self._comp_data + + def _write_header(self, initlength): + if self._aifc and self._comptype != 'NONE': + self._init_compression() + self._file.write('FORM') + if not self._nframes: + self._nframes = initlength // (self._nchannels * self._sampwidth) + self._datalength = self._nframes * self._nchannels * self._sampwidth + if self._datalength & 1: + self._datalength = self._datalength + 1 + if self._aifc: + if self._comptype in ('ULAW', 'ulaw', 'ALAW', 'alaw'): + self._datalength = self._datalength // 2 + if self._datalength & 1: + self._datalength = self._datalength + 1 + elif self._comptype == 'G722': + self._datalength = (self._datalength + 3) // 4 + if self._datalength & 1: + self._datalength = self._datalength + 1 + try: + self._form_length_pos = self._file.tell() + except (AttributeError, IOError): + self._form_length_pos = None + commlength = self._write_form_length(self._datalength) + if self._aifc: + self._file.write('AIFC') + self._file.write('FVER') + _write_ulong(self._file, 4) + _write_ulong(self._file, self._version) + else: + self._file.write('AIFF') + self._file.write('COMM') + _write_ulong(self._file, commlength) + _write_short(self._file, self._nchannels) + if self._form_length_pos is not None: + self._nframes_pos = self._file.tell() + _write_ulong(self._file, self._nframes) + if self._comptype in ('ULAW', 'ulaw', 'ALAW', 'alaw', 'G722'): + _write_short(self._file, 8) + else: + _write_short(self._file, self._sampwidth * 8) + _write_float(self._file, self._framerate) + if self._aifc: + self._file.write(self._comptype) + _write_string(self._file, self._compname) + self._file.write('SSND') + if self._form_length_pos is not None: + self._ssnd_length_pos = self._file.tell() + _write_ulong(self._file, self._datalength + 8) + _write_ulong(self._file, 0) + _write_ulong(self._file, 0) + + def _write_form_length(self, datalength): + if self._aifc: + commlength = 18 + 5 + len(self._compname) + if commlength & 1: + commlength = commlength + 1 + verslength = 12 + else: + commlength = 18 + verslength = 0 + _write_ulong(self._file, 4 + verslength + self._marklength + \ + 8 + commlength + 16 + datalength) + return commlength + + def _patchheader(self): + curpos = self._file.tell() + if self._datawritten & 1: + datalength = self._datawritten + 1 + self._file.write(chr(0)) + else: + datalength = self._datawritten + if datalength == self._datalength and \ + self._nframes == self._nframeswritten and \ + self._marklength == 0: + self._file.seek(curpos, 0) + return + self._file.seek(self._form_length_pos, 0) + dummy = self._write_form_length(datalength) + self._file.seek(self._nframes_pos, 0) + _write_ulong(self._file, self._nframeswritten) + self._file.seek(self._ssnd_length_pos, 0) + _write_ulong(self._file, datalength + 8) + self._file.seek(curpos, 0) + self._nframes = self._nframeswritten + self._datalength = datalength + + def _writemarkers(self): + if len(self._markers) == 0: + return + self._file.write('MARK') + length = 2 + for marker in self._markers: + id, pos, name = marker + length = length + len(name) + 1 + 6 + if len(name) & 1 == 0: + length = length + 1 + _write_ulong(self._file, length) + self._marklength = length + 8 + _write_short(self._file, len(self._markers)) + for marker in self._markers: + id, pos, name = marker + _write_short(self._file, id) + _write_ulong(self._file, pos) + _write_string(self._file, name) + +def open(f, mode=None): + if mode is None: + if hasattr(f, 'mode'): + mode = f.mode + else: + mode = 'rb' + if mode in ('r', 'rb'): + return Aifc_read(f) + elif mode in ('w', 'wb'): + return Aifc_write(f) + else: + raise Error, "mode must be 'r', 'rb', 'w', or 'wb'" + +openfp = open # B/W compatibility + +if __name__ == '__main__': + import sys + if not sys.argv[1:]: + sys.argv.append('/usr/demos/data/audio/bach.aiff') + fn = sys.argv[1] + f = open(fn, 'r') + try: + print "Reading", fn + print "nchannels =", f.getnchannels() + print "nframes =", f.getnframes() + print "sampwidth =", f.getsampwidth() + print "framerate =", f.getframerate() + print "comptype =", f.getcomptype() + print "compname =", f.getcompname() + if sys.argv[2:]: + gn = sys.argv[2] + print "Writing", gn + g = open(gn, 'w') + try: + g.setparams(f.getparams()) + while 1: + data = f.readframes(1024) + if not data: + break + g.writeframes(data) + finally: + g.close() + print "Done." + finally: + f.close() diff --git a/PythonHome/Lib/aifc.pyc b/PythonHome/Lib/aifc.pyc deleted file mode 100644 index 0055df3480dc7623f54715773c095f5a8e82dec8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29358 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 RpWqDOUp~4S&u_vQ{}(?9QnvsA diff --git a/PythonHome/Lib/antigravity.py b/PythonHome/Lib/antigravity.py new file mode 100644 index 0000000000..7fb7d8282a --- /dev/null +++ b/PythonHome/Lib/antigravity.py @@ -0,0 +1,4 @@ + +import webbrowser + +webbrowser.open("http://xkcd.com/353/") diff --git a/PythonHome/Lib/antigravity.pyc b/PythonHome/Lib/antigravity.pyc deleted file mode 100644 index 4ae647eedf62ec4539201c92e1c0b0cbd203e766..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 188 zcmZSn%*(YYJRvxl0ScIav;z7L0>5GrATy(+q`*pFzal$1MK3u&SKrvwSYHEVTnQJDC{ImFD#|Y}PAw{70dn&T zQu8!`Gy{SF8=@EElbIBgm{*dSUX)mtSyHK2P+7tORA-Z$pHiBWY6mi~7)0a`rDa961yaga&>$ov8iXPzo@^{7c4Rx+_o}@C4JUzu z3viBCQ*#5xHRFrzWx64;7F?wO)tF%bk4fs>bk)(XlvGQ z1kg9ql@OJY19~XoQ?BYx`Yzu}3@90EfE2lmTRuRZMYfy;R zIyf>gXalK3>KWWk+C&0XdQ(+;7_AFcRdDH=*&(xqw|sRK1uPF6Yl1cta-nX)*Z>zi zxKPCom#4%oHsm+6jIA6;G^&W_Th_A{;y-xcr1p5pX9L;SR}Y`R&*0^(Q3wX1PGK5* zEao-@N+yA&UPY^W+(6sQeVIG5m^x$mdbiunp-^hyAN{zO(u)dKu%D1J3>`wa84+v? z(g0p-Paf<+$slX#lNYVC0~|WtbgG8r>gkttJMZQW5(s!FE*4VWZ9yCJz)DAY2vumkxW20XoG2{ k{sAqXy!dc}zGN}8UFJS{pQ3OWCTHScZ2y{=G%aiK2TzbGYybcN delta 1131 zcma)4&2G~`5dPM7oH$J&LZRXSYDA03sdofI6|_Q?svJ^KAu2M7cayk@e`;?;Bc%$^ z9uXJbf*T<91vv2}JOJVhGwX^I2W;)^{O`_eH5~PcfgPsj#VIGGSz$4QIWRxnLs)fy(VSl(~xEL5^} zC)Zqf7GBU5a6ISbgpcXu?}-qWgyIy4fKwY{VPm-vKQ1%}4?IvGDMy!EOk2KgF`zr3|&r_H@~85lFd4oyd| zkmO4>?9Zl}@G*10ge#2FB-4Z*k0(i0Y~qbH45zAKru~s&C{`7z`H@WJl+WNph63*; z>G4mj8UK51Y_dzeA!?##-LO52Z~8^2eT59BVc(ZYKsE7Pc1{A7>M)6ms`+8FaCzZr z_BHSFT6gQTL@--yJh~. + +"""Command-line parsing library + +This module is an optparse-inspired command-line parsing library that: + + - handles both optional and positional arguments + - produces highly informative usage messages + - supports parsers that dispatch to sub-parsers + +The following is a simple usage example that sums integers from the +command-line and writes the result to a file:: + + parser = argparse.ArgumentParser( + description='sum the integers at the command line') + parser.add_argument( + 'integers', metavar='int', nargs='+', type=int, + help='an integer to be summed') + parser.add_argument( + '--log', default=sys.stdout, type=argparse.FileType('w'), + help='the file where the sum should be written') + args = parser.parse_args() + args.log.write('%s' % sum(args.integers)) + args.log.close() + +The module contains the following public classes: + + - ArgumentParser -- The main entry point for command-line parsing. As the + example above shows, the add_argument() method is used to populate + the parser with actions for optional and positional arguments. Then + the parse_args() method is invoked to convert the args at the + command-line into an object with attributes. + + - ArgumentError -- The exception raised by ArgumentParser objects when + there are errors with the parser's actions. Errors raised while + parsing the command-line are caught by ArgumentParser and emitted + as command-line messages. + + - FileType -- A factory for defining types of files to be created. As the + example above shows, instances of FileType are typically passed as + the type= argument of add_argument() calls. + + - Action -- The base class for parser actions. Typically actions are + selected by passing strings like 'store_true' or 'append_const' to + the action= argument of add_argument(). However, for greater + customization of ArgumentParser actions, subclasses of Action may + be defined and passed as the action= argument. + + - HelpFormatter, RawDescriptionHelpFormatter, RawTextHelpFormatter, + ArgumentDefaultsHelpFormatter -- Formatter classes which + may be passed as the formatter_class= argument to the + ArgumentParser constructor. HelpFormatter is the default, + RawDescriptionHelpFormatter and RawTextHelpFormatter tell the parser + not to change the formatting for help text, and + ArgumentDefaultsHelpFormatter adds information about argument defaults + to the help. + +All other classes in this module are considered implementation details. +(Also note that HelpFormatter and RawDescriptionHelpFormatter are only +considered public as object names -- the API of the formatter objects is +still considered an implementation detail.) +""" + +__version__ = '1.1' +__all__ = [ + 'ArgumentParser', + 'ArgumentError', + 'ArgumentTypeError', + 'FileType', + 'HelpFormatter', + 'ArgumentDefaultsHelpFormatter', + 'RawDescriptionHelpFormatter', + 'RawTextHelpFormatter', + 'Namespace', + 'Action', + 'ONE_OR_MORE', + 'OPTIONAL', + 'PARSER', + 'REMAINDER', + 'SUPPRESS', + 'ZERO_OR_MORE', +] + + +import collections as _collections +import copy as _copy +import os as _os +import re as _re +import sys as _sys +import textwrap as _textwrap + +from gettext import gettext as _ + + +def _callable(obj): + return hasattr(obj, '__call__') or hasattr(obj, '__bases__') + + +SUPPRESS = '==SUPPRESS==' + +OPTIONAL = '?' +ZERO_OR_MORE = '*' +ONE_OR_MORE = '+' +PARSER = 'A...' +REMAINDER = '...' +_UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args' + +# ============================= +# Utility functions and classes +# ============================= + +class _AttributeHolder(object): + """Abstract base class that provides __repr__. + + The __repr__ method returns a string in the format:: + ClassName(attr=name, attr=name, ...) + The attributes are determined either by a class-level attribute, + '_kwarg_names', or by inspecting the instance __dict__. + """ + + def __repr__(self): + type_name = type(self).__name__ + arg_strings = [] + for arg in self._get_args(): + arg_strings.append(repr(arg)) + for name, value in self._get_kwargs(): + arg_strings.append('%s=%r' % (name, value)) + return '%s(%s)' % (type_name, ', '.join(arg_strings)) + + def _get_kwargs(self): + return sorted(self.__dict__.items()) + + def _get_args(self): + return [] + + +def _ensure_value(namespace, name, value): + if getattr(namespace, name, None) is None: + setattr(namespace, name, value) + return getattr(namespace, name) + + +# =============== +# Formatting Help +# =============== + +class HelpFormatter(object): + """Formatter for generating usage messages and argument help strings. + + Only the name of this class is considered a public API. All the methods + provided by the class are considered an implementation detail. + """ + + def __init__(self, + prog, + indent_increment=2, + max_help_position=24, + width=None): + + # default setting for width + if width is None: + try: + width = int(_os.environ['COLUMNS']) + except (KeyError, ValueError): + width = 80 + width -= 2 + + self._prog = prog + self._indent_increment = indent_increment + self._max_help_position = max_help_position + self._max_help_position = min(max_help_position, + max(width - 20, indent_increment * 2)) + self._width = width + + self._current_indent = 0 + self._level = 0 + self._action_max_length = 0 + + self._root_section = self._Section(self, None) + self._current_section = self._root_section + + self._whitespace_matcher = _re.compile(r'\s+') + self._long_break_matcher = _re.compile(r'\n\n\n+') + + # =============================== + # Section and indentation methods + # =============================== + def _indent(self): + self._current_indent += self._indent_increment + self._level += 1 + + def _dedent(self): + self._current_indent -= self._indent_increment + assert self._current_indent >= 0, 'Indent decreased below 0.' + self._level -= 1 + + class _Section(object): + + def __init__(self, formatter, parent, heading=None): + self.formatter = formatter + self.parent = parent + self.heading = heading + self.items = [] + + def format_help(self): + # format the indented section + if self.parent is not None: + self.formatter._indent() + join = self.formatter._join_parts + for func, args in self.items: + func(*args) + item_help = join([func(*args) for func, args in self.items]) + if self.parent is not None: + self.formatter._dedent() + + # return nothing if the section was empty + if not item_help: + return '' + + # add the heading if the section was non-empty + if self.heading is not SUPPRESS and self.heading is not None: + current_indent = self.formatter._current_indent + heading = '%*s%s:\n' % (current_indent, '', self.heading) + else: + heading = '' + + # join the section-initial newline, the heading and the help + return join(['\n', heading, item_help, '\n']) + + def _add_item(self, func, args): + self._current_section.items.append((func, args)) + + # ======================== + # Message building methods + # ======================== + def start_section(self, heading): + self._indent() + section = self._Section(self, self._current_section, heading) + self._add_item(section.format_help, []) + self._current_section = section + + def end_section(self): + self._current_section = self._current_section.parent + self._dedent() + + def add_text(self, text): + if text is not SUPPRESS and text is not None: + self._add_item(self._format_text, [text]) + + def add_usage(self, usage, actions, groups, prefix=None): + if usage is not SUPPRESS: + args = usage, actions, groups, prefix + self._add_item(self._format_usage, args) + + def add_argument(self, action): + if action.help is not SUPPRESS: + + # find all invocations + get_invocation = self._format_action_invocation + invocations = [get_invocation(action)] + for subaction in self._iter_indented_subactions(action): + invocations.append(get_invocation(subaction)) + + # update the maximum item length + invocation_length = max([len(s) for s in invocations]) + action_length = invocation_length + self._current_indent + self._action_max_length = max(self._action_max_length, + action_length) + + # add the item to the list + self._add_item(self._format_action, [action]) + + def add_arguments(self, actions): + for action in actions: + self.add_argument(action) + + # ======================= + # Help-formatting methods + # ======================= + def format_help(self): + help = self._root_section.format_help() + if help: + help = self._long_break_matcher.sub('\n\n', help) + help = help.strip('\n') + '\n' + return help + + def _join_parts(self, part_strings): + return ''.join([part + for part in part_strings + if part and part is not SUPPRESS]) + + def _format_usage(self, usage, actions, groups, prefix): + if prefix is None: + prefix = _('usage: ') + + # if usage is specified, use that + if usage is not None: + usage = usage % dict(prog=self._prog) + + # if no optionals or positionals are available, usage is just prog + elif usage is None and not actions: + usage = '%(prog)s' % dict(prog=self._prog) + + # if optionals and positionals are available, calculate usage + elif usage is None: + prog = '%(prog)s' % dict(prog=self._prog) + + # split optionals from positionals + optionals = [] + positionals = [] + for action in actions: + if action.option_strings: + optionals.append(action) + else: + positionals.append(action) + + # build full usage string + format = self._format_actions_usage + action_usage = format(optionals + positionals, groups) + usage = ' '.join([s for s in [prog, action_usage] if s]) + + # wrap the usage parts if it's too long + text_width = self._width - self._current_indent + if len(prefix) + len(usage) > text_width: + + # break usage into wrappable parts + part_regexp = r'\(.*?\)+|\[.*?\]+|\S+' + opt_usage = format(optionals, groups) + pos_usage = format(positionals, groups) + opt_parts = _re.findall(part_regexp, opt_usage) + pos_parts = _re.findall(part_regexp, pos_usage) + assert ' '.join(opt_parts) == opt_usage + assert ' '.join(pos_parts) == pos_usage + + # helper for wrapping lines + def get_lines(parts, indent, prefix=None): + lines = [] + line = [] + if prefix is not None: + line_len = len(prefix) - 1 + else: + line_len = len(indent) - 1 + for part in parts: + if line_len + 1 + len(part) > text_width and line: + lines.append(indent + ' '.join(line)) + line = [] + line_len = len(indent) - 1 + line.append(part) + line_len += len(part) + 1 + if line: + lines.append(indent + ' '.join(line)) + if prefix is not None: + lines[0] = lines[0][len(indent):] + return lines + + # if prog is short, follow it with optionals or positionals + if len(prefix) + len(prog) <= 0.75 * text_width: + indent = ' ' * (len(prefix) + len(prog) + 1) + if opt_parts: + lines = get_lines([prog] + opt_parts, indent, prefix) + lines.extend(get_lines(pos_parts, indent)) + elif pos_parts: + lines = get_lines([prog] + pos_parts, indent, prefix) + else: + lines = [prog] + + # if prog is long, put it on its own line + else: + indent = ' ' * len(prefix) + parts = opt_parts + pos_parts + lines = get_lines(parts, indent) + if len(lines) > 1: + lines = [] + lines.extend(get_lines(opt_parts, indent)) + lines.extend(get_lines(pos_parts, indent)) + lines = [prog] + lines + + # join lines into usage + usage = '\n'.join(lines) + + # prefix with 'usage:' + return '%s%s\n\n' % (prefix, usage) + + def _format_actions_usage(self, actions, groups): + # find group indices and identify actions in groups + group_actions = set() + inserts = {} + for group in groups: + try: + start = actions.index(group._group_actions[0]) + except ValueError: + continue + else: + end = start + len(group._group_actions) + if actions[start:end] == group._group_actions: + for action in group._group_actions: + group_actions.add(action) + if not group.required: + if start in inserts: + inserts[start] += ' [' + else: + inserts[start] = '[' + inserts[end] = ']' + else: + if start in inserts: + inserts[start] += ' (' + else: + inserts[start] = '(' + inserts[end] = ')' + for i in range(start + 1, end): + inserts[i] = '|' + + # collect all actions format strings + parts = [] + for i, action in enumerate(actions): + + # suppressed arguments are marked with None + # remove | separators for suppressed arguments + if action.help is SUPPRESS: + parts.append(None) + if inserts.get(i) == '|': + inserts.pop(i) + elif inserts.get(i + 1) == '|': + inserts.pop(i + 1) + + # produce all arg strings + elif not action.option_strings: + part = self._format_args(action, action.dest) + + # if it's in a group, strip the outer [] + if action in group_actions: + if part[0] == '[' and part[-1] == ']': + part = part[1:-1] + + # add the action string to the list + parts.append(part) + + # produce the first way to invoke the option in brackets + else: + option_string = action.option_strings[0] + + # if the Optional doesn't take a value, format is: + # -s or --long + if action.nargs == 0: + part = '%s' % option_string + + # if the Optional takes a value, format is: + # -s ARGS or --long ARGS + else: + default = action.dest.upper() + args_string = self._format_args(action, default) + part = '%s %s' % (option_string, args_string) + + # make it look optional if it's not required or in a group + if not action.required and action not in group_actions: + part = '[%s]' % part + + # add the action string to the list + parts.append(part) + + # insert things at the necessary indices + for i in sorted(inserts, reverse=True): + parts[i:i] = [inserts[i]] + + # join all the action items with spaces + text = ' '.join([item for item in parts if item is not None]) + + # clean up separators for mutually exclusive groups + open = r'[\[(]' + close = r'[\])]' + text = _re.sub(r'(%s) ' % open, r'\1', text) + text = _re.sub(r' (%s)' % close, r'\1', text) + text = _re.sub(r'%s *%s' % (open, close), r'', text) + text = _re.sub(r'\(([^|]*)\)', r'\1', text) + text = text.strip() + + # return the text + return text + + def _format_text(self, text): + if '%(prog)' in text: + text = text % dict(prog=self._prog) + text_width = max(self._width - self._current_indent, 11) + indent = ' ' * self._current_indent + return self._fill_text(text, text_width, indent) + '\n\n' + + def _format_action(self, action): + # determine the required width and the entry label + help_position = min(self._action_max_length + 2, + self._max_help_position) + help_width = max(self._width - help_position, 11) + action_width = help_position - self._current_indent - 2 + action_header = self._format_action_invocation(action) + + # ho nelp; start on same line and add a final newline + if not action.help: + tup = self._current_indent, '', action_header + action_header = '%*s%s\n' % tup + + # short action name; start on the same line and pad two spaces + elif len(action_header) <= action_width: + tup = self._current_indent, '', action_width, action_header + action_header = '%*s%-*s ' % tup + indent_first = 0 + + # long action name; start on the next line + else: + tup = self._current_indent, '', action_header + action_header = '%*s%s\n' % tup + indent_first = help_position + + # collect the pieces of the action help + parts = [action_header] + + # if there was help for the action, add lines of help text + if action.help: + help_text = self._expand_help(action) + help_lines = self._split_lines(help_text, help_width) + parts.append('%*s%s\n' % (indent_first, '', help_lines[0])) + for line in help_lines[1:]: + parts.append('%*s%s\n' % (help_position, '', line)) + + # or add a newline if the description doesn't end with one + elif not action_header.endswith('\n'): + parts.append('\n') + + # if there are any sub-actions, add their help as well + for subaction in self._iter_indented_subactions(action): + parts.append(self._format_action(subaction)) + + # return a single string + return self._join_parts(parts) + + def _format_action_invocation(self, action): + if not action.option_strings: + metavar, = self._metavar_formatter(action, action.dest)(1) + return metavar + + else: + parts = [] + + # if the Optional doesn't take a value, format is: + # -s, --long + if action.nargs == 0: + parts.extend(action.option_strings) + + # if the Optional takes a value, format is: + # -s ARGS, --long ARGS + else: + default = action.dest.upper() + args_string = self._format_args(action, default) + for option_string in action.option_strings: + parts.append('%s %s' % (option_string, args_string)) + + return ', '.join(parts) + + def _metavar_formatter(self, action, default_metavar): + if action.metavar is not None: + result = action.metavar + elif action.choices is not None: + choice_strs = [str(choice) for choice in action.choices] + result = '{%s}' % ','.join(choice_strs) + else: + result = default_metavar + + def format(tuple_size): + if isinstance(result, tuple): + return result + else: + return (result, ) * tuple_size + return format + + def _format_args(self, action, default_metavar): + get_metavar = self._metavar_formatter(action, default_metavar) + if action.nargs is None: + result = '%s' % get_metavar(1) + elif action.nargs == OPTIONAL: + result = '[%s]' % get_metavar(1) + elif action.nargs == ZERO_OR_MORE: + result = '[%s [%s ...]]' % get_metavar(2) + elif action.nargs == ONE_OR_MORE: + result = '%s [%s ...]' % get_metavar(2) + elif action.nargs == REMAINDER: + result = '...' + elif action.nargs == PARSER: + result = '%s ...' % get_metavar(1) + else: + formats = ['%s' for _ in range(action.nargs)] + result = ' '.join(formats) % get_metavar(action.nargs) + return result + + def _expand_help(self, action): + params = dict(vars(action), prog=self._prog) + for name in list(params): + if params[name] is SUPPRESS: + del params[name] + for name in list(params): + if hasattr(params[name], '__name__'): + params[name] = params[name].__name__ + if params.get('choices') is not None: + choices_str = ', '.join([str(c) for c in params['choices']]) + params['choices'] = choices_str + return self._get_help_string(action) % params + + def _iter_indented_subactions(self, action): + try: + get_subactions = action._get_subactions + except AttributeError: + pass + else: + self._indent() + for subaction in get_subactions(): + yield subaction + self._dedent() + + def _split_lines(self, text, width): + text = self._whitespace_matcher.sub(' ', text).strip() + return _textwrap.wrap(text, width) + + def _fill_text(self, text, width, indent): + text = self._whitespace_matcher.sub(' ', text).strip() + return _textwrap.fill(text, width, initial_indent=indent, + subsequent_indent=indent) + + def _get_help_string(self, action): + return action.help + + +class RawDescriptionHelpFormatter(HelpFormatter): + """Help message formatter which retains any formatting in descriptions. + + Only the name of this class is considered a public API. All the methods + provided by the class are considered an implementation detail. + """ + + def _fill_text(self, text, width, indent): + return ''.join([indent + line for line in text.splitlines(True)]) + + +class RawTextHelpFormatter(RawDescriptionHelpFormatter): + """Help message formatter which retains formatting of all help text. + + Only the name of this class is considered a public API. All the methods + provided by the class are considered an implementation detail. + """ + + def _split_lines(self, text, width): + return text.splitlines() + + +class ArgumentDefaultsHelpFormatter(HelpFormatter): + """Help message formatter which adds default values to argument help. + + Only the name of this class is considered a public API. All the methods + provided by the class are considered an implementation detail. + """ + + def _get_help_string(self, action): + help = action.help + if '%(default)' not in action.help: + if action.default is not SUPPRESS: + defaulting_nargs = [OPTIONAL, ZERO_OR_MORE] + if action.option_strings or action.nargs in defaulting_nargs: + help += ' (default: %(default)s)' + return help + + +# ===================== +# Options and Arguments +# ===================== + +def _get_action_name(argument): + if argument is None: + return None + elif argument.option_strings: + return '/'.join(argument.option_strings) + elif argument.metavar not in (None, SUPPRESS): + return argument.metavar + elif argument.dest not in (None, SUPPRESS): + return argument.dest + else: + return None + + +class ArgumentError(Exception): + """An error from creating or using an argument (optional or positional). + + The string value of this exception is the message, augmented with + information about the argument that caused it. + """ + + def __init__(self, argument, message): + self.argument_name = _get_action_name(argument) + self.message = message + + def __str__(self): + if self.argument_name is None: + format = '%(message)s' + else: + format = 'argument %(argument_name)s: %(message)s' + return format % dict(message=self.message, + argument_name=self.argument_name) + + +class ArgumentTypeError(Exception): + """An error from trying to convert a command line string to a type.""" + pass + + +# ============== +# Action classes +# ============== + +class Action(_AttributeHolder): + """Information about how to convert command line strings to Python objects. + + Action objects are used by an ArgumentParser to represent the information + needed to parse a single argument from one or more strings from the + command line. The keyword arguments to the Action constructor are also + all attributes of Action instances. + + Keyword Arguments: + + - option_strings -- A list of command-line option strings which + should be associated with this action. + + - dest -- The name of the attribute to hold the created object(s) + + - nargs -- The number of command-line arguments that should be + consumed. By default, one argument will be consumed and a single + value will be produced. Other values include: + - N (an integer) consumes N arguments (and produces a list) + - '?' consumes zero or one arguments + - '*' consumes zero or more arguments (and produces a list) + - '+' consumes one or more arguments (and produces a list) + Note that the difference between the default and nargs=1 is that + with the default, a single value will be produced, while with + nargs=1, a list containing a single value will be produced. + + - const -- The value to be produced if the option is specified and the + option uses an action that takes no values. + + - default -- The value to be produced if the option is not specified. + + - type -- A callable that accepts a single string argument, and + returns the converted value. The standard Python types str, int, + float, and complex are useful examples of such callables. If None, + str is used. + + - choices -- A container of values that should be allowed. If not None, + after a command-line argument has been converted to the appropriate + type, an exception will be raised if it is not a member of this + collection. + + - required -- True if the action must always be specified at the + command line. This is only meaningful for optional command-line + arguments. + + - help -- The help string describing the argument. + + - metavar -- The name to be used for the option's argument with the + help string. If None, the 'dest' value will be used as the name. + """ + + def __init__(self, + option_strings, + dest, + nargs=None, + const=None, + default=None, + type=None, + choices=None, + required=False, + help=None, + metavar=None): + self.option_strings = option_strings + self.dest = dest + self.nargs = nargs + self.const = const + self.default = default + self.type = type + self.choices = choices + self.required = required + self.help = help + self.metavar = metavar + + def _get_kwargs(self): + names = [ + 'option_strings', + 'dest', + 'nargs', + 'const', + 'default', + 'type', + 'choices', + 'help', + 'metavar', + ] + return [(name, getattr(self, name)) for name in names] + + def __call__(self, parser, namespace, values, option_string=None): + raise NotImplementedError(_('.__call__() not defined')) + + +class _StoreAction(Action): + + def __init__(self, + option_strings, + dest, + nargs=None, + const=None, + default=None, + type=None, + choices=None, + required=False, + help=None, + metavar=None): + if nargs == 0: + raise ValueError('nargs for store actions must be > 0; if you ' + 'have nothing to store, actions such as store ' + 'true or store const may be more appropriate') + if const is not None and nargs != OPTIONAL: + raise ValueError('nargs must be %r to supply const' % OPTIONAL) + super(_StoreAction, self).__init__( + option_strings=option_strings, + dest=dest, + nargs=nargs, + const=const, + default=default, + type=type, + choices=choices, + required=required, + help=help, + metavar=metavar) + + def __call__(self, parser, namespace, values, option_string=None): + setattr(namespace, self.dest, values) + + +class _StoreConstAction(Action): + + def __init__(self, + option_strings, + dest, + const, + default=None, + required=False, + help=None, + metavar=None): + super(_StoreConstAction, self).__init__( + option_strings=option_strings, + dest=dest, + nargs=0, + const=const, + default=default, + required=required, + help=help) + + def __call__(self, parser, namespace, values, option_string=None): + setattr(namespace, self.dest, self.const) + + +class _StoreTrueAction(_StoreConstAction): + + def __init__(self, + option_strings, + dest, + default=False, + required=False, + help=None): + super(_StoreTrueAction, self).__init__( + option_strings=option_strings, + dest=dest, + const=True, + default=default, + required=required, + help=help) + + +class _StoreFalseAction(_StoreConstAction): + + def __init__(self, + option_strings, + dest, + default=True, + required=False, + help=None): + super(_StoreFalseAction, self).__init__( + option_strings=option_strings, + dest=dest, + const=False, + default=default, + required=required, + help=help) + + +class _AppendAction(Action): + + def __init__(self, + option_strings, + dest, + nargs=None, + const=None, + default=None, + type=None, + choices=None, + required=False, + help=None, + metavar=None): + if nargs == 0: + raise ValueError('nargs for append actions must be > 0; if arg ' + 'strings are not supplying the value to append, ' + 'the append const action may be more appropriate') + if const is not None and nargs != OPTIONAL: + raise ValueError('nargs must be %r to supply const' % OPTIONAL) + super(_AppendAction, self).__init__( + option_strings=option_strings, + dest=dest, + nargs=nargs, + const=const, + default=default, + type=type, + choices=choices, + required=required, + help=help, + metavar=metavar) + + def __call__(self, parser, namespace, values, option_string=None): + items = _copy.copy(_ensure_value(namespace, self.dest, [])) + items.append(values) + setattr(namespace, self.dest, items) + + +class _AppendConstAction(Action): + + def __init__(self, + option_strings, + dest, + const, + default=None, + required=False, + help=None, + metavar=None): + super(_AppendConstAction, self).__init__( + option_strings=option_strings, + dest=dest, + nargs=0, + const=const, + default=default, + required=required, + help=help, + metavar=metavar) + + def __call__(self, parser, namespace, values, option_string=None): + items = _copy.copy(_ensure_value(namespace, self.dest, [])) + items.append(self.const) + setattr(namespace, self.dest, items) + + +class _CountAction(Action): + + def __init__(self, + option_strings, + dest, + default=None, + required=False, + help=None): + super(_CountAction, self).__init__( + option_strings=option_strings, + dest=dest, + nargs=0, + default=default, + required=required, + help=help) + + def __call__(self, parser, namespace, values, option_string=None): + new_count = _ensure_value(namespace, self.dest, 0) + 1 + setattr(namespace, self.dest, new_count) + + +class _HelpAction(Action): + + def __init__(self, + option_strings, + dest=SUPPRESS, + default=SUPPRESS, + help=None): + super(_HelpAction, self).__init__( + option_strings=option_strings, + dest=dest, + default=default, + nargs=0, + help=help) + + def __call__(self, parser, namespace, values, option_string=None): + parser.print_help() + parser.exit() + + +class _VersionAction(Action): + + def __init__(self, + option_strings, + version=None, + dest=SUPPRESS, + default=SUPPRESS, + help="show program's version number and exit"): + super(_VersionAction, self).__init__( + option_strings=option_strings, + dest=dest, + default=default, + nargs=0, + help=help) + self.version = version + + def __call__(self, parser, namespace, values, option_string=None): + version = self.version + if version is None: + version = parser.version + formatter = parser._get_formatter() + formatter.add_text(version) + parser.exit(message=formatter.format_help()) + + +class _SubParsersAction(Action): + + class _ChoicesPseudoAction(Action): + + def __init__(self, name, help): + sup = super(_SubParsersAction._ChoicesPseudoAction, self) + sup.__init__(option_strings=[], dest=name, help=help) + + def __init__(self, + option_strings, + prog, + parser_class, + dest=SUPPRESS, + help=None, + metavar=None): + + self._prog_prefix = prog + self._parser_class = parser_class + self._name_parser_map = _collections.OrderedDict() + self._choices_actions = [] + + super(_SubParsersAction, self).__init__( + option_strings=option_strings, + dest=dest, + nargs=PARSER, + choices=self._name_parser_map, + help=help, + metavar=metavar) + + def add_parser(self, name, **kwargs): + # set prog from the existing prefix + if kwargs.get('prog') is None: + kwargs['prog'] = '%s %s' % (self._prog_prefix, name) + + # create a pseudo-action to hold the choice help + if 'help' in kwargs: + help = kwargs.pop('help') + choice_action = self._ChoicesPseudoAction(name, help) + self._choices_actions.append(choice_action) + + # create the parser and add it to the map + parser = self._parser_class(**kwargs) + self._name_parser_map[name] = parser + return parser + + def _get_subactions(self): + return self._choices_actions + + def __call__(self, parser, namespace, values, option_string=None): + parser_name = values[0] + arg_strings = values[1:] + + # set the parser name if requested + if self.dest is not SUPPRESS: + setattr(namespace, self.dest, parser_name) + + # select the parser + try: + parser = self._name_parser_map[parser_name] + except KeyError: + tup = parser_name, ', '.join(self._name_parser_map) + msg = _('unknown parser %r (choices: %s)') % tup + raise ArgumentError(self, msg) + + # parse all the remaining options into the namespace + # store any unrecognized options on the object, so that the top + # level parser can decide what to do with them + namespace, arg_strings = parser.parse_known_args(arg_strings, namespace) + if arg_strings: + vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, []) + getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings) + + +# ============== +# Type classes +# ============== + +class FileType(object): + """Factory for creating file object types + + Instances of FileType are typically passed as type= arguments to the + ArgumentParser add_argument() method. + + Keyword Arguments: + - mode -- A string indicating how the file is to be opened. Accepts the + same values as the builtin open() function. + - bufsize -- The file's desired buffer size. Accepts the same values as + the builtin open() function. + """ + + def __init__(self, mode='r', bufsize=-1): + self._mode = mode + self._bufsize = bufsize + + def __call__(self, string): + # the special argument "-" means sys.std{in,out} + if string == '-': + if 'r' in self._mode: + return _sys.stdin + elif 'w' in self._mode: + return _sys.stdout + else: + msg = _('argument "-" with mode %r') % self._mode + raise ValueError(msg) + + # all other arguments are used as file names + try: + return open(string, self._mode, self._bufsize) + except IOError as e: + message = _("can't open '%s': %s") + raise ArgumentTypeError(message % (string, e)) + + def __repr__(self): + args = self._mode, self._bufsize + args_str = ', '.join(repr(arg) for arg in args if arg != -1) + return '%s(%s)' % (type(self).__name__, args_str) + +# =========================== +# Optional and Positional Parsing +# =========================== + +class Namespace(_AttributeHolder): + """Simple object for storing attributes. + + Implements equality by attribute names and values, and provides a simple + string representation. + """ + + def __init__(self, **kwargs): + for name in kwargs: + setattr(self, name, kwargs[name]) + + __hash__ = None + + def __eq__(self, other): + if not isinstance(other, Namespace): + return NotImplemented + return vars(self) == vars(other) + + def __ne__(self, other): + if not isinstance(other, Namespace): + return NotImplemented + return not (self == other) + + def __contains__(self, key): + return key in self.__dict__ + + +class _ActionsContainer(object): + + def __init__(self, + description, + prefix_chars, + argument_default, + conflict_handler): + super(_ActionsContainer, self).__init__() + + self.description = description + self.argument_default = argument_default + self.prefix_chars = prefix_chars + self.conflict_handler = conflict_handler + + # set up registries + self._registries = {} + + # register actions + self.register('action', None, _StoreAction) + self.register('action', 'store', _StoreAction) + self.register('action', 'store_const', _StoreConstAction) + self.register('action', 'store_true', _StoreTrueAction) + self.register('action', 'store_false', _StoreFalseAction) + self.register('action', 'append', _AppendAction) + self.register('action', 'append_const', _AppendConstAction) + self.register('action', 'count', _CountAction) + self.register('action', 'help', _HelpAction) + self.register('action', 'version', _VersionAction) + self.register('action', 'parsers', _SubParsersAction) + + # raise an exception if the conflict handler is invalid + self._get_handler() + + # action storage + self._actions = [] + self._option_string_actions = {} + + # groups + self._action_groups = [] + self._mutually_exclusive_groups = [] + + # defaults storage + self._defaults = {} + + # determines whether an "option" looks like a negative number + self._negative_number_matcher = _re.compile(r'^-\d+$|^-\d*\.\d+$') + + # whether or not there are any optionals that look like negative + # numbers -- uses a list so it can be shared and edited + self._has_negative_number_optionals = [] + + # ==================== + # Registration methods + # ==================== + def register(self, registry_name, value, object): + registry = self._registries.setdefault(registry_name, {}) + registry[value] = object + + def _registry_get(self, registry_name, value, default=None): + return self._registries[registry_name].get(value, default) + + # ================================== + # Namespace default accessor methods + # ================================== + def set_defaults(self, **kwargs): + self._defaults.update(kwargs) + + # if these defaults match any existing arguments, replace + # the previous default on the object with the new one + for action in self._actions: + if action.dest in kwargs: + action.default = kwargs[action.dest] + + def get_default(self, dest): + for action in self._actions: + if action.dest == dest and action.default is not None: + return action.default + return self._defaults.get(dest, None) + + + # ======================= + # Adding argument actions + # ======================= + def add_argument(self, *args, **kwargs): + """ + add_argument(dest, ..., name=value, ...) + add_argument(option_string, option_string, ..., name=value, ...) + """ + + # if no positional args are supplied or only one is supplied and + # it doesn't look like an option string, parse a positional + # argument + chars = self.prefix_chars + if not args or len(args) == 1 and args[0][0] not in chars: + if args and 'dest' in kwargs: + raise ValueError('dest supplied twice for positional argument') + kwargs = self._get_positional_kwargs(*args, **kwargs) + + # otherwise, we're adding an optional argument + else: + kwargs = self._get_optional_kwargs(*args, **kwargs) + + # if no default was supplied, use the parser-level default + if 'default' not in kwargs: + dest = kwargs['dest'] + if dest in self._defaults: + kwargs['default'] = self._defaults[dest] + elif self.argument_default is not None: + kwargs['default'] = self.argument_default + + # create the action object, and add it to the parser + action_class = self._pop_action_class(kwargs) + if not _callable(action_class): + raise ValueError('unknown action "%s"' % (action_class,)) + action = action_class(**kwargs) + + # raise an error if the action type is not callable + type_func = self._registry_get('type', action.type, action.type) + if not _callable(type_func): + raise ValueError('%r is not callable' % (type_func,)) + + # raise an error if the metavar does not match the type + if hasattr(self, "_get_formatter"): + try: + self._get_formatter()._format_args(action, None) + except TypeError: + raise ValueError("length of metavar tuple does not match nargs") + + return self._add_action(action) + + def add_argument_group(self, *args, **kwargs): + group = _ArgumentGroup(self, *args, **kwargs) + self._action_groups.append(group) + return group + + def add_mutually_exclusive_group(self, **kwargs): + group = _MutuallyExclusiveGroup(self, **kwargs) + self._mutually_exclusive_groups.append(group) + return group + + def _add_action(self, action): + # resolve any conflicts + self._check_conflict(action) + + # add to actions list + self._actions.append(action) + action.container = self + + # index the action by any option strings it has + for option_string in action.option_strings: + self._option_string_actions[option_string] = action + + # set the flag if any option strings look like negative numbers + for option_string in action.option_strings: + if self._negative_number_matcher.match(option_string): + if not self._has_negative_number_optionals: + self._has_negative_number_optionals.append(True) + + # return the created action + return action + + def _remove_action(self, action): + self._actions.remove(action) + + def _add_container_actions(self, container): + # collect groups by titles + title_group_map = {} + for group in self._action_groups: + if group.title in title_group_map: + msg = _('cannot merge actions - two groups are named %r') + raise ValueError(msg % (group.title)) + title_group_map[group.title] = group + + # map each action to its group + group_map = {} + for group in container._action_groups: + + # if a group with the title exists, use that, otherwise + # create a new group matching the container's group + if group.title not in title_group_map: + title_group_map[group.title] = self.add_argument_group( + title=group.title, + description=group.description, + conflict_handler=group.conflict_handler) + + # map the actions to their new group + for action in group._group_actions: + group_map[action] = title_group_map[group.title] + + # add container's mutually exclusive groups + # NOTE: if add_mutually_exclusive_group ever gains title= and + # description= then this code will need to be expanded as above + for group in container._mutually_exclusive_groups: + mutex_group = self.add_mutually_exclusive_group( + required=group.required) + + # map the actions to their new mutex group + for action in group._group_actions: + group_map[action] = mutex_group + + # add all actions to this container or their group + for action in container._actions: + group_map.get(action, self)._add_action(action) + + def _get_positional_kwargs(self, dest, **kwargs): + # make sure required is not specified + if 'required' in kwargs: + msg = _("'required' is an invalid argument for positionals") + raise TypeError(msg) + + # mark positional arguments as required if at least one is + # always required + if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]: + kwargs['required'] = True + if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs: + kwargs['required'] = True + + # return the keyword arguments with no option strings + return dict(kwargs, dest=dest, option_strings=[]) + + def _get_optional_kwargs(self, *args, **kwargs): + # determine short and long option strings + option_strings = [] + long_option_strings = [] + for option_string in args: + # error on strings that don't start with an appropriate prefix + if not option_string[0] in self.prefix_chars: + msg = _('invalid option string %r: ' + 'must start with a character %r') + tup = option_string, self.prefix_chars + raise ValueError(msg % tup) + + # strings starting with two prefix characters are long options + option_strings.append(option_string) + if option_string[0] in self.prefix_chars: + if len(option_string) > 1: + if option_string[1] in self.prefix_chars: + long_option_strings.append(option_string) + + # infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x' + dest = kwargs.pop('dest', None) + if dest is None: + if long_option_strings: + dest_option_string = long_option_strings[0] + else: + dest_option_string = option_strings[0] + dest = dest_option_string.lstrip(self.prefix_chars) + if not dest: + msg = _('dest= is required for options like %r') + raise ValueError(msg % option_string) + dest = dest.replace('-', '_') + + # return the updated keyword arguments + return dict(kwargs, dest=dest, option_strings=option_strings) + + def _pop_action_class(self, kwargs, default=None): + action = kwargs.pop('action', default) + return self._registry_get('action', action, action) + + def _get_handler(self): + # determine function from conflict handler string + handler_func_name = '_handle_conflict_%s' % self.conflict_handler + try: + return getattr(self, handler_func_name) + except AttributeError: + msg = _('invalid conflict_resolution value: %r') + raise ValueError(msg % self.conflict_handler) + + def _check_conflict(self, action): + + # find all options that conflict with this option + confl_optionals = [] + for option_string in action.option_strings: + if option_string in self._option_string_actions: + confl_optional = self._option_string_actions[option_string] + confl_optionals.append((option_string, confl_optional)) + + # resolve any conflicts + if confl_optionals: + conflict_handler = self._get_handler() + conflict_handler(action, confl_optionals) + + def _handle_conflict_error(self, action, conflicting_actions): + message = _('conflicting option string(s): %s') + conflict_string = ', '.join([option_string + for option_string, action + in conflicting_actions]) + raise ArgumentError(action, message % conflict_string) + + def _handle_conflict_resolve(self, action, conflicting_actions): + + # remove all conflicting options + for option_string, action in conflicting_actions: + + # remove the conflicting option + action.option_strings.remove(option_string) + self._option_string_actions.pop(option_string, None) + + # if the option now has no option string, remove it from the + # container holding it + if not action.option_strings: + action.container._remove_action(action) + + +class _ArgumentGroup(_ActionsContainer): + + def __init__(self, container, title=None, description=None, **kwargs): + # add any missing keyword arguments by checking the container + update = kwargs.setdefault + update('conflict_handler', container.conflict_handler) + update('prefix_chars', container.prefix_chars) + update('argument_default', container.argument_default) + super_init = super(_ArgumentGroup, self).__init__ + super_init(description=description, **kwargs) + + # group attributes + self.title = title + self._group_actions = [] + + # share most attributes with the container + self._registries = container._registries + self._actions = container._actions + self._option_string_actions = container._option_string_actions + self._defaults = container._defaults + self._has_negative_number_optionals = \ + container._has_negative_number_optionals + self._mutually_exclusive_groups = container._mutually_exclusive_groups + + def _add_action(self, action): + action = super(_ArgumentGroup, self)._add_action(action) + self._group_actions.append(action) + return action + + def _remove_action(self, action): + super(_ArgumentGroup, self)._remove_action(action) + self._group_actions.remove(action) + + +class _MutuallyExclusiveGroup(_ArgumentGroup): + + def __init__(self, container, required=False): + super(_MutuallyExclusiveGroup, self).__init__(container) + self.required = required + self._container = container + + def _add_action(self, action): + if action.required: + msg = _('mutually exclusive arguments must be optional') + raise ValueError(msg) + action = self._container._add_action(action) + self._group_actions.append(action) + return action + + def _remove_action(self, action): + self._container._remove_action(action) + self._group_actions.remove(action) + + +class ArgumentParser(_AttributeHolder, _ActionsContainer): + """Object for parsing command line strings into Python objects. + + Keyword Arguments: + - prog -- The name of the program (default: sys.argv[0]) + - usage -- A usage message (default: auto-generated from arguments) + - description -- A description of what the program does + - epilog -- Text following the argument descriptions + - parents -- Parsers whose arguments should be copied into this one + - formatter_class -- HelpFormatter class for printing help messages + - prefix_chars -- Characters that prefix optional arguments + - fromfile_prefix_chars -- Characters that prefix files containing + additional arguments + - argument_default -- The default value for all arguments + - conflict_handler -- String indicating how to handle conflicts + - add_help -- Add a -h/-help option + """ + + def __init__(self, + prog=None, + usage=None, + description=None, + epilog=None, + version=None, + parents=[], + formatter_class=HelpFormatter, + prefix_chars='-', + fromfile_prefix_chars=None, + argument_default=None, + conflict_handler='error', + add_help=True): + + if version is not None: + import warnings + warnings.warn( + """The "version" argument to ArgumentParser is deprecated. """ + """Please use """ + """"add_argument(..., action='version', version="N", ...)" """ + """instead""", DeprecationWarning) + + superinit = super(ArgumentParser, self).__init__ + superinit(description=description, + prefix_chars=prefix_chars, + argument_default=argument_default, + conflict_handler=conflict_handler) + + # default setting for prog + if prog is None: + prog = _os.path.basename(_sys.argv[0]) + + self.prog = prog + self.usage = usage + self.epilog = epilog + self.version = version + self.formatter_class = formatter_class + self.fromfile_prefix_chars = fromfile_prefix_chars + self.add_help = add_help + + add_group = self.add_argument_group + self._positionals = add_group(_('positional arguments')) + self._optionals = add_group(_('optional arguments')) + self._subparsers = None + + # register types + def identity(string): + return string + self.register('type', None, identity) + + # add help and version arguments if necessary + # (using explicit default to override global argument_default) + default_prefix = '-' if '-' in prefix_chars else prefix_chars[0] + if self.add_help: + self.add_argument( + default_prefix+'h', default_prefix*2+'help', + action='help', default=SUPPRESS, + help=_('show this help message and exit')) + if self.version: + self.add_argument( + default_prefix+'v', default_prefix*2+'version', + action='version', default=SUPPRESS, + version=self.version, + help=_("show program's version number and exit")) + + # add parent arguments and defaults + for parent in parents: + self._add_container_actions(parent) + try: + defaults = parent._defaults + except AttributeError: + pass + else: + self._defaults.update(defaults) + + # ======================= + # Pretty __repr__ methods + # ======================= + def _get_kwargs(self): + names = [ + 'prog', + 'usage', + 'description', + 'version', + 'formatter_class', + 'conflict_handler', + 'add_help', + ] + return [(name, getattr(self, name)) for name in names] + + # ================================== + # Optional/Positional adding methods + # ================================== + def add_subparsers(self, **kwargs): + if self._subparsers is not None: + self.error(_('cannot have multiple subparser arguments')) + + # add the parser class to the arguments if it's not present + kwargs.setdefault('parser_class', type(self)) + + if 'title' in kwargs or 'description' in kwargs: + title = _(kwargs.pop('title', 'subcommands')) + description = _(kwargs.pop('description', None)) + self._subparsers = self.add_argument_group(title, description) + else: + self._subparsers = self._positionals + + # prog defaults to the usage message of this parser, skipping + # optional arguments and with no "usage:" prefix + if kwargs.get('prog') is None: + formatter = self._get_formatter() + positionals = self._get_positional_actions() + groups = self._mutually_exclusive_groups + formatter.add_usage(self.usage, positionals, groups, '') + kwargs['prog'] = formatter.format_help().strip() + + # create the parsers action and add it to the positionals list + parsers_class = self._pop_action_class(kwargs, 'parsers') + action = parsers_class(option_strings=[], **kwargs) + self._subparsers._add_action(action) + + # return the created parsers action + return action + + def _add_action(self, action): + if action.option_strings: + self._optionals._add_action(action) + else: + self._positionals._add_action(action) + return action + + def _get_optional_actions(self): + return [action + for action in self._actions + if action.option_strings] + + def _get_positional_actions(self): + return [action + for action in self._actions + if not action.option_strings] + + # ===================================== + # Command line argument parsing methods + # ===================================== + def parse_args(self, args=None, namespace=None): + args, argv = self.parse_known_args(args, namespace) + if argv: + msg = _('unrecognized arguments: %s') + self.error(msg % ' '.join(argv)) + return args + + def parse_known_args(self, args=None, namespace=None): + if args is None: + # args default to the system args + args = _sys.argv[1:] + else: + # make sure that args are mutable + args = list(args) + + # default Namespace built from parser defaults + if namespace is None: + namespace = Namespace() + + # add any action defaults that aren't present + for action in self._actions: + if action.dest is not SUPPRESS: + if not hasattr(namespace, action.dest): + if action.default is not SUPPRESS: + setattr(namespace, action.dest, action.default) + + # add any parser defaults that aren't present + for dest in self._defaults: + if not hasattr(namespace, dest): + setattr(namespace, dest, self._defaults[dest]) + + # parse the arguments and exit if there are any errors + try: + namespace, args = self._parse_known_args(args, namespace) + if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR): + args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR)) + delattr(namespace, _UNRECOGNIZED_ARGS_ATTR) + return namespace, args + except ArgumentError: + err = _sys.exc_info()[1] + self.error(str(err)) + + def _parse_known_args(self, arg_strings, namespace): + # replace arg strings that are file references + if self.fromfile_prefix_chars is not None: + arg_strings = self._read_args_from_files(arg_strings) + + # map all mutually exclusive arguments to the other arguments + # they can't occur with + action_conflicts = {} + for mutex_group in self._mutually_exclusive_groups: + group_actions = mutex_group._group_actions + for i, mutex_action in enumerate(mutex_group._group_actions): + conflicts = action_conflicts.setdefault(mutex_action, []) + conflicts.extend(group_actions[:i]) + conflicts.extend(group_actions[i + 1:]) + + # find all option indices, and determine the arg_string_pattern + # which has an 'O' if there is an option at an index, + # an 'A' if there is an argument, or a '-' if there is a '--' + option_string_indices = {} + arg_string_pattern_parts = [] + arg_strings_iter = iter(arg_strings) + for i, arg_string in enumerate(arg_strings_iter): + + # all args after -- are non-options + if arg_string == '--': + arg_string_pattern_parts.append('-') + for arg_string in arg_strings_iter: + arg_string_pattern_parts.append('A') + + # otherwise, add the arg to the arg strings + # and note the index if it was an option + else: + option_tuple = self._parse_optional(arg_string) + if option_tuple is None: + pattern = 'A' + else: + option_string_indices[i] = option_tuple + pattern = 'O' + arg_string_pattern_parts.append(pattern) + + # join the pieces together to form the pattern + arg_strings_pattern = ''.join(arg_string_pattern_parts) + + # converts arg strings to the appropriate and then takes the action + seen_actions = set() + seen_non_default_actions = set() + + def take_action(action, argument_strings, option_string=None): + seen_actions.add(action) + argument_values = self._get_values(action, argument_strings) + + # error if this argument is not allowed with other previously + # seen arguments, assuming that actions that use the default + # value don't really count as "present" + if argument_values is not action.default: + seen_non_default_actions.add(action) + for conflict_action in action_conflicts.get(action, []): + if conflict_action in seen_non_default_actions: + msg = _('not allowed with argument %s') + action_name = _get_action_name(conflict_action) + raise ArgumentError(action, msg % action_name) + + # take the action if we didn't receive a SUPPRESS value + # (e.g. from a default) + if argument_values is not SUPPRESS: + action(self, namespace, argument_values, option_string) + + # function to convert arg_strings into an optional action + def consume_optional(start_index): + + # get the optional identified at this index + option_tuple = option_string_indices[start_index] + action, option_string, explicit_arg = option_tuple + + # identify additional optionals in the same arg string + # (e.g. -xyz is the same as -x -y -z if no args are required) + match_argument = self._match_argument + action_tuples = [] + while True: + + # if we found no optional action, skip it + if action is None: + extras.append(arg_strings[start_index]) + return start_index + 1 + + # if there is an explicit argument, try to match the + # optional's string arguments to only this + if explicit_arg is not None: + arg_count = match_argument(action, 'A') + + # if the action is a single-dash option and takes no + # arguments, try to parse more single-dash options out + # of the tail of the option string + chars = self.prefix_chars + if arg_count == 0 and option_string[1] not in chars: + action_tuples.append((action, [], option_string)) + char = option_string[0] + option_string = char + explicit_arg[0] + new_explicit_arg = explicit_arg[1:] or None + optionals_map = self._option_string_actions + if option_string in optionals_map: + action = optionals_map[option_string] + explicit_arg = new_explicit_arg + else: + msg = _('ignored explicit argument %r') + raise ArgumentError(action, msg % explicit_arg) + + # if the action expect exactly one argument, we've + # successfully matched the option; exit the loop + elif arg_count == 1: + stop = start_index + 1 + args = [explicit_arg] + action_tuples.append((action, args, option_string)) + break + + # error if a double-dash option did not use the + # explicit argument + else: + msg = _('ignored explicit argument %r') + raise ArgumentError(action, msg % explicit_arg) + + # if there is no explicit argument, try to match the + # optional's string arguments with the following strings + # if successful, exit the loop + else: + start = start_index + 1 + selected_patterns = arg_strings_pattern[start:] + arg_count = match_argument(action, selected_patterns) + stop = start + arg_count + args = arg_strings[start:stop] + action_tuples.append((action, args, option_string)) + break + + # add the Optional to the list and return the index at which + # the Optional's string args stopped + assert action_tuples + for action, args, option_string in action_tuples: + take_action(action, args, option_string) + return stop + + # the list of Positionals left to be parsed; this is modified + # by consume_positionals() + positionals = self._get_positional_actions() + + # function to convert arg_strings into positional actions + def consume_positionals(start_index): + # match as many Positionals as possible + match_partial = self._match_arguments_partial + selected_pattern = arg_strings_pattern[start_index:] + arg_counts = match_partial(positionals, selected_pattern) + + # slice off the appropriate arg strings for each Positional + # and add the Positional and its args to the list + for action, arg_count in zip(positionals, arg_counts): + args = arg_strings[start_index: start_index + arg_count] + start_index += arg_count + take_action(action, args) + + # slice off the Positionals that we just parsed and return the + # index at which the Positionals' string args stopped + positionals[:] = positionals[len(arg_counts):] + return start_index + + # consume Positionals and Optionals alternately, until we have + # passed the last option string + extras = [] + start_index = 0 + if option_string_indices: + max_option_string_index = max(option_string_indices) + else: + max_option_string_index = -1 + while start_index <= max_option_string_index: + + # consume any Positionals preceding the next option + next_option_string_index = min([ + index + for index in option_string_indices + if index >= start_index]) + if start_index != next_option_string_index: + positionals_end_index = consume_positionals(start_index) + + # only try to parse the next optional if we didn't consume + # the option string during the positionals parsing + if positionals_end_index > start_index: + start_index = positionals_end_index + continue + else: + start_index = positionals_end_index + + # if we consumed all the positionals we could and we're not + # at the index of an option string, there were extra arguments + if start_index not in option_string_indices: + strings = arg_strings[start_index:next_option_string_index] + extras.extend(strings) + start_index = next_option_string_index + + # consume the next optional and any arguments for it + start_index = consume_optional(start_index) + + # consume any positionals following the last Optional + stop_index = consume_positionals(start_index) + + # if we didn't consume all the argument strings, there were extras + extras.extend(arg_strings[stop_index:]) + + # if we didn't use all the Positional objects, there were too few + # arg strings supplied. + if positionals: + self.error(_('too few arguments')) + + # make sure all required actions were present, and convert defaults. + for action in self._actions: + if action not in seen_actions: + if action.required: + name = _get_action_name(action) + self.error(_('argument %s is required') % name) + else: + # Convert action default now instead of doing it before + # parsing arguments to avoid calling convert functions + # twice (which may fail) if the argument was given, but + # only if it was defined already in the namespace + if (action.default is not None and + isinstance(action.default, basestring) and + hasattr(namespace, action.dest) and + action.default is getattr(namespace, action.dest)): + setattr(namespace, action.dest, + self._get_value(action, action.default)) + + # make sure all required groups had one option present + for group in self._mutually_exclusive_groups: + if group.required: + for action in group._group_actions: + if action in seen_non_default_actions: + break + + # if no actions were used, report the error + else: + names = [_get_action_name(action) + for action in group._group_actions + if action.help is not SUPPRESS] + msg = _('one of the arguments %s is required') + self.error(msg % ' '.join(names)) + + # return the updated namespace and the extra arguments + return namespace, extras + + def _read_args_from_files(self, arg_strings): + # expand arguments referencing files + new_arg_strings = [] + for arg_string in arg_strings: + + # for regular arguments, just add them back into the list + if not arg_string or arg_string[0] not in self.fromfile_prefix_chars: + new_arg_strings.append(arg_string) + + # replace arguments referencing files with the file content + else: + try: + args_file = open(arg_string[1:]) + try: + arg_strings = [] + for arg_line in args_file.read().splitlines(): + for arg in self.convert_arg_line_to_args(arg_line): + arg_strings.append(arg) + arg_strings = self._read_args_from_files(arg_strings) + new_arg_strings.extend(arg_strings) + finally: + args_file.close() + except IOError: + err = _sys.exc_info()[1] + self.error(str(err)) + + # return the modified argument list + return new_arg_strings + + def convert_arg_line_to_args(self, arg_line): + return [arg_line] + + def _match_argument(self, action, arg_strings_pattern): + # match the pattern for this action to the arg strings + nargs_pattern = self._get_nargs_pattern(action) + match = _re.match(nargs_pattern, arg_strings_pattern) + + # raise an exception if we weren't able to find a match + if match is None: + nargs_errors = { + None: _('expected one argument'), + OPTIONAL: _('expected at most one argument'), + ONE_OR_MORE: _('expected at least one argument'), + } + default = _('expected %s argument(s)') % action.nargs + msg = nargs_errors.get(action.nargs, default) + raise ArgumentError(action, msg) + + # return the number of arguments matched + return len(match.group(1)) + + def _match_arguments_partial(self, actions, arg_strings_pattern): + # progressively shorten the actions list by slicing off the + # final actions until we find a match + result = [] + for i in range(len(actions), 0, -1): + actions_slice = actions[:i] + pattern = ''.join([self._get_nargs_pattern(action) + for action in actions_slice]) + match = _re.match(pattern, arg_strings_pattern) + if match is not None: + result.extend([len(string) for string in match.groups()]) + break + + # return the list of arg string counts + return result + + def _parse_optional(self, arg_string): + # if it's an empty string, it was meant to be a positional + if not arg_string: + return None + + # if it doesn't start with a prefix, it was meant to be positional + if not arg_string[0] in self.prefix_chars: + return None + + # if the option string is present in the parser, return the action + if arg_string in self._option_string_actions: + action = self._option_string_actions[arg_string] + return action, arg_string, None + + # if it's just a single character, it was meant to be positional + if len(arg_string) == 1: + return None + + # if the option string before the "=" is present, return the action + if '=' in arg_string: + option_string, explicit_arg = arg_string.split('=', 1) + if option_string in self._option_string_actions: + action = self._option_string_actions[option_string] + return action, option_string, explicit_arg + + # search through all possible prefixes of the option string + # and all actions in the parser for possible interpretations + option_tuples = self._get_option_tuples(arg_string) + + # if multiple actions match, the option string was ambiguous + if len(option_tuples) > 1: + options = ', '.join([option_string + for action, option_string, explicit_arg in option_tuples]) + tup = arg_string, options + self.error(_('ambiguous option: %s could match %s') % tup) + + # if exactly one action matched, this segmentation is good, + # so return the parsed action + elif len(option_tuples) == 1: + option_tuple, = option_tuples + return option_tuple + + # if it was not found as an option, but it looks like a negative + # number, it was meant to be positional + # unless there are negative-number-like options + if self._negative_number_matcher.match(arg_string): + if not self._has_negative_number_optionals: + return None + + # if it contains a space, it was meant to be a positional + if ' ' in arg_string: + return None + + # it was meant to be an optional but there is no such option + # in this parser (though it might be a valid option in a subparser) + return None, arg_string, None + + def _get_option_tuples(self, option_string): + result = [] + + # option strings starting with two prefix characters are only + # split at the '=' + chars = self.prefix_chars + if option_string[0] in chars and option_string[1] in chars: + if '=' in option_string: + option_prefix, explicit_arg = option_string.split('=', 1) + else: + option_prefix = option_string + explicit_arg = None + for option_string in self._option_string_actions: + if option_string.startswith(option_prefix): + action = self._option_string_actions[option_string] + tup = action, option_string, explicit_arg + result.append(tup) + + # single character options can be concatenated with their arguments + # but multiple character options always have to have their argument + # separate + elif option_string[0] in chars and option_string[1] not in chars: + option_prefix = option_string + explicit_arg = None + short_option_prefix = option_string[:2] + short_explicit_arg = option_string[2:] + + for option_string in self._option_string_actions: + if option_string == short_option_prefix: + action = self._option_string_actions[option_string] + tup = action, option_string, short_explicit_arg + result.append(tup) + elif option_string.startswith(option_prefix): + action = self._option_string_actions[option_string] + tup = action, option_string, explicit_arg + result.append(tup) + + # shouldn't ever get here + else: + self.error(_('unexpected option string: %s') % option_string) + + # return the collected option tuples + return result + + def _get_nargs_pattern(self, action): + # in all examples below, we have to allow for '--' args + # which are represented as '-' in the pattern + nargs = action.nargs + + # the default (None) is assumed to be a single argument + if nargs is None: + nargs_pattern = '(-*A-*)' + + # allow zero or one arguments + elif nargs == OPTIONAL: + nargs_pattern = '(-*A?-*)' + + # allow zero or more arguments + elif nargs == ZERO_OR_MORE: + nargs_pattern = '(-*[A-]*)' + + # allow one or more arguments + elif nargs == ONE_OR_MORE: + nargs_pattern = '(-*A[A-]*)' + + # allow any number of options or arguments + elif nargs == REMAINDER: + nargs_pattern = '([-AO]*)' + + # allow one argument followed by any number of options or arguments + elif nargs == PARSER: + nargs_pattern = '(-*A[-AO]*)' + + # all others should be integers + else: + nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs) + + # if this is an optional action, -- is not allowed + if action.option_strings: + nargs_pattern = nargs_pattern.replace('-*', '') + nargs_pattern = nargs_pattern.replace('-', '') + + # return the pattern + return nargs_pattern + + # ======================== + # Value conversion methods + # ======================== + def _get_values(self, action, arg_strings): + # for everything but PARSER, REMAINDER args, strip out first '--' + if action.nargs not in [PARSER, REMAINDER]: + try: + arg_strings.remove('--') + except ValueError: + pass + + # optional argument produces a default when not present + if not arg_strings and action.nargs == OPTIONAL: + if action.option_strings: + value = action.const + else: + value = action.default + if isinstance(value, basestring): + value = self._get_value(action, value) + self._check_value(action, value) + + # when nargs='*' on a positional, if there were no command-line + # args, use the default if it is anything other than None + elif (not arg_strings and action.nargs == ZERO_OR_MORE and + not action.option_strings): + if action.default is not None: + value = action.default + else: + value = arg_strings + self._check_value(action, value) + + # single argument or optional argument produces a single value + elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]: + arg_string, = arg_strings + value = self._get_value(action, arg_string) + self._check_value(action, value) + + # REMAINDER arguments convert all values, checking none + elif action.nargs == REMAINDER: + value = [self._get_value(action, v) for v in arg_strings] + + # PARSER arguments convert all values, but check only the first + elif action.nargs == PARSER: + value = [self._get_value(action, v) for v in arg_strings] + self._check_value(action, value[0]) + + # all other types of nargs produce a list + else: + value = [self._get_value(action, v) for v in arg_strings] + for v in value: + self._check_value(action, v) + + # return the converted value + return value + + def _get_value(self, action, arg_string): + type_func = self._registry_get('type', action.type, action.type) + if not _callable(type_func): + msg = _('%r is not callable') + raise ArgumentError(action, msg % type_func) + + # convert the value to the appropriate type + try: + result = type_func(arg_string) + + # ArgumentTypeErrors indicate errors + except ArgumentTypeError: + name = getattr(action.type, '__name__', repr(action.type)) + msg = str(_sys.exc_info()[1]) + raise ArgumentError(action, msg) + + # TypeErrors or ValueErrors also indicate errors + except (TypeError, ValueError): + name = getattr(action.type, '__name__', repr(action.type)) + msg = _('invalid %s value: %r') + raise ArgumentError(action, msg % (name, arg_string)) + + # return the converted value + return result + + def _check_value(self, action, value): + # converted value must be one of the choices (if specified) + if action.choices is not None and value not in action.choices: + tup = value, ', '.join(map(repr, action.choices)) + msg = _('invalid choice: %r (choose from %s)') % tup + raise ArgumentError(action, msg) + + # ======================= + # Help-formatting methods + # ======================= + def format_usage(self): + formatter = self._get_formatter() + formatter.add_usage(self.usage, self._actions, + self._mutually_exclusive_groups) + return formatter.format_help() + + def format_help(self): + formatter = self._get_formatter() + + # usage + formatter.add_usage(self.usage, self._actions, + self._mutually_exclusive_groups) + + # description + formatter.add_text(self.description) + + # positionals, optionals and user-defined groups + for action_group in self._action_groups: + formatter.start_section(action_group.title) + formatter.add_text(action_group.description) + formatter.add_arguments(action_group._group_actions) + formatter.end_section() + + # epilog + formatter.add_text(self.epilog) + + # determine help from format above + return formatter.format_help() + + def format_version(self): + import warnings + warnings.warn( + 'The format_version method is deprecated -- the "version" ' + 'argument to ArgumentParser is no longer supported.', + DeprecationWarning) + formatter = self._get_formatter() + formatter.add_text(self.version) + return formatter.format_help() + + def _get_formatter(self): + return self.formatter_class(prog=self.prog) + + # ===================== + # Help-printing methods + # ===================== + def print_usage(self, file=None): + if file is None: + file = _sys.stdout + self._print_message(self.format_usage(), file) + + def print_help(self, file=None): + if file is None: + file = _sys.stdout + self._print_message(self.format_help(), file) + + def print_version(self, file=None): + import warnings + warnings.warn( + 'The print_version method is deprecated -- the "version" ' + 'argument to ArgumentParser is no longer supported.', + DeprecationWarning) + self._print_message(self.format_version(), file) + + def _print_message(self, message, file=None): + if message: + if file is None: + file = _sys.stderr + file.write(message) + + # =============== + # Exiting methods + # =============== + def exit(self, status=0, message=None): + if message: + self._print_message(message, _sys.stderr) + _sys.exit(status) + + def error(self, message): + """error(message: string) + + Prints a usage message incorporating the message to stderr and + exits. + + If you override this in a subclass, it should not return -- it + should either exit or raise an exception. + """ + self.print_usage(_sys.stderr) + self.exit(2, _('%s: error: %s\n') % (self.prog, message)) diff --git a/PythonHome/Lib/argparse.pyc b/PythonHome/Lib/argparse.pyc deleted file mode 100644 index 961d7781557ac7cb4fbed8aaf965b45e20c125b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61934 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%0AP-uzJ-+WfLSuB%9fw+ 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 + +# ====================================================================== +# Copyright 1996 by Sam Rushing +# +# 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 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. +# ====================================================================== + +r"""A class supporting chat-style (command/response) protocols. + +This class adds support for 'chat' style protocols - where one side +sends a 'command', and the other sends a response (examples would be +the common internet protocols - smtp, nntp, ftp, etc..). + +The handle_read() method looks at the input stream for the current +'terminator' (usually '\r\n' for single-line responses, '\r\n.\r\n' +for multi-line output), calling self.found_terminator() on its +receipt. + +for example: +Say you build an async nntp client using this class. At the start +of the connection, you'll have self.terminator set to '\r\n', in +order to process the single-line greeting. Just before issuing a +'LIST' command you'll set it to '\r\n.\r\n'. The output of the LIST +command will be accumulated (using your own 'collect_incoming_data' +method) up to the terminator, and then control will be returned to +you - by calling your self.found_terminator() method. +""" + +import socket +import asyncore +from collections import deque +from sys import py3kwarning +from warnings import filterwarnings, catch_warnings + +class async_chat (asyncore.dispatcher): + """This is an abstract class. You must derive from this class, and add + the two methods collect_incoming_data() and found_terminator()""" + + # these are overridable defaults + + ac_in_buffer_size = 4096 + ac_out_buffer_size = 4096 + + def __init__ (self, sock=None, map=None): + # for string terminator matching + self.ac_in_buffer = '' + + # we use a list here rather than cStringIO for a few reasons... + # del lst[:] is faster than sio.truncate(0) + # lst = [] is faster than sio.truncate(0) + # cStringIO will be gaining unicode support in py3k, which + # will negatively affect the performance of bytes compared to + # a ''.join() equivalent + self.incoming = [] + + # we toss the use of the "simple producer" and replace it with + # a pure deque, which the original fifo was a wrapping of + self.producer_fifo = deque() + asyncore.dispatcher.__init__ (self, sock, map) + + def collect_incoming_data(self, data): + raise NotImplementedError("must be implemented in subclass") + + def _collect_incoming_data(self, data): + self.incoming.append(data) + + def _get_data(self): + d = ''.join(self.incoming) + del self.incoming[:] + return d + + def found_terminator(self): + raise NotImplementedError("must be implemented in subclass") + + def set_terminator (self, term): + "Set the input delimiter. Can be a fixed string of any length, an integer, or None" + self.terminator = term + + def get_terminator (self): + return self.terminator + + # grab some more data from the socket, + # throw it to the collector method, + # check for the terminator, + # if found, transition to the next state. + + def handle_read (self): + + try: + data = self.recv (self.ac_in_buffer_size) + except socket.error, why: + self.handle_error() + return + + self.ac_in_buffer = self.ac_in_buffer + data + + # Continue to search for self.terminator in self.ac_in_buffer, + # while calling self.collect_incoming_data. The while loop + # is necessary because we might read several data+terminator + # combos with a single recv(4096). + + while self.ac_in_buffer: + lb = len(self.ac_in_buffer) + terminator = self.get_terminator() + if not terminator: + # no terminator, collect it all + self.collect_incoming_data (self.ac_in_buffer) + self.ac_in_buffer = '' + elif isinstance(terminator, int) or isinstance(terminator, long): + # numeric terminator + n = terminator + if lb < n: + self.collect_incoming_data (self.ac_in_buffer) + self.ac_in_buffer = '' + self.terminator = self.terminator - lb + else: + self.collect_incoming_data (self.ac_in_buffer[:n]) + self.ac_in_buffer = self.ac_in_buffer[n:] + self.terminator = 0 + self.found_terminator() + else: + # 3 cases: + # 1) end of buffer matches terminator exactly: + # collect data, transition + # 2) end of buffer matches some prefix: + # collect data to the prefix + # 3) end of buffer does not match any prefix: + # collect data + terminator_len = len(terminator) + index = self.ac_in_buffer.find(terminator) + if index != -1: + # we found the terminator + if index > 0: + # don't bother reporting the empty string (source of subtle bugs) + self.collect_incoming_data (self.ac_in_buffer[:index]) + self.ac_in_buffer = self.ac_in_buffer[index+terminator_len:] + # This does the Right Thing if the terminator is changed here. + self.found_terminator() + else: + # check for a prefix of the terminator + index = find_prefix_at_end (self.ac_in_buffer, terminator) + if index: + if index != lb: + # we found a prefix, collect up to the prefix + self.collect_incoming_data (self.ac_in_buffer[:-index]) + self.ac_in_buffer = self.ac_in_buffer[-index:] + break + else: + # no prefix, collect it all + self.collect_incoming_data (self.ac_in_buffer) + self.ac_in_buffer = '' + + def handle_write (self): + self.initiate_send() + + def handle_close (self): + self.close() + + def push (self, data): + sabs = self.ac_out_buffer_size + if len(data) > sabs: + for i in xrange(0, len(data), sabs): + self.producer_fifo.append(data[i:i+sabs]) + else: + self.producer_fifo.append(data) + self.initiate_send() + + def push_with_producer (self, producer): + self.producer_fifo.append(producer) + self.initiate_send() + + def readable (self): + "predicate for inclusion in the readable for select()" + # cannot use the old predicate, it violates the claim of the + # set_terminator method. + + # return (len(self.ac_in_buffer) <= self.ac_in_buffer_size) + return 1 + + def writable (self): + "predicate for inclusion in the writable for select()" + return self.producer_fifo or (not self.connected) + + def close_when_done (self): + "automatically close this channel once the outgoing queue is empty" + self.producer_fifo.append(None) + + def initiate_send(self): + while self.producer_fifo and self.connected: + first = self.producer_fifo[0] + # handle empty string/buffer or None entry + if not first: + del self.producer_fifo[0] + if first is None: + self.handle_close() + return + + # handle classic producer behavior + obs = self.ac_out_buffer_size + try: + with catch_warnings(): + if py3kwarning: + filterwarnings("ignore", ".*buffer", DeprecationWarning) + data = buffer(first, 0, obs) + except TypeError: + data = first.more() + if data: + self.producer_fifo.appendleft(data) + else: + del self.producer_fifo[0] + continue + + # send the data + try: + num_sent = self.send(data) + except socket.error: + self.handle_error() + return + + if num_sent: + if num_sent < len(data) or obs < len(first): + self.producer_fifo[0] = first[num_sent:] + else: + del self.producer_fifo[0] + # we tried to send some actual data + return + + def discard_buffers (self): + # Emergencies only! + self.ac_in_buffer = '' + del self.incoming[:] + self.producer_fifo.clear() + +class simple_producer: + + def __init__ (self, data, buffer_size=512): + self.data = data + self.buffer_size = buffer_size + + def more (self): + if len (self.data) > self.buffer_size: + result = self.data[:self.buffer_size] + self.data = self.data[self.buffer_size:] + return result + else: + result = self.data + self.data = '' + return result + +class fifo: + def __init__ (self, list=None): + if not list: + self.list = deque() + else: + self.list = deque(list) + + def __len__ (self): + return len(self.list) + + def is_empty (self): + return not self.list + + def first (self): + return self.list[0] + + def push (self, data): + self.list.append(data) + + def pop (self): + if self.list: + return (1, self.list.popleft()) + else: + return (0, None) + +# Given 'haystack', see if any prefix of 'needle' is at its end. This +# assumes an exact match has already been checked. Return the number of +# characters matched. +# for example: +# f_p_a_e ("qwerty\r", "\r\n") => 1 +# f_p_a_e ("qwertydkjf", "\r\n") => 0 +# f_p_a_e ("qwerty\r\n", "\r\n") => + +# this could maybe be made faster with a computed regex? +# [answer: no; circa Python-2.0, Jan 2001] +# new python: 28961/s +# old python: 18307/s +# re: 12820/s +# regex: 14035/s + +def find_prefix_at_end (haystack, needle): + l = len(needle) - 1 + while l and not haystack.endswith(needle[:l]): + l -= 1 + return l diff --git a/PythonHome/Lib/asynchat.pyc b/PythonHome/Lib/asynchat.pyc deleted file mode 100644 index 994fa3c61df590afa353258bacd3b879a86d5760..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8190 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 jjMU+*%A!|nA@S{(NJi%d?#hkHl5@^|=1 + +# ====================================================================== +# Copyright 1996 by Sam Rushing +# +# 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 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. +# ====================================================================== + +"""Basic infrastructure for asynchronous socket service clients and servers. + +There are only two ways to have a program on a single processor do "more +than one thing at a time". Multi-threaded programming is the simplest and +most popular way to do it, but there is another very different technique, +that lets you have nearly all the advantages of multi-threading, without +actually using multiple threads. it's really only practical if your program +is largely I/O bound. If your program is CPU bound, then pre-emptive +scheduled threads are probably what you really need. Network servers are +rarely CPU-bound, however. + +If your operating system supports the select() system call in its I/O +library (and nearly all do), then you can use it to juggle multiple +communication channels at once; doing other work while your I/O is taking +place in the "background." Although this strategy can seem strange and +complex, especially at first, it is in many ways easier to understand and +control than multi-threaded programming. The module documented here solves +many of the difficult problems for you, making the task of building +sophisticated high-performance network servers and clients a snap. +""" + +import select +import socket +import sys +import time +import warnings + +import os +from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, EINVAL, \ + ENOTCONN, ESHUTDOWN, EINTR, EISCONN, EBADF, ECONNABORTED, EPIPE, EAGAIN, \ + errorcode + +_DISCONNECTED = frozenset((ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED, EPIPE, + EBADF)) + +try: + socket_map +except NameError: + socket_map = {} + +def _strerror(err): + try: + return os.strerror(err) + except (ValueError, OverflowError, NameError): + if err in errorcode: + return errorcode[err] + return "Unknown error %s" %err + +class ExitNow(Exception): + pass + +_reraised_exceptions = (ExitNow, KeyboardInterrupt, SystemExit) + +def read(obj): + try: + obj.handle_read_event() + except _reraised_exceptions: + raise + except: + obj.handle_error() + +def write(obj): + try: + obj.handle_write_event() + except _reraised_exceptions: + raise + except: + obj.handle_error() + +def _exception(obj): + try: + obj.handle_expt_event() + except _reraised_exceptions: + raise + except: + obj.handle_error() + +def readwrite(obj, flags): + try: + if flags & select.POLLIN: + obj.handle_read_event() + if flags & select.POLLOUT: + obj.handle_write_event() + if flags & select.POLLPRI: + obj.handle_expt_event() + if flags & (select.POLLHUP | select.POLLERR | select.POLLNVAL): + obj.handle_close() + except socket.error, e: + if e.args[0] not in _DISCONNECTED: + obj.handle_error() + else: + obj.handle_close() + except _reraised_exceptions: + raise + except: + obj.handle_error() + +def poll(timeout=0.0, map=None): + if map is None: + map = socket_map + if map: + r = []; w = []; e = [] + for fd, obj in map.items(): + is_r = obj.readable() + is_w = obj.writable() + if is_r: + r.append(fd) + # accepting sockets should not be writable + if is_w and not obj.accepting: + w.append(fd) + if is_r or is_w: + e.append(fd) + if [] == r == w == e: + time.sleep(timeout) + return + + try: + r, w, e = select.select(r, w, e, timeout) + except select.error, err: + if err.args[0] != EINTR: + raise + else: + return + + for fd in r: + obj = map.get(fd) + if obj is None: + continue + read(obj) + + for fd in w: + obj = map.get(fd) + if obj is None: + continue + write(obj) + + for fd in e: + obj = map.get(fd) + if obj is None: + continue + _exception(obj) + +def poll2(timeout=0.0, map=None): + # Use the poll() support added to the select module in Python 2.0 + if map is None: + map = socket_map + if timeout is not None: + # timeout is in milliseconds + timeout = int(timeout*1000) + pollster = select.poll() + if map: + for fd, obj in map.items(): + flags = 0 + if obj.readable(): + flags |= select.POLLIN | select.POLLPRI + # accepting sockets should not be writable + if obj.writable() and not obj.accepting: + flags |= select.POLLOUT + if flags: + # Only check for exceptions if object was either readable + # or writable. + flags |= select.POLLERR | select.POLLHUP | select.POLLNVAL + pollster.register(fd, flags) + try: + r = pollster.poll(timeout) + except select.error, err: + if err.args[0] != EINTR: + raise + r = [] + for fd, flags in r: + obj = map.get(fd) + if obj is None: + continue + readwrite(obj, flags) + +poll3 = poll2 # Alias for backward compatibility + +def loop(timeout=30.0, use_poll=False, map=None, count=None): + if map is None: + map = socket_map + + if use_poll and hasattr(select, 'poll'): + poll_fun = poll2 + else: + poll_fun = poll + + if count is None: + while map: + poll_fun(timeout, map) + + else: + while map and count > 0: + poll_fun(timeout, map) + count = count - 1 + +class dispatcher: + + debug = False + connected = False + accepting = False + connecting = False + closing = False + addr = None + ignore_log_types = frozenset(['warning']) + + def __init__(self, sock=None, map=None): + if map is None: + self._map = socket_map + else: + self._map = map + + self._fileno = None + + if sock: + # Set to nonblocking just to make sure for cases where we + # get a socket from a blocking source. + sock.setblocking(0) + self.set_socket(sock, map) + self.connected = True + # The constructor no longer requires that the socket + # passed be connected. + try: + self.addr = sock.getpeername() + except socket.error, err: + if err.args[0] in (ENOTCONN, EINVAL): + # To handle the case where we got an unconnected + # socket. + self.connected = False + else: + # The socket is broken in some unknown way, alert + # the user and remove it from the map (to prevent + # polling of broken sockets). + self.del_channel(map) + raise + else: + self.socket = None + + def __repr__(self): + status = [self.__class__.__module__+"."+self.__class__.__name__] + if self.accepting and self.addr: + status.append('listening') + elif self.connected: + status.append('connected') + if self.addr is not None: + try: + status.append('%s:%d' % self.addr) + except TypeError: + status.append(repr(self.addr)) + return '<%s at %#x>' % (' '.join(status), id(self)) + + __str__ = __repr__ + + def add_channel(self, map=None): + #self.log_info('adding channel %s' % self) + if map is None: + map = self._map + map[self._fileno] = self + + def del_channel(self, map=None): + fd = self._fileno + if map is None: + map = self._map + if fd in map: + #self.log_info('closing channel %d:%s' % (fd, self)) + del map[fd] + self._fileno = None + + def create_socket(self, family, type): + self.family_and_type = family, type + sock = socket.socket(family, type) + sock.setblocking(0) + self.set_socket(sock) + + def set_socket(self, sock, map=None): + self.socket = sock +## self.__dict__['socket'] = sock + self._fileno = sock.fileno() + self.add_channel(map) + + def set_reuse_addr(self): + # try to re-use a server port if possible + try: + self.socket.setsockopt( + socket.SOL_SOCKET, socket.SO_REUSEADDR, + self.socket.getsockopt(socket.SOL_SOCKET, + socket.SO_REUSEADDR) | 1 + ) + except socket.error: + pass + + # ================================================== + # predicates for select() + # these are used as filters for the lists of sockets + # to pass to select(). + # ================================================== + + def readable(self): + return True + + def writable(self): + return True + + # ================================================== + # socket object methods. + # ================================================== + + def listen(self, num): + self.accepting = True + if os.name == 'nt' and num > 5: + num = 5 + return self.socket.listen(num) + + def bind(self, addr): + self.addr = addr + return self.socket.bind(addr) + + def connect(self, address): + self.connected = False + self.connecting = True + err = self.socket.connect_ex(address) + if err in (EINPROGRESS, EALREADY, EWOULDBLOCK) \ + or err == EINVAL and os.name in ('nt', 'ce'): + self.addr = address + return + if err in (0, EISCONN): + self.addr = address + self.handle_connect_event() + else: + raise socket.error(err, errorcode[err]) + + def accept(self): + # XXX can return either an address pair or None + try: + conn, addr = self.socket.accept() + except TypeError: + return None + except socket.error as why: + if why.args[0] in (EWOULDBLOCK, ECONNABORTED, EAGAIN): + return None + else: + raise + else: + return conn, addr + + def send(self, data): + try: + result = self.socket.send(data) + return result + except socket.error, why: + if why.args[0] == EWOULDBLOCK: + return 0 + elif why.args[0] in _DISCONNECTED: + self.handle_close() + return 0 + else: + raise + + def recv(self, buffer_size): + try: + data = self.socket.recv(buffer_size) + if not data: + # a closed connection is indicated by signaling + # a read condition, and having recv() return 0. + self.handle_close() + return '' + else: + return data + except socket.error, why: + # winsock sometimes raises ENOTCONN + if why.args[0] in _DISCONNECTED: + self.handle_close() + return '' + else: + raise + + def close(self): + self.connected = False + self.accepting = False + self.connecting = False + self.del_channel() + try: + self.socket.close() + except socket.error, why: + if why.args[0] not in (ENOTCONN, EBADF): + raise + + # cheap inheritance, used to pass all other attribute + # references to the underlying socket object. + def __getattr__(self, attr): + try: + retattr = getattr(self.socket, attr) + except AttributeError: + raise AttributeError("%s instance has no attribute '%s'" + %(self.__class__.__name__, attr)) + else: + msg = "%(me)s.%(attr)s is deprecated. Use %(me)s.socket.%(attr)s " \ + "instead." % {'me': self.__class__.__name__, 'attr':attr} + warnings.warn(msg, DeprecationWarning, stacklevel=2) + return retattr + + # log and log_info may be overridden to provide more sophisticated + # logging and warning methods. In general, log is for 'hit' logging + # and 'log_info' is for informational, warning and error logging. + + def log(self, message): + sys.stderr.write('log: %s\n' % str(message)) + + def log_info(self, message, type='info'): + if type not in self.ignore_log_types: + print '%s: %s' % (type, message) + + def handle_read_event(self): + if self.accepting: + # accepting sockets are never connected, they "spawn" new + # sockets that are connected + self.handle_accept() + elif not self.connected: + if self.connecting: + self.handle_connect_event() + self.handle_read() + else: + self.handle_read() + + def handle_connect_event(self): + err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) + if err != 0: + raise socket.error(err, _strerror(err)) + self.handle_connect() + self.connected = True + self.connecting = False + + def handle_write_event(self): + if self.accepting: + # Accepting sockets shouldn't get a write event. + # We will pretend it didn't happen. + return + + if not self.connected: + if self.connecting: + self.handle_connect_event() + self.handle_write() + + def handle_expt_event(self): + # handle_expt_event() is called if there might be an error on the + # socket, or if there is OOB data + # check for the error condition first + err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) + if err != 0: + # we can get here when select.select() says that there is an + # exceptional condition on the socket + # since there is an error, we'll go ahead and close the socket + # like we would in a subclassed handle_read() that received no + # data + self.handle_close() + else: + self.handle_expt() + + def handle_error(self): + nil, t, v, tbinfo = compact_traceback() + + # sometimes a user repr method will crash. + try: + self_repr = repr(self) + except: + self_repr = '<__repr__(self) failed for object at %0x>' % id(self) + + self.log_info( + 'uncaptured python exception, closing channel %s (%s:%s %s)' % ( + self_repr, + t, + v, + tbinfo + ), + 'error' + ) + self.handle_close() + + def handle_expt(self): + self.log_info('unhandled incoming priority event', 'warning') + + def handle_read(self): + self.log_info('unhandled read event', 'warning') + + def handle_write(self): + self.log_info('unhandled write event', 'warning') + + def handle_connect(self): + self.log_info('unhandled connect event', 'warning') + + def handle_accept(self): + self.log_info('unhandled accept event', 'warning') + + def handle_close(self): + self.log_info('unhandled close event', 'warning') + self.close() + +# --------------------------------------------------------------------------- +# adds simple buffered output capability, useful for simple clients. +# [for more sophisticated usage use asynchat.async_chat] +# --------------------------------------------------------------------------- + +class dispatcher_with_send(dispatcher): + + def __init__(self, sock=None, map=None): + dispatcher.__init__(self, sock, map) + self.out_buffer = '' + + def initiate_send(self): + num_sent = 0 + num_sent = dispatcher.send(self, self.out_buffer[:512]) + self.out_buffer = self.out_buffer[num_sent:] + + def handle_write(self): + self.initiate_send() + + def writable(self): + return (not self.connected) or len(self.out_buffer) + + def send(self, data): + if self.debug: + self.log_info('sending %s' % repr(data)) + self.out_buffer = self.out_buffer + data + self.initiate_send() + +# --------------------------------------------------------------------------- +# used for debugging. +# --------------------------------------------------------------------------- + +def compact_traceback(): + t, v, tb = sys.exc_info() + tbinfo = [] + if not tb: # Must have a traceback + raise AssertionError("traceback does not exist") + while tb: + tbinfo.append(( + tb.tb_frame.f_code.co_filename, + tb.tb_frame.f_code.co_name, + str(tb.tb_lineno) + )) + tb = tb.tb_next + + # just to be safe + del tb + + file, function, line = tbinfo[-1] + info = ' '.join(['[%s|%s|%s]' % x for x in tbinfo]) + return (file, function, line), t, v, info + +def close_all(map=None, ignore_all=False): + if map is None: + map = socket_map + for x in map.values(): + try: + x.close() + except OSError, x: + if x.args[0] == EBADF: + pass + elif not ignore_all: + raise + except _reraised_exceptions: + raise + except: + if not ignore_all: + raise + map.clear() + +# Asynchronous File I/O: +# +# After a little research (reading man pages on various unixen, and +# digging through the linux kernel), I've determined that select() +# isn't meant for doing asynchronous file i/o. +# Heartening, though - reading linux/mm/filemap.c shows that linux +# supports asynchronous read-ahead. So _MOST_ of the time, the data +# will be sitting in memory for us already when we go to read it. +# +# What other OS's (besides NT) support async file i/o? [VMS?] +# +# Regardless, this is useful for pipes, and stdin/stdout... + +if os.name == 'posix': + import fcntl + + class file_wrapper: + # Here we override just enough to make a file + # look like a socket for the purposes of asyncore. + # The passed fd is automatically os.dup()'d + + def __init__(self, fd): + self.fd = os.dup(fd) + + def recv(self, *args): + return os.read(self.fd, *args) + + def send(self, *args): + return os.write(self.fd, *args) + + def getsockopt(self, level, optname, buflen=None): + if (level == socket.SOL_SOCKET and + optname == socket.SO_ERROR and + not buflen): + return 0 + raise NotImplementedError("Only asyncore specific behaviour " + "implemented.") + + read = recv + write = send + + def close(self): + os.close(self.fd) + + def fileno(self): + return self.fd + + class file_dispatcher(dispatcher): + + def __init__(self, fd, map=None): + dispatcher.__init__(self, None, map) + self.connected = True + try: + fd = fd.fileno() + except AttributeError: + pass + self.set_file(fd) + # set it to non-blocking mode + flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0) + flags = flags | os.O_NONBLOCK + fcntl.fcntl(fd, fcntl.F_SETFL, flags) + + def set_file(self, fd): + self.socket = file_wrapper(fd) + self._fileno = self.socket.fileno() + self.add_channel() diff --git a/PythonHome/Lib/asyncore.pyc b/PythonHome/Lib/asyncore.pyc deleted file mode 100644 index c52ec016b96c19ce2e67a30a9b952c9222158314..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17953 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 sys.stderr, "Error in atexit._run_exitfuncs:" + traceback.print_exc() + exc_info = sys.exc_info() + + if exc_info is not None: + raise exc_info[0], exc_info[1], exc_info[2] + + +def register(func, *targs, **kargs): + """register a function to be executed upon normal program termination + + func - function to be called at exit + targs - optional arguments to pass to func + kargs - optional keyword arguments to pass to func + + func is returned to facilitate usage as a decorator. + """ + _exithandlers.append((func, targs, kargs)) + return func + +if hasattr(sys, "exitfunc"): + # Assume it's another registered exit function - append it to our list + register(sys.exitfunc) +sys.exitfunc = _run_exitfuncs + +if __name__ == "__main__": + def x1(): + print "running x1" + def x2(n): + print "running x2(%r)" % (n,) + def x3(n, kwd=None): + print "running x3(%r, kwd=%r)" % (n, kwd) + + register(x1) + register(x2, 12) + register(x3, 5, "bar") + register(x3, "no kwd args") diff --git a/PythonHome/Lib/atexit.pyc b/PythonHome/Lib/atexit.pyc index 345a645ca8f5bcd2ecedf6d511763e852f79bd18..61e5ab5ca6ecc56acad92e3bc17c0ab4293011f6 100644 GIT binary patch delta 340 zcmew>a8hW)9cDvo1_p*ytC;l6l8n-%nDG1xJ+EMYzn}o;82{3eg3^*0m(--v^q7Fk wl8pR3kNn)!&99k{GLo)s@_yE4GIRy9RgtAjWb!+<3Nm$evM(epF delta 128 zcmX>p^jBcR9cF$>1_lOatC)bwl8pR3BlFF?EJqp91t&AJHDicvXRE>xOJeWA5R>QF KiXq0z=>h-~#UoDu diff --git a/PythonHome/Lib/audiodev.py b/PythonHome/Lib/audiodev.py new file mode 100644 index 0000000000..b6831a692f --- /dev/null +++ b/PythonHome/Lib/audiodev.py @@ -0,0 +1,260 @@ +"""Classes for manipulating audio devices (currently only for Sun and SGI)""" +from warnings import warnpy3k +warnpy3k("the audiodev module has been removed in Python 3.0", stacklevel=2) +del warnpy3k + +__all__ = ["error","AudioDev"] + +class error(Exception): + pass + +class Play_Audio_sgi: + # Private instance variables +## if 0: access frameratelist, nchannelslist, sampwidthlist, oldparams, \ +## params, config, inited_outrate, inited_width, \ +## inited_nchannels, port, converter, classinited: private + + classinited = 0 + frameratelist = nchannelslist = sampwidthlist = None + + def initclass(self): + import AL + self.frameratelist = [ + (48000, AL.RATE_48000), + (44100, AL.RATE_44100), + (32000, AL.RATE_32000), + (22050, AL.RATE_22050), + (16000, AL.RATE_16000), + (11025, AL.RATE_11025), + ( 8000, AL.RATE_8000), + ] + self.nchannelslist = [ + (1, AL.MONO), + (2, AL.STEREO), + (4, AL.QUADRO), + ] + self.sampwidthlist = [ + (1, AL.SAMPLE_8), + (2, AL.SAMPLE_16), + (3, AL.SAMPLE_24), + ] + self.classinited = 1 + + def __init__(self): + import al, AL + if not self.classinited: + self.initclass() + self.oldparams = [] + self.params = [AL.OUTPUT_RATE, 0] + self.config = al.newconfig() + self.inited_outrate = 0 + self.inited_width = 0 + self.inited_nchannels = 0 + self.converter = None + self.port = None + return + + def __del__(self): + if self.port: + self.stop() + if self.oldparams: + import al, AL + al.setparams(AL.DEFAULT_DEVICE, self.oldparams) + self.oldparams = [] + + def wait(self): + if not self.port: + return + import time + while self.port.getfilled() > 0: + time.sleep(0.1) + self.stop() + + def stop(self): + if self.port: + self.port.closeport() + self.port = None + if self.oldparams: + import al, AL + al.setparams(AL.DEFAULT_DEVICE, self.oldparams) + self.oldparams = [] + + def setoutrate(self, rate): + for (raw, cooked) in self.frameratelist: + if rate == raw: + self.params[1] = cooked + self.inited_outrate = 1 + break + else: + raise error, 'bad output rate' + + def setsampwidth(self, width): + for (raw, cooked) in self.sampwidthlist: + if width == raw: + self.config.setwidth(cooked) + self.inited_width = 1 + break + else: + if width == 0: + import AL + self.inited_width = 0 + self.config.setwidth(AL.SAMPLE_16) + self.converter = self.ulaw2lin + else: + raise error, 'bad sample width' + + def setnchannels(self, nchannels): + for (raw, cooked) in self.nchannelslist: + if nchannels == raw: + self.config.setchannels(cooked) + self.inited_nchannels = 1 + break + else: + raise error, 'bad # of channels' + + def writeframes(self, data): + if not (self.inited_outrate and self.inited_nchannels): + raise error, 'params not specified' + if not self.port: + import al, AL + self.port = al.openport('Python', 'w', self.config) + self.oldparams = self.params[:] + al.getparams(AL.DEFAULT_DEVICE, self.oldparams) + al.setparams(AL.DEFAULT_DEVICE, self.params) + if self.converter: + data = self.converter(data) + self.port.writesamps(data) + + def getfilled(self): + if self.port: + return self.port.getfilled() + else: + return 0 + + def getfillable(self): + if self.port: + return self.port.getfillable() + else: + return self.config.getqueuesize() + + # private methods +## if 0: access *: private + + def ulaw2lin(self, data): + import audioop + return audioop.ulaw2lin(data, 2) + +class Play_Audio_sun: +## if 0: access outrate, sampwidth, nchannels, inited_outrate, inited_width, \ +## inited_nchannels, converter: private + + def __init__(self): + self.outrate = 0 + self.sampwidth = 0 + self.nchannels = 0 + self.inited_outrate = 0 + self.inited_width = 0 + self.inited_nchannels = 0 + self.converter = None + self.port = None + return + + def __del__(self): + self.stop() + + def setoutrate(self, rate): + self.outrate = rate + self.inited_outrate = 1 + + def setsampwidth(self, width): + self.sampwidth = width + self.inited_width = 1 + + def setnchannels(self, nchannels): + self.nchannels = nchannels + self.inited_nchannels = 1 + + def writeframes(self, data): + if not (self.inited_outrate and self.inited_width and self.inited_nchannels): + raise error, 'params not specified' + if not self.port: + import sunaudiodev, SUNAUDIODEV + self.port = sunaudiodev.open('w') + info = self.port.getinfo() + info.o_sample_rate = self.outrate + info.o_channels = self.nchannels + if self.sampwidth == 0: + info.o_precision = 8 + self.o_encoding = SUNAUDIODEV.ENCODING_ULAW + # XXX Hack, hack -- leave defaults + else: + info.o_precision = 8 * self.sampwidth + info.o_encoding = SUNAUDIODEV.ENCODING_LINEAR + self.port.setinfo(info) + if self.converter: + data = self.converter(data) + self.port.write(data) + + def wait(self): + if not self.port: + return + self.port.drain() + self.stop() + + def stop(self): + if self.port: + self.port.flush() + self.port.close() + self.port = None + + def getfilled(self): + if self.port: + return self.port.obufcount() + else: + return 0 + +## # Nobody remembers what this method does, and it's broken. :-( +## def getfillable(self): +## return BUFFERSIZE - self.getfilled() + +def AudioDev(): + # Dynamically try to import and use a platform specific module. + try: + import al + except ImportError: + try: + import sunaudiodev + return Play_Audio_sun() + except ImportError: + try: + import Audio_mac + except ImportError: + raise error, 'no audio device' + else: + return Audio_mac.Play_Audio_mac() + else: + return Play_Audio_sgi() + +def test(fn = None): + import sys + if sys.argv[1:]: + fn = sys.argv[1] + else: + fn = 'f:just samples:just.aif' + import aifc + af = aifc.open(fn, 'r') + print fn, af.getparams() + p = AudioDev() + p.setoutrate(af.getframerate()) + p.setsampwidth(af.getsampwidth()) + p.setnchannels(af.getnchannels()) + BUFSIZ = af.getframerate()/af.getsampwidth()/af.getnchannels() + while 1: + data = af.readframes(BUFSIZ) + if not data: break + print len(data) + p.writeframes(data) + p.wait() + +if __name__ == '__main__': + test() diff --git a/PythonHome/Lib/audiodev.pyc b/PythonHome/Lib/audiodev.pyc deleted file mode 100644 index 4efa711efd7e4e7dd0a09cdccdbf892fecb35e42..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8063 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 G*8c$116K?H diff --git a/PythonHome/Lib/base64.py b/PythonHome/Lib/base64.py new file mode 100644 index 0000000000..85204dd022 --- /dev/null +++ b/PythonHome/Lib/base64.py @@ -0,0 +1,360 @@ +#! /usr/bin/env python + +"""RFC 3548: Base16, Base32, Base64 Data Encodings""" + +# Modified 04-Oct-1995 by Jack Jansen to use binascii module +# Modified 30-Dec-2003 by Barry Warsaw to add full RFC 3548 support + +import re +import struct +import binascii + + +__all__ = [ + # Legacy interface exports traditional RFC 1521 Base64 encodings + 'encode', 'decode', 'encodestring', 'decodestring', + # Generalized interface for other encodings + 'b64encode', 'b64decode', 'b32encode', 'b32decode', + 'b16encode', 'b16decode', + # Standard Base64 encoding + 'standard_b64encode', 'standard_b64decode', + # Some common Base64 alternatives. As referenced by RFC 3458, see thread + # starting at: + # + # http://zgp.org/pipermail/p2p-hackers/2001-September/000316.html + 'urlsafe_b64encode', 'urlsafe_b64decode', + ] + +_translation = [chr(_x) for _x in range(256)] +EMPTYSTRING = '' + + +def _translate(s, altchars): + translation = _translation[:] + for k, v in altchars.items(): + translation[ord(k)] = v + return s.translate(''.join(translation)) + + + +# Base64 encoding/decoding uses binascii + +def b64encode(s, altchars=None): + """Encode a string using Base64. + + s is the string to encode. Optional altchars must be a string of at least + length 2 (additional characters are ignored) which specifies an + alternative alphabet for the '+' and '/' characters. This allows an + application to e.g. generate url or filesystem safe Base64 strings. + + The encoded string is returned. + """ + # Strip off the trailing newline + encoded = binascii.b2a_base64(s)[:-1] + if altchars is not None: + return _translate(encoded, {'+': altchars[0], '/': altchars[1]}) + return encoded + + +def b64decode(s, altchars=None): + """Decode a Base64 encoded string. + + s is the string to decode. Optional altchars must be a string of at least + length 2 (additional characters are ignored) which specifies the + alternative alphabet used instead of the '+' and '/' characters. + + The decoded string is returned. A TypeError is raised if s were + incorrectly padded or if there are non-alphabet characters present in the + string. + """ + if altchars is not None: + s = _translate(s, {altchars[0]: '+', altchars[1]: '/'}) + try: + return binascii.a2b_base64(s) + except binascii.Error, msg: + # Transform this exception for consistency + raise TypeError(msg) + + +def standard_b64encode(s): + """Encode a string using the standard Base64 alphabet. + + s is the string to encode. The encoded string is returned. + """ + return b64encode(s) + +def standard_b64decode(s): + """Decode a string encoded with the standard Base64 alphabet. + + s is the string to decode. The decoded string is returned. A TypeError + is raised if the string is incorrectly padded or if there are non-alphabet + characters present in the string. + """ + return b64decode(s) + +def urlsafe_b64encode(s): + """Encode a string using a url-safe Base64 alphabet. + + s is the string to encode. The encoded string is returned. The alphabet + uses '-' instead of '+' and '_' instead of '/'. + """ + return b64encode(s, '-_') + +def urlsafe_b64decode(s): + """Decode a string encoded with the standard Base64 alphabet. + + s is the string to decode. The decoded string is returned. A TypeError + is raised if the string is incorrectly padded or if there are non-alphabet + characters present in the string. + + The alphabet uses '-' instead of '+' and '_' instead of '/'. + """ + return b64decode(s, '-_') + + + +# Base32 encoding/decoding must be done in Python +_b32alphabet = { + 0: 'A', 9: 'J', 18: 'S', 27: '3', + 1: 'B', 10: 'K', 19: 'T', 28: '4', + 2: 'C', 11: 'L', 20: 'U', 29: '5', + 3: 'D', 12: 'M', 21: 'V', 30: '6', + 4: 'E', 13: 'N', 22: 'W', 31: '7', + 5: 'F', 14: 'O', 23: 'X', + 6: 'G', 15: 'P', 24: 'Y', + 7: 'H', 16: 'Q', 25: 'Z', + 8: 'I', 17: 'R', 26: '2', + } + +_b32tab = _b32alphabet.items() +_b32tab.sort() +_b32tab = [v for k, v in _b32tab] +_b32rev = dict([(v, long(k)) for k, v in _b32alphabet.items()]) + + +def b32encode(s): + """Encode a string using Base32. + + s is the string to encode. The encoded string is returned. + """ + parts = [] + quanta, leftover = divmod(len(s), 5) + # Pad the last quantum with zero bits if necessary + if leftover: + s += ('\0' * (5 - leftover)) + quanta += 1 + for i in range(quanta): + # c1 and c2 are 16 bits wide, c3 is 8 bits wide. The intent of this + # code is to process the 40 bits in units of 5 bits. So we take the 1 + # leftover bit of c1 and tack it onto c2. Then we take the 2 leftover + # bits of c2 and tack them onto c3. The shifts and masks are intended + # to give us values of exactly 5 bits in width. + c1, c2, c3 = struct.unpack('!HHB', s[i*5:(i+1)*5]) + c2 += (c1 & 1) << 16 # 17 bits wide + c3 += (c2 & 3) << 8 # 10 bits wide + parts.extend([_b32tab[c1 >> 11], # bits 1 - 5 + _b32tab[(c1 >> 6) & 0x1f], # bits 6 - 10 + _b32tab[(c1 >> 1) & 0x1f], # bits 11 - 15 + _b32tab[c2 >> 12], # bits 16 - 20 (1 - 5) + _b32tab[(c2 >> 7) & 0x1f], # bits 21 - 25 (6 - 10) + _b32tab[(c2 >> 2) & 0x1f], # bits 26 - 30 (11 - 15) + _b32tab[c3 >> 5], # bits 31 - 35 (1 - 5) + _b32tab[c3 & 0x1f], # bits 36 - 40 (1 - 5) + ]) + encoded = EMPTYSTRING.join(parts) + # Adjust for any leftover partial quanta + if leftover == 1: + return encoded[:-6] + '======' + elif leftover == 2: + return encoded[:-4] + '====' + elif leftover == 3: + return encoded[:-3] + '===' + elif leftover == 4: + return encoded[:-1] + '=' + return encoded + + +def b32decode(s, casefold=False, map01=None): + """Decode a Base32 encoded string. + + s is the string to decode. Optional casefold is a flag specifying whether + a lowercase alphabet is acceptable as input. For security purposes, the + default is False. + + RFC 3548 allows for optional mapping of the digit 0 (zero) to the letter O + (oh), and for optional mapping of the digit 1 (one) to either the letter I + (eye) or letter L (el). The optional argument map01 when not None, + specifies which letter the digit 1 should be mapped to (when map01 is not + None, the digit 0 is always mapped to the letter O). For security + purposes the default is None, so that 0 and 1 are not allowed in the + input. + + The decoded string is returned. A TypeError is raised if s were + incorrectly padded or if there are non-alphabet characters present in the + string. + """ + quanta, leftover = divmod(len(s), 8) + if leftover: + raise TypeError('Incorrect padding') + # Handle section 2.4 zero and one mapping. The flag map01 will be either + # False, or the character to map the digit 1 (one) to. It should be + # either L (el) or I (eye). + if map01: + s = _translate(s, {'0': 'O', '1': map01}) + if casefold: + s = s.upper() + # Strip off pad characters from the right. We need to count the pad + # characters because this will tell us how many null bytes to remove from + # the end of the decoded string. + padchars = 0 + mo = re.search('(?P[=]*)$', s) + if mo: + padchars = len(mo.group('pad')) + if padchars > 0: + s = s[:-padchars] + # Now decode the full quanta + parts = [] + acc = 0 + shift = 35 + for c in s: + val = _b32rev.get(c) + if val is None: + raise TypeError('Non-base32 digit found') + acc += _b32rev[c] << shift + shift -= 5 + if shift < 0: + parts.append(binascii.unhexlify('%010x' % acc)) + acc = 0 + shift = 35 + # Process the last, partial quanta + last = binascii.unhexlify('%010x' % acc) + if padchars == 0: + last = '' # No characters + elif padchars == 1: + last = last[:-1] + elif padchars == 3: + last = last[:-2] + elif padchars == 4: + last = last[:-3] + elif padchars == 6: + last = last[:-4] + else: + raise TypeError('Incorrect padding') + parts.append(last) + return EMPTYSTRING.join(parts) + + + +# RFC 3548, Base 16 Alphabet specifies uppercase, but hexlify() returns +# lowercase. The RFC also recommends against accepting input case +# insensitively. +def b16encode(s): + """Encode a string using Base16. + + s is the string to encode. The encoded string is returned. + """ + return binascii.hexlify(s).upper() + + +def b16decode(s, casefold=False): + """Decode a Base16 encoded string. + + s is the string to decode. Optional casefold is a flag specifying whether + a lowercase alphabet is acceptable as input. For security purposes, the + default is False. + + The decoded string is returned. A TypeError is raised if s were + incorrectly padded or if there are non-alphabet characters present in the + string. + """ + if casefold: + s = s.upper() + if re.search('[^0-9A-F]', s): + raise TypeError('Non-base16 digit found') + return binascii.unhexlify(s) + + + +# Legacy interface. This code could be cleaned up since I don't believe +# binascii has any line length limitations. It just doesn't seem worth it +# though. + +MAXLINESIZE = 76 # Excluding the CRLF +MAXBINSIZE = (MAXLINESIZE//4)*3 + +def encode(input, output): + """Encode a file.""" + while True: + s = input.read(MAXBINSIZE) + if not s: + break + while len(s) < MAXBINSIZE: + ns = input.read(MAXBINSIZE-len(s)) + if not ns: + break + s += ns + line = binascii.b2a_base64(s) + output.write(line) + + +def decode(input, output): + """Decode a file.""" + while True: + line = input.readline() + if not line: + break + s = binascii.a2b_base64(line) + output.write(s) + + +def encodestring(s): + """Encode a string into multiple lines of base-64 data.""" + pieces = [] + for i in range(0, len(s), MAXBINSIZE): + chunk = s[i : i + MAXBINSIZE] + pieces.append(binascii.b2a_base64(chunk)) + return "".join(pieces) + + +def decodestring(s): + """Decode a string.""" + return binascii.a2b_base64(s) + + + +# Useable as a script... +def test(): + """Small test program""" + import sys, getopt + try: + opts, args = getopt.getopt(sys.argv[1:], 'deut') + except getopt.error, msg: + sys.stdout = sys.stderr + print msg + print """usage: %s [-d|-e|-u|-t] [file|-] + -d, -u: decode + -e: encode (default) + -t: encode and decode string 'Aladdin:open sesame'"""%sys.argv[0] + sys.exit(2) + func = encode + for o, a in opts: + if o == '-e': func = encode + if o == '-d': func = decode + if o == '-u': func = decode + if o == '-t': test1(); return + if args and args[0] != '-': + with open(args[0], 'rb') as f: + func(f, sys.stdout) + else: + func(sys.stdin, sys.stdout) + + +def test1(): + s0 = "Aladdin:open sesame" + s1 = encodestring(s0) + s2 = decodestring(s1) + print s0, repr(s1), s2 + + +if __name__ == '__main__': + test() diff --git a/PythonHome/Lib/base64.pyc b/PythonHome/Lib/base64.pyc index fce23d0014c0a9b6f92d6bb976e55f7561cb7d49..bcba52795bacf77798087be2a93a8ff0e487e2e7 100644 GIT binary patch delta 997 zcmZ1%GAVMyV-`be1_p*ytC;l6l8n-%nDG1xJ+EMYzn}o;82{3eg3^*0m(--v^q7Fk zl8pR3kNn)!&7W8bnaI#q#D0hjZIhk3UXfv$4R!xv~A?SLQeQk z5lLky!*3iiM&vlsQ#Ou_XxqF^KAsHQCaWmEBg1QoN>=1pmZjWIx@D78)EPN8Yp4h^ XldgBNhx!-Nb#3<62qVXP8#Li^Fi{W*x jc65c4|Ea1ovTs&X6J*Aa%Fz6RF1EQ>D-6?I5uG{!-1BRc diff --git a/PythonHome/Lib/bdb.py b/PythonHome/Lib/bdb.py new file mode 100644 index 0000000000..59440a99a0 --- /dev/null +++ b/PythonHome/Lib/bdb.py @@ -0,0 +1,645 @@ +"""Debugger basics""" + +import fnmatch +import sys +import os +import types + +__all__ = ["BdbQuit","Bdb","Breakpoint"] + +class BdbQuit(Exception): + """Exception to give up completely""" + + +class Bdb: + + """Generic Python debugger base class. + + This class takes care of details of the trace facility; + a derived class should implement user interaction. + The standard debugger class (pdb.Pdb) is an example. + """ + + def __init__(self, skip=None): + self.skip = set(skip) if skip else None + self.breaks = {} + self.fncache = {} + self.frame_returning = None + + def canonic(self, filename): + if filename == "<" + filename[1:-1] + ">": + return filename + canonic = self.fncache.get(filename) + if not canonic: + canonic = os.path.abspath(filename) + canonic = os.path.normcase(canonic) + self.fncache[filename] = canonic + return canonic + + def reset(self): + import linecache + linecache.checkcache() + self.botframe = None + self._set_stopinfo(None, None) + + def trace_dispatch(self, frame, event, arg): + if self.quitting: + return # None + if event == 'line': + return self.dispatch_line(frame) + if event == 'call': + return self.dispatch_call(frame, arg) + if event == 'return': + return self.dispatch_return(frame, arg) + if event == 'exception': + return self.dispatch_exception(frame, arg) + if event == 'c_call': + return self.trace_dispatch + if event == 'c_exception': + return self.trace_dispatch + if event == 'c_return': + return self.trace_dispatch + print 'bdb.Bdb.dispatch: unknown debugging event:', repr(event) + return self.trace_dispatch + + def dispatch_line(self, frame): + if self.stop_here(frame) or self.break_here(frame): + self.user_line(frame) + if self.quitting: raise BdbQuit + return self.trace_dispatch + + def dispatch_call(self, frame, arg): + # XXX 'arg' is no longer used + if self.botframe is None: + # First call of dispatch since reset() + self.botframe = frame.f_back # (CT) Note that this may also be None! + return self.trace_dispatch + if not (self.stop_here(frame) or self.break_anywhere(frame)): + # No need to trace this function + return # None + self.user_call(frame, arg) + if self.quitting: raise BdbQuit + return self.trace_dispatch + + def dispatch_return(self, frame, arg): + if self.stop_here(frame) or frame == self.returnframe: + try: + self.frame_returning = frame + self.user_return(frame, arg) + finally: + self.frame_returning = None + if self.quitting: raise BdbQuit + return self.trace_dispatch + + def dispatch_exception(self, frame, arg): + if self.stop_here(frame): + self.user_exception(frame, arg) + if self.quitting: raise BdbQuit + return self.trace_dispatch + + # Normally derived classes don't override the following + # methods, but they may if they want to redefine the + # definition of stopping and breakpoints. + + def is_skipped_module(self, module_name): + for pattern in self.skip: + if fnmatch.fnmatch(module_name, pattern): + return True + return False + + def stop_here(self, frame): + # (CT) stopframe may now also be None, see dispatch_call. + # (CT) the former test for None is therefore removed from here. + if self.skip and \ + self.is_skipped_module(frame.f_globals.get('__name__')): + return False + if frame is self.stopframe: + if self.stoplineno == -1: + return False + return frame.f_lineno >= self.stoplineno + while frame is not None and frame is not self.stopframe: + if frame is self.botframe: + return True + frame = frame.f_back + return False + + def break_here(self, frame): + filename = self.canonic(frame.f_code.co_filename) + if not filename in self.breaks: + return False + lineno = frame.f_lineno + if not lineno in self.breaks[filename]: + # The line itself has no breakpoint, but maybe the line is the + # first line of a function with breakpoint set by function name. + lineno = frame.f_code.co_firstlineno + if not lineno in self.breaks[filename]: + return False + + # flag says ok to delete temp. bp + (bp, flag) = effective(filename, lineno, frame) + if bp: + self.currentbp = bp.number + if (flag and bp.temporary): + self.do_clear(str(bp.number)) + return True + else: + return False + + def do_clear(self, arg): + raise NotImplementedError, "subclass of bdb must implement do_clear()" + + def break_anywhere(self, frame): + return self.canonic(frame.f_code.co_filename) in self.breaks + + # Derived classes should override the user_* methods + # to gain control. + + def user_call(self, frame, argument_list): + """This method is called when there is the remote possibility + that we ever need to stop in this function.""" + pass + + def user_line(self, frame): + """This method is called when we stop or break at this line.""" + pass + + def user_return(self, frame, return_value): + """This method is called when a return trap is set here.""" + pass + + def user_exception(self, frame, exc_info): + exc_type, exc_value, exc_traceback = exc_info + """This method is called if an exception occurs, + but only if we are to stop at or just below this level.""" + pass + + def _set_stopinfo(self, stopframe, returnframe, stoplineno=0): + self.stopframe = stopframe + self.returnframe = returnframe + self.quitting = 0 + # stoplineno >= 0 means: stop at line >= the stoplineno + # stoplineno -1 means: don't stop at all + self.stoplineno = stoplineno + + # Derived classes and clients can call the following methods + # to affect the stepping state. + + def set_until(self, frame): #the name "until" is borrowed from gdb + """Stop when the line with the line no greater than the current one is + reached or when returning from current frame""" + self._set_stopinfo(frame, frame, frame.f_lineno+1) + + def set_step(self): + """Stop after one line of code.""" + # Issue #13183: pdb skips frames after hitting a breakpoint and running + # step commands. + # Restore the trace function in the caller (that may not have been set + # for performance reasons) when returning from the current frame. + if self.frame_returning: + caller_frame = self.frame_returning.f_back + if caller_frame and not caller_frame.f_trace: + caller_frame.f_trace = self.trace_dispatch + self._set_stopinfo(None, None) + + def set_next(self, frame): + """Stop on the next line in or below the given frame.""" + self._set_stopinfo(frame, None) + + def set_return(self, frame): + """Stop when returning from the given frame.""" + self._set_stopinfo(frame.f_back, frame) + + def set_trace(self, frame=None): + """Start debugging from `frame`. + + If frame is not specified, debugging starts from caller's frame. + """ + if frame is None: + frame = sys._getframe().f_back + self.reset() + while frame: + frame.f_trace = self.trace_dispatch + self.botframe = frame + frame = frame.f_back + self.set_step() + sys.settrace(self.trace_dispatch) + + def set_continue(self): + # Don't stop except at breakpoints or when finished + self._set_stopinfo(self.botframe, None, -1) + if not self.breaks: + # no breakpoints; run without debugger overhead + sys.settrace(None) + frame = sys._getframe().f_back + while frame and frame is not self.botframe: + del frame.f_trace + frame = frame.f_back + + def set_quit(self): + self.stopframe = self.botframe + self.returnframe = None + self.quitting = 1 + sys.settrace(None) + + # Derived classes and clients can call the following methods + # to manipulate breakpoints. These methods return an + # error message is something went wrong, None if all is well. + # Set_break prints out the breakpoint line and file:lineno. + # Call self.get_*break*() to see the breakpoints or better + # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint(). + + def set_break(self, filename, lineno, temporary=0, cond = None, + funcname=None): + filename = self.canonic(filename) + import linecache # Import as late as possible + line = linecache.getline(filename, lineno) + if not line: + return 'Line %s:%d does not exist' % (filename, + lineno) + if not filename in self.breaks: + self.breaks[filename] = [] + list = self.breaks[filename] + if not lineno in list: + list.append(lineno) + bp = Breakpoint(filename, lineno, temporary, cond, funcname) + + def _prune_breaks(self, filename, lineno): + if (filename, lineno) not in Breakpoint.bplist: + self.breaks[filename].remove(lineno) + if not self.breaks[filename]: + del self.breaks[filename] + + def clear_break(self, filename, lineno): + filename = self.canonic(filename) + if not filename in self.breaks: + return 'There are no breakpoints in %s' % filename + if lineno not in self.breaks[filename]: + return 'There is no breakpoint at %s:%d' % (filename, + lineno) + # If there's only one bp in the list for that file,line + # pair, then remove the breaks entry + for bp in Breakpoint.bplist[filename, lineno][:]: + bp.deleteMe() + self._prune_breaks(filename, lineno) + + def clear_bpbynumber(self, arg): + try: + number = int(arg) + except: + return 'Non-numeric breakpoint number (%s)' % arg + try: + bp = Breakpoint.bpbynumber[number] + except IndexError: + return 'Breakpoint number (%d) out of range' % number + if not bp: + return 'Breakpoint (%d) already deleted' % number + bp.deleteMe() + self._prune_breaks(bp.file, bp.line) + + def clear_all_file_breaks(self, filename): + filename = self.canonic(filename) + if not filename in self.breaks: + return 'There are no breakpoints in %s' % filename + for line in self.breaks[filename]: + blist = Breakpoint.bplist[filename, line] + for bp in blist: + bp.deleteMe() + del self.breaks[filename] + + def clear_all_breaks(self): + if not self.breaks: + return 'There are no breakpoints' + for bp in Breakpoint.bpbynumber: + if bp: + bp.deleteMe() + self.breaks = {} + + def get_break(self, filename, lineno): + filename = self.canonic(filename) + return filename in self.breaks and \ + lineno in self.breaks[filename] + + def get_breaks(self, filename, lineno): + filename = self.canonic(filename) + return filename in self.breaks and \ + lineno in self.breaks[filename] and \ + Breakpoint.bplist[filename, lineno] or [] + + def get_file_breaks(self, filename): + filename = self.canonic(filename) + if filename in self.breaks: + return self.breaks[filename] + else: + return [] + + def get_all_breaks(self): + return self.breaks + + # Derived classes and clients can call the following method + # to get a data structure representing a stack trace. + + def get_stack(self, f, t): + stack = [] + if t and t.tb_frame is f: + t = t.tb_next + while f is not None: + stack.append((f, f.f_lineno)) + if f is self.botframe: + break + f = f.f_back + stack.reverse() + i = max(0, len(stack) - 1) + while t is not None: + stack.append((t.tb_frame, t.tb_lineno)) + t = t.tb_next + if f is None: + i = max(0, len(stack) - 1) + return stack, i + + # + + def format_stack_entry(self, frame_lineno, lprefix=': '): + import linecache, repr + frame, lineno = frame_lineno + filename = self.canonic(frame.f_code.co_filename) + s = '%s(%r)' % (filename, lineno) + if frame.f_code.co_name: + s = s + frame.f_code.co_name + else: + s = s + "" + if '__args__' in frame.f_locals: + args = frame.f_locals['__args__'] + else: + args = None + if args: + s = s + repr.repr(args) + else: + s = s + '()' + if '__return__' in frame.f_locals: + rv = frame.f_locals['__return__'] + s = s + '->' + s = s + repr.repr(rv) + line = linecache.getline(filename, lineno, frame.f_globals) + if line: s = s + lprefix + line.strip() + return s + + # The following two methods can be called by clients to use + # a debugger to debug a statement, given as a string. + + def run(self, cmd, globals=None, locals=None): + if globals is None: + import __main__ + globals = __main__.__dict__ + if locals is None: + locals = globals + self.reset() + sys.settrace(self.trace_dispatch) + if not isinstance(cmd, types.CodeType): + cmd = cmd+'\n' + try: + exec cmd in globals, locals + except BdbQuit: + pass + finally: + self.quitting = 1 + sys.settrace(None) + + def runeval(self, expr, globals=None, locals=None): + if globals is None: + import __main__ + globals = __main__.__dict__ + if locals is None: + locals = globals + self.reset() + sys.settrace(self.trace_dispatch) + if not isinstance(expr, types.CodeType): + expr = expr+'\n' + try: + return eval(expr, globals, locals) + except BdbQuit: + pass + finally: + self.quitting = 1 + sys.settrace(None) + + def runctx(self, cmd, globals, locals): + # B/W compatibility + self.run(cmd, globals, locals) + + # This method is more useful to debug a single function call. + + def runcall(self, func, *args, **kwds): + self.reset() + sys.settrace(self.trace_dispatch) + res = None + try: + res = func(*args, **kwds) + except BdbQuit: + pass + finally: + self.quitting = 1 + sys.settrace(None) + return res + + +def set_trace(): + Bdb().set_trace() + + +class Breakpoint: + + """Breakpoint class + + Implements temporary breakpoints, ignore counts, disabling and + (re)-enabling, and conditionals. + + Breakpoints are indexed by number through bpbynumber and by + the file,line tuple using bplist. The former points to a + single instance of class Breakpoint. The latter points to a + list of such instances since there may be more than one + breakpoint per line. + + """ + + # XXX Keeping state in the class is a mistake -- this means + # you cannot have more than one active Bdb instance. + + next = 1 # Next bp to be assigned + bplist = {} # indexed by (file, lineno) tuple + bpbynumber = [None] # Each entry is None or an instance of Bpt + # index 0 is unused, except for marking an + # effective break .... see effective() + + def __init__(self, file, line, temporary=0, cond=None, funcname=None): + self.funcname = funcname + # Needed if funcname is not None. + self.func_first_executable_line = None + self.file = file # This better be in canonical form! + self.line = line + self.temporary = temporary + self.cond = cond + self.enabled = 1 + self.ignore = 0 + self.hits = 0 + self.number = Breakpoint.next + Breakpoint.next = Breakpoint.next + 1 + # Build the two lists + self.bpbynumber.append(self) + if (file, line) in self.bplist: + self.bplist[file, line].append(self) + else: + self.bplist[file, line] = [self] + + + def deleteMe(self): + index = (self.file, self.line) + self.bpbynumber[self.number] = None # No longer in list + self.bplist[index].remove(self) + if not self.bplist[index]: + # No more bp for this f:l combo + del self.bplist[index] + + def enable(self): + self.enabled = 1 + + def disable(self): + self.enabled = 0 + + def bpprint(self, out=None): + if out is None: + out = sys.stdout + if self.temporary: + disp = 'del ' + else: + disp = 'keep ' + if self.enabled: + disp = disp + 'yes ' + else: + disp = disp + 'no ' + print >>out, '%-4dbreakpoint %s at %s:%d' % (self.number, disp, + self.file, self.line) + if self.cond: + print >>out, '\tstop only if %s' % (self.cond,) + if self.ignore: + print >>out, '\tignore next %d hits' % (self.ignore) + if (self.hits): + if (self.hits > 1): ss = 's' + else: ss = '' + print >>out, ('\tbreakpoint already hit %d time%s' % + (self.hits, ss)) + +# -----------end of Breakpoint class---------- + +def checkfuncname(b, frame): + """Check whether we should break here because of `b.funcname`.""" + if not b.funcname: + # Breakpoint was set via line number. + if b.line != frame.f_lineno: + # Breakpoint was set at a line with a def statement and the function + # defined is called: don't break. + return False + return True + + # Breakpoint set via function name. + + if frame.f_code.co_name != b.funcname: + # It's not a function call, but rather execution of def statement. + return False + + # We are in the right frame. + if not b.func_first_executable_line: + # The function is entered for the 1st time. + b.func_first_executable_line = frame.f_lineno + + if b.func_first_executable_line != frame.f_lineno: + # But we are not at the first line number: don't break. + return False + return True + +# Determines if there is an effective (active) breakpoint at this +# line of code. Returns breakpoint number or 0 if none +def effective(file, line, frame): + """Determine which breakpoint for this file:line is to be acted upon. + + Called only if we know there is a bpt at this + location. Returns breakpoint that was triggered and a flag + that indicates if it is ok to delete a temporary bp. + + """ + possibles = Breakpoint.bplist[file,line] + for i in range(0, len(possibles)): + b = possibles[i] + if b.enabled == 0: + continue + if not checkfuncname(b, frame): + continue + # Count every hit when bp is enabled + b.hits = b.hits + 1 + if not b.cond: + # If unconditional, and ignoring, + # go on to next, else break + if b.ignore > 0: + b.ignore = b.ignore -1 + continue + else: + # breakpoint and marker that's ok + # to delete if temporary + return (b,1) + else: + # Conditional bp. + # Ignore count applies only to those bpt hits where the + # condition evaluates to true. + try: + val = eval(b.cond, frame.f_globals, + frame.f_locals) + if val: + if b.ignore > 0: + b.ignore = b.ignore -1 + # continue + else: + return (b,1) + # else: + # continue + except: + # if eval fails, most conservative + # thing is to stop on breakpoint + # regardless of ignore count. + # Don't delete temporary, + # as another hint to user. + return (b,0) + return (None, None) + +# -------------------- testing -------------------- + +class Tdb(Bdb): + def user_call(self, frame, args): + name = frame.f_code.co_name + if not name: name = '???' + print '+++ call', name, args + def user_line(self, frame): + import linecache + name = frame.f_code.co_name + if not name: name = '???' + fn = self.canonic(frame.f_code.co_filename) + line = linecache.getline(fn, frame.f_lineno, frame.f_globals) + print '+++', fn, frame.f_lineno, name, ':', line.strip() + def user_return(self, frame, retval): + print '+++ return', retval + def user_exception(self, frame, exc_stuff): + print '+++ exception', exc_stuff + self.set_continue() + +def foo(n): + print 'foo(', n, ')' + x = bar(n*10) + print 'bar returned', x + +def bar(a): + print 'bar(', a, ')' + return a/2 + +def test(): + t = Tdb() + t.run('import bdb; bdb.foo(10)') + +# end diff --git a/PythonHome/Lib/bdb.pyc b/PythonHome/Lib/bdb.pyc deleted file mode 100644 index 151a7a4c72fbb16d1ec2cbc332c84e358916c65d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18186 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

7%AB${v!0I_e# z8dqGwgSx6A03vtRWcNBgM>ABA#nQNDh7bM)KBOd{vio3js2WkEid4M7I=C^Z!WH{{ z8pRtwlhD{dLxXnIPXA5;XoWHGDQ$W)O#3OZcL1Nmi1vgpr#&SG7#txkk-Q{pmPEA} zy^)Fo?L=78KuVzb4vc@2y$B8Gb+>?k>&qd4ng<(RM@KQ5!9o}bOa85y*{+Phj2xHd z63W}*akA0r?8IP<@DQQt&G4FMXx9=c9Jh)H74s=~vyi`wf!GI(YiTPWs&WfQhmdN; z;35jw%h=+uaB$pyvL*Q0_->TN1ZQV3m={|ubSE)~0BAL%lt{QhLb6I-ptjhl`x=9r zsQ9@xJW8HKTPMGq{C@E@c|^;KsUG#qyc_G$#?tTM8__N*;@q|ljaUk z_a4%g$of4?HeD;KL7U7 z>U`qD0*PFj?MlS3FVOyqIby^A7Lo!qDOgtrEBk)r T-mO*kov$6PJ#la^ 0x7f): + break + else: + finfo.Type = 'TEXT' + fp.seek(0, 2) + dsize = fp.tell() + fp.close() + dir, file = os.path.split(name) + file = file.replace(':', '-', 1) + return file, finfo, dsize, 0 + + class openrsrc: + def __init__(self, *args): + pass + + def read(self, *args): + return '' + + def write(self, *args): + pass + + def close(self): + pass + +class _Hqxcoderengine: + """Write data to the coder in 3-byte chunks""" + + def __init__(self, ofp): + self.ofp = ofp + self.data = '' + self.hqxdata = '' + self.linelen = LINELEN-1 + + def write(self, data): + self.data = self.data + data + datalen = len(self.data) + todo = (datalen//3)*3 + data = self.data[:todo] + self.data = self.data[todo:] + if not data: + return + self.hqxdata = self.hqxdata + binascii.b2a_hqx(data) + self._flush(0) + + def _flush(self, force): + first = 0 + while first <= len(self.hqxdata)-self.linelen: + last = first + self.linelen + self.ofp.write(self.hqxdata[first:last]+'\n') + self.linelen = LINELEN + first = last + self.hqxdata = self.hqxdata[first:] + if force: + self.ofp.write(self.hqxdata + ':\n') + + def close(self): + if self.data: + self.hqxdata = \ + self.hqxdata + binascii.b2a_hqx(self.data) + self._flush(1) + self.ofp.close() + del self.ofp + +class _Rlecoderengine: + """Write data to the RLE-coder in suitably large chunks""" + + def __init__(self, ofp): + self.ofp = ofp + self.data = '' + + def write(self, data): + self.data = self.data + data + if len(self.data) < REASONABLY_LARGE: + return + rledata = binascii.rlecode_hqx(self.data) + self.ofp.write(rledata) + self.data = '' + + def close(self): + if self.data: + rledata = binascii.rlecode_hqx(self.data) + self.ofp.write(rledata) + self.ofp.close() + del self.ofp + +class BinHex: + def __init__(self, name_finfo_dlen_rlen, ofp): + name, finfo, dlen, rlen = name_finfo_dlen_rlen + if type(ofp) == type(''): + ofname = ofp + ofp = open(ofname, 'w') + ofp.write('(This file must be converted with BinHex 4.0)\n\n:') + hqxer = _Hqxcoderengine(ofp) + self.ofp = _Rlecoderengine(hqxer) + self.crc = 0 + if finfo is None: + finfo = FInfo() + self.dlen = dlen + self.rlen = rlen + self._writeinfo(name, finfo) + self.state = _DID_HEADER + + def _writeinfo(self, name, finfo): + nl = len(name) + if nl > 63: + raise Error, 'Filename too long' + d = chr(nl) + name + '\0' + d2 = finfo.Type + finfo.Creator + + # Force all structs to be packed with big-endian + d3 = struct.pack('>h', finfo.Flags) + d4 = struct.pack('>ii', self.dlen, self.rlen) + info = d + d2 + d3 + d4 + self._write(info) + self._writecrc() + + def _write(self, data): + self.crc = binascii.crc_hqx(data, self.crc) + self.ofp.write(data) + + def _writecrc(self): + # XXXX Should this be here?? + # self.crc = binascii.crc_hqx('\0\0', self.crc) + if self.crc < 0: + fmt = '>h' + else: + fmt = '>H' + self.ofp.write(struct.pack(fmt, self.crc)) + self.crc = 0 + + def write(self, data): + if self.state != _DID_HEADER: + raise Error, 'Writing data at the wrong time' + self.dlen = self.dlen - len(data) + self._write(data) + + def close_data(self): + if self.dlen != 0: + raise Error, 'Incorrect data size, diff=%r' % (self.rlen,) + self._writecrc() + self.state = _DID_DATA + + def write_rsrc(self, data): + if self.state < _DID_DATA: + self.close_data() + if self.state != _DID_DATA: + raise Error, 'Writing resource data at the wrong time' + self.rlen = self.rlen - len(data) + self._write(data) + + def close(self): + if self.state < _DID_DATA: + self.close_data() + if self.state != _DID_DATA: + raise Error, 'Close at the wrong time' + if self.rlen != 0: + raise Error, \ + "Incorrect resource-datasize, diff=%r" % (self.rlen,) + self._writecrc() + self.ofp.close() + self.state = None + del self.ofp + +def binhex(inp, out): + """(infilename, outfilename) - Create binhex-encoded copy of a file""" + finfo = getfileinfo(inp) + ofp = BinHex(finfo, out) + + ifp = open(inp, 'rb') + # XXXX Do textfile translation on non-mac systems + while 1: + d = ifp.read(128000) + if not d: break + ofp.write(d) + ofp.close_data() + ifp.close() + + ifp = openrsrc(inp, 'rb') + while 1: + d = ifp.read(128000) + if not d: break + ofp.write_rsrc(d) + ofp.close() + ifp.close() + +class _Hqxdecoderengine: + """Read data via the decoder in 4-byte chunks""" + + def __init__(self, ifp): + self.ifp = ifp + self.eof = 0 + + def read(self, totalwtd): + """Read at least wtd bytes (or until EOF)""" + decdata = '' + wtd = totalwtd + # + # The loop here is convoluted, since we don't really now how + # much to decode: there may be newlines in the incoming data. + while wtd > 0: + if self.eof: return decdata + wtd = ((wtd+2)//3)*4 + data = self.ifp.read(wtd) + # + # Next problem: there may not be a complete number of + # bytes in what we pass to a2b. Solve by yet another + # loop. + # + while 1: + try: + decdatacur, self.eof = \ + binascii.a2b_hqx(data) + break + except binascii.Incomplete: + pass + newdata = self.ifp.read(1) + if not newdata: + raise Error, \ + 'Premature EOF on binhex file' + data = data + newdata + decdata = decdata + decdatacur + wtd = totalwtd - len(decdata) + if not decdata and not self.eof: + raise Error, 'Premature EOF on binhex file' + return decdata + + def close(self): + self.ifp.close() + +class _Rledecoderengine: + """Read data via the RLE-coder""" + + def __init__(self, ifp): + self.ifp = ifp + self.pre_buffer = '' + self.post_buffer = '' + self.eof = 0 + + def read(self, wtd): + if wtd > len(self.post_buffer): + self._fill(wtd-len(self.post_buffer)) + rv = self.post_buffer[:wtd] + self.post_buffer = self.post_buffer[wtd:] + return rv + + def _fill(self, wtd): + self.pre_buffer = self.pre_buffer + self.ifp.read(wtd+4) + if self.ifp.eof: + self.post_buffer = self.post_buffer + \ + binascii.rledecode_hqx(self.pre_buffer) + self.pre_buffer = '' + return + + # + # Obfuscated code ahead. We have to take care that we don't + # end up with an orphaned RUNCHAR later on. So, we keep a couple + # of bytes in the buffer, depending on what the end of + # the buffer looks like: + # '\220\0\220' - Keep 3 bytes: repeated \220 (escaped as \220\0) + # '?\220' - Keep 2 bytes: repeated something-else + # '\220\0' - Escaped \220: Keep 2 bytes. + # '?\220?' - Complete repeat sequence: decode all + # otherwise: keep 1 byte. + # + mark = len(self.pre_buffer) + if self.pre_buffer[-3:] == RUNCHAR + '\0' + RUNCHAR: + mark = mark - 3 + elif self.pre_buffer[-1] == RUNCHAR: + mark = mark - 2 + elif self.pre_buffer[-2:] == RUNCHAR + '\0': + mark = mark - 2 + elif self.pre_buffer[-2] == RUNCHAR: + pass # Decode all + else: + mark = mark - 1 + + self.post_buffer = self.post_buffer + \ + binascii.rledecode_hqx(self.pre_buffer[:mark]) + self.pre_buffer = self.pre_buffer[mark:] + + def close(self): + self.ifp.close() + +class HexBin: + def __init__(self, ifp): + if type(ifp) == type(''): + ifp = open(ifp) + # + # Find initial colon. + # + while 1: + ch = ifp.read(1) + if not ch: + raise Error, "No binhex data found" + # Cater for \r\n terminated lines (which show up as \n\r, hence + # all lines start with \r) + if ch == '\r': + continue + if ch == ':': + break + if ch != '\n': + dummy = ifp.readline() + + hqxifp = _Hqxdecoderengine(ifp) + self.ifp = _Rledecoderengine(hqxifp) + self.crc = 0 + self._readheader() + + def _read(self, len): + data = self.ifp.read(len) + self.crc = binascii.crc_hqx(data, self.crc) + return data + + def _checkcrc(self): + filecrc = struct.unpack('>h', self.ifp.read(2))[0] & 0xffff + #self.crc = binascii.crc_hqx('\0\0', self.crc) + # XXXX Is this needed?? + self.crc = self.crc & 0xffff + if filecrc != self.crc: + raise Error, 'CRC error, computed %x, read %x' \ + %(self.crc, filecrc) + self.crc = 0 + + def _readheader(self): + len = self._read(1) + fname = self._read(ord(len)) + rest = self._read(1+4+4+2+4+4) + self._checkcrc() + + type = rest[1:5] + creator = rest[5:9] + flags = struct.unpack('>h', rest[9:11])[0] + self.dlen = struct.unpack('>l', rest[11:15])[0] + self.rlen = struct.unpack('>l', rest[15:19])[0] + + self.FName = fname + self.FInfo = FInfo() + self.FInfo.Creator = creator + self.FInfo.Type = type + self.FInfo.Flags = flags + + self.state = _DID_HEADER + + def read(self, *n): + if self.state != _DID_HEADER: + raise Error, 'Read data at wrong time' + if n: + n = n[0] + n = min(n, self.dlen) + else: + n = self.dlen + rv = '' + while len(rv) < n: + rv = rv + self._read(n-len(rv)) + self.dlen = self.dlen - n + return rv + + def close_data(self): + if self.state != _DID_HEADER: + raise Error, 'close_data at wrong time' + if self.dlen: + dummy = self._read(self.dlen) + self._checkcrc() + self.state = _DID_DATA + + def read_rsrc(self, *n): + if self.state == _DID_HEADER: + self.close_data() + if self.state != _DID_DATA: + raise Error, 'Read resource data at wrong time' + if n: + n = n[0] + n = min(n, self.rlen) + else: + n = self.rlen + self.rlen = self.rlen - n + return self._read(n) + + def close(self): + if self.rlen: + dummy = self.read_rsrc(self.rlen) + self._checkcrc() + self.state = _DID_RSRC + self.ifp.close() + +def hexbin(inp, out): + """(infilename, outfilename) - Decode binhexed file""" + ifp = HexBin(inp) + finfo = ifp.FInfo + if not out: + out = ifp.FName + + ofp = open(out, 'wb') + # XXXX Do translation on non-mac systems + while 1: + d = ifp.read(128000) + if not d: break + ofp.write(d) + ofp.close() + ifp.close_data() + + d = ifp.read_rsrc(128000) + if d: + ofp = openrsrc(out, 'wb') + ofp.write(d) + while 1: + d = ifp.read_rsrc(128000) + if not d: break + ofp.write(d) + ofp.close() + + ifp.close() + +def _test(): + fname = sys.argv[1] + binhex(fname, fname+'.hqx') + hexbin(fname+'.hqx', fname+'.viahqx') + #hexbin(fname, fname+'.unpacked') + sys.exit(1) + +if __name__ == '__main__': + _test() diff --git a/PythonHome/Lib/binhex.pyc b/PythonHome/Lib/binhex.pyc deleted file mode 100644 index 564ccd8c38de431d6ef15b5c9daeb8eea0997672..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14635 zcmcgzTWl0rdOp?NZo3;B0|smuW@u)a!LY#WTy|GGnhRjeCCm0q%B-02GTXGfs&V0V zx2Y-*kTAInXr`U^Nec3!k%H{jMzq-nR zFHCNRIzIP0=l{R|a{f~;|9qnUCpT^_bX@i`g5T%xB!BEV7dW?w)N?_}^*pzTjO9yi zu{6w=-C}u|ueimE3s6Kl;%=j9gqg7Fx)@k>kDYtu+{cTfE*x{gsC(qOo9I+?i*>iS z%LQX@aohzcPPlNl3+n8!IO!g|qZjOQy*+MquUp*fR`{-HrY^R|%)xO5Md(4?n@A3y!;BPrjCYF4#L9h5Rcnn9AD@y1wT=3ii9; zRTmt{t7lwr&;=)4Fr8N&asg^*U2rI`I_!eOEG)j@0{lPef+Km`5f{AZf>SPdDX&8L zs0+UAf<|8Tk_(P$1~j~^Ov8o8T<|5gQgZQ+y|6)YdVTPyZgNb zxv>=Wm&5yw&R}&d4wEDr^j{0Y4W+a7de}}LG|)YayX{W+cHM@|M*X$*v>WxpetR`M z-59K=8_Fl^m=zs&>J|Mbewt|&YqDvTwXrFoHXp}>I0qjf=Puw$#*l=doag+7S>)Yp z2}#Q8R*MU2wbHr@tAk*@hobdDl~XR6MDFa(Ythn8d-2(|2R`RGiYH;F>P2PzirlXu zImg_Okl1^;-b)J$Yhg!=ymYnS9n5lZTK-@y?8n^>%cFQIc;@gV9G^P(5E%E|9gnQ} z%yVhU-6^{}m8|||$$f_ZWrvy3699gMB3di%PL*tg^q|IL8S;TCM!0Wwt?byf>K>Ne zL(e_L+z`16FhL?Wu?FYjr3k5um`}L%Q}NPl4ZnT%Np~T+w6JzLOtoDN86+upx7JRV zMTlgr7p1Bq4U|d3a7CFk?Dc%oW0r}k$S95LMj&9ycLq_cCIU;Z=&q?80B6d?$P~QX zjE!39?NHd{yl-OKWFHde?ek_zlinV0+_O|X;(qz+%XpGgNI)RW3(A8#eQ22yYe4ox z(`1(zhzc-aVV1jZ4vCeLHR%Ow0yuZ++q1+=qm^%ap!&H1$O6Ey;^Cv z=M#DzJo?GyVK0g%4}p^&C{ZxjtSvIbb<_y{4e;f#FVdr#aCh(H z$F{^e?cw@^wJ;?U=i;!P4q}smUi)@pGQeR;*y}#WK3lD*AEm9Dt_9SR^s&$;pVbxI=$wt_b;ktQf&1R%0facKSU?&}W!Z$Kgeloo^yG7jN|t*e^w zqC6B{wvBOKFRi&db$4f1wi0TBs{3rzJsfp+VD(06{$Tqam9t9B4ME1N5@f2oX5_$X z;jj_?D)-8rU!VWzdLi0seOu|7h`^YgKqAul%xMT18;HeGlB_}NOEw2_;J?7WyO~gd ziu0Y`APIfG-lvZ6$Js!5#Nk>GV`s?$Nq|q7`uo|=bp`FTt#z0d4U*`WLZ5=_Pa!Gz zy(z1w(d8HMB!`gzHKlRyfH&cN*&8d>B;j>$1~opLJM6+AZubJ7gqH9rd4WhghDCvI zQc^~K3Ts9vN?dPeC`SA(ZJ}LIURcw#6-(Y2VV7+)>uR-aNDP0BxP+_5MoI z;f9Bg$ViS;0X(I}tp@r`IG$lMfSjvz{|tti)N>6c*4;J#Bny<;<-7MKmdszf+MK^O z-&B1M+o$E_8pJ98E65ep-ITCIc8n*pVASk2Pg|*=wv0zx`4wca&^y}DwCxCb!K$c< zVVb0s4?{-xLoa8Y%dP=~oEMJTNDw8tt}U}gl%R73gY7v@E<<+*inGKjuOLq5?_o6t zED?pP#K!&C@mu~S+{Jd%i6W6@>5X;^B$M0M>h{)?WoZhdP)<}*bm+gNgJ7@&*$CeI zcrvGD51f_VP;GnQ0#v+11p!G!5%71Ap}SIY_ZLYj^HJzw8hJ`?X2pYl$2KF%bVkLY zoPz2Y|`a!%zXpik9wDWi!3%39Qzg%YHe3-muX4Aha=-QT9ShBoLVw7wF!~&ta9|P&7a8?WU?Nm?WNv> zMh`}IYejhwGi{ZAETZd&`c*CRv%Jfh;4raKXNjg_M+Lp{}(#{~Rid9ho1%cbi&1kK7Jh zp;Y_|;nIOO@J~Ovr_(e7WEK_`oQ z31xcr`f`*s7*c4gt|w_@iEdW^(=blMpm8rsmm5a-##?8`bgfZ&oSZ<8Vyfke_?ea|9~1if0rvSSw&5RLKbMl9C9h9!QsF^ghyr z6uXp#E8%Pp8ofdPwm@RXiT9Qj$9XS`W~spZx0q0C7>Ac*JNuGalGP-Q*E{Bh;Do&5 zzsUYia-=1;<5&-tD+`KRez2rA%vWm zIPUHD_LL8JFNnGML4txWf#*R2%%o>0sf64@j45lTl+75KA{I?eA})3%WOP?|azT9z`fEI9P0En265Y^e zSwUTI+XEC<$}WC^(P4;|i4&U;7lr_c8#>%Ulu!#n*}x!fqM1;W(1VKlx9x!0PIbV% z7X$Z=G+GVKoLxmf{|Xb1GXx9!h@DF&h^WG%zchI;<%;boB2L;jF5!HpY+E%3N$ATsl)Ia9{BBgkIucLs5cSiJ3%VWiWIAnJDCeI>R% zN-VWKs$`!GF{z{?zIgund7o5}Gw~c@2&r^My;^jO{t-j-9UsKG;#tOi7hP<}WGrxd zL`7f{d&|5VEXkXv=#R$x7xS=9p-K_ zDQNWHgMdgQRo99UzWyi7nYn|Luq;~v;(O@!KOzs50C99vlrxd2JcXm&a|GQi_R5n# z-U=@o=`AP_8Vsp~WEu;aV_38CjL<}Aa>;Qd1?+~DK0`P>3BMXTZcStY(bOdw=U+nd zydacU`!5)f5Yi5`HTq6^W%#Ofln_Sev9LG?nyY%5b(C$1fw?r|{U@yBIto3l+@{{c z1@!v~o`l{AVrF}4yK9wN9jC%-ZA=0{)0>MtZ4!(O2u%+k5en#Km={1A>Ki&uriP9s ziWPVNB%M3xI=YnT5A`NoCPEv!zfYb}W9U1wiB+bC@)*&%#BS(+@BfupLc!0W4fbzGHgET?a{vQ*i7 z7z}-D`(P+V0AK>sA?pcS!H_+9%pXN9 zeW5u#$FAW+DVkeE+LEKpHr%|sl|G}k`7KKK4yKJ_&D>bj8WIB+17>BFvbUh9^pfTtV zKUAQ!*@e;)Uw4a%B<8EgDbUq^V@V-d>OQLI)ivBChi2Jm)GRora~35r9UwM~g=#Di zM-?u7pw1#7oG5GPtjFrt5AQukK!od>CSd3nIrx0l3Vc6E*FJAwwd|EkGu{X!jpZsN ztp=UVpyXbjx#%zrA3=-4XZQhYspN!ic4-#CHucTQ=Wt`x`5WlG#cj&FoQ9w`0za>1 zXk)}4&PwWL(T$f)cOXu)kFw3OwMi;lqfm>=UP7T+zHgq@Z1h zZ-^;YFrSvcfDD#zW|g3T`v^7jhF~HMw6SRh%|llcJM>(G(k?}T!Z4ywVaA(*Del+K zz&+#?rf5OIw=YB+!1BTAu#wNunv@SFkh7K={PzW%5xot)j_55 zP9ck%W-ajdzOBCUj_D0cyAJyyo@D%k@PdC-YQy$y<7g<~Jz{U>T4wf2j{_OW~(_W7HQeHuld;T-?$`iNKHH8oAcbv?NUv^9!- z*t$`dU2t(b^6Z)s>1N9G-|-!l|1A_vnewwLeaI922XkbpIU6{9Y}A?rr%wjkQGNnB z278ORFg2!Bp8xIU+?DhG)9mL8R@?E)4ggq1w`&9djfC?WI2l%PHmrG-iAh8zCKO(s z*6(tu4pn*h|4#)DxGo|Q7s|Be8yx1RR3LZp+#WJ4y?cjK6Z6@P$!P6MiX9=yi-=*dFLuJvVyzFHuVMLx#o^Tu1YTX zW_H-h+zGT+H2f2H_f!@Fh8%IiRr9pbqpD-tDNP4=20`93d*eS84Bmkiz###N%-I3* zTZk)5bX$2C5PXsd(7t3EnFLhGt2r1t3bfCS?qIzi=-zR{f0=#Qv2F^SZ1FELA?nS> zkxCGB2m$N}ue|*>+sI0DHRjoY8otFI%XkoHC0*@m;TD@YNyom23)WXxABf|K$VT0@ z9i)WDmPTWgM=;xVMk4IwU7oo;geDW|*?DU>>Q7qt-CsYI+7I zERq%8U!m)@fm;||xKjSdEONUWB%aFPIpRQOEJ&aqa5FpzT70=f@{>H&8bTq}5x|G_ z0)Jef7Hc@eN}-?+0aoX-z#eou3fc0lKQISF@Ll2uXtON>NZryfhJ-0>fH1?gG%d=v zZ2A!u4qu^SouvMpKi3HP$?0i*61&a|f>-XJZg4ZmSTu=|KrwZ_ugLE$l#OzvmpskF z;7fVZYh~;g&0C+yEF#re4m&I8`y-NWoCCa9%lrhO3LPl|K5^pU368rS3UEd#EKo)s z5HJ*EefFqm5fY0&@fZT?SKKj39t$Ay2nvYI>(~LAWi7}%>W+~mW9|?ygsc(wGH8U1 z*7HVEJ0EQAbri~I)JBM;+Fs~dJV6E58`;6gMTFfhzf(tzKkc~#We{n#B36C#y1}4sG1>@hX5|{ z9R&{1?HdgQc%>rp5H@I>`)^8}%UGZ@WITSHG2DWdRQ7hl1UPx>yzAT7CEz)ZotSQ@ zpGcgh!f`$&P)Z%g%OZv?w#o%E3X|4FG+PI`)u_KAs!f&_Dh*PCt2Q4-Zl}}#adhFI zJmldvYUH|i0K~0=;KzoCHmWy1Qg6I2*p9fM8?@IqG6J%vo&58UODwWQg9w_KCo9#` zOlB~35rbx&vLMQ4q%aZ)(8BU}Fuu@I{--SB*#>4e(fVhFR$?%>hMgncO(Js71eQSc zIWon*;R0+P@5cAC*goRj&^dX$8-TmH5pZ%0IGH}3EdYm4V-1KPP6irN6L1%#^@d+D zH?SC?XBej43Pu)JC=kRATWp-0^M9R*?hk|^)luSn?sj|HNww34C@TJ!B;tMyDx$VS zC~fw!#07LTV#Y5iW81b+YK|1s<`hqp9uO@57)hp&Ollf3w24P3`-DPq6XGxUa~7<= z#l{mzz8FL};%~V-I#)co5*}N`p$jNdf0_Lh#kDZKo0Du$SU*OWm~YJD&@;6WM4|U1 z8a-BVe}Y^JE>M3D>)Xh zL`>Q@*A}5-mC@kcg*fM-V@{|Ky*=h|)Rfw@!SPQ?dSEqw2gl{}WG{SjO!60-yzs{x zUWkSBO%}q2I?e*u3=VG>xW1?pU* zl32)~wK+_@{_>%|GAEiw+ipFsvkRVWv<_kW_hc|%!7w%T?f534>MD%h#D;+NM5)6O z98W7E_FqH>>^FDw&}S&f4Z&u>m}xLt->O)NmHd{Gl^7xwMgB^dIHUO;3A1P6-Y28X zAa;$sjs!A3$piZn8GNGlDQ|n6&jsl^KfE8McH4u6>_7%{sS!y{!HnT;;{-y52TD4x zv|6j}sQ=7gITf^hI`=Y{@-CC_F%fs=-sExAR;%6X;m@dQXrI5|3D;8mahRN2EhcXF zZ--`SX-fRZOx|b07@pr`vW7&brMY&zH0Ynb1XSsdiG(3dgTF-kU_pN< x. So if x already appears in the list, a.insert(x) will + insert just after the rightmost x already there. + + Optional args lo (default 0) and hi (default len(a)) bound the + slice of a to be searched. + """ + + if lo < 0: + raise ValueError('lo must be non-negative') + if hi is None: + hi = len(a) + while lo < hi: + mid = (lo+hi)//2 + if x < a[mid]: hi = mid + else: lo = mid+1 + return lo + +bisect = bisect_right # backward compatibility + +def insort_left(a, x, lo=0, hi=None): + """Insert item x in list a, and keep it sorted assuming a is sorted. + + If x is already in a, insert it to the left of the leftmost x. + + Optional args lo (default 0) and hi (default len(a)) bound the + slice of a to be searched. + """ + + if lo < 0: + raise ValueError('lo must be non-negative') + if hi is None: + hi = len(a) + while lo < hi: + mid = (lo+hi)//2 + if a[mid] < x: lo = mid+1 + else: hi = mid + a.insert(lo, x) + + +def bisect_left(a, x, lo=0, hi=None): + """Return the index where to insert item x in list a, assuming a is sorted. + + The return value i is such that all e in a[:i] have e < x, and all e in + a[i:] have e >= x. So if x already appears in the list, a.insert(x) will + insert just before the leftmost x already there. + + Optional args lo (default 0) and hi (default len(a)) bound the + slice of a to be searched. + """ + + if lo < 0: + raise ValueError('lo must be non-negative') + if hi is None: + hi = len(a) + while lo < hi: + mid = (lo+hi)//2 + if a[mid] < x: lo = mid+1 + else: hi = mid + return lo + +# Overwrite above definitions with a fast C implementation +try: + from _bisect import * +except ImportError: + pass diff --git a/PythonHome/Lib/bisect.pyc b/PythonHome/Lib/bisect.pyc index 5500c027bda8ff3793a5baba9032815f89efe805..97dd8b3b33c1e7a4a45743afe1f0a8a84d3bd70a 100644 GIT binary patch delta 280 zcmaDRK0$KBLncFO1_p*ytC;l6l8n-%nDG1xJ+EMYzn}o;82{3eg3^*0m(--v^q7Fk pl8pR3kNn)!%^#Q!lcVhrt1CI$#5fL-p>6VWt{tR%ZSp#93jj=xW5NIc delta 110 zcmbOr`AmGnLneMn1_lOatC)bwl8pR3BlFEd%!e@r+1Ok$1#37CVF*sn=iY&C= 3) + +if (sys.version_info >= (2, 6)) and (sys.version_info < (3, 0)) : + import warnings + if sys.py3kwarning and (__name__ != 'bsddb3') : + warnings.warnpy3k("in 3.x, the bsddb module has been removed; " + "please use the pybsddb project instead", + DeprecationWarning, 2) + warnings.filterwarnings("ignore", ".*CObject.*", DeprecationWarning, + "bsddb.__init__") + +try: + if __name__ == 'bsddb3': + # import _pybsddb binary as it should be the more recent version from + # a standalone pybsddb addon package than the version included with + # python as bsddb._bsddb. + if absolute_import : + # Because this syntaxis is not valid before Python 2.5 + exec("from . import _pybsddb") + else : + import _pybsddb + _bsddb = _pybsddb + from bsddb3.dbutils import DeadlockWrap as _DeadlockWrap + else: + import _bsddb + from bsddb.dbutils import DeadlockWrap as _DeadlockWrap +except ImportError: + # Remove ourselves from sys.modules + import sys + del sys.modules[__name__] + raise + +# bsddb3 calls it db, but provide _db for backwards compatibility +db = _db = _bsddb +__version__ = db.__version__ + +error = db.DBError # So bsddb.error will mean something... + +#---------------------------------------------------------------------- + +import sys, os + +from weakref import ref + +if sys.version_info < (2, 6) : + import UserDict + MutableMapping = UserDict.DictMixin +else : + import collections + MutableMapping = collections.MutableMapping + +class _iter_mixin(MutableMapping): + def _make_iter_cursor(self): + cur = _DeadlockWrap(self.db.cursor) + key = id(cur) + self._cursor_refs[key] = ref(cur, self._gen_cref_cleaner(key)) + return cur + + def _gen_cref_cleaner(self, key): + # use generate the function for the weakref callback here + # to ensure that we do not hold a strict reference to cur + # in the callback. + return lambda ref: self._cursor_refs.pop(key, None) + + def __iter__(self): + self._kill_iteration = False + self._in_iter += 1 + try: + try: + cur = self._make_iter_cursor() + + # FIXME-20031102-greg: race condition. cursor could + # be closed by another thread before this call. + + # since we're only returning keys, we call the cursor + # methods with flags=0, dlen=0, dofs=0 + key = _DeadlockWrap(cur.first, 0,0,0)[0] + yield key + + next = getattr(cur, "next") + while 1: + try: + key = _DeadlockWrap(next, 0,0,0)[0] + yield key + except _bsddb.DBCursorClosedError: + if self._kill_iteration: + raise RuntimeError('Database changed size ' + 'during iteration.') + cur = self._make_iter_cursor() + # FIXME-20031101-greg: race condition. cursor could + # be closed by another thread before this call. + _DeadlockWrap(cur.set, key,0,0,0) + next = getattr(cur, "next") + except _bsddb.DBNotFoundError: + pass + except _bsddb.DBCursorClosedError: + # the database was modified during iteration. abort. + pass +# When Python 2.4 not supported in bsddb3, we can change this to "finally" + except : + self._in_iter -= 1 + raise + + self._in_iter -= 1 + + def iteritems(self): + if not self.db: + return + self._kill_iteration = False + self._in_iter += 1 + try: + try: + cur = self._make_iter_cursor() + + # FIXME-20031102-greg: race condition. cursor could + # be closed by another thread before this call. + + kv = _DeadlockWrap(cur.first) + key = kv[0] + yield kv + + next = getattr(cur, "next") + while 1: + try: + kv = _DeadlockWrap(next) + key = kv[0] + yield kv + except _bsddb.DBCursorClosedError: + if self._kill_iteration: + raise RuntimeError('Database changed size ' + 'during iteration.') + cur = self._make_iter_cursor() + # FIXME-20031101-greg: race condition. cursor could + # be closed by another thread before this call. + _DeadlockWrap(cur.set, key,0,0,0) + next = getattr(cur, "next") + except _bsddb.DBNotFoundError: + pass + except _bsddb.DBCursorClosedError: + # the database was modified during iteration. abort. + pass +# When Python 2.4 not supported in bsddb3, we can change this to "finally" + except : + self._in_iter -= 1 + raise + + self._in_iter -= 1 + + +class _DBWithCursor(_iter_mixin): + """ + A simple wrapper around DB that makes it look like the bsddbobject in + the old module. It uses a cursor as needed to provide DB traversal. + """ + def __init__(self, db): + self.db = db + self.db.set_get_returns_none(0) + + # FIXME-20031101-greg: I believe there is still the potential + # for deadlocks in a multithreaded environment if someone + # attempts to use the any of the cursor interfaces in one + # thread while doing a put or delete in another thread. The + # reason is that _checkCursor and _closeCursors are not atomic + # operations. Doing our own locking around self.dbc, + # self.saved_dbc_key and self._cursor_refs could prevent this. + # TODO: A test case demonstrating the problem needs to be written. + + # self.dbc is a DBCursor object used to implement the + # first/next/previous/last/set_location methods. + self.dbc = None + self.saved_dbc_key = None + + # a collection of all DBCursor objects currently allocated + # by the _iter_mixin interface. + self._cursor_refs = {} + self._in_iter = 0 + self._kill_iteration = False + + def __del__(self): + self.close() + + def _checkCursor(self): + if self.dbc is None: + self.dbc = _DeadlockWrap(self.db.cursor) + if self.saved_dbc_key is not None: + _DeadlockWrap(self.dbc.set, self.saved_dbc_key) + self.saved_dbc_key = None + + # This method is needed for all non-cursor DB calls to avoid + # Berkeley DB deadlocks (due to being opened with DB_INIT_LOCK + # and DB_THREAD to be thread safe) when intermixing database + # operations that use the cursor internally with those that don't. + def _closeCursors(self, save=1): + if self.dbc: + c = self.dbc + self.dbc = None + if save: + try: + self.saved_dbc_key = _DeadlockWrap(c.current, 0,0,0)[0] + except db.DBError: + pass + _DeadlockWrap(c.close) + del c + for cref in self._cursor_refs.values(): + c = cref() + if c is not None: + _DeadlockWrap(c.close) + + def _checkOpen(self): + if self.db is None: + raise error, "BSDDB object has already been closed" + + def isOpen(self): + return self.db is not None + + def __len__(self): + self._checkOpen() + return _DeadlockWrap(lambda: len(self.db)) # len(self.db) + + if sys.version_info >= (2, 6) : + def __repr__(self) : + if self.isOpen() : + return repr(dict(_DeadlockWrap(self.db.items))) + return repr(dict()) + + def __getitem__(self, key): + self._checkOpen() + return _DeadlockWrap(lambda: self.db[key]) # self.db[key] + + def __setitem__(self, key, value): + self._checkOpen() + self._closeCursors() + if self._in_iter and key not in self: + self._kill_iteration = True + def wrapF(): + self.db[key] = value + _DeadlockWrap(wrapF) # self.db[key] = value + + def __delitem__(self, key): + self._checkOpen() + self._closeCursors() + if self._in_iter and key in self: + self._kill_iteration = True + def wrapF(): + del self.db[key] + _DeadlockWrap(wrapF) # del self.db[key] + + def close(self): + self._closeCursors(save=0) + if self.dbc is not None: + _DeadlockWrap(self.dbc.close) + v = 0 + if self.db is not None: + v = _DeadlockWrap(self.db.close) + self.dbc = None + self.db = None + return v + + def keys(self): + self._checkOpen() + return _DeadlockWrap(self.db.keys) + + def has_key(self, key): + self._checkOpen() + return _DeadlockWrap(self.db.has_key, key) + + def set_location(self, key): + self._checkOpen() + self._checkCursor() + return _DeadlockWrap(self.dbc.set_range, key) + + def next(self): # Renamed by "2to3" + self._checkOpen() + self._checkCursor() + rv = _DeadlockWrap(getattr(self.dbc, "next")) + return rv + + if sys.version_info[0] >= 3 : # For "2to3" conversion + next = __next__ + + def previous(self): + self._checkOpen() + self._checkCursor() + rv = _DeadlockWrap(self.dbc.prev) + return rv + + def first(self): + self._checkOpen() + # fix 1725856: don't needlessly try to restore our cursor position + self.saved_dbc_key = None + self._checkCursor() + rv = _DeadlockWrap(self.dbc.first) + return rv + + def last(self): + self._checkOpen() + # fix 1725856: don't needlessly try to restore our cursor position + self.saved_dbc_key = None + self._checkCursor() + rv = _DeadlockWrap(self.dbc.last) + return rv + + def sync(self): + self._checkOpen() + return _DeadlockWrap(self.db.sync) + + +#---------------------------------------------------------------------- +# Compatibility object factory functions + +def hashopen(file, flag='c', mode=0666, pgsize=None, ffactor=None, nelem=None, + cachesize=None, lorder=None, hflags=0): + + flags = _checkflag(flag, file) + e = _openDBEnv(cachesize) + d = db.DB(e) + d.set_flags(hflags) + if pgsize is not None: d.set_pagesize(pgsize) + if lorder is not None: d.set_lorder(lorder) + if ffactor is not None: d.set_h_ffactor(ffactor) + if nelem is not None: d.set_h_nelem(nelem) + d.open(file, db.DB_HASH, flags, mode) + return _DBWithCursor(d) + +#---------------------------------------------------------------------- + +def btopen(file, flag='c', mode=0666, + btflags=0, cachesize=None, maxkeypage=None, minkeypage=None, + pgsize=None, lorder=None): + + flags = _checkflag(flag, file) + e = _openDBEnv(cachesize) + d = db.DB(e) + if pgsize is not None: d.set_pagesize(pgsize) + if lorder is not None: d.set_lorder(lorder) + d.set_flags(btflags) + if minkeypage is not None: d.set_bt_minkey(minkeypage) + if maxkeypage is not None: d.set_bt_maxkey(maxkeypage) + d.open(file, db.DB_BTREE, flags, mode) + return _DBWithCursor(d) + +#---------------------------------------------------------------------- + + +def rnopen(file, flag='c', mode=0666, + rnflags=0, cachesize=None, pgsize=None, lorder=None, + rlen=None, delim=None, source=None, pad=None): + + flags = _checkflag(flag, file) + e = _openDBEnv(cachesize) + d = db.DB(e) + if pgsize is not None: d.set_pagesize(pgsize) + if lorder is not None: d.set_lorder(lorder) + d.set_flags(rnflags) + if delim is not None: d.set_re_delim(delim) + if rlen is not None: d.set_re_len(rlen) + if source is not None: d.set_re_source(source) + if pad is not None: d.set_re_pad(pad) + d.open(file, db.DB_RECNO, flags, mode) + return _DBWithCursor(d) + +#---------------------------------------------------------------------- + +def _openDBEnv(cachesize): + e = db.DBEnv() + if cachesize is not None: + if cachesize >= 20480: + e.set_cachesize(0, cachesize) + else: + raise error, "cachesize must be >= 20480" + e.set_lk_detect(db.DB_LOCK_DEFAULT) + e.open('.', db.DB_PRIVATE | db.DB_CREATE | db.DB_THREAD | db.DB_INIT_LOCK | db.DB_INIT_MPOOL) + return e + +def _checkflag(flag, file): + if flag == 'r': + flags = db.DB_RDONLY + elif flag == 'rw': + flags = 0 + elif flag == 'w': + flags = db.DB_CREATE + elif flag == 'c': + flags = db.DB_CREATE + elif flag == 'n': + flags = db.DB_CREATE + #flags = db.DB_CREATE | db.DB_TRUNCATE + # we used db.DB_TRUNCATE flag for this before but Berkeley DB + # 4.2.52 changed to disallowed truncate with txn environments. + if file is not None and os.path.isfile(file): + os.unlink(file) + else: + raise error, "flags should be one of 'r', 'w', 'c' or 'n'" + return flags | db.DB_THREAD + +#---------------------------------------------------------------------- + + +# This is a silly little hack that allows apps to continue to use the +# DB_THREAD flag even on systems without threads without freaking out +# Berkeley DB. +# +# This assumes that if Python was built with thread support then +# Berkeley DB was too. + +try: + # 2to3 automatically changes "import thread" to "import _thread" + import thread as T + del T + +except ImportError: + db.DB_THREAD = 0 + +#---------------------------------------------------------------------- diff --git a/PythonHome/Lib/bsddb/__init__.pyc b/PythonHome/Lib/bsddb/__init__.pyc deleted file mode 100644 index 13f909d208a3efe19748f8db803c7957296c2d8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11893 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 td_Phsm(CZ)@i7zNgxYf9T>acH$E=C5LDY= 3) + +if not absolute_import : + if __name__.startswith('bsddb3.') : + # import _pybsddb binary as it should be the more recent version from + # a standalone pybsddb addon package than the version included with + # python as bsddb._bsddb. + from _pybsddb import * + from _pybsddb import __version__ + else: + from _bsddb import * + from _bsddb import __version__ +else : + # Because this syntaxis is not valid before Python 2.5 + if __name__.startswith('bsddb3.') : + exec("from ._pybsddb import *") + exec("from ._pybsddb import __version__") + else : + exec("from ._bsddb import *") + exec("from ._bsddb import __version__") diff --git a/PythonHome/Lib/bsddb/db.pyc b/PythonHome/Lib/bsddb/db.pyc deleted file mode 100644 index 94bba42432d22aa29322423e9a21e5f261563dd4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 577 zcmZ`!OHRWu5PeS4B&0_6D3r@h* zH~@^36be$U_|1&pyvZB;b3ORDx$WPfJ~qWuy6T-k(8rJf10V(_48p>mu<_8qz(Q<6 zWr%G|90&(548=vMX&`Cf%BWqFr7i|8*yG!R^nOThL1u@42fadg=I73}@T-_@K&;hI zK^+oz@%B9$jI9rMbUHVV$O zQ5tiu11gjr6= 3) +if absolute_import : + # Because this syntaxis is not valid before Python 2.5 + exec("from . import db") +else : + import db + +if sys.version_info < (2, 6) : + from UserDict import DictMixin as MutableMapping +else : + import collections + MutableMapping = collections.MutableMapping + +class DBEnv: + def __init__(self, *args, **kwargs): + self._cobj = db.DBEnv(*args, **kwargs) + + def close(self, *args, **kwargs): + return self._cobj.close(*args, **kwargs) + def open(self, *args, **kwargs): + return self._cobj.open(*args, **kwargs) + def remove(self, *args, **kwargs): + return self._cobj.remove(*args, **kwargs) + def set_shm_key(self, *args, **kwargs): + return self._cobj.set_shm_key(*args, **kwargs) + def set_cachesize(self, *args, **kwargs): + return self._cobj.set_cachesize(*args, **kwargs) + def set_data_dir(self, *args, **kwargs): + return self._cobj.set_data_dir(*args, **kwargs) + def set_flags(self, *args, **kwargs): + return self._cobj.set_flags(*args, **kwargs) + def set_lg_bsize(self, *args, **kwargs): + return self._cobj.set_lg_bsize(*args, **kwargs) + def set_lg_dir(self, *args, **kwargs): + return self._cobj.set_lg_dir(*args, **kwargs) + def set_lg_max(self, *args, **kwargs): + return self._cobj.set_lg_max(*args, **kwargs) + def set_lk_detect(self, *args, **kwargs): + return self._cobj.set_lk_detect(*args, **kwargs) + if db.version() < (4,5): + def set_lk_max(self, *args, **kwargs): + return self._cobj.set_lk_max(*args, **kwargs) + def set_lk_max_locks(self, *args, **kwargs): + return self._cobj.set_lk_max_locks(*args, **kwargs) + def set_lk_max_lockers(self, *args, **kwargs): + return self._cobj.set_lk_max_lockers(*args, **kwargs) + def set_lk_max_objects(self, *args, **kwargs): + return self._cobj.set_lk_max_objects(*args, **kwargs) + def set_mp_mmapsize(self, *args, **kwargs): + return self._cobj.set_mp_mmapsize(*args, **kwargs) + def set_timeout(self, *args, **kwargs): + return self._cobj.set_timeout(*args, **kwargs) + def set_tmp_dir(self, *args, **kwargs): + return self._cobj.set_tmp_dir(*args, **kwargs) + def txn_begin(self, *args, **kwargs): + return self._cobj.txn_begin(*args, **kwargs) + def txn_checkpoint(self, *args, **kwargs): + return self._cobj.txn_checkpoint(*args, **kwargs) + def txn_stat(self, *args, **kwargs): + return self._cobj.txn_stat(*args, **kwargs) + def set_tx_max(self, *args, **kwargs): + return self._cobj.set_tx_max(*args, **kwargs) + def set_tx_timestamp(self, *args, **kwargs): + return self._cobj.set_tx_timestamp(*args, **kwargs) + def lock_detect(self, *args, **kwargs): + return self._cobj.lock_detect(*args, **kwargs) + def lock_get(self, *args, **kwargs): + return self._cobj.lock_get(*args, **kwargs) + def lock_id(self, *args, **kwargs): + return self._cobj.lock_id(*args, **kwargs) + def lock_put(self, *args, **kwargs): + return self._cobj.lock_put(*args, **kwargs) + def lock_stat(self, *args, **kwargs): + return self._cobj.lock_stat(*args, **kwargs) + def log_archive(self, *args, **kwargs): + return self._cobj.log_archive(*args, **kwargs) + + def set_get_returns_none(self, *args, **kwargs): + return self._cobj.set_get_returns_none(*args, **kwargs) + + def log_stat(self, *args, **kwargs): + return self._cobj.log_stat(*args, **kwargs) + + def dbremove(self, *args, **kwargs): + return self._cobj.dbremove(*args, **kwargs) + def dbrename(self, *args, **kwargs): + return self._cobj.dbrename(*args, **kwargs) + def set_encrypt(self, *args, **kwargs): + return self._cobj.set_encrypt(*args, **kwargs) + + if db.version() >= (4,4): + def fileid_reset(self, *args, **kwargs): + return self._cobj.fileid_reset(*args, **kwargs) + + def lsn_reset(self, *args, **kwargs): + return self._cobj.lsn_reset(*args, **kwargs) + + +class DB(MutableMapping): + def __init__(self, dbenv, *args, **kwargs): + # give it the proper DBEnv C object that its expecting + self._cobj = db.DB(*((dbenv._cobj,) + args), **kwargs) + + # TODO are there other dict methods that need to be overridden? + def __len__(self): + return len(self._cobj) + def __getitem__(self, arg): + return self._cobj[arg] + def __setitem__(self, key, value): + self._cobj[key] = value + def __delitem__(self, arg): + del self._cobj[arg] + + if sys.version_info >= (2, 6) : + def __iter__(self) : + return self._cobj.__iter__() + + def append(self, *args, **kwargs): + return self._cobj.append(*args, **kwargs) + def associate(self, *args, **kwargs): + return self._cobj.associate(*args, **kwargs) + def close(self, *args, **kwargs): + return self._cobj.close(*args, **kwargs) + def consume(self, *args, **kwargs): + return self._cobj.consume(*args, **kwargs) + def consume_wait(self, *args, **kwargs): + return self._cobj.consume_wait(*args, **kwargs) + def cursor(self, *args, **kwargs): + return self._cobj.cursor(*args, **kwargs) + def delete(self, *args, **kwargs): + return self._cobj.delete(*args, **kwargs) + def fd(self, *args, **kwargs): + return self._cobj.fd(*args, **kwargs) + def get(self, *args, **kwargs): + return self._cobj.get(*args, **kwargs) + def pget(self, *args, **kwargs): + return self._cobj.pget(*args, **kwargs) + def get_both(self, *args, **kwargs): + return self._cobj.get_both(*args, **kwargs) + def get_byteswapped(self, *args, **kwargs): + return self._cobj.get_byteswapped(*args, **kwargs) + def get_size(self, *args, **kwargs): + return self._cobj.get_size(*args, **kwargs) + def get_type(self, *args, **kwargs): + return self._cobj.get_type(*args, **kwargs) + def join(self, *args, **kwargs): + return self._cobj.join(*args, **kwargs) + def key_range(self, *args, **kwargs): + return self._cobj.key_range(*args, **kwargs) + def has_key(self, *args, **kwargs): + return self._cobj.has_key(*args, **kwargs) + def items(self, *args, **kwargs): + return self._cobj.items(*args, **kwargs) + def keys(self, *args, **kwargs): + return self._cobj.keys(*args, **kwargs) + def open(self, *args, **kwargs): + return self._cobj.open(*args, **kwargs) + def put(self, *args, **kwargs): + return self._cobj.put(*args, **kwargs) + def remove(self, *args, **kwargs): + return self._cobj.remove(*args, **kwargs) + def rename(self, *args, **kwargs): + return self._cobj.rename(*args, **kwargs) + def set_bt_minkey(self, *args, **kwargs): + return self._cobj.set_bt_minkey(*args, **kwargs) + def set_bt_compare(self, *args, **kwargs): + return self._cobj.set_bt_compare(*args, **kwargs) + def set_cachesize(self, *args, **kwargs): + return self._cobj.set_cachesize(*args, **kwargs) + def set_dup_compare(self, *args, **kwargs) : + return self._cobj.set_dup_compare(*args, **kwargs) + def set_flags(self, *args, **kwargs): + return self._cobj.set_flags(*args, **kwargs) + def set_h_ffactor(self, *args, **kwargs): + return self._cobj.set_h_ffactor(*args, **kwargs) + def set_h_nelem(self, *args, **kwargs): + return self._cobj.set_h_nelem(*args, **kwargs) + def set_lorder(self, *args, **kwargs): + return self._cobj.set_lorder(*args, **kwargs) + def set_pagesize(self, *args, **kwargs): + return self._cobj.set_pagesize(*args, **kwargs) + def set_re_delim(self, *args, **kwargs): + return self._cobj.set_re_delim(*args, **kwargs) + def set_re_len(self, *args, **kwargs): + return self._cobj.set_re_len(*args, **kwargs) + def set_re_pad(self, *args, **kwargs): + return self._cobj.set_re_pad(*args, **kwargs) + def set_re_source(self, *args, **kwargs): + return self._cobj.set_re_source(*args, **kwargs) + def set_q_extentsize(self, *args, **kwargs): + return self._cobj.set_q_extentsize(*args, **kwargs) + def stat(self, *args, **kwargs): + return self._cobj.stat(*args, **kwargs) + def sync(self, *args, **kwargs): + return self._cobj.sync(*args, **kwargs) + def type(self, *args, **kwargs): + return self._cobj.type(*args, **kwargs) + def upgrade(self, *args, **kwargs): + return self._cobj.upgrade(*args, **kwargs) + def values(self, *args, **kwargs): + return self._cobj.values(*args, **kwargs) + def verify(self, *args, **kwargs): + return self._cobj.verify(*args, **kwargs) + def set_get_returns_none(self, *args, **kwargs): + return self._cobj.set_get_returns_none(*args, **kwargs) + + def set_encrypt(self, *args, **kwargs): + return self._cobj.set_encrypt(*args, **kwargs) + + +class DBSequence: + def __init__(self, *args, **kwargs): + self._cobj = db.DBSequence(*args, **kwargs) + + def close(self, *args, **kwargs): + return self._cobj.close(*args, **kwargs) + def get(self, *args, **kwargs): + return self._cobj.get(*args, **kwargs) + def get_dbp(self, *args, **kwargs): + return self._cobj.get_dbp(*args, **kwargs) + def get_key(self, *args, **kwargs): + return self._cobj.get_key(*args, **kwargs) + def init_value(self, *args, **kwargs): + return self._cobj.init_value(*args, **kwargs) + def open(self, *args, **kwargs): + return self._cobj.open(*args, **kwargs) + def remove(self, *args, **kwargs): + return self._cobj.remove(*args, **kwargs) + def stat(self, *args, **kwargs): + return self._cobj.stat(*args, **kwargs) + def set_cachesize(self, *args, **kwargs): + return self._cobj.set_cachesize(*args, **kwargs) + def set_flags(self, *args, **kwargs): + return self._cobj.set_flags(*args, **kwargs) + def set_range(self, *args, **kwargs): + return self._cobj.set_range(*args, **kwargs) + def get_cachesize(self, *args, **kwargs): + return self._cobj.get_cachesize(*args, **kwargs) + def get_flags(self, *args, **kwargs): + return self._cobj.get_flags(*args, **kwargs) + def get_range(self, *args, **kwargs): + return self._cobj.get_range(*args, **kwargs) diff --git a/PythonHome/Lib/bsddb/dbobj.pyc b/PythonHome/Lib/bsddb/dbobj.pyc deleted file mode 100644 index 166a0e47ecd5f86b2bf87c137b53c151b97e8f2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17218 zcmds#fzL zAKavCpXuqU{&m$;RZl%n^_E^)wc_QcpPQ_z?oSE7&*F%`ip1c5LDiL-QYuhtwxCQ= zZ80S^*Qch6Dk!S<31yb?qGea2q3rsSnkr@2uU2zPwV#!*22_2SY9MRBDnuKys|VE7 zfC>iGY(Kv+%as{cW>CGL)Gei+nZoB4D(F`=+h_2mH zGvhcLzaN*QHl_ficz4tU?o6S?`k{a-DT&a>>fsqYS)T|4%JhqX2OAIp&$3(uJb^s- z)Ji@xbKx1~nWt8%V6~bZW|f$OQl&2`vs$iMqavIf7I`h}gc;W~J=9v~GJ8eXugpFX4&3&PWvW>FeFd{$zB;JP0TIf4SUp)j zgodcH+1R{1-hw0Ef+P_=y;)EBwi0`?CPbkaJBR2_e-E0MsEeLzq zQ5PV5@^;W@UbC)~6)0iM1 z(ghIAJnc0Mn1@{e zv1_n;0Fhx;CS_Bb7olP4l1mzM$2n7{8pavX%mWi!Ua<{<0fGvXm+go-)68p<&+1Nlw-i8?Rwb- z52v@}M&wn3>CoC#+loTOq|R%-a-Jj&tdZ(mtBIAB?SQ!rCA|$tZZnqlFp=WKw}#n{ zGA3QXWMg)6BhQ$<11MKq;ACSqaM-_4MU9qigY5*+(=MRc<2ifeoN;%dm}gw@P=SPJ zIz6+XEho?Qi zU7ZQ-*RA`&Qgy*YgNiddRM=|=Nv9pfUet`Nmy7#RUd;tqszcMcM&|gy%aVh&2^&YFrv8%(p+(< zZJPFyrj?>;6=+VydXx$09?dadbEwrE-!#V(%|5KzcQkcYQ&BVb7K2Z>)HD zSyDWKq`xp&8Z6%L-@3xkeb3)%$2l6yPYLNbj`;TltM~vzAczS( zD4y?$UT^^2bt&-y#6w!bxQw5aE1Zs z2Vj*QgWZqqFH0sWGKLUD%MgW_Ei!V2Sj48ArA6Zr(z*0;FnZ=1uQo>NC5=7Vj zGnYU6DPjxVwNg=hIM7N()^j}1z79rQ1I$~DoAK)j8Br2GNj->C7M>TDUY}dEyUFt@VKPdAKFAxh8W0W2YJGA19(t!=#E~0?bEzN4&1&c; z)`r;|P{>OTXk>b~HGY-@;G+&8WE`kAqqt*lsh$DH$6T<`w&}8X*Zt7iGJF)}eB1>P zRkzw{$4%={7~=+?aD{^50f7u#m3bpDKIsC5UAt!8na?8kr(9rgAj;v^c^uh4?Sg|Q zKr08xIP!nS1qjCkItePxWX4uW&Y_IYx`5%rL}2EVAimD=-&$kNqo~ihV9F{ePjKV{ zKtAshCYf(pcj-3)ek9O5Fft&9}__=W=r*?`v$^0+-2SpB986t0cvHm@Ki9!5Dfd`+OBZ@D1i!m&$K zZ8lnd+j@ZG`s>>cki?s4t2DIMzvBQRp{c-nF`X86cjl^?x1y-;I$#p#s%^!voxkS* zBFR*E#;eu*YGS_%VKDytE{N#3VN=a`5!NCN+Zxg+<_9i#IB=1t-fWw|dXYAXQhw+H zhh2g=Eq^-Kj?TBEoFBOaY6pnO*F)3_$Qb+Un0cfbtW^I4$3Lfx@j5 zKXrkVb$HZH-0ZZg))T}#LGv>gL~B?GH2QfjxRC@=l4t3}9UVV+0Yw8e&sKpc@o6c6DG7DH7uUu!ND!9q z>jv6O!-b(mLiBfp;$J&hfA19~*$r`id@^{xgIy~@m9YF_42qQme&sx1WbzUl&ko)}vQ<}F~t$vcwD+v;3GW(RJZYT_xTML|S|Ml#do=Qw4(_%|m*bk$eB|t)IV@`q zhPQ3_6kCp+A+-ak1De&Y`LvohDdV^;S#-OXreX0%9Pv&hi|?+a>2|k4jSSse(EF#K zW8xzbzpY=1oApi-cH2vF!g$H`bALsShR_oX(`%W*^&(jPXV!Lxqt-e{p4Ts5o30DGn6|iz8Pyw*Cdz ChpC4E diff --git a/PythonHome/Lib/bsddb/dbrecio.py b/PythonHome/Lib/bsddb/dbrecio.py new file mode 100644 index 0000000000..d439f3255e --- /dev/null +++ b/PythonHome/Lib/bsddb/dbrecio.py @@ -0,0 +1,190 @@ + +""" +File-like objects that read from or write to a bsddb record. + +This implements (nearly) all stdio methods. + +f = DBRecIO(db, key, txn=None) +f.close() # explicitly release resources held +flag = f.isatty() # always false +pos = f.tell() # get current position +f.seek(pos) # set current position +f.seek(pos, mode) # mode 0: absolute; 1: relative; 2: relative to EOF +buf = f.read() # read until EOF +buf = f.read(n) # read up to n bytes +f.truncate([size]) # truncate file at to at most size (default: current pos) +f.write(buf) # write at current position +f.writelines(list) # for line in list: f.write(line) + +Notes: +- fileno() is left unimplemented so that code which uses it triggers + an exception early. +- There's a simple test set (see end of this file) - not yet updated + for DBRecIO. +- readline() is not implemented yet. + + +From: + Itamar Shtull-Trauring +""" + +import errno +import string + +class DBRecIO: + def __init__(self, db, key, txn=None): + self.db = db + self.key = key + self.txn = txn + self.len = None + self.pos = 0 + self.closed = 0 + self.softspace = 0 + + def close(self): + if not self.closed: + self.closed = 1 + del self.db, self.txn + + def isatty(self): + if self.closed: + raise ValueError, "I/O operation on closed file" + return 0 + + def seek(self, pos, mode = 0): + if self.closed: + raise ValueError, "I/O operation on closed file" + if mode == 1: + pos = pos + self.pos + elif mode == 2: + pos = pos + self.len + self.pos = max(0, pos) + + def tell(self): + if self.closed: + raise ValueError, "I/O operation on closed file" + return self.pos + + def read(self, n = -1): + if self.closed: + raise ValueError, "I/O operation on closed file" + if n < 0: + newpos = self.len + else: + newpos = min(self.pos+n, self.len) + + dlen = newpos - self.pos + + r = self.db.get(self.key, txn=self.txn, dlen=dlen, doff=self.pos) + self.pos = newpos + return r + + __fixme = """ + def readline(self, length=None): + if self.closed: + raise ValueError, "I/O operation on closed file" + if self.buflist: + self.buf = self.buf + string.joinfields(self.buflist, '') + self.buflist = [] + i = string.find(self.buf, '\n', self.pos) + if i < 0: + newpos = self.len + else: + newpos = i+1 + if length is not None: + if self.pos + length < newpos: + newpos = self.pos + length + r = self.buf[self.pos:newpos] + self.pos = newpos + return r + + def readlines(self, sizehint = 0): + total = 0 + lines = [] + line = self.readline() + while line: + lines.append(line) + total += len(line) + if 0 < sizehint <= total: + break + line = self.readline() + return lines + """ + + def truncate(self, size=None): + if self.closed: + raise ValueError, "I/O operation on closed file" + if size is None: + size = self.pos + elif size < 0: + raise IOError(errno.EINVAL, + "Negative size not allowed") + elif size < self.pos: + self.pos = size + self.db.put(self.key, "", txn=self.txn, dlen=self.len-size, doff=size) + + def write(self, s): + if self.closed: + raise ValueError, "I/O operation on closed file" + if not s: return + if self.pos > self.len: + self.buflist.append('\0'*(self.pos - self.len)) + self.len = self.pos + newpos = self.pos + len(s) + self.db.put(self.key, s, txn=self.txn, dlen=len(s), doff=self.pos) + self.pos = newpos + + def writelines(self, list): + self.write(string.joinfields(list, '')) + + def flush(self): + if self.closed: + raise ValueError, "I/O operation on closed file" + + +""" +# A little test suite + +def _test(): + import sys + if sys.argv[1:]: + file = sys.argv[1] + else: + file = '/etc/passwd' + lines = open(file, 'r').readlines() + text = open(file, 'r').read() + f = StringIO() + for line in lines[:-2]: + f.write(line) + f.writelines(lines[-2:]) + if f.getvalue() != text: + raise RuntimeError, 'write failed' + length = f.tell() + print 'File length =', length + f.seek(len(lines[0])) + f.write(lines[1]) + f.seek(0) + print 'First line =', repr(f.readline()) + here = f.tell() + line = f.readline() + print 'Second line =', repr(line) + f.seek(-len(line), 1) + line2 = f.read(len(line)) + if line != line2: + raise RuntimeError, 'bad result after seek back' + f.seek(len(line2), 1) + list = f.readlines() + line = list[-1] + f.seek(f.tell() - len(line)) + line2 = f.read() + if line != line2: + raise RuntimeError, 'bad result after seek back from EOF' + print 'Read', len(list), 'more lines' + print 'File length =', f.tell() + if f.tell() != length: + raise RuntimeError, 'bad length' + f.close() + +if __name__ == '__main__': + _test() +""" diff --git a/PythonHome/Lib/bsddb/dbrecio.pyc b/PythonHome/Lib/bsddb/dbrecio.pyc deleted file mode 100644 index 43e28ba802745526679bb4b7996b8aeb76a82e77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5121 zcmb7HQF9ze5uUx1Wa)G!Ar9CElMGe`pRgos3V0B52ubWJR|UE1PFhz zz1o?>78Ual=Y=YG=YcBzL;e~+0KTv1ZueZ0ZTX~~?V0K6>FMt2{3qe+$8M;ocMrSeGag9vm>?YC6gR_UTj7u2^(y-?~;`{=jSUT=xZ{{=yv zdp0+lxjiR2DRG(Esq^pyASSl4kolrwndva+KC4yg}3=>rXuLJ2Dxz4 zWK2ngJ~;8l;Q+px6iMt&?~${AHD7^uP0z-327hZfnBMeI)_F}X-AhdtPjbIKZxT91 zoZo|vwLR9R0fF^rm{0g~TNu~Nt@E;bh9KgQwguh}o6O{LbiLErEus2$XH(QGN>~AL zm7C1#Nl}NFNwq6OcqTBnembu4Pp2%E%==};{JxdqV=ho&+& z9D>-1NR2IVczCu4mupj`y38ORJJU$(dQ%sr*C$|@j8oV%g=n5+8pD)H`|}7vVY1I_ zi=_zr&OKbCZLHP$zK=(7rT2z@lINQbt9Vk`;!y8c8UJJyKPyICNjdtsWB-TWuD^hL zI^8Y-DZdulPw_a9#^CznzF%Y>_!ie6_dDWc-(TQGCxPpaL1X~TE-@Q$@PbM~Uy#9N zl`gCO6%n!`BOR4?gl$!&t3q^D+7;rW>hJZwhmDg3G<>MeXLuZ&uOs!fQUeezA<%6L zfmDP+OhK=}1HA$PMFIh(6mk;yTiGH3FvAEDQ$>^>Lv@Px+w5Y*P=FYLi%Np_FZ1Ef1!ZjDbo z^%)FoVf|pR2HMdQDq5NQODLC5ZI_SG!O4%n{?pk}W#ow*`$eKr{ zPf<}c=8?{)>>@bD4jUjGtr9dnt>INn1r4hoC@&S{o1hhI1^3={*U;Yo#RFZAO@&m3 zi-rGSX1OlGVPa3J?K^0`jPr@PTUBM%drRG^ZAj<0LDkB4BiSaQO0(xPG9+luJOSbm z_u#mts@v1xJZh=S&m&b_V~pZzaPAMYxptV7I7t^c`XU6f#P42@Ha&+ecv?$a1gmgW zaAubj57+0Ige)$7@HRawa}uL0DChGt!gpqY5<#LNE#akkS#%Lk%Yns(jwL&buLb2yolP*F%sed#KIIuz1dO{1(IgO zwJEa|Po9=p))TkOO&2RRabb%PDGVlw6yTM)ge5`6#kjCa6_WM}^As7d|K4o0I)4PQ zl6{VKj*FQn7(w0E)z-zav-B~VH*``vj$-G z6}_)tgRoN@0=w|<%Rv`X`f>P@Se!Z6$;(Hv~s;Vg}b zW)olzQ_XtgCsm=Vj*QGlQE&+C2OK)I0ONP`t@TDnU-~%bSS?D>B}V34Bj|E!(FT;& zD*zP%d&$(u<+(-DRy-a9{Q<5Li*k7O3tQj3Lj#^M4I|%zduzRS?f_Op*_ZdAFhGd- z_$ASAP`C=#68&VIWJ6{|UU|ue{{ivJYzVBhJj;e{#d^2HYQ|cKEV)Y@ z1BM?rMUXsp+8wlsPq@(qb+jx5up(ew$cw;=A#tvf{|Ydr6wP*&63a1lpEEx?qL5v4 zDBnrpn}nf_56SYWNr`m>Qj_e~zl3g25@wS+nNmXm<=FiPf;@0apyaB8EY_F1_jkYi z{TBkN0$`lXH!t9mzUqmXZ`5XVWq#gp&L_j%#dx>5pD;$gH z2$fIV%hD;VQ$MqEwxenFo1!5a^v&Lt`gF>7#D`~MBKmHco5f?{at0Xu0T=NS1k6qw z22ZgBy8dOf=kpbVLOxXg#)XZemefM@Ui1OnbSe5(a1^&=AjqBj2?&}?sxB=qU>O&P zCYOjO`)>b7Xahd_2$Y;76b`|~bEQZQQwJMM&iM{N^EF@Ee@D+zl!{Kny;r0A`fKZr z=ssME`l`Jx%%i!peBy@xprW)U@5QcsNKQYhig;uO12NBF0Ps7>(e0D9FQKwZ>LQzW z*?gZ3Pv+l2GnjrO4+fciHZpz9Sz5lo&gSQ68nX)ZnyRDIQ7SjF}I8cn*o7c`uG0= 3) +if absolute_import : + # Because this syntaxis is not valid before Python 2.5 + exec("from . import db") +else : + import db + +if sys.version_info[0] >= 3 : + import cPickle # Will be converted to "pickle" by "2to3" +else : + if sys.version_info < (2, 6) : + import cPickle + else : + # When we drop support for python 2.4 + # we could use: (in 2.5 we need a __future__ statement) + # + # with warnings.catch_warnings(): + # warnings.filterwarnings(...) + # ... + # + # We can not use "with" as is, because it would be invalid syntax + # in python 2.4 and (with no __future__) 2.5. + # Here we simulate "with" following PEP 343 : + import warnings + w = warnings.catch_warnings() + w.__enter__() + try : + warnings.filterwarnings('ignore', + message='the cPickle module has been removed in Python 3.0', + category=DeprecationWarning) + import cPickle + finally : + w.__exit__() + del w + +HIGHEST_PROTOCOL = cPickle.HIGHEST_PROTOCOL +def _dumps(object, protocol): + return cPickle.dumps(object, protocol=protocol) + +if sys.version_info < (2, 6) : + from UserDict import DictMixin as MutableMapping +else : + import collections + MutableMapping = collections.MutableMapping + +#------------------------------------------------------------------------ + + +def open(filename, flags=db.DB_CREATE, mode=0660, filetype=db.DB_HASH, + dbenv=None, dbname=None): + """ + A simple factory function for compatibility with the standard + shleve.py module. It can be used like this, where key is a string + and data is a pickleable object: + + from bsddb import dbshelve + db = dbshelve.open(filename) + + db[key] = data + + db.close() + """ + if type(flags) == type(''): + sflag = flags + if sflag == 'r': + flags = db.DB_RDONLY + elif sflag == 'rw': + flags = 0 + elif sflag == 'w': + flags = db.DB_CREATE + elif sflag == 'c': + flags = db.DB_CREATE + elif sflag == 'n': + flags = db.DB_TRUNCATE | db.DB_CREATE + else: + raise db.DBError, "flags should be one of 'r', 'w', 'c' or 'n' or use the bsddb.db.DB_* flags" + + d = DBShelf(dbenv) + d.open(filename, dbname, filetype, flags, mode) + return d + +#--------------------------------------------------------------------------- + +class DBShelveError(db.DBError): pass + + +class DBShelf(MutableMapping): + """A shelf to hold pickled objects, built upon a bsddb DB object. It + automatically pickles/unpickles data objects going to/from the DB. + """ + def __init__(self, dbenv=None): + self.db = db.DB(dbenv) + self._closed = True + if HIGHEST_PROTOCOL: + self.protocol = HIGHEST_PROTOCOL + else: + self.protocol = 1 + + + def __del__(self): + self.close() + + + def __getattr__(self, name): + """Many methods we can just pass through to the DB object. + (See below) + """ + return getattr(self.db, name) + + + #----------------------------------- + # Dictionary access methods + + def __len__(self): + return len(self.db) + + + def __getitem__(self, key): + data = self.db[key] + return cPickle.loads(data) + + + def __setitem__(self, key, value): + data = _dumps(value, self.protocol) + self.db[key] = data + + + def __delitem__(self, key): + del self.db[key] + + + def keys(self, txn=None): + if txn is not None: + return self.db.keys(txn) + else: + return self.db.keys() + + if sys.version_info >= (2, 6) : + def __iter__(self) : # XXX: Load all keys in memory :-( + for k in self.db.keys() : + yield k + + # Do this when "DB" support iteration + # Or is it enough to pass thru "getattr"? + # + # def __iter__(self) : + # return self.db.__iter__() + + + def open(self, *args, **kwargs): + self.db.open(*args, **kwargs) + self._closed = False + + + def close(self, *args, **kwargs): + self.db.close(*args, **kwargs) + self._closed = True + + + def __repr__(self): + if self._closed: + return '' % (id(self)) + else: + return repr(dict(self.iteritems())) + + + def items(self, txn=None): + if txn is not None: + items = self.db.items(txn) + else: + items = self.db.items() + newitems = [] + + for k, v in items: + newitems.append( (k, cPickle.loads(v)) ) + return newitems + + def values(self, txn=None): + if txn is not None: + values = self.db.values(txn) + else: + values = self.db.values() + + return map(cPickle.loads, values) + + #----------------------------------- + # Other methods + + def __append(self, value, txn=None): + data = _dumps(value, self.protocol) + return self.db.append(data, txn) + + def append(self, value, txn=None): + if self.get_type() == db.DB_RECNO: + return self.__append(value, txn=txn) + raise DBShelveError, "append() only supported when dbshelve opened with filetype=dbshelve.db.DB_RECNO" + + + def associate(self, secondaryDB, callback, flags=0): + def _shelf_callback(priKey, priData, realCallback=callback): + # Safe in Python 2.x because expresion short circuit + if sys.version_info[0] < 3 or isinstance(priData, bytes) : + data = cPickle.loads(priData) + else : + data = cPickle.loads(bytes(priData, "iso8859-1")) # 8 bits + return realCallback(priKey, data) + + return self.db.associate(secondaryDB, _shelf_callback, flags) + + + #def get(self, key, default=None, txn=None, flags=0): + def get(self, *args, **kw): + # We do it with *args and **kw so if the default value wasn't + # given nothing is passed to the extension module. That way + # an exception can be raised if set_get_returns_none is turned + # off. + data = self.db.get(*args, **kw) + try: + return cPickle.loads(data) + except (EOFError, TypeError, cPickle.UnpicklingError): + return data # we may be getting the default value, or None, + # so it doesn't need unpickled. + + def get_both(self, key, value, txn=None, flags=0): + data = _dumps(value, self.protocol) + data = self.db.get(key, data, txn, flags) + return cPickle.loads(data) + + + def cursor(self, txn=None, flags=0): + c = DBShelfCursor(self.db.cursor(txn, flags)) + c.protocol = self.protocol + return c + + + def put(self, key, value, txn=None, flags=0): + data = _dumps(value, self.protocol) + return self.db.put(key, data, txn, flags) + + + def join(self, cursorList, flags=0): + raise NotImplementedError + + + #---------------------------------------------- + # Methods allowed to pass-through to self.db + # + # close, delete, fd, get_byteswapped, get_type, has_key, + # key_range, open, remove, rename, stat, sync, + # upgrade, verify, and all set_* methods. + + +#--------------------------------------------------------------------------- + +class DBShelfCursor: + """ + """ + def __init__(self, cursor): + self.dbc = cursor + + def __del__(self): + self.close() + + + def __getattr__(self, name): + """Some methods we can just pass through to the cursor object. (See below)""" + return getattr(self.dbc, name) + + + #---------------------------------------------- + + def dup(self, flags=0): + c = DBShelfCursor(self.dbc.dup(flags)) + c.protocol = self.protocol + return c + + + def put(self, key, value, flags=0): + data = _dumps(value, self.protocol) + return self.dbc.put(key, data, flags) + + + def get(self, *args): + count = len(args) # a method overloading hack + method = getattr(self, 'get_%d' % count) + method(*args) + + def get_1(self, flags): + rec = self.dbc.get(flags) + return self._extract(rec) + + def get_2(self, key, flags): + rec = self.dbc.get(key, flags) + return self._extract(rec) + + def get_3(self, key, value, flags): + data = _dumps(value, self.protocol) + rec = self.dbc.get(key, flags) + return self._extract(rec) + + + def current(self, flags=0): return self.get_1(flags|db.DB_CURRENT) + def first(self, flags=0): return self.get_1(flags|db.DB_FIRST) + def last(self, flags=0): return self.get_1(flags|db.DB_LAST) + def next(self, flags=0): return self.get_1(flags|db.DB_NEXT) + def prev(self, flags=0): return self.get_1(flags|db.DB_PREV) + def consume(self, flags=0): return self.get_1(flags|db.DB_CONSUME) + def next_dup(self, flags=0): return self.get_1(flags|db.DB_NEXT_DUP) + def next_nodup(self, flags=0): return self.get_1(flags|db.DB_NEXT_NODUP) + def prev_nodup(self, flags=0): return self.get_1(flags|db.DB_PREV_NODUP) + + + def get_both(self, key, value, flags=0): + data = _dumps(value, self.protocol) + rec = self.dbc.get_both(key, flags) + return self._extract(rec) + + + def set(self, key, flags=0): + rec = self.dbc.set(key, flags) + return self._extract(rec) + + def set_range(self, key, flags=0): + rec = self.dbc.set_range(key, flags) + return self._extract(rec) + + def set_recno(self, recno, flags=0): + rec = self.dbc.set_recno(recno, flags) + return self._extract(rec) + + set_both = get_both + + def _extract(self, rec): + if rec is None: + return None + else: + key, data = rec + # Safe in Python 2.x because expresion short circuit + if sys.version_info[0] < 3 or isinstance(data, bytes) : + return key, cPickle.loads(data) + else : + return key, cPickle.loads(bytes(data, "iso8859-1")) # 8 bits + + #---------------------------------------------- + # Methods allowed to pass-through to self.dbc + # + # close, count, delete, get_recno, join_item + + +#--------------------------------------------------------------------------- diff --git a/PythonHome/Lib/bsddb/dbshelve.pyc b/PythonHome/Lib/bsddb/dbshelve.pyc deleted file mode 100644 index 17e097db76d90cd9638080c5978f8774c3a2bb4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12242 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 + +# This provides a simple database table interface built on top of +# the Python Berkeley DB 3 interface. +# +_cvsid = '$Id$' + +import re +import sys +import copy +import random +import struct + + +if sys.version_info[0] >= 3 : + import pickle +else : + if sys.version_info < (2, 6) : + import cPickle as pickle + else : + # When we drop support for python 2.4 + # we could use: (in 2.5 we need a __future__ statement) + # + # with warnings.catch_warnings(): + # warnings.filterwarnings(...) + # ... + # + # We can not use "with" as is, because it would be invalid syntax + # in python 2.4 and (with no __future__) 2.5. + # Here we simulate "with" following PEP 343 : + import warnings + w = warnings.catch_warnings() + w.__enter__() + try : + warnings.filterwarnings('ignore', + message='the cPickle module has been removed in Python 3.0', + category=DeprecationWarning) + import cPickle as pickle + finally : + w.__exit__() + del w + +try: + # For Pythons w/distutils pybsddb + from bsddb3 import db +except ImportError: + # For Python 2.3 + from bsddb import db + +class TableDBError(StandardError): + pass +class TableAlreadyExists(TableDBError): + pass + + +class Cond: + """This condition matches everything""" + def __call__(self, s): + return 1 + +class ExactCond(Cond): + """Acts as an exact match condition function""" + def __init__(self, strtomatch): + self.strtomatch = strtomatch + def __call__(self, s): + return s == self.strtomatch + +class PrefixCond(Cond): + """Acts as a condition function for matching a string prefix""" + def __init__(self, prefix): + self.prefix = prefix + def __call__(self, s): + return s[:len(self.prefix)] == self.prefix + +class PostfixCond(Cond): + """Acts as a condition function for matching a string postfix""" + def __init__(self, postfix): + self.postfix = postfix + def __call__(self, s): + return s[-len(self.postfix):] == self.postfix + +class LikeCond(Cond): + """ + Acts as a function that will match using an SQL 'LIKE' style + string. Case insensitive and % signs are wild cards. + This isn't perfect but it should work for the simple common cases. + """ + def __init__(self, likestr, re_flags=re.IGNORECASE): + # escape python re characters + chars_to_escape = '.*+()[]?' + for char in chars_to_escape : + likestr = likestr.replace(char, '\\'+char) + # convert %s to wildcards + self.likestr = likestr.replace('%', '.*') + self.re = re.compile('^'+self.likestr+'$', re_flags) + def __call__(self, s): + return self.re.match(s) + +# +# keys used to store database metadata +# +_table_names_key = '__TABLE_NAMES__' # list of the tables in this db +_columns = '._COLUMNS__' # table_name+this key contains a list of columns + +def _columns_key(table): + return table + _columns + +# +# these keys are found within table sub databases +# +_data = '._DATA_.' # this+column+this+rowid key contains table data +_rowid = '._ROWID_.' # this+rowid+this key contains a unique entry for each + # row in the table. (no data is stored) +_rowid_str_len = 8 # length in bytes of the unique rowid strings + + +def _data_key(table, col, rowid): + return table + _data + col + _data + rowid + +def _search_col_data_key(table, col): + return table + _data + col + _data + +def _search_all_data_key(table): + return table + _data + +def _rowid_key(table, rowid): + return table + _rowid + rowid + _rowid + +def _search_rowid_key(table): + return table + _rowid + +def contains_metastrings(s) : + """Verify that the given string does not contain any + metadata strings that might interfere with dbtables database operation. + """ + if (s.find(_table_names_key) >= 0 or + s.find(_columns) >= 0 or + s.find(_data) >= 0 or + s.find(_rowid) >= 0): + # Then + return 1 + else: + return 0 + + +class bsdTableDB : + def __init__(self, filename, dbhome, create=0, truncate=0, mode=0600, + recover=0, dbflags=0): + """bsdTableDB(filename, dbhome, create=0, truncate=0, mode=0600) + + Open database name in the dbhome Berkeley DB directory. + Use keyword arguments when calling this constructor. + """ + self.db = None + myflags = db.DB_THREAD + if create: + myflags |= db.DB_CREATE + flagsforenv = (db.DB_INIT_MPOOL | db.DB_INIT_LOCK | db.DB_INIT_LOG | + db.DB_INIT_TXN | dbflags) + # DB_AUTO_COMMIT isn't a valid flag for env.open() + try: + dbflags |= db.DB_AUTO_COMMIT + except AttributeError: + pass + if recover: + flagsforenv = flagsforenv | db.DB_RECOVER + self.env = db.DBEnv() + # enable auto deadlock avoidance + self.env.set_lk_detect(db.DB_LOCK_DEFAULT) + self.env.open(dbhome, myflags | flagsforenv) + if truncate: + myflags |= db.DB_TRUNCATE + self.db = db.DB(self.env) + # this code relies on DBCursor.set* methods to raise exceptions + # rather than returning None + self.db.set_get_returns_none(1) + # allow duplicate entries [warning: be careful w/ metadata] + self.db.set_flags(db.DB_DUP) + self.db.open(filename, db.DB_BTREE, dbflags | myflags, mode) + self.dbfilename = filename + + if sys.version_info[0] >= 3 : + class cursor_py3k(object) : + def __init__(self, dbcursor) : + self._dbcursor = dbcursor + + def close(self) : + return self._dbcursor.close() + + def set_range(self, search) : + v = self._dbcursor.set_range(bytes(search, "iso8859-1")) + if v is not None : + v = (v[0].decode("iso8859-1"), + v[1].decode("iso8859-1")) + return v + + def __next__(self) : + v = getattr(self._dbcursor, "next")() + if v is not None : + v = (v[0].decode("iso8859-1"), + v[1].decode("iso8859-1")) + return v + + class db_py3k(object) : + def __init__(self, db) : + self._db = db + + def cursor(self, txn=None) : + return cursor_py3k(self._db.cursor(txn=txn)) + + def has_key(self, key, txn=None) : + return getattr(self._db,"has_key")(bytes(key, "iso8859-1"), + txn=txn) + + def put(self, key, value, flags=0, txn=None) : + key = bytes(key, "iso8859-1") + if value is not None : + value = bytes(value, "iso8859-1") + return self._db.put(key, value, flags=flags, txn=txn) + + def put_bytes(self, key, value, txn=None) : + key = bytes(key, "iso8859-1") + return self._db.put(key, value, txn=txn) + + def get(self, key, txn=None, flags=0) : + key = bytes(key, "iso8859-1") + v = self._db.get(key, txn=txn, flags=flags) + if v is not None : + v = v.decode("iso8859-1") + return v + + def get_bytes(self, key, txn=None, flags=0) : + key = bytes(key, "iso8859-1") + return self._db.get(key, txn=txn, flags=flags) + + def delete(self, key, txn=None) : + key = bytes(key, "iso8859-1") + return self._db.delete(key, txn=txn) + + def close (self) : + return self._db.close() + + self.db = db_py3k(self.db) + else : # Python 2.x + pass + + # Initialize the table names list if this is a new database + txn = self.env.txn_begin() + try: + if not getattr(self.db, "has_key")(_table_names_key, txn): + getattr(self.db, "put_bytes", self.db.put) \ + (_table_names_key, pickle.dumps([], 1), txn=txn) + # Yes, bare except + except: + txn.abort() + raise + else: + txn.commit() + # TODO verify more of the database's metadata? + self.__tablecolumns = {} + + def __del__(self): + self.close() + + def close(self): + if self.db is not None: + self.db.close() + self.db = None + if self.env is not None: + self.env.close() + self.env = None + + def checkpoint(self, mins=0): + self.env.txn_checkpoint(mins) + + def sync(self): + self.db.sync() + + def _db_print(self) : + """Print the database to stdout for debugging""" + print "******** Printing raw database for debugging ********" + cur = self.db.cursor() + try: + key, data = cur.first() + while 1: + print repr({key: data}) + next = cur.next() + if next: + key, data = next + else: + cur.close() + return + except db.DBNotFoundError: + cur.close() + + + def CreateTable(self, table, columns): + """CreateTable(table, columns) - Create a new table in the database. + + raises TableDBError if it already exists or for other DB errors. + """ + assert isinstance(columns, list) + + txn = None + try: + # checking sanity of the table and column names here on + # table creation will prevent problems elsewhere. + if contains_metastrings(table): + raise ValueError( + "bad table name: contains reserved metastrings") + for column in columns : + if contains_metastrings(column): + raise ValueError( + "bad column name: contains reserved metastrings") + + columnlist_key = _columns_key(table) + if getattr(self.db, "has_key")(columnlist_key): + raise TableAlreadyExists, "table already exists" + + txn = self.env.txn_begin() + # store the table's column info + getattr(self.db, "put_bytes", self.db.put)(columnlist_key, + pickle.dumps(columns, 1), txn=txn) + + # add the table name to the tablelist + tablelist = pickle.loads(getattr(self.db, "get_bytes", + self.db.get) (_table_names_key, txn=txn, flags=db.DB_RMW)) + tablelist.append(table) + # delete 1st, in case we opened with DB_DUP + self.db.delete(_table_names_key, txn=txn) + getattr(self.db, "put_bytes", self.db.put)(_table_names_key, + pickle.dumps(tablelist, 1), txn=txn) + + txn.commit() + txn = None + except db.DBError, dberror: + if txn: + txn.abort() + if sys.version_info < (2, 6) : + raise TableDBError, dberror[1] + else : + raise TableDBError, dberror.args[1] + + + def ListTableColumns(self, table): + """Return a list of columns in the given table. + [] if the table doesn't exist. + """ + assert isinstance(table, str) + if contains_metastrings(table): + raise ValueError, "bad table name: contains reserved metastrings" + + columnlist_key = _columns_key(table) + if not getattr(self.db, "has_key")(columnlist_key): + return [] + pickledcolumnlist = getattr(self.db, "get_bytes", + self.db.get)(columnlist_key) + if pickledcolumnlist: + return pickle.loads(pickledcolumnlist) + else: + return [] + + def ListTables(self): + """Return a list of tables in this database.""" + pickledtablelist = self.db.get_get(_table_names_key) + if pickledtablelist: + return pickle.loads(pickledtablelist) + else: + return [] + + def CreateOrExtendTable(self, table, columns): + """CreateOrExtendTable(table, columns) + + Create a new table in the database. + + If a table of this name already exists, extend it to have any + additional columns present in the given list as well as + all of its current columns. + """ + assert isinstance(columns, list) + + try: + self.CreateTable(table, columns) + except TableAlreadyExists: + # the table already existed, add any new columns + txn = None + try: + columnlist_key = _columns_key(table) + txn = self.env.txn_begin() + + # load the current column list + oldcolumnlist = pickle.loads( + getattr(self.db, "get_bytes", + self.db.get)(columnlist_key, txn=txn, flags=db.DB_RMW)) + # create a hash table for fast lookups of column names in the + # loop below + oldcolumnhash = {} + for c in oldcolumnlist: + oldcolumnhash[c] = c + + # create a new column list containing both the old and new + # column names + newcolumnlist = copy.copy(oldcolumnlist) + for c in columns: + if not c in oldcolumnhash: + newcolumnlist.append(c) + + # store the table's new extended column list + if newcolumnlist != oldcolumnlist : + # delete the old one first since we opened with DB_DUP + self.db.delete(columnlist_key, txn=txn) + getattr(self.db, "put_bytes", self.db.put)(columnlist_key, + pickle.dumps(newcolumnlist, 1), + txn=txn) + + txn.commit() + txn = None + + self.__load_column_info(table) + except db.DBError, dberror: + if txn: + txn.abort() + if sys.version_info < (2, 6) : + raise TableDBError, dberror[1] + else : + raise TableDBError, dberror.args[1] + + + def __load_column_info(self, table) : + """initialize the self.__tablecolumns dict""" + # check the column names + try: + tcolpickles = getattr(self.db, "get_bytes", + self.db.get)(_columns_key(table)) + except db.DBNotFoundError: + raise TableDBError, "unknown table: %r" % (table,) + if not tcolpickles: + raise TableDBError, "unknown table: %r" % (table,) + self.__tablecolumns[table] = pickle.loads(tcolpickles) + + def __new_rowid(self, table, txn) : + """Create a new unique row identifier""" + unique = 0 + while not unique: + # Generate a random 64-bit row ID string + # (note: might have <64 bits of true randomness + # but it's plenty for our database id needs!) + blist = [] + for x in xrange(_rowid_str_len): + blist.append(random.randint(0,255)) + newid = struct.pack('B'*_rowid_str_len, *blist) + + if sys.version_info[0] >= 3 : + newid = newid.decode("iso8859-1") # 8 bits + + # Guarantee uniqueness by adding this key to the database + try: + self.db.put(_rowid_key(table, newid), None, txn=txn, + flags=db.DB_NOOVERWRITE) + except db.DBKeyExistError: + pass + else: + unique = 1 + + return newid + + + def Insert(self, table, rowdict) : + """Insert(table, datadict) - Insert a new row into the table + using the keys+values from rowdict as the column values. + """ + + txn = None + try: + if not getattr(self.db, "has_key")(_columns_key(table)): + raise TableDBError, "unknown table" + + # check the validity of each column name + if not table in self.__tablecolumns: + self.__load_column_info(table) + for column in rowdict.keys() : + if not self.__tablecolumns[table].count(column): + raise TableDBError, "unknown column: %r" % (column,) + + # get a unique row identifier for this row + txn = self.env.txn_begin() + rowid = self.__new_rowid(table, txn=txn) + + # insert the row values into the table database + for column, dataitem in rowdict.items(): + # store the value + self.db.put(_data_key(table, column, rowid), dataitem, txn=txn) + + txn.commit() + txn = None + + except db.DBError, dberror: + # WIBNI we could just abort the txn and re-raise the exception? + # But no, because TableDBError is not related to DBError via + # inheritance, so it would be backwards incompatible. Do the next + # best thing. + info = sys.exc_info() + if txn: + txn.abort() + self.db.delete(_rowid_key(table, rowid)) + if sys.version_info < (2, 6) : + raise TableDBError, dberror[1], info[2] + else : + raise TableDBError, dberror.args[1], info[2] + + + def Modify(self, table, conditions={}, mappings={}): + """Modify(table, conditions={}, mappings={}) - Modify items in rows matching 'conditions' using mapping functions in 'mappings' + + * table - the table name + * conditions - a dictionary keyed on column names containing + a condition callable expecting the data string as an + argument and returning a boolean. + * mappings - a dictionary keyed on column names containing a + condition callable expecting the data string as an argument and + returning the new string for that column. + """ + + try: + matching_rowids = self.__Select(table, [], conditions) + + # modify only requested columns + columns = mappings.keys() + for rowid in matching_rowids.keys(): + txn = None + try: + for column in columns: + txn = self.env.txn_begin() + # modify the requested column + try: + dataitem = self.db.get( + _data_key(table, column, rowid), + txn=txn) + self.db.delete( + _data_key(table, column, rowid), + txn=txn) + except db.DBNotFoundError: + # XXXXXXX row key somehow didn't exist, assume no + # error + dataitem = None + dataitem = mappings[column](dataitem) + if dataitem is not None: + self.db.put( + _data_key(table, column, rowid), + dataitem, txn=txn) + txn.commit() + txn = None + + # catch all exceptions here since we call unknown callables + except: + if txn: + txn.abort() + raise + + except db.DBError, dberror: + if sys.version_info < (2, 6) : + raise TableDBError, dberror[1] + else : + raise TableDBError, dberror.args[1] + + def Delete(self, table, conditions={}): + """Delete(table, conditions) - Delete items matching the given + conditions from the table. + + * conditions - a dictionary keyed on column names containing + condition functions expecting the data string as an + argument and returning a boolean. + """ + + try: + matching_rowids = self.__Select(table, [], conditions) + + # delete row data from all columns + columns = self.__tablecolumns[table] + for rowid in matching_rowids.keys(): + txn = None + try: + txn = self.env.txn_begin() + for column in columns: + # delete the data key + try: + self.db.delete(_data_key(table, column, rowid), + txn=txn) + except db.DBNotFoundError: + # XXXXXXX column may not exist, assume no error + pass + + try: + self.db.delete(_rowid_key(table, rowid), txn=txn) + except db.DBNotFoundError: + # XXXXXXX row key somehow didn't exist, assume no error + pass + txn.commit() + txn = None + except db.DBError, dberror: + if txn: + txn.abort() + raise + except db.DBError, dberror: + if sys.version_info < (2, 6) : + raise TableDBError, dberror[1] + else : + raise TableDBError, dberror.args[1] + + + def Select(self, table, columns, conditions={}): + """Select(table, columns, conditions) - retrieve specific row data + Returns a list of row column->value mapping dictionaries. + + * columns - a list of which column data to return. If + columns is None, all columns will be returned. + * conditions - a dictionary keyed on column names + containing callable conditions expecting the data string as an + argument and returning a boolean. + """ + try: + if not table in self.__tablecolumns: + self.__load_column_info(table) + if columns is None: + columns = self.__tablecolumns[table] + matching_rowids = self.__Select(table, columns, conditions) + except db.DBError, dberror: + if sys.version_info < (2, 6) : + raise TableDBError, dberror[1] + else : + raise TableDBError, dberror.args[1] + # return the matches as a list of dictionaries + return matching_rowids.values() + + + def __Select(self, table, columns, conditions): + """__Select() - Used to implement Select and Delete (above) + Returns a dictionary keyed on rowids containing dicts + holding the row data for columns listed in the columns param + that match the given conditions. + * conditions is a dictionary keyed on column names + containing callable conditions expecting the data string as an + argument and returning a boolean. + """ + # check the validity of each column name + if not table in self.__tablecolumns: + self.__load_column_info(table) + if columns is None: + columns = self.tablecolumns[table] + for column in (columns + conditions.keys()): + if not self.__tablecolumns[table].count(column): + raise TableDBError, "unknown column: %r" % (column,) + + # keyed on rows that match so far, containings dicts keyed on + # column names containing the data for that row and column. + matching_rowids = {} + # keys are rowids that do not match + rejected_rowids = {} + + # attempt to sort the conditions in such a way as to minimize full + # column lookups + def cmp_conditions(atuple, btuple): + a = atuple[1] + b = btuple[1] + if type(a) is type(b): + + # Needed for python 3. "cmp" vanished in 3.0.1 + def cmp(a, b) : + if a==b : return 0 + if a 0: + for rowid, rowdata in matching_rowids.items(): + for column in columns: + if column in rowdata: + continue + try: + rowdata[column] = self.db.get( + _data_key(table, column, rowid)) + except db.DBError, dberror: + if sys.version_info < (2, 6) : + if dberror[0] != db.DB_NOTFOUND: + raise + else : + if dberror.args[0] != db.DB_NOTFOUND: + raise + rowdata[column] = None + + # return the matches + return matching_rowids + + + def Drop(self, table): + """Remove an entire table from the database""" + txn = None + try: + txn = self.env.txn_begin() + + # delete the column list + self.db.delete(_columns_key(table), txn=txn) + + cur = self.db.cursor(txn) + + # delete all keys containing this tables column and row info + table_key = _search_all_data_key(table) + while 1: + try: + key, data = cur.set_range(table_key) + except db.DBNotFoundError: + break + # only delete items in this table + if key[:len(table_key)] != table_key: + break + cur.delete() + + # delete all rowids used by this table + table_key = _search_rowid_key(table) + while 1: + try: + key, data = cur.set_range(table_key) + except db.DBNotFoundError: + break + # only delete items in this table + if key[:len(table_key)] != table_key: + break + cur.delete() + + cur.close() + + # delete the tablename from the table name list + tablelist = pickle.loads( + getattr(self.db, "get_bytes", self.db.get)(_table_names_key, + txn=txn, flags=db.DB_RMW)) + try: + tablelist.remove(table) + except ValueError: + # hmm, it wasn't there, oh well, that's what we want. + pass + # delete 1st, incase we opened with DB_DUP + self.db.delete(_table_names_key, txn=txn) + getattr(self.db, "put_bytes", self.db.put)(_table_names_key, + pickle.dumps(tablelist, 1), txn=txn) + + txn.commit() + txn = None + + if table in self.__tablecolumns: + del self.__tablecolumns[table] + + except db.DBError, dberror: + if txn: + txn.abort() + raise TableDBError(dberror.args[1]) diff --git a/PythonHome/Lib/bsddb/dbtables.pyc b/PythonHome/Lib/bsddb/dbtables.pyc deleted file mode 100644 index 89df2e01f359c9801f5fbef07f4f81c5cc4544fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23627 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 +# +# Note: I don't know how useful this is in reality since when a +# DBLockDeadlockError happens the current transaction is supposed to be +# aborted. If it doesn't then when the operation is attempted again +# the deadlock is still happening... +# --Robin +# +#------------------------------------------------------------------------ + + +# +# import the time.sleep function in a namespace safe way to allow +# "from bsddb.dbutils import *" +# +from time import sleep as _sleep + +import sys +absolute_import = (sys.version_info[0] >= 3) +if absolute_import : + # Because this syntaxis is not valid before Python 2.5 + exec("from . import db") +else : + import db + +# always sleep at least N seconds between retrys +_deadlock_MinSleepTime = 1.0/128 +# never sleep more than N seconds between retrys +_deadlock_MaxSleepTime = 3.14159 + +# Assign a file object to this for a "sleeping" message to be written to it +# each retry +_deadlock_VerboseFile = None + + +def DeadlockWrap(function, *_args, **_kwargs): + """DeadlockWrap(function, *_args, **_kwargs) - automatically retries + function in case of a database deadlock. + + This is a function intended to be used to wrap database calls such + that they perform retrys with exponentially backing off sleeps in + between when a DBLockDeadlockError exception is raised. + + A 'max_retries' parameter may optionally be passed to prevent it + from retrying forever (in which case the exception will be reraised). + + d = DB(...) + d.open(...) + DeadlockWrap(d.put, "foo", data="bar") # set key "foo" to "bar" + """ + sleeptime = _deadlock_MinSleepTime + max_retries = _kwargs.get('max_retries', -1) + if 'max_retries' in _kwargs: + del _kwargs['max_retries'] + while True: + try: + return function(*_args, **_kwargs) + except db.DBLockDeadlockError: + if _deadlock_VerboseFile: + _deadlock_VerboseFile.write( + 'dbutils.DeadlockWrap: sleeping %1.3f\n' % sleeptime) + _sleep(sleeptime) + # exponential backoff in the sleep time + sleeptime *= 2 + if sleeptime > _deadlock_MaxSleepTime: + sleeptime = _deadlock_MaxSleepTime + max_retries -= 1 + if max_retries == -1: + raise + + +#------------------------------------------------------------------------ diff --git a/PythonHome/Lib/bsddb/dbutils.pyc b/PythonHome/Lib/bsddb/dbutils.pyc deleted file mode 100644 index 3a72bd7fc54b273e2d76c377b6c5e4cab72cd901..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1597 zcmaJ>&u<$=6n?X7JMqTQv{fsiUWP!`O%)bZTmTUoP~lX9WCv1Nk<9Gw*q(U3vz?j6 zv6M=PB92J>1N;%(slE?SegH)X!w_T$=Pk%Xcr9}BD8goU(Tt6r^MtE; zrH$ixI-zNRmk-r9SWU|B@4Wou_3lwdUdRcR&#~Cw&^Ul+AzTJ<&WIfbejdOxq{3)$ z)&Y}H1G|SMz{QW?0x-YA@;Y1sT>3>n01Qr_K7f|dm`ThyZtRw&qe1R(^s4YL-QpQwQ&xbPBzwBcRELoLLE!C%0)08d{4Mtp+h6r~)* zTg2yK0PskPywKU~)QBn`*Jb9EE)V$qkuVdB_5IOoLCt;s78kYCbKz7biekx)bVf-V zas1XBxhi=ktmJyk1ODfRMIkR4{2%nLb)lI7nLq$>68bXifpFJ3E~=ae<=_^>Aj@VEu<{@ zVv0uaM;|{%HP)(pVvIKEDw7rILZFRM2yVsXBYtl#E=DUU?(s?(F_%snJ{L=_{iY_q z#5ucSRT=p;BIC+6;?aF17fV8jL~z#d7^PfHRW@w|MV=ct7OE&nCnFm;`zt(j7CApe z7IBg!``*1DOLQg6e~zs=`jgL-s&)r_Z>;s+fmi%+FBN8QpYu1km5$F)WoWRGl>^G) z6NREu{!XNGEv!#WEithuio1!`f1H}Th2vMQzLX}_R(`4q>0gG0QBJxJt?~Ea-;u?| z-;rZ_05HYyOV`7x zO_|=tzI_u7Th$FN&k6w5#u>B)#m?dhd9l zEZ*OdD#zMg!wHdEUDQsFnpdz-6#FD-pI%Y#?ikajPxSh<;fjfG{U04t>Vvt?>q35b Y2ix`rn%$tsZn93W6ZFC;=(IZFUwp!oH~;_u diff --git a/PythonHome/Lib/cProfile.py b/PythonHome/Lib/cProfile.py new file mode 100644 index 0000000000..b2efd047d3 --- /dev/null +++ b/PythonHome/Lib/cProfile.py @@ -0,0 +1,199 @@ +#! /usr/bin/env python + +"""Python interface for the 'lsprof' profiler. + Compatible with the 'profile' module. +""" + +__all__ = ["run", "runctx", "help", "Profile"] + +import _lsprof + +# ____________________________________________________________ +# Simple interface + +def run(statement, filename=None, sort=-1): + """Run statement under profiler optionally saving results in filename + + This function takes a single argument that can be passed to the + "exec" statement, and an optional file name. In all cases this + routine attempts to "exec" its first argument and gather profiling + statistics from the execution. If no file name is present, then this + function automatically prints a simple profiling report, sorted by the + standard name string (file/line/function-name) that is presented in + each line. + """ + prof = Profile() + result = None + try: + try: + prof = prof.run(statement) + except SystemExit: + pass + finally: + if filename is not None: + prof.dump_stats(filename) + else: + result = prof.print_stats(sort) + return result + +def runctx(statement, globals, locals, filename=None, sort=-1): + """Run statement under profiler, supplying your own globals and locals, + optionally saving results in filename. + + statement and filename have the same semantics as profile.run + """ + prof = Profile() + result = None + try: + try: + prof = prof.runctx(statement, globals, locals) + except SystemExit: + pass + finally: + if filename is not None: + prof.dump_stats(filename) + else: + result = prof.print_stats(sort) + return result + +# Backwards compatibility. +def help(): + print "Documentation for the profile/cProfile modules can be found " + print "in the Python Library Reference, section 'The Python Profiler'." + +# ____________________________________________________________ + +class Profile(_lsprof.Profiler): + """Profile(custom_timer=None, time_unit=None, subcalls=True, builtins=True) + + Builds a profiler object using the specified timer function. + The default timer is a fast built-in one based on real time. + For custom timer functions returning integers, time_unit can + be a float specifying a scale (i.e. how long each integer unit + is, in seconds). + """ + + # Most of the functionality is in the base class. + # This subclass only adds convenient and backward-compatible methods. + + def print_stats(self, sort=-1): + import pstats + pstats.Stats(self).strip_dirs().sort_stats(sort).print_stats() + + def dump_stats(self, file): + import marshal + f = open(file, 'wb') + self.create_stats() + marshal.dump(self.stats, f) + f.close() + + def create_stats(self): + self.disable() + self.snapshot_stats() + + def snapshot_stats(self): + entries = self.getstats() + self.stats = {} + callersdicts = {} + # call information + for entry in entries: + func = label(entry.code) + nc = entry.callcount # ncalls column of pstats (before '/') + cc = nc - entry.reccallcount # ncalls column of pstats (after '/') + tt = entry.inlinetime # tottime column of pstats + ct = entry.totaltime # cumtime column of pstats + callers = {} + callersdicts[id(entry.code)] = callers + self.stats[func] = cc, nc, tt, ct, callers + # subcall information + for entry in entries: + if entry.calls: + func = label(entry.code) + for subentry in entry.calls: + try: + callers = callersdicts[id(subentry.code)] + except KeyError: + continue + nc = subentry.callcount + cc = nc - subentry.reccallcount + tt = subentry.inlinetime + ct = subentry.totaltime + if func in callers: + prev = callers[func] + nc += prev[0] + cc += prev[1] + tt += prev[2] + ct += prev[3] + callers[func] = nc, cc, tt, ct + + # The following two methods can be called by clients to use + # a profiler to profile a statement, given as a string. + + def run(self, cmd): + import __main__ + dict = __main__.__dict__ + return self.runctx(cmd, dict, dict) + + def runctx(self, cmd, globals, locals): + self.enable() + try: + exec cmd in globals, locals + finally: + self.disable() + return self + + # This method is more useful to profile a single function call. + def runcall(self, func, *args, **kw): + self.enable() + try: + return func(*args, **kw) + finally: + self.disable() + +# ____________________________________________________________ + +def label(code): + if isinstance(code, str): + return ('~', 0, code) # built-in functions ('~' sorts at the end) + else: + return (code.co_filename, code.co_firstlineno, code.co_name) + +# ____________________________________________________________ + +def main(): + import os, sys + from optparse import OptionParser + usage = "cProfile.py [-o output_file_path] [-s sort] scriptfile [arg] ..." + parser = OptionParser(usage=usage) + parser.allow_interspersed_args = False + parser.add_option('-o', '--outfile', dest="outfile", + help="Save stats to ", default=None) + parser.add_option('-s', '--sort', dest="sort", + help="Sort order when printing to stdout, based on pstats.Stats class", + default=-1) + + if not sys.argv[1:]: + parser.print_usage() + sys.exit(2) + + (options, args) = parser.parse_args() + sys.argv[:] = args + + if len(args) > 0: + progname = args[0] + sys.path.insert(0, os.path.dirname(progname)) + with open(progname, 'rb') as fp: + code = compile(fp.read(), progname, 'exec') + globs = { + '__file__': progname, + '__name__': '__main__', + '__package__': None, + } + runctx(code, globs, None, options.outfile, options.sort) + else: + parser.print_usage() + return parser + +# When invoked as main program, invoke the profiler on a script +if __name__ == '__main__': + main() diff --git a/PythonHome/Lib/cProfile.pyc b/PythonHome/Lib/cProfile.pyc deleted file mode 100644 index 13267b5defdf1e068b8b99c96f8be3265dbb36e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6098 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 O8*2}nv(0bLd;bBrA|=NF diff --git a/PythonHome/Lib/calendar.py b/PythonHome/Lib/calendar.py new file mode 100644 index 0000000000..d3bd2362e9 --- /dev/null +++ b/PythonHome/Lib/calendar.py @@ -0,0 +1,713 @@ +"""Calendar printing functions + +Note when comparing these calendars to the ones printed by cal(1): By +default, these calendars have Monday as the first day of the week, and +Sunday as the last (the European convention). Use setfirstweekday() to +set the first day of the week (0=Monday, 6=Sunday).""" + +import sys +import datetime +import locale as _locale + +__all__ = ["IllegalMonthError", "IllegalWeekdayError", "setfirstweekday", + "firstweekday", "isleap", "leapdays", "weekday", "monthrange", + "monthcalendar", "prmonth", "month", "prcal", "calendar", + "timegm", "month_name", "month_abbr", "day_name", "day_abbr"] + +# Exception raised for bad input (with string parameter for details) +error = ValueError + +# Exceptions raised for bad input +class IllegalMonthError(ValueError): + def __init__(self, month): + self.month = month + def __str__(self): + return "bad month number %r; must be 1-12" % self.month + + +class IllegalWeekdayError(ValueError): + def __init__(self, weekday): + self.weekday = weekday + def __str__(self): + return "bad weekday number %r; must be 0 (Monday) to 6 (Sunday)" % self.weekday + + +# Constants for months referenced later +January = 1 +February = 2 + +# Number of days per month (except for February in leap years) +mdays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] + +# This module used to have hard-coded lists of day and month names, as +# English strings. The classes following emulate a read-only version of +# that, but supply localized names. Note that the values are computed +# fresh on each call, in case the user changes locale between calls. + +class _localized_month: + + _months = [datetime.date(2001, i+1, 1).strftime for i in range(12)] + _months.insert(0, lambda x: "") + + def __init__(self, format): + self.format = format + + def __getitem__(self, i): + funcs = self._months[i] + if isinstance(i, slice): + return [f(self.format) for f in funcs] + else: + return funcs(self.format) + + def __len__(self): + return 13 + + +class _localized_day: + + # January 1, 2001, was a Monday. + _days = [datetime.date(2001, 1, i+1).strftime for i in range(7)] + + def __init__(self, format): + self.format = format + + def __getitem__(self, i): + funcs = self._days[i] + if isinstance(i, slice): + return [f(self.format) for f in funcs] + else: + return funcs(self.format) + + def __len__(self): + return 7 + + +# Full and abbreviated names of weekdays +day_name = _localized_day('%A') +day_abbr = _localized_day('%a') + +# Full and abbreviated names of months (1-based arrays!!!) +month_name = _localized_month('%B') +month_abbr = _localized_month('%b') + +# Constants for weekdays +(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY) = range(7) + + +def isleap(year): + """Return True for leap years, False for non-leap years.""" + return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) + + +def leapdays(y1, y2): + """Return number of leap years in range [y1, y2). + Assume y1 <= y2.""" + y1 -= 1 + y2 -= 1 + return (y2//4 - y1//4) - (y2//100 - y1//100) + (y2//400 - y1//400) + + +def weekday(year, month, day): + """Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12), + day (1-31).""" + return datetime.date(year, month, day).weekday() + + +def monthrange(year, month): + """Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for + year, month.""" + if not 1 <= month <= 12: + raise IllegalMonthError(month) + day1 = weekday(year, month, 1) + ndays = mdays[month] + (month == February and isleap(year)) + return day1, ndays + + +class Calendar(object): + """ + Base calendar class. This class doesn't do any formatting. It simply + provides data to subclasses. + """ + + def __init__(self, firstweekday=0): + self.firstweekday = firstweekday # 0 = Monday, 6 = Sunday + + def getfirstweekday(self): + return self._firstweekday % 7 + + def setfirstweekday(self, firstweekday): + self._firstweekday = firstweekday + + firstweekday = property(getfirstweekday, setfirstweekday) + + def iterweekdays(self): + """ + Return a iterator for one week of weekday numbers starting with the + configured first one. + """ + for i in range(self.firstweekday, self.firstweekday + 7): + yield i%7 + + def itermonthdates(self, year, month): + """ + Return an iterator for one month. The iterator will yield datetime.date + values and will always iterate through complete weeks, so it will yield + dates outside the specified month. + """ + date = datetime.date(year, month, 1) + # Go back to the beginning of the week + days = (date.weekday() - self.firstweekday) % 7 + date -= datetime.timedelta(days=days) + oneday = datetime.timedelta(days=1) + while True: + yield date + try: + date += oneday + except OverflowError: + # Adding one day could fail after datetime.MAXYEAR + break + if date.month != month and date.weekday() == self.firstweekday: + break + + def itermonthdays2(self, year, month): + """ + Like itermonthdates(), but will yield (day number, weekday number) + tuples. For days outside the specified month the day number is 0. + """ + for date in self.itermonthdates(year, month): + if date.month != month: + yield (0, date.weekday()) + else: + yield (date.day, date.weekday()) + + def itermonthdays(self, year, month): + """ + Like itermonthdates(), but will yield day numbers. For days outside + the specified month the day number is 0. + """ + for date in self.itermonthdates(year, month): + if date.month != month: + yield 0 + else: + yield date.day + + def monthdatescalendar(self, year, month): + """ + Return a matrix (list of lists) representing a month's calendar. + Each row represents a week; week entries are datetime.date values. + """ + dates = list(self.itermonthdates(year, month)) + return [ dates[i:i+7] for i in range(0, len(dates), 7) ] + + def monthdays2calendar(self, year, month): + """ + Return a matrix representing a month's calendar. + Each row represents a week; week entries are + (day number, weekday number) tuples. Day numbers outside this month + are zero. + """ + days = list(self.itermonthdays2(year, month)) + return [ days[i:i+7] for i in range(0, len(days), 7) ] + + def monthdayscalendar(self, year, month): + """ + Return a matrix representing a month's calendar. + Each row represents a week; days outside this month are zero. + """ + days = list(self.itermonthdays(year, month)) + return [ days[i:i+7] for i in range(0, len(days), 7) ] + + def yeardatescalendar(self, year, width=3): + """ + Return the data for the specified year ready for formatting. The return + value is a list of month rows. Each month row contains up to width months. + Each month contains between 4 and 6 weeks and each week contains 1-7 + days. Days are datetime.date objects. + """ + months = [ + self.monthdatescalendar(year, i) + for i in range(January, January+12) + ] + return [months[i:i+width] for i in range(0, len(months), width) ] + + def yeardays2calendar(self, year, width=3): + """ + Return the data for the specified year ready for formatting (similar to + yeardatescalendar()). Entries in the week lists are + (day number, weekday number) tuples. Day numbers outside this month are + zero. + """ + months = [ + self.monthdays2calendar(year, i) + for i in range(January, January+12) + ] + return [months[i:i+width] for i in range(0, len(months), width) ] + + def yeardayscalendar(self, year, width=3): + """ + Return the data for the specified year ready for formatting (similar to + yeardatescalendar()). Entries in the week lists are day numbers. + Day numbers outside this month are zero. + """ + months = [ + self.monthdayscalendar(year, i) + for i in range(January, January+12) + ] + return [months[i:i+width] for i in range(0, len(months), width) ] + + +class TextCalendar(Calendar): + """ + Subclass of Calendar that outputs a calendar as a simple plain text + similar to the UNIX program cal. + """ + + def prweek(self, theweek, width): + """ + Print a single week (no newline). + """ + print self.formatweek(theweek, width), + + def formatday(self, day, weekday, width): + """ + Returns a formatted day. + """ + if day == 0: + s = '' + else: + s = '%2i' % day # right-align single-digit days + return s.center(width) + + def formatweek(self, theweek, width): + """ + Returns a single week in a string (no newline). + """ + return ' '.join(self.formatday(d, wd, width) for (d, wd) in theweek) + + def formatweekday(self, day, width): + """ + Returns a formatted week day name. + """ + if width >= 9: + names = day_name + else: + names = day_abbr + return names[day][:width].center(width) + + def formatweekheader(self, width): + """ + Return a header for a week. + """ + return ' '.join(self.formatweekday(i, width) for i in self.iterweekdays()) + + def formatmonthname(self, theyear, themonth, width, withyear=True): + """ + Return a formatted month name. + """ + s = month_name[themonth] + if withyear: + s = "%s %r" % (s, theyear) + return s.center(width) + + def prmonth(self, theyear, themonth, w=0, l=0): + """ + Print a month's calendar. + """ + print self.formatmonth(theyear, themonth, w, l), + + def formatmonth(self, theyear, themonth, w=0, l=0): + """ + Return a month's calendar string (multi-line). + """ + w = max(2, w) + l = max(1, l) + s = self.formatmonthname(theyear, themonth, 7 * (w + 1) - 1) + s = s.rstrip() + s += '\n' * l + s += self.formatweekheader(w).rstrip() + s += '\n' * l + for week in self.monthdays2calendar(theyear, themonth): + s += self.formatweek(week, w).rstrip() + s += '\n' * l + return s + + def formatyear(self, theyear, w=2, l=1, c=6, m=3): + """ + Returns a year's calendar as a multi-line string. + """ + w = max(2, w) + l = max(1, l) + c = max(2, c) + colwidth = (w + 1) * 7 - 1 + v = [] + a = v.append + a(repr(theyear).center(colwidth*m+c*(m-1)).rstrip()) + a('\n'*l) + header = self.formatweekheader(w) + for (i, row) in enumerate(self.yeardays2calendar(theyear, m)): + # months in this row + months = range(m*i+1, min(m*(i+1)+1, 13)) + a('\n'*l) + names = (self.formatmonthname(theyear, k, colwidth, False) + for k in months) + a(formatstring(names, colwidth, c).rstrip()) + a('\n'*l) + headers = (header for k in months) + a(formatstring(headers, colwidth, c).rstrip()) + a('\n'*l) + # max number of weeks for this row + height = max(len(cal) for cal in row) + for j in range(height): + weeks = [] + for cal in row: + if j >= len(cal): + weeks.append('') + else: + weeks.append(self.formatweek(cal[j], w)) + a(formatstring(weeks, colwidth, c).rstrip()) + a('\n' * l) + return ''.join(v) + + def pryear(self, theyear, w=0, l=0, c=6, m=3): + """Print a year's calendar.""" + print self.formatyear(theyear, w, l, c, m) + + +class HTMLCalendar(Calendar): + """ + This calendar returns complete HTML pages. + """ + + # CSS classes for the day s + cssclasses = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"] + + def formatday(self, day, weekday): + """ + Return a day as a table cell. + """ + if day == 0: + return ' ' # day outside month + else: + return '%d' % (self.cssclasses[weekday], day) + + def formatweek(self, theweek): + """ + Return a complete week as a table row. + """ + s = ''.join(self.formatday(d, wd) for (d, wd) in theweek) + return '%s' % s + + def formatweekday(self, day): + """ + Return a weekday name as a table header. + """ + return '%s' % (self.cssclasses[day], day_abbr[day]) + + def formatweekheader(self): + """ + Return a header for a week as a table row. + """ + s = ''.join(self.formatweekday(i) for i in self.iterweekdays()) + return '%s' % s + + def formatmonthname(self, theyear, themonth, withyear=True): + """ + Return a month name as a table row. + """ + if withyear: + s = '%s %s' % (month_name[themonth], theyear) + else: + s = '%s' % month_name[themonth] + return '%s' % s + + def formatmonth(self, theyear, themonth, withyear=True): + """ + Return a formatted month as a table. + """ + v = [] + a = v.append + a('') + a('\n') + a(self.formatmonthname(theyear, themonth, withyear=withyear)) + a('\n') + a(self.formatweekheader()) + a('\n') + for week in self.monthdays2calendar(theyear, themonth): + a(self.formatweek(week)) + a('\n') + a('
') + a('\n') + return ''.join(v) + + def formatyear(self, theyear, width=3): + """ + Return a formatted year as a table of tables. + """ + v = [] + a = v.append + width = max(width, 1) + a('') + a('\n') + a('' % (width, theyear)) + for i in range(January, January+12, width): + # months in this row + months = range(i, min(i+width, 13)) + a('') + for m in months: + a('') + a('') + a('
%s
') + a(self.formatmonth(theyear, m, withyear=False)) + a('
') + return ''.join(v) + + def formatyearpage(self, theyear, width=3, css='calendar.css', encoding=None): + """ + Return a formatted year as a complete HTML page. + """ + if encoding is None: + encoding = sys.getdefaultencoding() + v = [] + a = v.append + a('\n' % encoding) + a('\n') + a('\n') + a('\n') + a('\n' % encoding) + if css is not None: + a('\n' % css) + a('Calendar for %d\n' % theyear) + a('\n') + a('\n') + a(self.formatyear(theyear, width)) + a('\n') + a('\n') + return ''.join(v).encode(encoding, "xmlcharrefreplace") + + +class TimeEncoding: + def __init__(self, locale): + self.locale = locale + + def __enter__(self): + self.oldlocale = _locale.getlocale(_locale.LC_TIME) + _locale.setlocale(_locale.LC_TIME, self.locale) + return _locale.getlocale(_locale.LC_TIME)[1] + + def __exit__(self, *args): + _locale.setlocale(_locale.LC_TIME, self.oldlocale) + + +class LocaleTextCalendar(TextCalendar): + """ + This class can be passed a locale name in the constructor and will return + month and weekday names in the specified locale. If this locale includes + an encoding all strings containing month and weekday names will be returned + as unicode. + """ + + def __init__(self, firstweekday=0, locale=None): + TextCalendar.__init__(self, firstweekday) + if locale is None: + locale = _locale.getdefaultlocale() + self.locale = locale + + def formatweekday(self, day, width): + with TimeEncoding(self.locale) as encoding: + if width >= 9: + names = day_name + else: + names = day_abbr + name = names[day] + if encoding is not None: + name = name.decode(encoding) + return name[:width].center(width) + + def formatmonthname(self, theyear, themonth, width, withyear=True): + with TimeEncoding(self.locale) as encoding: + s = month_name[themonth] + if encoding is not None: + s = s.decode(encoding) + if withyear: + s = "%s %r" % (s, theyear) + return s.center(width) + + +class LocaleHTMLCalendar(HTMLCalendar): + """ + This class can be passed a locale name in the constructor and will return + month and weekday names in the specified locale. If this locale includes + an encoding all strings containing month and weekday names will be returned + as unicode. + """ + def __init__(self, firstweekday=0, locale=None): + HTMLCalendar.__init__(self, firstweekday) + if locale is None: + locale = _locale.getdefaultlocale() + self.locale = locale + + def formatweekday(self, day): + with TimeEncoding(self.locale) as encoding: + s = day_abbr[day] + if encoding is not None: + s = s.decode(encoding) + return '%s' % (self.cssclasses[day], s) + + def formatmonthname(self, theyear, themonth, withyear=True): + with TimeEncoding(self.locale) as encoding: + s = month_name[themonth] + if encoding is not None: + s = s.decode(encoding) + if withyear: + s = '%s %s' % (s, theyear) + return '%s' % s + + +# Support for old module level interface +c = TextCalendar() + +firstweekday = c.getfirstweekday + +def setfirstweekday(firstweekday): + try: + firstweekday.__index__ + except AttributeError: + raise IllegalWeekdayError(firstweekday) + if not MONDAY <= firstweekday <= SUNDAY: + raise IllegalWeekdayError(firstweekday) + c.firstweekday = firstweekday + +monthcalendar = c.monthdayscalendar +prweek = c.prweek +week = c.formatweek +weekheader = c.formatweekheader +prmonth = c.prmonth +month = c.formatmonth +calendar = c.formatyear +prcal = c.pryear + + +# Spacing of month columns for multi-column year calendar +_colwidth = 7*3 - 1 # Amount printed by prweek() +_spacing = 6 # Number of spaces between columns + + +def format(cols, colwidth=_colwidth, spacing=_spacing): + """Prints multi-column formatting for year calendars""" + print formatstring(cols, colwidth, spacing) + + +def formatstring(cols, colwidth=_colwidth, spacing=_spacing): + """Returns a string formatted from n strings, centered within n columns.""" + spacing *= ' ' + return spacing.join(c.center(colwidth) for c in cols) + + +EPOCH = 1970 +_EPOCH_ORD = datetime.date(EPOCH, 1, 1).toordinal() + + +def timegm(tuple): + """Unrelated but handy function to calculate Unix timestamp from GMT.""" + year, month, day, hour, minute, second = tuple[:6] + days = datetime.date(year, month, 1).toordinal() - _EPOCH_ORD + day - 1 + hours = days*24 + hour + minutes = hours*60 + minute + seconds = minutes*60 + second + return seconds + + +def main(args): + import optparse + parser = optparse.OptionParser(usage="usage: %prog [options] [year [month]]") + parser.add_option( + "-w", "--width", + dest="width", type="int", default=2, + help="width of date column (default 2, text only)" + ) + parser.add_option( + "-l", "--lines", + dest="lines", type="int", default=1, + help="number of lines for each week (default 1, text only)" + ) + parser.add_option( + "-s", "--spacing", + dest="spacing", type="int", default=6, + help="spacing between months (default 6, text only)" + ) + parser.add_option( + "-m", "--months", + dest="months", type="int", default=3, + help="months per row (default 3, text only)" + ) + parser.add_option( + "-c", "--css", + dest="css", default="calendar.css", + help="CSS to use for page (html only)" + ) + parser.add_option( + "-L", "--locale", + dest="locale", default=None, + help="locale to be used from month and weekday names" + ) + parser.add_option( + "-e", "--encoding", + dest="encoding", default=None, + help="Encoding to use for output" + ) + parser.add_option( + "-t", "--type", + dest="type", default="text", + choices=("text", "html"), + help="output type (text or html)" + ) + + (options, args) = parser.parse_args(args) + + if options.locale and not options.encoding: + parser.error("if --locale is specified --encoding is required") + sys.exit(1) + + locale = options.locale, options.encoding + + if options.type == "html": + if options.locale: + cal = LocaleHTMLCalendar(locale=locale) + else: + cal = HTMLCalendar() + encoding = options.encoding + if encoding is None: + encoding = sys.getdefaultencoding() + optdict = dict(encoding=encoding, css=options.css) + if len(args) == 1: + print cal.formatyearpage(datetime.date.today().year, **optdict) + elif len(args) == 2: + print cal.formatyearpage(int(args[1]), **optdict) + else: + parser.error("incorrect number of arguments") + sys.exit(1) + else: + if options.locale: + cal = LocaleTextCalendar(locale=locale) + else: + cal = TextCalendar() + optdict = dict(w=options.width, l=options.lines) + if len(args) != 3: + optdict["c"] = options.spacing + optdict["m"] = options.months + if len(args) == 1: + result = cal.formatyear(datetime.date.today().year, **optdict) + elif len(args) == 2: + result = cal.formatyear(int(args[1]), **optdict) + elif len(args) == 3: + result = cal.formatmonth(int(args[1]), int(args[2]), **optdict) + else: + parser.error("incorrect number of arguments") + sys.exit(1) + if options.encoding: + result = result.encode(options.encoding) + print result + + +if __name__ == "__main__": + main(sys.argv) diff --git a/PythonHome/Lib/calendar.pyc b/PythonHome/Lib/calendar.pyc index 37fa3745f218e0bbb12c75b99cc8d46d69176199..8b76527156412ffbea273ea25a2b5654849d2063 100644 GIT binary patch delta 4400 zcmbW5-%C?r7{_<2vzgX5UE6A+s7Pei+G50<)NET|&fM7M%sM(8Y;(h!7h5Pqm_Y=c zn|Opo>PEVW3Z$nW7fBK3O%XVXK%t8WvVtIQMXBvic)x$Z=X{>;^SsY{4rls{wDntB zcp^JbYBZXZN6BOhqs62$ke{&kL_>X%uwMxk3**It5=bSB86`Yf7|mbq&RV|F}pj=gF#VJ;+j!EJez27|vP?75I02Qbi2dISBN^3P!;v{GHR3j~! z-uppZMv6WKP%HW|fC?JI(k{AZcqGnp+$bSUN!PB6%SfqflVrYG=Kz$vY+l)Xw8gBmy$oh}CkYvq{MtX77CoUwN{f9WkTXqXprUJ-R zhaQm`EM|J`1YRXPdwdBHa?W*or+7T7%&x_q2Fd5{EJkv$!w96LoM!_N4!2wBdS_0Y zysJREQdccf=Ems^Aj|lg5!p!0%#ZzF0hDLYyh4VT z?0$!AlGA3Up5D9SouR+Ip8@LAxo-fq)HerEW1+Y>#ifuN>Hq$S6__@ay37=f{u8g0 zMq5ETde#ihJDC?mo@7fOKaIluS$4(I#M-zDkFC+Wp= zM}DErW~&Rg#V#1V>49JsEgLHRaa;oaaD4}`O6MbB0k2BB>n8ATuBgbkHODWBFk3*Q zOl~J|Q+#ei2Kdm%L10_+?ud-%^Kx;RDfQ=1ieb`}ZeY)pK44LIOp zTa4CQ)kSnM7=Z^?f%dpueIT!e1*kVYsmBI|R!^Zz0Hf`1(3ANoLp8gFP1f zss$_JWQ_u5nmDuq;hEaYBIDsm1YRxwI$VH8vsOzz9Cezlp9AZc2Di1~KokW0I=TbG z>}>oEko2(1HAly>uoioV?=j)a-dD|VUC?6lN3n4B=&2;f-veKZj{r08(fO8Ik#kdP z2%4E<{%}Huy|CQo0Z0w)r$D>VUS_GK<0s(&@aaSlt(gwAraB!M9POHg@nhW unlimited input +maxlen = 0 + +def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0): + """Parse a query in the environment or from a file (default stdin) + + Arguments, all optional: + + fp : file pointer; default: sys.stdin + + environ : environment dictionary; default: os.environ + + keep_blank_values: flag indicating whether blank values in + percent-encoded forms should be treated as blank strings. + A true value indicates that blanks should be retained as + blank strings. The default false value indicates that + blank values are to be ignored and treated as if they were + not included. + + strict_parsing: flag indicating what to do with parsing errors. + If false (the default), errors are silently ignored. + If true, errors raise a ValueError exception. + """ + if fp is None: + fp = sys.stdin + if not 'REQUEST_METHOD' in environ: + environ['REQUEST_METHOD'] = 'GET' # For testing stand-alone + if environ['REQUEST_METHOD'] == 'POST': + ctype, pdict = parse_header(environ['CONTENT_TYPE']) + if ctype == 'multipart/form-data': + return parse_multipart(fp, pdict) + elif ctype == 'application/x-www-form-urlencoded': + clength = int(environ['CONTENT_LENGTH']) + if maxlen and clength > maxlen: + raise ValueError, 'Maximum content length exceeded' + qs = fp.read(clength) + else: + qs = '' # Unknown content-type + if 'QUERY_STRING' in environ: + if qs: qs = qs + '&' + qs = qs + environ['QUERY_STRING'] + elif sys.argv[1:]: + if qs: qs = qs + '&' + qs = qs + sys.argv[1] + environ['QUERY_STRING'] = qs # XXX Shouldn't, really + elif 'QUERY_STRING' in environ: + qs = environ['QUERY_STRING'] + else: + if sys.argv[1:]: + qs = sys.argv[1] + else: + qs = "" + environ['QUERY_STRING'] = qs # XXX Shouldn't, really + return urlparse.parse_qs(qs, keep_blank_values, strict_parsing) + + +# parse query string function called from urlparse, +# this is done in order to maintain backward compatiblity. + +def parse_qs(qs, keep_blank_values=0, strict_parsing=0): + """Parse a query given as a string argument.""" + warn("cgi.parse_qs is deprecated, use urlparse.parse_qs instead", + PendingDeprecationWarning, 2) + return urlparse.parse_qs(qs, keep_blank_values, strict_parsing) + + +def parse_qsl(qs, keep_blank_values=0, strict_parsing=0): + """Parse a query given as a string argument.""" + warn("cgi.parse_qsl is deprecated, use urlparse.parse_qsl instead", + PendingDeprecationWarning, 2) + return urlparse.parse_qsl(qs, keep_blank_values, strict_parsing) + +def parse_multipart(fp, pdict): + """Parse multipart input. + + Arguments: + fp : input file + pdict: dictionary containing other parameters of content-type header + + Returns a dictionary just like parse_qs(): keys are the field names, each + value is a list of values for that field. This is easy to use but not + much good if you are expecting megabytes to be uploaded -- in that case, + use the FieldStorage class instead which is much more flexible. Note + that content-type is the raw, unparsed contents of the content-type + header. + + XXX This does not parse nested multipart parts -- use FieldStorage for + that. + + XXX This should really be subsumed by FieldStorage altogether -- no + point in having two implementations of the same parsing algorithm. + Also, FieldStorage protects itself better against certain DoS attacks + by limiting the size of the data read in one chunk. The API here + does not support that kind of protection. This also affects parse() + since it can call parse_multipart(). + + """ + boundary = "" + if 'boundary' in pdict: + boundary = pdict['boundary'] + if not valid_boundary(boundary): + raise ValueError, ('Invalid boundary in multipart form: %r' + % (boundary,)) + + nextpart = "--" + boundary + lastpart = "--" + boundary + "--" + partdict = {} + terminator = "" + + while terminator != lastpart: + bytes = -1 + data = None + if terminator: + # At start of next part. Read headers first. + headers = mimetools.Message(fp) + clength = headers.getheader('content-length') + if clength: + try: + bytes = int(clength) + except ValueError: + pass + if bytes > 0: + if maxlen and bytes > maxlen: + raise ValueError, 'Maximum content length exceeded' + data = fp.read(bytes) + else: + data = "" + # Read lines until end of part. + lines = [] + while 1: + line = fp.readline() + if not line: + terminator = lastpart # End outer loop + break + if line[:2] == "--": + terminator = line.strip() + if terminator in (nextpart, lastpart): + break + lines.append(line) + # Done with part. + if data is None: + continue + if bytes < 0: + if lines: + # Strip final line terminator + line = lines[-1] + if line[-2:] == "\r\n": + line = line[:-2] + elif line[-1:] == "\n": + line = line[:-1] + lines[-1] = line + data = "".join(lines) + line = headers['content-disposition'] + if not line: + continue + key, params = parse_header(line) + if key != 'form-data': + continue + if 'name' in params: + name = params['name'] + else: + continue + if name in partdict: + partdict[name].append(data) + else: + partdict[name] = [data] + + return partdict + + +def _parseparam(s): + while s[:1] == ';': + s = s[1:] + end = s.find(';') + while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2: + end = s.find(';', end + 1) + if end < 0: + end = len(s) + f = s[:end] + yield f.strip() + s = s[end:] + +def parse_header(line): + """Parse a Content-type like header. + + Return the main content-type and a dictionary of options. + + """ + parts = _parseparam(';' + line) + key = parts.next() + pdict = {} + for p in parts: + i = p.find('=') + if i >= 0: + name = p[:i].strip().lower() + value = p[i+1:].strip() + if len(value) >= 2 and value[0] == value[-1] == '"': + value = value[1:-1] + value = value.replace('\\\\', '\\').replace('\\"', '"') + pdict[name] = value + return key, pdict + + +# Classes for field storage +# ========================= + +class MiniFieldStorage: + + """Like FieldStorage, for use when no file uploads are possible.""" + + # Dummy attributes + filename = None + list = None + type = None + file = None + type_options = {} + disposition = None + disposition_options = {} + headers = {} + + def __init__(self, name, value): + """Constructor from field name and value.""" + self.name = name + self.value = value + # self.file = StringIO(value) + + def __repr__(self): + """Return printable representation.""" + return "MiniFieldStorage(%r, %r)" % (self.name, self.value) + + +class FieldStorage: + + """Store a sequence of fields, reading multipart/form-data. + + This class provides naming, typing, files stored on disk, and + more. At the top level, it is accessible like a dictionary, whose + keys are the field names. (Note: None can occur as a field name.) + The items are either a Python list (if there's multiple values) or + another FieldStorage or MiniFieldStorage object. If it's a single + object, it has the following attributes: + + name: the field name, if specified; otherwise None + + filename: the filename, if specified; otherwise None; this is the + client side filename, *not* the file name on which it is + stored (that's a temporary file you don't deal with) + + value: the value as a *string*; for file uploads, this + transparently reads the file every time you request the value + + file: the file(-like) object from which you can read the data; + None if the data is stored a simple string + + type: the content-type, or None if not specified + + type_options: dictionary of options specified on the content-type + line + + disposition: content-disposition, or None if not specified + + disposition_options: dictionary of corresponding options + + headers: a dictionary(-like) object (sometimes rfc822.Message or a + subclass thereof) containing *all* headers + + The class is subclassable, mostly for the purpose of overriding + the make_file() method, which is called internally to come up with + a file open for reading and writing. This makes it possible to + override the default choice of storing all files in a temporary + directory and unlinking them as soon as they have been opened. + + """ + + def __init__(self, fp=None, headers=None, outerboundary="", + environ=os.environ, keep_blank_values=0, strict_parsing=0): + """Constructor. Read multipart/* until last part. + + Arguments, all optional: + + fp : file pointer; default: sys.stdin + (not used when the request method is GET) + + headers : header dictionary-like object; default: + taken from environ as per CGI spec + + outerboundary : terminating multipart boundary + (for internal use only) + + environ : environment dictionary; default: os.environ + + keep_blank_values: flag indicating whether blank values in + percent-encoded forms should be treated as blank strings. + A true value indicates that blanks should be retained as + blank strings. The default false value indicates that + blank values are to be ignored and treated as if they were + not included. + + strict_parsing: flag indicating what to do with parsing errors. + If false (the default), errors are silently ignored. + If true, errors raise a ValueError exception. + + """ + method = 'GET' + self.keep_blank_values = keep_blank_values + self.strict_parsing = strict_parsing + if 'REQUEST_METHOD' in environ: + method = environ['REQUEST_METHOD'].upper() + self.qs_on_post = None + if method == 'GET' or method == 'HEAD': + if 'QUERY_STRING' in environ: + qs = environ['QUERY_STRING'] + elif sys.argv[1:]: + qs = sys.argv[1] + else: + qs = "" + fp = StringIO(qs) + if headers is None: + headers = {'content-type': + "application/x-www-form-urlencoded"} + if headers is None: + headers = {} + if method == 'POST': + # Set default content-type for POST to what's traditional + headers['content-type'] = "application/x-www-form-urlencoded" + if 'CONTENT_TYPE' in environ: + headers['content-type'] = environ['CONTENT_TYPE'] + if 'QUERY_STRING' in environ: + self.qs_on_post = environ['QUERY_STRING'] + if 'CONTENT_LENGTH' in environ: + headers['content-length'] = environ['CONTENT_LENGTH'] + self.fp = fp or sys.stdin + self.headers = headers + self.outerboundary = outerboundary + + # Process content-disposition header + cdisp, pdict = "", {} + if 'content-disposition' in self.headers: + cdisp, pdict = parse_header(self.headers['content-disposition']) + self.disposition = cdisp + self.disposition_options = pdict + self.name = None + if 'name' in pdict: + self.name = pdict['name'] + self.filename = None + if 'filename' in pdict: + self.filename = pdict['filename'] + + # Process content-type header + # + # Honor any existing content-type header. But if there is no + # content-type header, use some sensible defaults. Assume + # outerboundary is "" at the outer level, but something non-false + # inside a multi-part. The default for an inner part is text/plain, + # but for an outer part it should be urlencoded. This should catch + # bogus clients which erroneously forget to include a content-type + # header. + # + # See below for what we do if there does exist a content-type header, + # but it happens to be something we don't understand. + if 'content-type' in self.headers: + ctype, pdict = parse_header(self.headers['content-type']) + elif self.outerboundary or method != 'POST': + ctype, pdict = "text/plain", {} + else: + ctype, pdict = 'application/x-www-form-urlencoded', {} + self.type = ctype + self.type_options = pdict + self.innerboundary = "" + if 'boundary' in pdict: + self.innerboundary = pdict['boundary'] + clen = -1 + if 'content-length' in self.headers: + try: + clen = int(self.headers['content-length']) + except ValueError: + pass + if maxlen and clen > maxlen: + raise ValueError, 'Maximum content length exceeded' + self.length = clen + + self.list = self.file = None + self.done = 0 + if ctype == 'application/x-www-form-urlencoded': + self.read_urlencoded() + elif ctype[:10] == 'multipart/': + self.read_multi(environ, keep_blank_values, strict_parsing) + else: + self.read_single() + + def __repr__(self): + """Return a printable representation.""" + return "FieldStorage(%r, %r, %r)" % ( + self.name, self.filename, self.value) + + def __iter__(self): + return iter(self.keys()) + + def __getattr__(self, name): + if name != 'value': + raise AttributeError, name + if self.file: + self.file.seek(0) + value = self.file.read() + self.file.seek(0) + elif self.list is not None: + value = self.list + else: + value = None + return value + + def __getitem__(self, key): + """Dictionary style indexing.""" + if self.list is None: + raise TypeError, "not indexable" + found = [] + for item in self.list: + if item.name == key: found.append(item) + if not found: + raise KeyError, key + if len(found) == 1: + return found[0] + else: + return found + + def getvalue(self, key, default=None): + """Dictionary style get() method, including 'value' lookup.""" + if key in self: + value = self[key] + if type(value) is type([]): + return map(attrgetter('value'), value) + else: + return value.value + else: + return default + + def getfirst(self, key, default=None): + """ Return the first value received.""" + if key in self: + value = self[key] + if type(value) is type([]): + return value[0].value + else: + return value.value + else: + return default + + def getlist(self, key): + """ Return list of received values.""" + if key in self: + value = self[key] + if type(value) is type([]): + return map(attrgetter('value'), value) + else: + return [value.value] + else: + return [] + + def keys(self): + """Dictionary style keys() method.""" + if self.list is None: + raise TypeError, "not indexable" + return list(set(item.name for item in self.list)) + + def has_key(self, key): + """Dictionary style has_key() method.""" + if self.list is None: + raise TypeError, "not indexable" + return any(item.name == key for item in self.list) + + def __contains__(self, key): + """Dictionary style __contains__ method.""" + if self.list is None: + raise TypeError, "not indexable" + return any(item.name == key for item in self.list) + + def __len__(self): + """Dictionary style len(x) support.""" + return len(self.keys()) + + def __nonzero__(self): + return bool(self.list) + + def read_urlencoded(self): + """Internal: read data in query string format.""" + qs = self.fp.read(self.length) + if self.qs_on_post: + qs += '&' + self.qs_on_post + self.list = list = [] + for key, value in urlparse.parse_qsl(qs, self.keep_blank_values, + self.strict_parsing): + list.append(MiniFieldStorage(key, value)) + self.skip_lines() + + FieldStorageClass = None + + def read_multi(self, environ, keep_blank_values, strict_parsing): + """Internal: read a part that is itself multipart.""" + ib = self.innerboundary + if not valid_boundary(ib): + raise ValueError, 'Invalid boundary in multipart form: %r' % (ib,) + self.list = [] + if self.qs_on_post: + for key, value in urlparse.parse_qsl(self.qs_on_post, + self.keep_blank_values, self.strict_parsing): + self.list.append(MiniFieldStorage(key, value)) + FieldStorageClass = None + + klass = self.FieldStorageClass or self.__class__ + part = klass(self.fp, {}, ib, + environ, keep_blank_values, strict_parsing) + # Throw first part away + while not part.done: + headers = rfc822.Message(self.fp) + part = klass(self.fp, headers, ib, + environ, keep_blank_values, strict_parsing) + self.list.append(part) + self.skip_lines() + + def read_single(self): + """Internal: read an atomic part.""" + if self.length >= 0: + self.read_binary() + self.skip_lines() + else: + self.read_lines() + self.file.seek(0) + + bufsize = 8*1024 # I/O buffering size for copy to file + + def read_binary(self): + """Internal: read binary data.""" + self.file = self.make_file('b') + todo = self.length + if todo >= 0: + while todo > 0: + data = self.fp.read(min(todo, self.bufsize)) + if not data: + self.done = -1 + break + self.file.write(data) + todo = todo - len(data) + + def read_lines(self): + """Internal: read lines until EOF or outerboundary.""" + self.file = self.__file = StringIO() + if self.outerboundary: + self.read_lines_to_outerboundary() + else: + self.read_lines_to_eof() + + def __write(self, line): + if self.__file is not None: + if self.__file.tell() + len(line) > 1000: + self.file = self.make_file('') + self.file.write(self.__file.getvalue()) + self.__file = None + self.file.write(line) + + def read_lines_to_eof(self): + """Internal: read lines until EOF.""" + while 1: + line = self.fp.readline(1<<16) + if not line: + self.done = -1 + break + self.__write(line) + + def read_lines_to_outerboundary(self): + """Internal: read lines until outerboundary.""" + next = "--" + self.outerboundary + last = next + "--" + delim = "" + last_line_lfend = True + while 1: + line = self.fp.readline(1<<16) + if not line: + self.done = -1 + break + if delim == "\r": + line = delim + line + delim = "" + if line[:2] == "--" and last_line_lfend: + strippedline = line.strip() + if strippedline == next: + break + if strippedline == last: + self.done = 1 + break + odelim = delim + if line[-2:] == "\r\n": + delim = "\r\n" + line = line[:-2] + last_line_lfend = True + elif line[-1] == "\n": + delim = "\n" + line = line[:-1] + last_line_lfend = True + elif line[-1] == "\r": + # We may interrupt \r\n sequences if they span the 2**16 + # byte boundary + delim = "\r" + line = line[:-1] + last_line_lfend = False + else: + delim = "" + last_line_lfend = False + self.__write(odelim + line) + + def skip_lines(self): + """Internal: skip lines until outer boundary if defined.""" + if not self.outerboundary or self.done: + return + next = "--" + self.outerboundary + last = next + "--" + last_line_lfend = True + while 1: + line = self.fp.readline(1<<16) + if not line: + self.done = -1 + break + if line[:2] == "--" and last_line_lfend: + strippedline = line.strip() + if strippedline == next: + break + if strippedline == last: + self.done = 1 + break + last_line_lfend = line.endswith('\n') + + def make_file(self, binary=None): + """Overridable: return a readable & writable file. + + The file will be used as follows: + - data is written to it + - seek(0) + - data is read from it + + The 'binary' argument is unused -- the file is always opened + in binary mode. + + This version opens a temporary file for reading and writing, + and immediately deletes (unlinks) it. The trick (on Unix!) is + that the file can still be used, but it can't be opened by + another process, and it will automatically be deleted when it + is closed or when the current process terminates. + + If you want a more permanent file, you derive a class which + overrides this method. If you want a visible temporary file + that is nevertheless automatically deleted when the script + terminates, try defining a __del__ method in a derived class + which unlinks the temporary files you have created. + + """ + import tempfile + return tempfile.TemporaryFile("w+b") + + + +# Backwards Compatibility Classes +# =============================== + +class FormContentDict(UserDict.UserDict): + """Form content as dictionary with a list of values per field. + + form = FormContentDict() + + form[key] -> [value, value, ...] + key in form -> Boolean + form.keys() -> [key, key, ...] + form.values() -> [[val, val, ...], [val, val, ...], ...] + form.items() -> [(key, [val, val, ...]), (key, [val, val, ...]), ...] + form.dict == {key: [val, val, ...], ...} + + """ + def __init__(self, environ=os.environ, keep_blank_values=0, strict_parsing=0): + self.dict = self.data = parse(environ=environ, + keep_blank_values=keep_blank_values, + strict_parsing=strict_parsing) + self.query_string = environ['QUERY_STRING'] + + +class SvFormContentDict(FormContentDict): + """Form content as dictionary expecting a single value per field. + + If you only expect a single value for each field, then form[key] + will return that single value. It will raise an IndexError if + that expectation is not true. If you expect a field to have + possible multiple values, than you can use form.getlist(key) to + get all of the values. values() and items() are a compromise: + they return single strings where there is a single value, and + lists of strings otherwise. + + """ + def __getitem__(self, key): + if len(self.dict[key]) > 1: + raise IndexError, 'expecting a single value' + return self.dict[key][0] + def getlist(self, key): + return self.dict[key] + def values(self): + result = [] + for value in self.dict.values(): + if len(value) == 1: + result.append(value[0]) + else: result.append(value) + return result + def items(self): + result = [] + for key, value in self.dict.items(): + if len(value) == 1: + result.append((key, value[0])) + else: result.append((key, value)) + return result + + +class InterpFormContentDict(SvFormContentDict): + """This class is present for backwards compatibility only.""" + def __getitem__(self, key): + v = SvFormContentDict.__getitem__(self, key) + if v[0] in '0123456789+-.': + try: return int(v) + except ValueError: + try: return float(v) + except ValueError: pass + return v.strip() + def values(self): + result = [] + for key in self.keys(): + try: + result.append(self[key]) + except IndexError: + result.append(self.dict[key]) + return result + def items(self): + result = [] + for key in self.keys(): + try: + result.append((key, self[key])) + except IndexError: + result.append((key, self.dict[key])) + return result + + +class FormContent(FormContentDict): + """This class is present for backwards compatibility only.""" + def values(self, key): + if key in self.dict :return self.dict[key] + else: return None + def indexed_value(self, key, location): + if key in self.dict: + if len(self.dict[key]) > location: + return self.dict[key][location] + else: return None + else: return None + def value(self, key): + if key in self.dict: return self.dict[key][0] + else: return None + def length(self, key): + return len(self.dict[key]) + def stripped(self, key): + if key in self.dict: return self.dict[key][0].strip() + else: return None + def pars(self): + return self.dict + + +# Test/debug code +# =============== + +def test(environ=os.environ): + """Robust test CGI script, usable as main program. + + Write minimal HTTP headers and dump all information provided to + the script in HTML form. + + """ + print "Content-type: text/html" + print + sys.stderr = sys.stdout + try: + form = FieldStorage() # Replace with other classes to test those + print_directory() + print_arguments() + print_form(form) + print_environ(environ) + print_environ_usage() + def f(): + exec "testing print_exception() -- italics?" + def g(f=f): + f() + print "

What follows is a test, not an actual exception:

" + g() + except: + print_exception() + + print "

Second try with a small maxlen...

" + + global maxlen + maxlen = 50 + try: + form = FieldStorage() # Replace with other classes to test those + print_directory() + print_arguments() + print_form(form) + print_environ(environ) + except: + print_exception() + +def print_exception(type=None, value=None, tb=None, limit=None): + if type is None: + type, value, tb = sys.exc_info() + import traceback + print + print "

Traceback (most recent call last):

" + list = traceback.format_tb(tb, limit) + \ + traceback.format_exception_only(type, value) + print "
%s%s
" % ( + escape("".join(list[:-1])), + escape(list[-1]), + ) + del tb + +def print_environ(environ=os.environ): + """Dump the shell environment as HTML.""" + keys = environ.keys() + keys.sort() + print + print "

Shell Environment:

" + print "
" + for key in keys: + print "
", escape(key), "
", escape(environ[key]) + print "
" + print + +def print_form(form): + """Dump the contents of a form as HTML.""" + keys = form.keys() + keys.sort() + print + print "

Form Contents:

" + if not keys: + print "

No form fields." + print "

" + for key in keys: + print "
" + escape(key) + ":", + value = form[key] + print "" + escape(repr(type(value))) + "" + print "
" + escape(repr(value)) + print "
" + print + +def print_directory(): + """Dump the current directory as HTML.""" + print + print "

Current Working Directory:

" + try: + pwd = os.getcwd() + except os.error, msg: + print "os.error:", escape(str(msg)) + else: + print escape(pwd) + print + +def print_arguments(): + print + print "

Command Line Arguments:

" + print + print sys.argv + print + +def print_environ_usage(): + """Dump a list of environment variables used by CGI as HTML.""" + print """ +

These environment variables could have been set:

+
    +
  • AUTH_TYPE +
  • CONTENT_LENGTH +
  • CONTENT_TYPE +
  • DATE_GMT +
  • DATE_LOCAL +
  • DOCUMENT_NAME +
  • DOCUMENT_ROOT +
  • DOCUMENT_URI +
  • GATEWAY_INTERFACE +
  • LAST_MODIFIED +
  • PATH +
  • PATH_INFO +
  • PATH_TRANSLATED +
  • QUERY_STRING +
  • REMOTE_ADDR +
  • REMOTE_HOST +
  • REMOTE_IDENT +
  • REMOTE_USER +
  • REQUEST_METHOD +
  • SCRIPT_NAME +
  • SERVER_NAME +
  • SERVER_PORT +
  • SERVER_PROTOCOL +
  • SERVER_ROOT +
  • SERVER_SOFTWARE +
+In addition, HTTP headers sent by the server may be passed in the +environment as well. Here are some common variable names: +
    +
  • HTTP_ACCEPT +
  • HTTP_CONNECTION +
  • HTTP_HOST +
  • HTTP_PRAGMA +
  • HTTP_REFERER +
  • HTTP_USER_AGENT +
+""" + + +# Utilities +# ========= + +def escape(s, quote=None): + '''Replace special characters "&", "<" and ">" to HTML-safe sequences. + If the optional flag quote is true, the quotation mark character (") + is also translated.''' + s = s.replace("&", "&") # Must be done first! + s = s.replace("<", "<") + s = s.replace(">", ">") + if quote: + s = s.replace('"', """) + return s + +def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"): + import re + return re.match(_vb_pattern, s) + +# Invoke mainline +# =============== + +# Call test() when this file is run as a script (not imported as a module) +if __name__ == '__main__': + test() diff --git a/PythonHome/Lib/cgi.pyc b/PythonHome/Lib/cgi.pyc index 25db095e652d8d6325c6f850d8ee31bf2505b10d..a517d773c74d64a786542428a45b57986770acef 100644 GIT binary patch delta 3835 zcmbW)-%C?r9LMn;=VUfouo^V*2Qj;_Ot6cX<&TXmQJb4KBgs?lhihkpIhW_ioGeo8 zHYQ&X6g5Gkn~Lgt5vVBCg%{;r?n-K4b`f+FBtk*$UwA%$z>D|uea`b7&MEwn9z7|0 zoi#`mJZXrOH#u}VUG%CPi>rzjmT#vrjoksi?`E%C_G{{>rplgZSc}QM6RMIL=}aY~ z^t19Cpo%95P}8P*$-pm6=?Zbo4VGIH!1AY!2z!2J+bCWmt$MNaC@eKjph=-xR|&7y z+RMbtymu~zGz0c^@fcOr6~q-w=k-R($c9UWNpF|YY;@A?5f4(({S;7U z&zQL4yeEqcXY06Jy0PAlAo5Du=(GS$-tWpFEOMg(Vas0Ri19{`9;nf-uTd)JzrF{+ zep0SaDdF#Zd7#XX0}qkU1Ixf3aN3Rr-XjC<4E6)D3$j%&&d4{E0MyRVKA_$Pj{x;9 zbXQ!lJv=Pd9e!Aq0#NbGuU_CJ3mOCtaP delta 1488 zcmZwHUr1A77{~D)=X9w!T+Z|&6}A+?1ieXyGXJdkhl!~rAx<5ptvPm_Q<>9AVt8Q? z>H~tJD5i85wkHTiFsSaj)m@2#6m(UPAfia^`uTbLdB5*-&U+5$ynK_AxKj4RIz`9R zy1`UKo<^f-wDvxl8uzIFst07q_yK0gB(PtZWlAa=vjS;yi9Z^jD1g>nJz~%l*UORy z3pW&9w5Sep3KZ8TugS&c6uF7h%_{cqEHN3<%Dsd%UMtb+lh0$bB5@1WcB^eTIM+G> zVa#fRFj^AG?72*asLaGSIe>GYWwEHZQi zwm5ta_Tjlp8rwX}a28U$Co-g*k)L3tz8+~D^_g*Cn*Xy5>CC?k_DzM)hrFY!&{YOr zfPD|RrLk+Q5}$Q^yjOXz$MAV1lh!@lCfE0>s!gU<8A$ZUHXKo#L R$L8U;#e1*TFjN --> + --> --> + + ''' + +__UNDEF__ = [] # a special sentinel object +def small(text): + if text: + return '' + text + '' + else: + return '' + +def strong(text): + if text: + return '' + text + '' + else: + return '' + +def grey(text): + if text: + return '' + text + '' + else: + return '' + +def lookup(name, frame, locals): + """Find the value for a given name in the given environment.""" + if name in locals: + return 'local', locals[name] + if name in frame.f_globals: + return 'global', frame.f_globals[name] + if '__builtins__' in frame.f_globals: + builtins = frame.f_globals['__builtins__'] + if type(builtins) is type({}): + if name in builtins: + return 'builtin', builtins[name] + else: + if hasattr(builtins, name): + return 'builtin', getattr(builtins, name) + return None, __UNDEF__ + +def scanvars(reader, frame, locals): + """Scan one logical line of Python and look up values of variables used.""" + vars, lasttoken, parent, prefix, value = [], None, None, '', __UNDEF__ + for ttype, token, start, end, line in tokenize.generate_tokens(reader): + if ttype == tokenize.NEWLINE: break + if ttype == tokenize.NAME and token not in keyword.kwlist: + if lasttoken == '.': + if parent is not __UNDEF__: + value = getattr(parent, token, __UNDEF__) + vars.append((prefix + token, prefix, value)) + else: + where, value = lookup(token, frame, locals) + vars.append((token, where, value)) + elif token == '.': + prefix += lasttoken + '.' + parent = value + else: + parent, prefix = None, '' + lasttoken = token + return vars + +def html(einfo, context=5): + """Return a nice HTML document describing a given traceback.""" + etype, evalue, etb = einfo + if type(etype) is types.ClassType: + etype = etype.__name__ + pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable + date = time.ctime(time.time()) + head = '' + pydoc.html.heading( + '%s' % + strong(pydoc.html.escape(str(etype))), + '#ffffff', '#6622aa', pyver + '
' + date) + ''' +

A problem occurred in a Python script. Here is the sequence of +function calls leading up to the error, in the order they occurred.

''' + + indent = '' + small(' ' * 5) + ' ' + frames = [] + records = inspect.getinnerframes(etb, context) + for frame, file, lnum, func, lines, index in records: + if file: + file = os.path.abspath(file) + link = '
%s' % (file, pydoc.html.escape(file)) + else: + file = link = '?' + args, varargs, varkw, locals = inspect.getargvalues(frame) + call = '' + if func != '?': + call = 'in ' + strong(func) + \ + inspect.formatargvalues(args, varargs, varkw, locals, + formatvalue=lambda value: '=' + pydoc.html.repr(value)) + + highlight = {} + def reader(lnum=[lnum]): + highlight[lnum[0]] = 1 + try: return linecache.getline(file, lnum[0]) + finally: lnum[0] += 1 + vars = scanvars(reader, frame, locals) + + rows = ['%s%s %s' % + (' ', link, call)] + if index is not None: + i = lnum - index + for line in lines: + num = small(' ' * (5-len(str(i))) + str(i)) + ' ' + if i in highlight: + line = '=>%s%s' % (num, pydoc.html.preformat(line)) + rows.append('%s' % line) + else: + line = '  %s%s' % (num, pydoc.html.preformat(line)) + rows.append('%s' % grey(line)) + i += 1 + + done, dump = {}, [] + for name, where, value in vars: + if name in done: continue + done[name] = 1 + if value is not __UNDEF__: + if where in ('global', 'builtin'): + name = ('%s ' % where) + strong(name) + elif where == 'local': + name = strong(name) + else: + name = where + strong(name.split('.')[-1]) + dump.append('%s = %s' % (name, pydoc.html.repr(value))) + else: + dump.append(name + ' undefined') + + rows.append('%s' % small(grey(', '.join(dump)))) + frames.append(''' + +%s
''' % '\n'.join(rows)) + + exception = ['

%s: %s' % (strong(pydoc.html.escape(str(etype))), + pydoc.html.escape(str(evalue)))] + if isinstance(evalue, BaseException): + for name in dir(evalue): + if name[:1] == '_': continue + value = pydoc.html.repr(getattr(evalue, name)) + exception.append('\n
%s%s =\n%s' % (indent, name, value)) + + return head + ''.join(frames) + ''.join(exception) + ''' + + + +''' % pydoc.html.escape( + ''.join(traceback.format_exception(etype, evalue, etb))) + +def text(einfo, context=5): + """Return a plain text document describing a given traceback.""" + etype, evalue, etb = einfo + if type(etype) is types.ClassType: + etype = etype.__name__ + pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable + date = time.ctime(time.time()) + head = "%s\n%s\n%s\n" % (str(etype), pyver, date) + ''' +A problem occurred in a Python script. Here is the sequence of +function calls leading up to the error, in the order they occurred. +''' + + frames = [] + records = inspect.getinnerframes(etb, context) + for frame, file, lnum, func, lines, index in records: + file = file and os.path.abspath(file) or '?' + args, varargs, varkw, locals = inspect.getargvalues(frame) + call = '' + if func != '?': + call = 'in ' + func + \ + inspect.formatargvalues(args, varargs, varkw, locals, + formatvalue=lambda value: '=' + pydoc.text.repr(value)) + + highlight = {} + def reader(lnum=[lnum]): + highlight[lnum[0]] = 1 + try: return linecache.getline(file, lnum[0]) + finally: lnum[0] += 1 + vars = scanvars(reader, frame, locals) + + rows = [' %s %s' % (file, call)] + if index is not None: + i = lnum - index + for line in lines: + num = '%5d ' % i + rows.append(num+line.rstrip()) + i += 1 + + done, dump = {}, [] + for name, where, value in vars: + if name in done: continue + done[name] = 1 + if value is not __UNDEF__: + if where == 'global': name = 'global ' + name + elif where != 'local': name = where + name.split('.')[-1] + dump.append('%s = %s' % (name, pydoc.text.repr(value))) + else: + dump.append(name + ' undefined') + + rows.append('\n'.join(dump)) + frames.append('\n%s\n' % '\n'.join(rows)) + + exception = ['%s: %s' % (str(etype), str(evalue))] + if isinstance(evalue, BaseException): + for name in dir(evalue): + value = pydoc.text.repr(getattr(evalue, name)) + exception.append('\n%s%s = %s' % (" "*4, name, value)) + + return head + ''.join(frames) + ''.join(exception) + ''' + +The above is a description of an error in a Python program. Here is +the original traceback: + +%s +''' % ''.join(traceback.format_exception(etype, evalue, etb)) + +class Hook: + """A hook to replace sys.excepthook that shows tracebacks in HTML.""" + + def __init__(self, display=1, logdir=None, context=5, file=None, + format="html"): + self.display = display # send tracebacks to browser if true + self.logdir = logdir # log tracebacks to files if not None + self.context = context # number of source code lines per frame + self.file = file or sys.stdout # place to send the output + self.format = format + + def __call__(self, etype, evalue, etb): + self.handle((etype, evalue, etb)) + + def handle(self, info=None): + info = info or sys.exc_info() + if self.format == "html": + self.file.write(reset()) + + formatter = (self.format=="html") and html or text + plain = False + try: + doc = formatter(info, self.context) + except: # just in case something goes wrong + doc = ''.join(traceback.format_exception(*info)) + plain = True + + if self.display: + if plain: + doc = doc.replace('&', '&').replace('<', '<') + self.file.write('

' + doc + '
\n') + else: + self.file.write(doc + '\n') + else: + self.file.write('

A problem occurred in a Python script.\n') + + if self.logdir is not None: + suffix = ['.txt', '.html'][self.format=="html"] + (fd, path) = tempfile.mkstemp(suffix=suffix, dir=self.logdir) + + try: + file = os.fdopen(fd, 'w') + file.write(doc) + file.close() + msg = '%s contains the description of this error.' % path + except: + msg = 'Tried to save traceback to %s, but failed.' % path + + if self.format == 'html': + self.file.write('

%s

\n' % msg) + else: + self.file.write(msg + '\n') + try: + self.file.flush() + except: pass + +handler = Hook().handle +def enable(display=1, logdir=None, context=5, format="html"): + """Install an exception handler that formats tracebacks as HTML. + + The optional argument 'display' can be set to 0 to suppress sending the + traceback to the browser, and 'logdir' can be set to a directory to cause + tracebacks to be written to files there.""" + sys.excepthook = Hook(display=display, logdir=logdir, + context=context, format=format) diff --git a/PythonHome/Lib/cgitb.pyc b/PythonHome/Lib/cgitb.pyc deleted file mode 100644 index 1c50904402f6d3977d91075205d2b788c5622e3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11914 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 self.chunksize: + raise RuntimeError + self.file.seek(self.offset + pos, 0) + self.size_read = pos + + def tell(self): + if self.closed: + raise ValueError, "I/O operation on closed file" + return self.size_read + + def read(self, size=-1): + """Read at most size bytes from the chunk. + If size is omitted or negative, read until the end + of the chunk. + """ + + if self.closed: + raise ValueError, "I/O operation on closed file" + if self.size_read >= self.chunksize: + return '' + if size < 0: + size = self.chunksize - self.size_read + if size > self.chunksize - self.size_read: + size = self.chunksize - self.size_read + data = self.file.read(size) + self.size_read = self.size_read + len(data) + if self.size_read == self.chunksize and \ + self.align and \ + (self.chunksize & 1): + dummy = self.file.read(1) + self.size_read = self.size_read + len(dummy) + return data + + def skip(self): + """Skip the rest of the chunk. + If you are not interested in the contents of the chunk, + this method should be called so that the file points to + the start of the next chunk. + """ + + if self.closed: + raise ValueError, "I/O operation on closed file" + if self.seekable: + try: + n = self.chunksize - self.size_read + # maybe fix alignment + if self.align and (self.chunksize & 1): + n = n + 1 + self.file.seek(n, 1) + self.size_read = self.size_read + n + return + except IOError: + pass + while self.size_read < self.chunksize: + n = min(8192, self.chunksize - self.size_read) + dummy = self.read(n) + if not dummy: + raise EOFError diff --git a/PythonHome/Lib/chunk.pyc b/PythonHome/Lib/chunk.pyc deleted file mode 100644 index a15f787b90a44d6e8df5dac5e98ab5b3b17e3f13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5426 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

)$b z-8he!JPWLz!}ly&(~I7_Xi9@cP}Th`Tg*;JI^#~KUnGMJx6&#}?-5=GX?TSLe_agU z to get list of completions. + """ + if state == 0: + import readline + origline = readline.get_line_buffer() + line = origline.lstrip() + stripped = len(origline) - len(line) + begidx = readline.get_begidx() - stripped + endidx = readline.get_endidx() - stripped + if begidx>0: + cmd, args, foo = self.parseline(line) + if cmd == '': + compfunc = self.completedefault + else: + try: + compfunc = getattr(self, 'complete_' + cmd) + except AttributeError: + compfunc = self.completedefault + else: + compfunc = self.completenames + self.completion_matches = compfunc(text, line, begidx, endidx) + try: + return self.completion_matches[state] + except IndexError: + return None + + def get_names(self): + # This method used to pull in base class attributes + # at a time dir() didn't do it yet. + return dir(self.__class__) + + def complete_help(self, *args): + commands = set(self.completenames(*args)) + topics = set(a[5:] for a in self.get_names() + if a.startswith('help_' + args[0])) + return list(commands | topics) + + def do_help(self, arg): + 'List available commands with "help" or detailed help with "help cmd".' + if arg: + # XXX check arg syntax + try: + func = getattr(self, 'help_' + arg) + except AttributeError: + try: + doc=getattr(self, 'do_' + arg).__doc__ + if doc: + self.stdout.write("%s\n"%str(doc)) + return + except AttributeError: + pass + self.stdout.write("%s\n"%str(self.nohelp % (arg,))) + return + func() + else: + names = self.get_names() + cmds_doc = [] + cmds_undoc = [] + help = {} + for name in names: + if name[:5] == 'help_': + help[name[5:]]=1 + names.sort() + # There can be duplicates if routines overridden + prevname = '' + for name in names: + if name[:3] == 'do_': + if name == prevname: + continue + prevname = name + cmd=name[3:] + if cmd in help: + cmds_doc.append(cmd) + del help[cmd] + elif getattr(self, name).__doc__: + cmds_doc.append(cmd) + else: + cmds_undoc.append(cmd) + self.stdout.write("%s\n"%str(self.doc_leader)) + self.print_topics(self.doc_header, cmds_doc, 15,80) + self.print_topics(self.misc_header, help.keys(),15,80) + self.print_topics(self.undoc_header, cmds_undoc, 15,80) + + def print_topics(self, header, cmds, cmdlen, maxcol): + if cmds: + self.stdout.write("%s\n"%str(header)) + if self.ruler: + self.stdout.write("%s\n"%str(self.ruler * len(header))) + self.columnize(cmds, maxcol-1) + self.stdout.write("\n") + + def columnize(self, list, displaywidth=80): + """Display a list of strings as a compact set of columns. + + Each column is only as wide as necessary. + Columns are separated by two spaces (one was not legible enough). + """ + if not list: + self.stdout.write("\n") + return + nonstrings = [i for i in range(len(list)) + if not isinstance(list[i], str)] + if nonstrings: + raise TypeError, ("list[i] not a string for i in %s" % + ", ".join(map(str, nonstrings))) + size = len(list) + if size == 1: + self.stdout.write('%s\n'%str(list[0])) + return + # Try every row count from 1 upwards + for nrows in range(1, len(list)): + ncols = (size+nrows-1) // nrows + colwidths = [] + totwidth = -2 + for col in range(ncols): + colwidth = 0 + for row in range(nrows): + i = row + nrows*col + if i >= size: + break + x = list[i] + colwidth = max(colwidth, len(x)) + colwidths.append(colwidth) + totwidth += colwidth + 2 + if totwidth > displaywidth: + break + if totwidth <= displaywidth: + break + else: + nrows = len(list) + ncols = 1 + colwidths = [0] + for row in range(nrows): + texts = [] + for col in range(ncols): + i = row + nrows*col + if i >= size: + x = "" + else: + x = list[i] + texts.append(x) + while texts and not texts[-1]: + del texts[-1] + for col in range(len(texts)): + texts[col] = texts[col].ljust(colwidths[col]) + self.stdout.write("%s\n"%str(" ".join(texts))) diff --git a/PythonHome/Lib/cmd.pyc b/PythonHome/Lib/cmd.pyc deleted file mode 100644 index 34ecf8fee3976252473b4257b92d86a7a1e680b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13724 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 I%3SUL062s33;+NC diff --git a/PythonHome/Lib/code.py b/PythonHome/Lib/code.py new file mode 100644 index 0000000000..3b39d1b346 --- /dev/null +++ b/PythonHome/Lib/code.py @@ -0,0 +1,310 @@ +"""Utilities needed to emulate Python's interactive interpreter. + +""" + +# Inspired by similar code by Jeff Epler and Fredrik Lundh. + + +import sys +import traceback +from codeop import CommandCompiler, compile_command + +__all__ = ["InteractiveInterpreter", "InteractiveConsole", "interact", + "compile_command"] + +def softspace(file, newvalue): + oldvalue = 0 + try: + oldvalue = file.softspace + except AttributeError: + pass + try: + file.softspace = newvalue + except (AttributeError, TypeError): + # "attribute-less object" or "read-only attributes" + pass + return oldvalue + +class InteractiveInterpreter: + """Base class for InteractiveConsole. + + This class deals with parsing and interpreter state (the user's + namespace); it doesn't deal with input buffering or prompting or + input file naming (the filename is always passed in explicitly). + + """ + + def __init__(self, locals=None): + """Constructor. + + The optional 'locals' argument specifies the dictionary in + which code will be executed; it defaults to a newly created + dictionary with key "__name__" set to "__console__" and key + "__doc__" set to None. + + """ + if locals is None: + locals = {"__name__": "__console__", "__doc__": None} + self.locals = locals + self.compile = CommandCompiler() + + def runsource(self, source, filename="", symbol="single"): + """Compile and run some source in the interpreter. + + Arguments are as for compile_command(). + + One several things can happen: + + 1) The input is incorrect; compile_command() raised an + exception (SyntaxError or OverflowError). A syntax traceback + will be printed by calling the showsyntaxerror() method. + + 2) The input is incomplete, and more input is required; + compile_command() returned None. Nothing happens. + + 3) The input is complete; compile_command() returned a code + object. The code is executed by calling self.runcode() (which + also handles run-time exceptions, except for SystemExit). + + The return value is True in case 2, False in the other cases (unless + an exception is raised). The return value can be used to + decide whether to use sys.ps1 or sys.ps2 to prompt the next + line. + + """ + try: + code = self.compile(source, filename, symbol) + except (OverflowError, SyntaxError, ValueError): + # Case 1 + self.showsyntaxerror(filename) + return False + + if code is None: + # Case 2 + return True + + # Case 3 + self.runcode(code) + return False + + def runcode(self, code): + """Execute a code object. + + When an exception occurs, self.showtraceback() is called to + display a traceback. All exceptions are caught except + SystemExit, which is reraised. + + A note about KeyboardInterrupt: this exception may occur + elsewhere in this code, and may not always be caught. The + caller should be prepared to deal with it. + + """ + try: + exec code in self.locals + except SystemExit: + raise + except: + self.showtraceback() + else: + if softspace(sys.stdout, 0): + print + + def showsyntaxerror(self, filename=None): + """Display the syntax error that just occurred. + + This doesn't display a stack trace because there isn't one. + + If a filename is given, it is stuffed in the exception instead + of what was there before (because Python's parser always uses + "" when reading from a string). + + The output is written by self.write(), below. + + """ + type, value, sys.last_traceback = sys.exc_info() + sys.last_type = type + sys.last_value = value + if filename and type is SyntaxError: + # Work hard to stuff the correct filename in the exception + try: + msg, (dummy_filename, lineno, offset, line) = value + except: + # Not the format we expect; leave it alone + pass + else: + # Stuff in the right filename + value = SyntaxError(msg, (filename, lineno, offset, line)) + sys.last_value = value + list = traceback.format_exception_only(type, value) + map(self.write, list) + + def showtraceback(self): + """Display the exception that just occurred. + + We remove the first stack item because it is our own code. + + The output is written by self.write(), below. + + """ + try: + type, value, tb = sys.exc_info() + sys.last_type = type + sys.last_value = value + sys.last_traceback = tb + tblist = traceback.extract_tb(tb) + del tblist[:1] + list = traceback.format_list(tblist) + if list: + list.insert(0, "Traceback (most recent call last):\n") + list[len(list):] = traceback.format_exception_only(type, value) + finally: + tblist = tb = None + map(self.write, list) + + def write(self, data): + """Write a string. + + The base implementation writes to sys.stderr; a subclass may + replace this with a different implementation. + + """ + sys.stderr.write(data) + + +class InteractiveConsole(InteractiveInterpreter): + """Closely emulate the behavior of the interactive Python interpreter. + + This class builds on InteractiveInterpreter and adds prompting + using the familiar sys.ps1 and sys.ps2, and input buffering. + + """ + + def __init__(self, locals=None, filename=""): + """Constructor. + + The optional locals argument will be passed to the + InteractiveInterpreter base class. + + The optional filename argument should specify the (file)name + of the input stream; it will show up in tracebacks. + + """ + InteractiveInterpreter.__init__(self, locals) + self.filename = filename + self.resetbuffer() + + def resetbuffer(self): + """Reset the input buffer.""" + self.buffer = [] + + def interact(self, banner=None): + """Closely emulate the interactive Python console. + + The optional banner argument specify the banner to print + before the first interaction; by default it prints a banner + similar to the one printed by the real Python interpreter, + followed by the current class name in parentheses (so as not + to confuse this with the real interpreter -- since it's so + close!). + + """ + try: + sys.ps1 + except AttributeError: + sys.ps1 = ">>> " + try: + sys.ps2 + except AttributeError: + sys.ps2 = "... " + cprt = 'Type "help", "copyright", "credits" or "license" for more information.' + if banner is None: + self.write("Python %s on %s\n%s\n(%s)\n" % + (sys.version, sys.platform, cprt, + self.__class__.__name__)) + else: + self.write("%s\n" % str(banner)) + more = 0 + while 1: + try: + if more: + prompt = sys.ps2 + else: + prompt = sys.ps1 + try: + line = self.raw_input(prompt) + # Can be None if sys.stdin was redefined + encoding = getattr(sys.stdin, "encoding", None) + if encoding and not isinstance(line, unicode): + line = line.decode(encoding) + except EOFError: + self.write("\n") + break + else: + more = self.push(line) + except KeyboardInterrupt: + self.write("\nKeyboardInterrupt\n") + self.resetbuffer() + more = 0 + + def push(self, line): + """Push a line to the interpreter. + + The line should not have a trailing newline; it may have + internal newlines. The line is appended to a buffer and the + interpreter's runsource() method is called with the + concatenated contents of the buffer as source. If this + indicates that the command was executed or invalid, the buffer + is reset; otherwise, the command is incomplete, and the buffer + is left as it was after the line was appended. The return + value is 1 if more input is required, 0 if the line was dealt + with in some way (this is the same as runsource()). + + """ + self.buffer.append(line) + source = "\n".join(self.buffer) + more = self.runsource(source, self.filename) + if not more: + self.resetbuffer() + return more + + def raw_input(self, prompt=""): + """Write a prompt and read a line. + + The returned line does not include the trailing newline. + When the user enters the EOF key sequence, EOFError is raised. + + The base implementation uses the built-in function + raw_input(); a subclass may replace this with a different + implementation. + + """ + return raw_input(prompt) + + +def interact(banner=None, readfunc=None, local=None): + """Closely emulate the interactive Python interpreter. + + This is a backwards compatible interface to the InteractiveConsole + class. When readfunc is not specified, it attempts to import the + readline module to enable GNU readline if it is available. + + Arguments (all optional, all default to None): + + banner -- passed to InteractiveConsole.interact() + readfunc -- if not None, replaces InteractiveConsole.raw_input() + local -- passed to InteractiveInterpreter.__init__() + + """ + console = InteractiveConsole(local) + if readfunc is not None: + console.raw_input = readfunc + else: + try: + import readline + except ImportError: + pass + console.interact(banner) + + +if __name__ == "__main__": + interact() diff --git a/PythonHome/Lib/code.pyc b/PythonHome/Lib/code.pyc deleted file mode 100644 index 427596e1cf6503e3ddc3633cfa3d44cf4fa5f223..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10093 zcmbVSO>^AXb$#e=el*#XG}1_#@hCA&kE~`wu_8I;#Yk2%W@g5d*pvctOj)I>4jOnZ zfSB_&mnlB!w6i&SNmjTc@|vPk6*B#W%F%KykBi&R$5Irjl*kfKIoj;WLdp|pe4meYbx&Y^0iVwf3(c1dRdJib)~-B zWpm~KRrRK=9<3_fQ*lo{ZK>jyO0V*5FGJ5-YPWxmz5N3eU)dy0Y@&^yX&vj>x4Ey! z(=@c&e=xHLd3MA2NoI8sMmBk_-T9=@xU;pglKdKfJN*_U+4Cs2^YJ*$V*E^!R2OnD zau);q@|nGYdSA{Z%Bd4*FCKrioo6ObwOz*TstB-_PDt9qXy5E2{XO@;oo|)I(PASZAP6;i^=yEj4OMwVzhiUUHt;&Q5|t_1T>5 zqA>Z$nn@UG%US%?+9DZFt^TYi@3z0*Oh5oSY%k?Eu7VLEjec^b<_A2pN| zW({XskAIR3A4hqtw+b`(i{rAD%kC>Q1btkp@+kuE3}9hwvXoOKr>#MR*v_>jj3(hP4&)* zr=V~p*gOT0y~ZVgCkwFK=h7Mvfab*6Vj9_;O2x_J-yY^7$4K%FqrH*l5hn459~Muh zW1U&wOmvitsJfiAIDvkmW-&weYY|5WNp#>7N|>%R^@kcG(-Ghry9w2!aGF|($o&u| z;3%E>QK7LEaV?`ESyu3=p84y80jF*-Soe*#d>eNnr>?xo)kVEp2A;-w)Tq9bXSy*| zyNao3NDy7A+OSLVPz3DssZN#!MOYdDH#4*VN~)Fy$5|!TG&&sx)SaBtzLCtZTgk9 zv28VKi^18Z!J)8?q?9JpTilX5Q`arf`^%Z z5KbmK`(%#XTN?sir+84WB#ZK*(2>0ZEQ)KWyg`4%FT#XM7tT?uUqo7P@Ar3SnGIiv zZKZDCN86(`Kav|8TNr|Gq=s+dp!6_|p4OPF06&3Y0G|CJpdF?u^`8o34)P=SuBPQi zN5&fdE^eUm_9?>{PhiRQrcCxY$F$XhEcCN!Qb4il9-J~(ZKp+s&ItZ}{KzzxGiVxZ zfB!_=l*N`$oxw_KD5_q!pAQc)=a?m05-|c;i%S2S^FamK0(4jh6VVs5QHz1u$!wWruzHcqW_d2|V0UJ$9)I>Cu}$Ex1K3O*zHliQpA=V+$} zEapWQSTBPn`_l|9JBL6N0&#WY6yyLzG`!Ue(FvOek3wcsk0^%aq)9x$ilZ5rFVp~% z%+|!*BF^0DZ9Z}CL?Dyt7q*rGAT=%6PM_Q$xPZdai629%n70O$EuHDl$O9Z}5dVH0 zk1zsC$&>`78DjA`V`AZ|rDC1nJwB!#bSf`)tnzK{{%kzVQ;{GGjH>Tq8^T{8-HG}> zg_4u058B>`-j&vxx6tafI_)*D_J-_2O*&@hOK%7I)%j{a`&f0fV_(;4<^D>k>_%no z#2I?vUk`O#>5e)C8S&I>u+^WaAH!`5Pla_;1{P0!=DZf1l;F5T_T1v^AL#5jF!Csx z7Qm)po625W2p}A&p)ELpio{IPaE3POsE~=rHsPqlLK4ctpPDd{w9z`ze{Yw zR?@sRH2YIO%RzO*VGic%w#^A?8-L!Ei`ziPo#-66%fw{EvP>> z&q7_{=&*z^3W87@W6T$ilusO?>x9KIqb2}2#1na~MxgN$fNU~8baUJ3tJE-k|*hO~>!JQyq zuEd!Imnnhfe_o%rF!FI|2laFf@+_T+K8(YO*mu`8BG{?JHOdfz%T{Pwr2+Sjc_JN) zr{nQ#P_31y6v>Q%2HtFf-4bQ{C!GBGFOKV*gy2v)D95|B4&yq6-hdRNGSo2)D1^@U1>ThJdN*0_ZlSPhgAwz1E+tD`!QiY`2~J<&FV`*=)k>p^Z``R{4mQAA|7W- zf{Suoa-;1X$qzaEL&b8fxGCk>9J8Z2h(jBmIdxoyUr_|#Q%j{~>)~9McrX~}@iaxe z9*~>5^&_zhzRiO39nc5_TmshtoSeN{Y>D>DoI|m=wAkvMJAb2lrT1Iis}b(VUmN9* zaF{Pp=w?O=S}j>oW}%?8ZS@9E!2od|sVQWtkdbn!DWs!tj*Jv;E;A8DLu>v6#dey* zz|ZP@C6#ih55ngO7(84NuO;v;Qp%_) zL6F0uky|)!1N6h7B0o6C{jc%DZ;)7W*^_x%sScZ6E({ugQPog?$E=77$qY8|y+>15 z<*zD-HE*aSpDv9xlhx|8)&?_6b%XUf(!0a;>u@ZYE9oZbrazrvN#~Tk8AQ8mQ6S1B za2E&5TvMUpCfyP^Efn*`I4oeDGnI{!{so7j(yEmUuu|e2X`6YHTxy`LGiC5MN(%O$g@~@`1aWY5wJRE z3-I)OihUATixtVXfnhAF;v)~7i5%fP^`(bvTpV8DGjs(!1B_xn`!*)zJxRv>5aX0& zoR}i^_Ca<*J!F3`mMjB3+<*2B-nb-h{6*spkb1nq%I`Z}l<}bQLmcSWZlBOI|A6&4 z&32t)t4ee5E~OfVSw<3lJSFUOseC3G3`njOs$}G1s)WJR&F0x1lIGaugvtFSb%vPN zcfx8JCV`EEiF3vQ){+4vN>6qkJ+e5@Z470ufna%{ntj>)1BXpiJwM4J$K* zj#GhGYzf6K9np31GuO=u{`aq&jTO^IJGc;@=Ry*u9?K=qV*Yfu5r zTAy~z(IAe;p-^I)Xi~T+hchfqIDZ`6<{RAEJkw^f?SIE%$WGL1+gp`Qwd!{f5f5qS z`>m^zY-pqGwYo?F)aPZU&6XSz@+)1&-kv=zy{P$*b1ptx>_cNK#xd-LHWT_ z5L9!|2ZF?>GS$TAwSI|M?mm^ZOqpX9q0l$U`X%oN(vnyU^|kn^74zq^RmR#b#B>399y}&)n=l=a9!B32(HG-7CDzbOiDeG!00k za~oQ66m>2fikoDJwUc;LDml?}F-+vaY2WcBFMWiJo~u_0!w|T~(cBzhTW^a=^$5v1 z)OJadaD;tyX;G$>d6Q~R%c*u*^SURJ58#a5@{^H&`Ub?N|9gDM4%AY)V>-8+GS47Q zvQvbePi}~E2$Hq&4L3#6lg3gVvyWnnT+nw9FcQgt!bvT=U@T%WnY4b$E!*F^_^rPTO{cO_?8~vsLg{ zX7aiCOevKrbV6U;d;@JVb=>YmCF@gBOvQBvq;g?V$D zjE1g=5DA6-ceN~?DDwsbkRg62fY#;B@;fM!lz?D#jEm40&Qr~!B-p-`ITj8iK$nzc zaKBksw3?8W9toR*^W(Qr!Ow8_Onsy7T%*3pj>)+ms7w#3+zYUq9Z!0LY*3hF=saqw zzUZG6>$r4jL5_ojEuT=mm3(t0y%-Fza^Q#Tn+vPwqZOs4UeCKHXK&jC>BU`#se2S) b_)Xa20{eOeG^^X{u3h@OE7`>ld*1&66Y|GD diff --git a/PythonHome/Lib/codecs.py b/PythonHome/Lib/codecs.py new file mode 100644 index 0000000000..93c16c358e --- /dev/null +++ b/PythonHome/Lib/codecs.py @@ -0,0 +1,1095 @@ +""" codecs -- Python Codec Registry, API and helpers. + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +"""#" + +import __builtin__, sys + +### Registry and builtin stateless codec functions + +try: + from _codecs import * +except ImportError, why: + raise SystemError('Failed to load the builtin codecs: %s' % why) + +__all__ = ["register", "lookup", "open", "EncodedFile", "BOM", "BOM_BE", + "BOM_LE", "BOM32_BE", "BOM32_LE", "BOM64_BE", "BOM64_LE", + "BOM_UTF8", "BOM_UTF16", "BOM_UTF16_LE", "BOM_UTF16_BE", + "BOM_UTF32", "BOM_UTF32_LE", "BOM_UTF32_BE", + "strict_errors", "ignore_errors", "replace_errors", + "xmlcharrefreplace_errors", + "register_error", "lookup_error"] + +### Constants + +# +# Byte Order Mark (BOM = ZERO WIDTH NO-BREAK SPACE = U+FEFF) +# and its possible byte string values +# for UTF8/UTF16/UTF32 output and little/big endian machines +# + +# UTF-8 +BOM_UTF8 = '\xef\xbb\xbf' + +# UTF-16, little endian +BOM_LE = BOM_UTF16_LE = '\xff\xfe' + +# UTF-16, big endian +BOM_BE = BOM_UTF16_BE = '\xfe\xff' + +# UTF-32, little endian +BOM_UTF32_LE = '\xff\xfe\x00\x00' + +# UTF-32, big endian +BOM_UTF32_BE = '\x00\x00\xfe\xff' + +if sys.byteorder == 'little': + + # UTF-16, native endianness + BOM = BOM_UTF16 = BOM_UTF16_LE + + # UTF-32, native endianness + BOM_UTF32 = BOM_UTF32_LE + +else: + + # UTF-16, native endianness + BOM = BOM_UTF16 = BOM_UTF16_BE + + # UTF-32, native endianness + BOM_UTF32 = BOM_UTF32_BE + +# Old broken names (don't use in new code) +BOM32_LE = BOM_UTF16_LE +BOM32_BE = BOM_UTF16_BE +BOM64_LE = BOM_UTF32_LE +BOM64_BE = BOM_UTF32_BE + + +### Codec base classes (defining the API) + +class CodecInfo(tuple): + + def __new__(cls, encode, decode, streamreader=None, streamwriter=None, + incrementalencoder=None, incrementaldecoder=None, name=None): + self = tuple.__new__(cls, (encode, decode, streamreader, streamwriter)) + self.name = name + self.encode = encode + self.decode = decode + self.incrementalencoder = incrementalencoder + self.incrementaldecoder = incrementaldecoder + self.streamwriter = streamwriter + self.streamreader = streamreader + return self + + def __repr__(self): + return "<%s.%s object for encoding %s at 0x%x>" % (self.__class__.__module__, self.__class__.__name__, self.name, id(self)) + +class Codec: + + """ Defines the interface for stateless encoders/decoders. + + The .encode()/.decode() methods may use different error + handling schemes by providing the errors argument. These + string values are predefined: + + 'strict' - raise a ValueError error (or a subclass) + 'ignore' - ignore the character and continue with the next + 'replace' - replace with a suitable replacement character; + Python will use the official U+FFFD REPLACEMENT + CHARACTER for the builtin Unicode codecs on + decoding and '?' on encoding. + 'xmlcharrefreplace' - Replace with the appropriate XML + character reference (only for encoding). + 'backslashreplace' - Replace with backslashed escape sequences + (only for encoding). + + The set of allowed values can be extended via register_error. + + """ + def encode(self, input, errors='strict'): + + """ Encodes the object input and returns a tuple (output + object, length consumed). + + errors defines the error handling to apply. It defaults to + 'strict' handling. + + The method may not store state in the Codec instance. Use + StreamCodec for codecs which have to keep state in order to + make encoding/decoding efficient. + + The encoder must be able to handle zero length input and + return an empty object of the output object type in this + situation. + + """ + raise NotImplementedError + + def decode(self, input, errors='strict'): + + """ Decodes the object input and returns a tuple (output + object, length consumed). + + input must be an object which provides the bf_getreadbuf + buffer slot. Python strings, buffer objects and memory + mapped files are examples of objects providing this slot. + + errors defines the error handling to apply. It defaults to + 'strict' handling. + + The method may not store state in the Codec instance. Use + StreamCodec for codecs which have to keep state in order to + make encoding/decoding efficient. + + The decoder must be able to handle zero length input and + return an empty object of the output object type in this + situation. + + """ + raise NotImplementedError + +class IncrementalEncoder(object): + """ + An IncrementalEncoder encodes an input in multiple steps. The input can be + passed piece by piece to the encode() method. The IncrementalEncoder remembers + the state of the Encoding process between calls to encode(). + """ + def __init__(self, errors='strict'): + """ + Creates an IncrementalEncoder instance. + + The IncrementalEncoder may use different error handling schemes by + providing the errors keyword argument. See the module docstring + for a list of possible values. + """ + self.errors = errors + self.buffer = "" + + def encode(self, input, final=False): + """ + Encodes input and returns the resulting object. + """ + raise NotImplementedError + + def reset(self): + """ + Resets the encoder to the initial state. + """ + + def getstate(self): + """ + Return the current state of the encoder. + """ + return 0 + + def setstate(self, state): + """ + Set the current state of the encoder. state must have been + returned by getstate(). + """ + +class BufferedIncrementalEncoder(IncrementalEncoder): + """ + This subclass of IncrementalEncoder can be used as the baseclass for an + incremental encoder if the encoder must keep some of the output in a + buffer between calls to encode(). + """ + def __init__(self, errors='strict'): + IncrementalEncoder.__init__(self, errors) + self.buffer = "" # unencoded input that is kept between calls to encode() + + def _buffer_encode(self, input, errors, final): + # Overwrite this method in subclasses: It must encode input + # and return an (output, length consumed) tuple + raise NotImplementedError + + def encode(self, input, final=False): + # encode input (taking the buffer into account) + data = self.buffer + input + (result, consumed) = self._buffer_encode(data, self.errors, final) + # keep unencoded input until the next call + self.buffer = data[consumed:] + return result + + def reset(self): + IncrementalEncoder.reset(self) + self.buffer = "" + + def getstate(self): + return self.buffer or 0 + + def setstate(self, state): + self.buffer = state or "" + +class IncrementalDecoder(object): + """ + An IncrementalDecoder decodes an input in multiple steps. The input can be + passed piece by piece to the decode() method. The IncrementalDecoder + remembers the state of the decoding process between calls to decode(). + """ + def __init__(self, errors='strict'): + """ + Creates a IncrementalDecoder instance. + + The IncrementalDecoder may use different error handling schemes by + providing the errors keyword argument. See the module docstring + for a list of possible values. + """ + self.errors = errors + + def decode(self, input, final=False): + """ + Decodes input and returns the resulting object. + """ + raise NotImplementedError + + def reset(self): + """ + Resets the decoder to the initial state. + """ + + def getstate(self): + """ + Return the current state of the decoder. + + This must be a (buffered_input, additional_state_info) tuple. + buffered_input must be a bytes object containing bytes that + were passed to decode() that have not yet been converted. + additional_state_info must be a non-negative integer + representing the state of the decoder WITHOUT yet having + processed the contents of buffered_input. In the initial state + and after reset(), getstate() must return (b"", 0). + """ + return (b"", 0) + + def setstate(self, state): + """ + Set the current state of the decoder. + + state must have been returned by getstate(). The effect of + setstate((b"", 0)) must be equivalent to reset(). + """ + +class BufferedIncrementalDecoder(IncrementalDecoder): + """ + This subclass of IncrementalDecoder can be used as the baseclass for an + incremental decoder if the decoder must be able to handle incomplete byte + sequences. + """ + def __init__(self, errors='strict'): + IncrementalDecoder.__init__(self, errors) + self.buffer = "" # undecoded input that is kept between calls to decode() + + def _buffer_decode(self, input, errors, final): + # Overwrite this method in subclasses: It must decode input + # and return an (output, length consumed) tuple + raise NotImplementedError + + def decode(self, input, final=False): + # decode input (taking the buffer into account) + data = self.buffer + input + (result, consumed) = self._buffer_decode(data, self.errors, final) + # keep undecoded input until the next call + self.buffer = data[consumed:] + return result + + def reset(self): + IncrementalDecoder.reset(self) + self.buffer = "" + + def getstate(self): + # additional state info is always 0 + return (self.buffer, 0) + + def setstate(self, state): + # ignore additional state info + self.buffer = state[0] + +# +# The StreamWriter and StreamReader class provide generic working +# interfaces which can be used to implement new encoding submodules +# very easily. See encodings/utf_8.py for an example on how this is +# done. +# + +class StreamWriter(Codec): + + def __init__(self, stream, errors='strict'): + + """ Creates a StreamWriter instance. + + stream must be a file-like object open for writing + (binary) data. + + The StreamWriter may use different error handling + schemes by providing the errors keyword argument. These + parameters are predefined: + + 'strict' - raise a ValueError (or a subclass) + 'ignore' - ignore the character and continue with the next + 'replace'- replace with a suitable replacement character + 'xmlcharrefreplace' - Replace with the appropriate XML + character reference. + 'backslashreplace' - Replace with backslashed escape + sequences (only for encoding). + + The set of allowed parameter values can be extended via + register_error. + """ + self.stream = stream + self.errors = errors + + def write(self, object): + + """ Writes the object's contents encoded to self.stream. + """ + data, consumed = self.encode(object, self.errors) + self.stream.write(data) + + def writelines(self, list): + + """ Writes the concatenated list of strings to the stream + using .write(). + """ + self.write(''.join(list)) + + def reset(self): + + """ Flushes and resets the codec buffers used for keeping 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 rescan the whole + stream to recover state. + + """ + pass + + def seek(self, offset, whence=0): + self.stream.seek(offset, whence) + if whence == 0 and offset == 0: + self.reset() + + def __getattr__(self, name, + getattr=getattr): + + """ Inherit all other methods from the underlying stream. + """ + return getattr(self.stream, name) + + def __enter__(self): + return self + + def __exit__(self, type, value, tb): + self.stream.close() + +### + +class StreamReader(Codec): + + def __init__(self, stream, errors='strict'): + + """ Creates a StreamReader instance. + + stream must be a file-like object open for reading + (binary) data. + + The StreamReader may use different error handling + schemes by providing the errors keyword argument. These + parameters are predefined: + + 'strict' - raise a ValueError (or a subclass) + 'ignore' - ignore the character and continue with the next + 'replace'- replace with a suitable replacement character; + + The set of allowed parameter values can be extended via + register_error. + """ + self.stream = stream + self.errors = errors + self.bytebuffer = "" + # For str->str decoding this will stay a str + # For str->unicode decoding the first read will promote it to unicode + self.charbuffer = "" + self.linebuffer = None + + def decode(self, input, errors='strict'): + raise NotImplementedError + + def read(self, size=-1, chars=-1, firstline=False): + + """ Decodes data from the stream self.stream and returns the + resulting object. + + chars indicates the number of characters to read from the + stream. read() will never return more than chars + characters, but it might return less, if there are not enough + characters available. + + size indicates the approximate maximum number of bytes to + read from the stream for decoding purposes. The decoder + can modify this setting as appropriate. The default value + -1 indicates to read and decode as much as possible. size + is intended to prevent having to decode huge files in one + step. + + If firstline is true, and a UnicodeDecodeError happens + after the first line terminator in the input only the first line + will be returned, the rest of the input will be kept until the + next call to read(). + + The method should use a greedy read strategy meaning that + it should read as much data as is allowed within the + definition of the encoding and the given size, e.g. if + optional encoding endings or state markers are available + on the stream, these should be read too. + """ + # If we have lines cached, first merge them back into characters + if self.linebuffer: + self.charbuffer = "".join(self.linebuffer) + self.linebuffer = None + + # read until we get the required number of characters (if available) + while True: + # can the request be satisfied from the character buffer? + if chars >= 0: + if len(self.charbuffer) >= chars: + break + elif size >= 0: + if len(self.charbuffer) >= size: + break + # we need more data + if size < 0: + newdata = self.stream.read() + else: + newdata = self.stream.read(size) + # decode bytes (those remaining from the last call included) + data = self.bytebuffer + newdata + try: + newchars, decodedbytes = self.decode(data, self.errors) + except UnicodeDecodeError, exc: + if firstline: + newchars, decodedbytes = self.decode(data[:exc.start], self.errors) + lines = newchars.splitlines(True) + if len(lines)<=1: + raise + else: + raise + # keep undecoded bytes until the next call + self.bytebuffer = data[decodedbytes:] + # put new characters in the character buffer + self.charbuffer += newchars + # there was no data available + if not newdata: + break + if chars < 0: + # Return everything we've got + result = self.charbuffer + self.charbuffer = "" + else: + # Return the first chars characters + result = self.charbuffer[:chars] + self.charbuffer = self.charbuffer[chars:] + return result + + def readline(self, size=None, keepends=True): + + """ Read one line from the input stream and return the + decoded data. + + size, if given, is passed as size argument to the + read() method. + + """ + # If we have lines cached from an earlier read, return + # them unconditionally + if self.linebuffer: + line = self.linebuffer[0] + del self.linebuffer[0] + if len(self.linebuffer) == 1: + # revert to charbuffer mode; we might need more data + # next time + self.charbuffer = self.linebuffer[0] + self.linebuffer = None + if not keepends: + line = line.splitlines(False)[0] + return line + + readsize = size or 72 + line = "" + # If size is given, we call read() only once + while True: + data = self.read(readsize, firstline=True) + if data: + # If we're at a "\r" read one extra character (which might + # be a "\n") to get a proper line ending. If the stream is + # temporarily exhausted we return the wrong line ending. + if data.endswith("\r"): + data += self.read(size=1, chars=1) + + line += data + lines = line.splitlines(True) + if lines: + if len(lines) > 1: + # More than one line result; the first line is a full line + # to return + line = lines[0] + del lines[0] + if len(lines) > 1: + # cache the remaining lines + lines[-1] += self.charbuffer + self.linebuffer = lines + self.charbuffer = None + else: + # only one remaining line, put it back into charbuffer + self.charbuffer = lines[0] + self.charbuffer + if not keepends: + line = line.splitlines(False)[0] + break + line0withend = lines[0] + line0withoutend = lines[0].splitlines(False)[0] + if line0withend != line0withoutend: # We really have a line end + # Put the rest back together and keep it until the next call + self.charbuffer = "".join(lines[1:]) + self.charbuffer + if keepends: + line = line0withend + else: + line = line0withoutend + break + # we didn't get anything or this was our only try + if not data or size is not None: + if line and not keepends: + line = line.splitlines(False)[0] + break + if readsize<8000: + readsize *= 2 + return line + + def readlines(self, sizehint=None, keepends=True): + + """ Read all lines available on the input stream + and return them as list of lines. + + Line breaks are implemented using the codec's decoder + method and are included in the list entries. + + sizehint, if given, is ignored since there is no efficient + way to finding the true end-of-line. + + """ + data = self.read() + return data.splitlines(keepends) + + def reset(self): + + """ Resets the codec buffers used for keeping state. + + Note that no stream repositioning should take place. + This method is primarily intended to be able to recover + from decoding errors. + + """ + self.bytebuffer = "" + self.charbuffer = u"" + self.linebuffer = None + + def seek(self, offset, whence=0): + """ Set the input stream's current position. + + Resets the codec buffers used for keeping state. + """ + self.stream.seek(offset, whence) + self.reset() + + def next(self): + + """ Return the next decoded line from the input stream.""" + line = self.readline() + if line: + return line + raise StopIteration + + def __iter__(self): + return self + + def __getattr__(self, name, + getattr=getattr): + + """ Inherit all other methods from the underlying stream. + """ + return getattr(self.stream, name) + + def __enter__(self): + return self + + def __exit__(self, type, value, tb): + self.stream.close() + +### + +class StreamReaderWriter: + + """ StreamReaderWriter instances allow wrapping streams which + work in both read and write modes. + + The design is such that one can use the factory functions + returned by the codec.lookup() function to construct the + instance. + + """ + # Optional attributes set by the file wrappers below + encoding = 'unknown' + + def __init__(self, stream, Reader, Writer, errors='strict'): + + """ Creates a StreamReaderWriter instance. + + stream must be a Stream-like object. + + Reader, Writer must be factory functions or classes + providing the StreamReader, StreamWriter interface resp. + + Error handling is done in the same way as defined for the + StreamWriter/Readers. + + """ + self.stream = stream + self.reader = Reader(stream, errors) + self.writer = Writer(stream, errors) + self.errors = errors + + def read(self, size=-1): + + return self.reader.read(size) + + def readline(self, size=None): + + return self.reader.readline(size) + + def readlines(self, sizehint=None): + + return self.reader.readlines(sizehint) + + def next(self): + + """ Return the next decoded line from the input stream.""" + return self.reader.next() + + def __iter__(self): + return self + + def write(self, data): + + return self.writer.write(data) + + def writelines(self, list): + + return self.writer.writelines(list) + + def reset(self): + + self.reader.reset() + self.writer.reset() + + def seek(self, offset, whence=0): + self.stream.seek(offset, whence) + self.reader.reset() + if whence == 0 and offset == 0: + self.writer.reset() + + def __getattr__(self, name, + getattr=getattr): + + """ Inherit all other methods from the underlying stream. + """ + return getattr(self.stream, name) + + # these are needed to make "with codecs.open(...)" work properly + + def __enter__(self): + return self + + def __exit__(self, type, value, tb): + self.stream.close() + +### + +class StreamRecoder: + + """ StreamRecoder instances provide a frontend - backend + view of encoding data. + + They use the complete set of APIs returned by the + codecs.lookup() function to implement their task. + + Data written to the stream is first decoded into an + intermediate format (which is dependent on the given codec + combination) and then written to the stream using an instance + of the provided Writer class. + + In the other direction, data is read from the stream using a + Reader instance and then return encoded data to the caller. + + """ + # Optional attributes set by the file wrappers below + data_encoding = 'unknown' + file_encoding = 'unknown' + + def __init__(self, stream, encode, decode, Reader, Writer, + errors='strict'): + + """ Creates a StreamRecoder instance which implements a two-way + conversion: encode and decode work on the frontend (the + input to .read() and output of .write()) while + Reader and Writer work on the backend (reading and + writing to the stream). + + You can use these objects to do transparent direct + recodings from e.g. latin-1 to utf-8 and back. + + stream must be a file-like object. + + encode, decode must adhere to the Codec interface, Reader, + Writer must be factory functions or classes providing the + StreamReader, StreamWriter interface resp. + + encode and decode are needed for the frontend translation, + Reader and Writer for the backend translation. Unicode is + used as intermediate encoding. + + Error handling is done in the same way as defined for the + StreamWriter/Readers. + + """ + self.stream = stream + self.encode = encode + self.decode = decode + self.reader = Reader(stream, errors) + self.writer = Writer(stream, errors) + self.errors = errors + + def read(self, size=-1): + + data = self.reader.read(size) + data, bytesencoded = self.encode(data, self.errors) + return data + + def readline(self, size=None): + + if size is None: + data = self.reader.readline() + else: + data = self.reader.readline(size) + data, bytesencoded = self.encode(data, self.errors) + return data + + def readlines(self, sizehint=None): + + data = self.reader.read() + data, bytesencoded = self.encode(data, self.errors) + return data.splitlines(1) + + def next(self): + + """ Return the next decoded line from the input stream.""" + data = self.reader.next() + data, bytesencoded = self.encode(data, self.errors) + return data + + def __iter__(self): + return self + + def write(self, data): + + data, bytesdecoded = self.decode(data, self.errors) + return self.writer.write(data) + + def writelines(self, list): + + data = ''.join(list) + data, bytesdecoded = self.decode(data, self.errors) + return self.writer.write(data) + + def reset(self): + + self.reader.reset() + self.writer.reset() + + def __getattr__(self, name, + getattr=getattr): + + """ Inherit all other methods from the underlying stream. + """ + return getattr(self.stream, name) + + def __enter__(self): + return self + + def __exit__(self, type, value, tb): + self.stream.close() + +### Shortcuts + +def open(filename, mode='rb', encoding=None, errors='strict', buffering=1): + + """ Open an encoded file using the given mode and return + a wrapped version providing transparent encoding/decoding. + + Note: The wrapped version will only accept the object format + defined by the codecs, i.e. Unicode objects for most builtin + codecs. Output is also codec dependent and will usually be + Unicode as well. + + Files are always opened in binary mode, even if no binary mode + was specified. This is done to avoid data loss due to encodings + using 8-bit values. The default file mode is 'rb' meaning to + open the file in binary read mode. + + encoding specifies the encoding which is to be used for the + file. + + errors may be given to define the error handling. It defaults + to 'strict' which causes ValueErrors to be raised in case an + encoding error occurs. + + buffering has the same meaning as for the builtin open() API. + It defaults to line buffered. + + The returned wrapped file object provides an extra attribute + .encoding which allows querying the used encoding. This + attribute is only available if an encoding was specified as + parameter. + + """ + if encoding is not None: + if 'U' in mode: + # No automatic conversion of '\n' is done on reading and writing + mode = mode.strip().replace('U', '') + if mode[:1] not in set('rwa'): + mode = 'r' + mode + if 'b' not in mode: + # Force opening of the file in binary mode + mode = mode + 'b' + file = __builtin__.open(filename, mode, buffering) + if encoding is None: + return file + info = lookup(encoding) + srw = StreamReaderWriter(file, info.streamreader, info.streamwriter, errors) + # Add attributes to simplify introspection + srw.encoding = encoding + return srw + +def EncodedFile(file, data_encoding, file_encoding=None, errors='strict'): + + """ Return a wrapped version of file which provides transparent + encoding translation. + + Strings written to the wrapped file are interpreted according + to the given data_encoding and then written to the original + file as string using file_encoding. The intermediate encoding + will usually be Unicode but depends on the specified codecs. + + Strings are read from the file using file_encoding and then + passed back to the caller as string using data_encoding. + + If file_encoding is not given, it defaults to data_encoding. + + errors may be given to define the error handling. It defaults + to 'strict' which causes ValueErrors to be raised in case an + encoding error occurs. + + The returned wrapped file object provides two extra attributes + .data_encoding and .file_encoding which reflect the given + parameters of the same name. The attributes can be used for + introspection by Python programs. + + """ + if file_encoding is None: + file_encoding = data_encoding + data_info = lookup(data_encoding) + file_info = lookup(file_encoding) + sr = StreamRecoder(file, data_info.encode, data_info.decode, + file_info.streamreader, file_info.streamwriter, errors) + # Add attributes to simplify introspection + sr.data_encoding = data_encoding + sr.file_encoding = file_encoding + return sr + +### Helpers for codec lookup + +def getencoder(encoding): + + """ Lookup up the codec for the given encoding and return + its encoder function. + + Raises a LookupError in case the encoding cannot be found. + + """ + return lookup(encoding).encode + +def getdecoder(encoding): + + """ Lookup up the codec for the given encoding and return + its decoder function. + + Raises a LookupError in case the encoding cannot be found. + + """ + return lookup(encoding).decode + +def getincrementalencoder(encoding): + + """ Lookup up the codec for the given encoding and return + its IncrementalEncoder class or factory function. + + Raises a LookupError in case the encoding cannot be found + or the codecs doesn't provide an incremental encoder. + + """ + encoder = lookup(encoding).incrementalencoder + if encoder is None: + raise LookupError(encoding) + return encoder + +def getincrementaldecoder(encoding): + + """ Lookup up the codec for the given encoding and return + its IncrementalDecoder class or factory function. + + Raises a LookupError in case the encoding cannot be found + or the codecs doesn't provide an incremental decoder. + + """ + decoder = lookup(encoding).incrementaldecoder + if decoder is None: + raise LookupError(encoding) + return decoder + +def getreader(encoding): + + """ Lookup up the codec for the given encoding and return + its StreamReader class or factory function. + + Raises a LookupError in case the encoding cannot be found. + + """ + return lookup(encoding).streamreader + +def getwriter(encoding): + + """ Lookup up the codec for the given encoding and return + its StreamWriter class or factory function. + + Raises a LookupError in case the encoding cannot be found. + + """ + return lookup(encoding).streamwriter + +def iterencode(iterator, encoding, errors='strict', **kwargs): + """ + Encoding iterator. + + Encodes the input strings from the iterator using a IncrementalEncoder. + + errors and kwargs are passed through to the IncrementalEncoder + constructor. + """ + encoder = getincrementalencoder(encoding)(errors, **kwargs) + for input in iterator: + output = encoder.encode(input) + if output: + yield output + output = encoder.encode("", True) + if output: + yield output + +def iterdecode(iterator, encoding, errors='strict', **kwargs): + """ + Decoding iterator. + + Decodes the input strings from the iterator using a IncrementalDecoder. + + errors and kwargs are passed through to the IncrementalDecoder + constructor. + """ + decoder = getincrementaldecoder(encoding)(errors, **kwargs) + for input in iterator: + output = decoder.decode(input) + if output: + yield output + output = decoder.decode("", True) + if output: + yield output + +### Helpers for charmap-based codecs + +def make_identity_dict(rng): + + """ make_identity_dict(rng) -> dict + + Return a dictionary where elements of the rng sequence are + mapped to themselves. + + """ + res = {} + for i in rng: + res[i]=i + return res + +def make_encoding_map(decoding_map): + + """ Creates an encoding map from a decoding map. + + If a target mapping in the decoding map occurs multiple + times, then that target is mapped to None (undefined mapping), + causing an exception when encountered by the charmap codec + during translation. + + One example where this happens is cp875.py which decodes + multiple character to \u001a. + + """ + m = {} + for k,v in decoding_map.items(): + if not v in m: + m[v] = k + else: + m[v] = None + return m + +### error handlers + +try: + strict_errors = lookup_error("strict") + ignore_errors = lookup_error("ignore") + replace_errors = lookup_error("replace") + xmlcharrefreplace_errors = lookup_error("xmlcharrefreplace") + backslashreplace_errors = lookup_error("backslashreplace") +except LookupError: + # In --disable-unicode builds, these error handler are missing + strict_errors = None + ignore_errors = None + replace_errors = None + xmlcharrefreplace_errors = None + backslashreplace_errors = None + +# Tell modulefinder that using codecs probably needs the encodings +# package +_false = 0 +if _false: + import encodings + +### Tests + +if __name__ == '__main__': + + # Make stdout translate Latin-1 output into UTF-8 output + sys.stdout = EncodedFile(sys.stdout, 'latin-1', 'utf-8') + + # Have stdin translate Latin-1 input into UTF-8 input + sys.stdin = EncodedFile(sys.stdin, 'utf-8', 'latin-1') diff --git a/PythonHome/Lib/codecs.pyc b/PythonHome/Lib/codecs.pyc index c39a3321e71c6579844a9db95d8bd9bc494785b4..ea2981c65406b9709f6f79d34ec937e680323da5 100644 GIT binary patch delta 5187 zcmbW*?MstU7zS|X)JX_J&sf&x%ml@@iY1!Zi(!pQY%dDA%}1%l+UDM*o`LBw7iufS zSa)U^1SWwAm3mW%MU=+uixkv{B0oj#W1k`jf?|Kdx&DA3*E#38cFxUcI{zl;FZ5|F z2lMjstWB~%s089(xii+kx3$A=Yj+%z?Qx|quE@uI-nd_OTvh_H=*d{bM^`jI0hK6r zi!1(Kyj}#bmC~?UoKd~hA+C5z%I1qR8rQ7?s(afMpwwme0ku%}6;RXLL*k0HJHDyJ z85J57K&1?y0TnAx0jkJYOPeN%T8tJzJF6v{G-_39nm5`2uc`2fD;}))gfzNm7mJ6{ z&MKhMoT*9xOJrwt8B(+UnjZ0;@sFAhNZ8w2q|+yMXT+CC1{2b0HbsD}T$fwS=K#56 zMp|6GXP^KGdusU&s71F#>-)a|GM$ikweC976i@vc5IEB%QFFr+K>lqw52)w?;0I3H z#*5-vJlR-)eDk?OaUjfm_#ZMqHCg>C4L`8{0!9>mc&ZJ!_msb$NmaX8HWo{s)$5Koxp@cE6xe=Jnn3-Kngv2W=K4Ywsu|u)NM%VT(dyd zI~VfN_PLRLEkdf!lLYp)=6MgOnXZ?B3d_hD=8B({k>a22z9+s)-qN#yT&`Ik@+2-_ zK#u>8|F!tW$QRfIlp`nu>P7GopmMX!SnoU_n?s|3`WQmqis>*`W8`9-h&&eG7q>>A zBY$3$#w!bfwB~_wP4w8sHt8V9zlXhfu>K8q6B zPryUz?v3lnsc1kYRoHs58)Au~=)c>ORZGJl>VQ--c z+c2@aMa;_fqInFIOK=t|_3NFOfEI1ay&B(p0%D6wqG0nS*q2agzZL>B%Gbau>_0@~ z`ifE9k$ie(m6KvHNv%dIta=8nuMU8XR^tK4*E)8fS&U`fL9Nmbj8yCJL-4ZWFV1SF zvrV1C{mxYwI=)|f6io0VpmXS&!D5ff0p7j4G-5aPy8Vvz+tTsx~^VgCilCj~yDwY~=16vX!q z2eCOdp?l(5&TN~*yCBcwt}xzSZ8sLA?MaGB>37d(FioThED^zzZja*kv7vVW*2)uR z?Rx~i)`!iApT%a_&cV-t(_%01KlCduZ4}?ahX-=tqBC8|MqIkeh*N{F0BLGa;+g9T jc}+L>Ks5Ib%^^l^eL(EIZ9|-;(>T+iJ9U8c?e4@s0?|j1 diff --git a/PythonHome/Lib/codeop.pyc b/PythonHome/Lib/codeop.py similarity index 56% rename from PythonHome/Lib/codeop.pyc rename to PythonHome/Lib/codeop.py index 8aecb7d4e23778b5b410c21727b7c9679222a711..5616d92a858ce3427ec80333e3b67f57b042227e 100644 GIT binary patch delta 1861 zcma)7-D(p-6sAS0ECskXf2*31s)?aeTWVi zNhgf({V*M7aUvL=LoSc}Cip!k%3n#EOO%h+d*j|qw)uK@pS{}I+kVeBw>GzS_YrIT zth2se##DnHZo&bkk&VqDm1-ng1J64W5wIa2_wQMstzH69ynQA33B6RF8f*)GivA7oB$dK? z6p0q4DZ=aVu%9Lb>WfpJ_#2a1WQ3I`kGC1u+PCmEcq6ieBPR&`DK-P(P^arUXlxfj z9C*%~Qdk+GRNEaLJa&sv!t_YsHyw0MC*7}E1#529xQunCZW~5Te=I$4p^CFmWCq@j zrQv5=N~KsxbXi(bXfB>>fX=Z)4Dwu`0#yk69D9R$wwZI}s#5hfskm$Zmp@9dXtzuL z{?lW{VQ0g$tx6>+GsKD#QDrbn;4n)ow49=XOpX0++on|_QvsEz0o^VXU!6*aDjsWb zjo-HCE!%0z^TC2Vx9Z9j{Fqka{6t)PIgpUnn*(thWraeehboiy%N8JRCYbFEzX|Pf_U%q}yV!2k zVlS7qCCt3wX}=Yw%mujyxhjfWYuk&w6BVZcxh!{YUHEt@Mt~fQo*x{NlWK|8%ikRNmgW QA-U2=wk}0ru9+6RzXEwFz5oCK delta 2510 zcmb7GTW=dx5T3KU+1QQ~hbE*XEw==aB~U~ILPAs}A_)>u+-Th@#4Q{g?O*v{?= ziX~esa2}9&qe8s!9}o(CHzI=iEbU-iT&qz z?zfFE%Qfo%M(|w5ihly}i7KFqe2eOeDvEZ90!6zPt$zM2Rcs0zeh+NwS@eZP``4*5 zLcUGDL;eWu*i>=Jcd0T;{wN*cxD5FjVY1|BY1z+_KSoCuRlvYzg8V#h_lPztV|<2R zAbLMouE`yb&ZjRbB)FHmKV-bvdHeqk0F-4BS**S`SCIws7 zQ1n@QuCI&YBv;Q2vI7Qxz`(s|;Lv0pI~j^b6==DWrF^uc41#wFnP6s= znTHm!+)jAoTdN;lxyU&$#YiFLLJ%^{F2D@f`MO#crd5sO7`dlhuE=ROOyX8OG%07I zuqBG6W+O0MoN~Kis)uV))Qn^!3R+Q-H%tN?oD@DXE+5o9h-!gh`8LqdsO|-+yuG*8 zOdY6)IM;?k5T)ngc_Z~Pik5__HT^)mVdlmuw^W1`35gkUi^+rA;no9IYPJ?zZ8HI( z-mA8^1cnU9RY>ADLCBg>c{QUlR$gVT2{mEacq=Fe&$)r8s~q*Bs

PN6x47Xy@> z00qfSdJbBGlUyotN(J<20KVDGK(O9k`B1OkDc#i{eY$>oQ?IVAu9fZ<`CKp0WSj}R zeKE8Pk#Rz~wfN)!yi|}rQ8AbNX4q&Qm|JP0!^TcMxYT<%eHy^2^MZ#*&FS}#e;I1C!B@l#xv4%#hSUl*Cz@Tp}y26}8URf@V zpFs7|$CFQz8e8+?Os`ImS`Ip23hz1I+;Yyc!R}-+_HNGzkqPK&pIf#N-TCLX95~bmc^idLtsK~B* z*O?6BO~4|Zvn8nQpLcm?66r9(p{`Zyb*)h+igO^OuBmY~sb*C=QBo!DeXR{EXua3; z5Abo&a+lVAv!=E8Jhr?Akh5EbOPhPJ1H4Vn1#(8QRKRgn);g8H87U}EB!bg z;fp8eVr&R5j=yt@Y6!geQ-|XAw85W8i>)z)JgKpn2c(=CC0M zW0bLTE3C 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__root + except AttributeError: + self.__root = root = [] # sentinel node + root[:] = [root, root, None] + self.__map = {} + self.__update(*args, **kwds) + + def __setitem__(self, key, value, dict_setitem=dict.__setitem__): + 'od.__setitem__(i, y) <==> od[i]=y' + # Setting a new item creates a new link at the end of the linked list, + # and the inherited dictionary is updated with the new key/value pair. + if key not in self: + root = self.__root + last = root[0] + last[1] = root[0] = self.__map[key] = [last, root, key] + return dict_setitem(self, key, value) + + def __delitem__(self, key, dict_delitem=dict.__delitem__): + 'od.__delitem__(y) <==> del od[y]' + # Deleting an existing item uses self.__map to find the link which gets + # removed by updating the links in the predecessor and successor nodes. + dict_delitem(self, key) + link_prev, link_next, _ = self.__map.pop(key) + link_prev[1] = link_next # update link_prev[NEXT] + link_next[0] = link_prev # update link_next[PREV] + + def __iter__(self): + 'od.__iter__() <==> iter(od)' + # Traverse the linked list in order. + root = self.__root + curr = root[1] # start at the first node + while curr is not root: + yield curr[2] # yield the curr[KEY] + curr = curr[1] # move to next node + + def __reversed__(self): + 'od.__reversed__() <==> reversed(od)' + # Traverse the linked list in reverse order. + root = self.__root + curr = root[0] # start at the last node + while curr is not root: + yield curr[2] # yield the curr[KEY] + curr = curr[0] # move to previous node + + def clear(self): + 'od.clear() -> None. Remove all items from od.' + root = self.__root + root[:] = [root, root, None] + self.__map.clear() + dict.clear(self) + + # -- the following methods do not depend on the internal structure -- + + def keys(self): + 'od.keys() -> list of keys in od' + return list(self) + + def values(self): + 'od.values() -> list of values in od' + return [self[key] for key in self] + + def items(self): + 'od.items() -> list of (key, value) pairs in od' + return [(key, self[key]) for key in self] + + def iterkeys(self): + 'od.iterkeys() -> an iterator over the keys in od' + return iter(self) + + def itervalues(self): + 'od.itervalues -> an iterator over the values in od' + for k in self: + yield self[k] + + def iteritems(self): + 'od.iteritems -> an iterator over the (key, value) pairs in od' + for k in self: + yield (k, self[k]) + + update = MutableMapping.update + + __update = update # let subclasses override update without breaking __init__ + + __marker = object() + + def pop(self, key, default=__marker): + '''od.pop(k[,d]) -> v, remove specified key and return the corresponding + value. If key is not found, d is returned if given, otherwise KeyError + is raised. + + ''' + if key in self: + result = self[key] + del self[key] + return result + if default is self.__marker: + raise KeyError(key) + return default + + def setdefault(self, key, default=None): + 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' + if key in self: + return self[key] + self[key] = default + return default + + def popitem(self, last=True): + '''od.popitem() -> (k, v), return and remove a (key, value) pair. + Pairs are returned in LIFO order if last is true or FIFO order if false. + + ''' + if not self: + raise KeyError('dictionary is empty') + key = next(reversed(self) if last else iter(self)) + value = self.pop(key) + return key, value + + def __repr__(self, _repr_running={}): + 'od.__repr__() <==> repr(od)' + call_key = id(self), _get_ident() + if call_key in _repr_running: + return '...' + _repr_running[call_key] = 1 + try: + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, self.items()) + finally: + del _repr_running[call_key] + + def __reduce__(self): + 'Return state information for pickling' + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + for k in vars(OrderedDict()): + inst_dict.pop(k, None) + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) + + def copy(self): + 'od.copy() -> a shallow copy of od' + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S. + If not specified, the value defaults to None. + + ''' + self = cls() + for key in iterable: + self[key] = value + return self + + def __eq__(self, other): + '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive + while comparison to a regular mapping is order-insensitive. + + ''' + if isinstance(other, OrderedDict): + return dict.__eq__(self, other) and all(_imap(_eq, self, other)) + return dict.__eq__(self, other) + + def __ne__(self, other): + 'od.__ne__(y) <==> od!=y' + return not self == other + + # -- the following methods support python 3.x style dictionary views -- + + def viewkeys(self): + "od.viewkeys() -> a set-like object providing a view on od's keys" + return KeysView(self) + + def viewvalues(self): + "od.viewvalues() -> an object providing a view on od's values" + return ValuesView(self) + + def viewitems(self): + "od.viewitems() -> a set-like object providing a view on od's items" + return ItemsView(self) + + +################################################################################ +### namedtuple +################################################################################ + +_class_template = '''\ +class {typename}(tuple): + '{typename}({arg_list})' + + __slots__ = () + + _fields = {field_names!r} + + def __new__(_cls, {arg_list}): + 'Create new instance of {typename}({arg_list})' + return _tuple.__new__(_cls, ({arg_list})) + + @classmethod + def _make(cls, iterable, new=tuple.__new__, len=len): + 'Make a new {typename} object from a sequence or iterable' + result = new(cls, iterable) + if len(result) != {num_fields:d}: + raise TypeError('Expected {num_fields:d} arguments, got %d' % len(result)) + return result + + def __repr__(self): + 'Return a nicely formatted representation string' + return '{typename}({repr_fmt})' % self + + def _asdict(self): + 'Return a new OrderedDict which maps field names to their values' + return OrderedDict(zip(self._fields, self)) + + def _replace(_self, **kwds): + 'Return a new {typename} object replacing specified fields with new values' + result = _self._make(map(kwds.pop, {field_names!r}, _self)) + if kwds: + raise ValueError('Got unexpected field names: %r' % kwds.keys()) + return result + + def __getnewargs__(self): + 'Return self as a plain tuple. Used by copy and pickle.' + return tuple(self) + + __dict__ = _property(_asdict) + + def __getstate__(self): + 'Exclude the OrderedDict from pickling' + pass + +{field_defs} +''' + +_repr_template = '{name}=%r' + +_field_template = '''\ + {name} = _property(_itemgetter({index:d}), doc='Alias for field number {index:d}') +''' + +def namedtuple(typename, field_names, verbose=False, rename=False): + """Returns a new subclass of tuple with named fields. + + >>> Point = namedtuple('Point', ['x', 'y']) + >>> Point.__doc__ # docstring for the new class + 'Point(x, y)' + >>> p = Point(11, y=22) # instantiate with positional args or keywords + >>> p[0] + p[1] # indexable like a plain tuple + 33 + >>> x, y = p # unpack like a regular tuple + >>> x, y + (11, 22) + >>> p.x + p.y # fields also accessable by name + 33 + >>> d = p._asdict() # convert to a dictionary + >>> d['x'] + 11 + >>> Point(**d) # convert from a dictionary + Point(x=11, y=22) + >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields + Point(x=100, y=22) + + """ + + # Validate the field names. At the user's option, either generate an error + # message or automatically replace the field name with a valid name. + if isinstance(field_names, basestring): + field_names = field_names.replace(',', ' ').split() + field_names = map(str, field_names) + typename = str(typename) + if rename: + seen = set() + for index, name in enumerate(field_names): + if (not all(c.isalnum() or c=='_' for c in name) + or _iskeyword(name) + or not name + or name[0].isdigit() + or name.startswith('_') + or name in seen): + field_names[index] = '_%d' % index + seen.add(name) + for name in [typename] + field_names: + if type(name) != str: + raise TypeError('Type names and field names must be strings') + if not all(c.isalnum() or c=='_' for c in name): + raise ValueError('Type names and field names can only contain ' + 'alphanumeric characters and underscores: %r' % name) + if _iskeyword(name): + raise ValueError('Type names and field names cannot be a ' + 'keyword: %r' % name) + if name[0].isdigit(): + raise ValueError('Type names and field names cannot start with ' + 'a number: %r' % name) + seen = set() + for name in field_names: + if name.startswith('_') and not rename: + raise ValueError('Field names cannot start with an underscore: ' + '%r' % name) + if name in seen: + raise ValueError('Encountered duplicate field name: %r' % name) + seen.add(name) + + # Fill-in the class template + class_definition = _class_template.format( + typename = typename, + field_names = tuple(field_names), + num_fields = len(field_names), + arg_list = repr(tuple(field_names)).replace("'", "")[1:-1], + repr_fmt = ', '.join(_repr_template.format(name=name) + for name in field_names), + field_defs = '\n'.join(_field_template.format(index=index, name=name) + for index, name in enumerate(field_names)) + ) + if verbose: + print class_definition + + # Execute the template string in a temporary namespace and support + # tracing utilities by setting a value for frame.f_globals['__name__'] + namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename, + OrderedDict=OrderedDict, _property=property, _tuple=tuple) + try: + exec class_definition in namespace + except SyntaxError as e: + raise SyntaxError(e.message + ':\n' + class_definition) + result = namespace[typename] + + # For pickling to work, the __module__ variable needs to be set to the frame + # where the named tuple is created. Bypass this step in environments where + # sys._getframe is not defined (Jython for example) or sys._getframe is not + # defined for arguments greater than 0 (IronPython). + try: + result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__') + except (AttributeError, ValueError): + pass + + return result + + +######################################################################## +### Counter +######################################################################## + +class Counter(dict): + '''Dict subclass for counting hashable items. Sometimes called a bag + or multiset. Elements are stored as dictionary keys and their counts + are stored as dictionary values. + + >>> c = Counter('abcdeabcdabcaba') # count elements from a string + + >>> c.most_common(3) # three most common elements + [('a', 5), ('b', 4), ('c', 3)] + >>> sorted(c) # list all unique elements + ['a', 'b', 'c', 'd', 'e'] + >>> ''.join(sorted(c.elements())) # list elements with repetitions + 'aaaaabbbbcccdde' + >>> sum(c.values()) # total of all counts + 15 + + >>> c['a'] # count of letter 'a' + 5 + >>> for elem in 'shazam': # update counts from an iterable + ... c[elem] += 1 # by adding 1 to each element's count + >>> c['a'] # now there are seven 'a' + 7 + >>> del c['b'] # remove all 'b' + >>> c['b'] # now there are zero 'b' + 0 + + >>> d = Counter('simsalabim') # make another counter + >>> c.update(d) # add in the second counter + >>> c['a'] # now there are nine 'a' + 9 + + >>> c.clear() # empty the counter + >>> c + Counter() + + Note: If a count is set to zero or reduced to zero, it will remain + in the counter until the entry is deleted or the counter is cleared: + + >>> c = Counter('aaabbc') + >>> c['b'] -= 2 # reduce the count of 'b' by two + >>> c.most_common() # 'b' is still in, but its count is zero + [('a', 3), ('c', 1), ('b', 0)] + + ''' + # References: + # http://en.wikipedia.org/wiki/Multiset + # http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html + # http://www.demo2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm + # http://code.activestate.com/recipes/259174/ + # Knuth, TAOCP Vol. II section 4.6.3 + + def __init__(self, iterable=None, **kwds): + '''Create a new, empty Counter object. And if given, count elements + from an input iterable. Or, initialize the count from another mapping + of elements to their counts. + + >>> c = Counter() # a new, empty counter + >>> c = Counter('gallahad') # a new counter from an iterable + >>> c = Counter({'a': 4, 'b': 2}) # a new counter from a mapping + >>> c = Counter(a=4, b=2) # a new counter from keyword args + + ''' + super(Counter, self).__init__() + self.update(iterable, **kwds) + + def __missing__(self, key): + 'The count of elements not in the Counter is zero.' + # Needed so that self[missing_item] does not raise KeyError + return 0 + + def most_common(self, n=None): + '''List the n most common elements and their counts from the most + common to the least. If n is None, then list all element counts. + + >>> Counter('abcdeabcdabcaba').most_common(3) + [('a', 5), ('b', 4), ('c', 3)] + + ''' + # Emulate Bag.sortedByCount from Smalltalk + if n is None: + return sorted(self.iteritems(), key=_itemgetter(1), reverse=True) + return _heapq.nlargest(n, self.iteritems(), key=_itemgetter(1)) + + def elements(self): + '''Iterator over elements repeating each as many times as its count. + + >>> c = Counter('ABCABC') + >>> sorted(c.elements()) + ['A', 'A', 'B', 'B', 'C', 'C'] + + # Knuth's example for prime factors of 1836: 2**2 * 3**3 * 17**1 + >>> prime_factors = Counter({2: 2, 3: 3, 17: 1}) + >>> product = 1 + >>> for factor in prime_factors.elements(): # loop over factors + ... product *= factor # and multiply them + >>> product + 1836 + + Note, if an element's count has been set to zero or is a negative + number, elements() will ignore it. + + ''' + # Emulate Bag.do from Smalltalk and Multiset.begin from C++. + return _chain.from_iterable(_starmap(_repeat, self.iteritems())) + + # Override dict methods where necessary + + @classmethod + def fromkeys(cls, iterable, v=None): + # There is no equivalent method for counters because setting v=1 + # means that no element can have a count greater than one. + raise NotImplementedError( + 'Counter.fromkeys() is undefined. Use Counter(iterable) instead.') + + def update(self, iterable=None, **kwds): + '''Like dict.update() but add counts instead of replacing them. + + Source can be an iterable, a dictionary, or another Counter instance. + + >>> c = Counter('which') + >>> c.update('witch') # add elements from another iterable + >>> d = Counter('watch') + >>> c.update(d) # add elements from another counter + >>> c['h'] # four 'h' in which, witch, and watch + 4 + + ''' + # The regular dict.update() operation makes no sense here because the + # replace behavior results in the some of original untouched counts + # being mixed-in with all of the other counts for a mismash that + # doesn't have a straight-forward interpretation in most counting + # contexts. Instead, we implement straight-addition. Both the inputs + # and outputs are allowed to contain zero and negative counts. + + if iterable is not None: + if isinstance(iterable, Mapping): + if self: + self_get = self.get + for elem, count in iterable.iteritems(): + self[elem] = self_get(elem, 0) + count + else: + super(Counter, self).update(iterable) # fast path when counter is empty + else: + self_get = self.get + for elem in iterable: + self[elem] = self_get(elem, 0) + 1 + if kwds: + self.update(kwds) + + def subtract(self, iterable=None, **kwds): + '''Like dict.update() but subtracts counts instead of replacing them. + Counts can be reduced below zero. Both the inputs and outputs are + allowed to contain zero and negative counts. + + Source can be an iterable, a dictionary, or another Counter instance. + + >>> c = Counter('which') + >>> c.subtract('witch') # subtract elements from another iterable + >>> c.subtract(Counter('watch')) # subtract elements from another counter + >>> c['h'] # 2 in which, minus 1 in witch, minus 1 in watch + 0 + >>> c['w'] # 1 in which, minus 1 in witch, minus 1 in watch + -1 + + ''' + if iterable is not None: + self_get = self.get + if isinstance(iterable, Mapping): + for elem, count in iterable.items(): + self[elem] = self_get(elem, 0) - count + else: + for elem in iterable: + self[elem] = self_get(elem, 0) - 1 + if kwds: + self.subtract(kwds) + + def copy(self): + 'Return a shallow copy.' + return self.__class__(self) + + def __reduce__(self): + return self.__class__, (dict(self),) + + def __delitem__(self, elem): + 'Like dict.__delitem__() but does not raise KeyError for missing values.' + if elem in self: + super(Counter, self).__delitem__(elem) + + def __repr__(self): + if not self: + return '%s()' % self.__class__.__name__ + items = ', '.join(map('%r: %r'.__mod__, self.most_common())) + return '%s({%s})' % (self.__class__.__name__, items) + + # Multiset-style mathematical operations discussed in: + # Knuth TAOCP Volume II section 4.6.3 exercise 19 + # and at http://en.wikipedia.org/wiki/Multiset + # + # Outputs guaranteed to only include positive counts. + # + # To strip negative and zero counts, add-in an empty counter: + # c += Counter() + + def __add__(self, other): + '''Add counts from two counters. + + >>> Counter('abbb') + Counter('bcc') + Counter({'b': 4, 'c': 2, 'a': 1}) + + ''' + if not isinstance(other, Counter): + return NotImplemented + result = Counter() + for elem, count in self.items(): + newcount = count + other[elem] + if newcount > 0: + result[elem] = newcount + for elem, count in other.items(): + if elem not in self and count > 0: + result[elem] = count + return result + + def __sub__(self, other): + ''' Subtract count, but keep only results with positive counts. + + >>> Counter('abbbc') - Counter('bccd') + Counter({'b': 2, 'a': 1}) + + ''' + if not isinstance(other, Counter): + return NotImplemented + result = Counter() + for elem, count in self.items(): + newcount = count - other[elem] + if newcount > 0: + result[elem] = newcount + for elem, count in other.items(): + if elem not in self and count < 0: + result[elem] = 0 - count + return result + + def __or__(self, other): + '''Union is the maximum of value in either of the input counters. + + >>> Counter('abbb') | Counter('bcc') + Counter({'b': 3, 'c': 2, 'a': 1}) + + ''' + if not isinstance(other, Counter): + return NotImplemented + result = Counter() + for elem, count in self.items(): + other_count = other[elem] + newcount = other_count if count < other_count else count + if newcount > 0: + result[elem] = newcount + for elem, count in other.items(): + if elem not in self and count > 0: + result[elem] = count + return result + + def __and__(self, other): + ''' Intersection is the minimum of corresponding counts. + + >>> Counter('abbb') & Counter('bcc') + Counter({'b': 1}) + + ''' + if not isinstance(other, Counter): + return NotImplemented + result = Counter() + for elem, count in self.items(): + other_count = other[elem] + newcount = count if count < other_count else other_count + if newcount > 0: + result[elem] = newcount + return result + + +if __name__ == '__main__': + # verify that instances can be pickled + from cPickle import loads, dumps + Point = namedtuple('Point', 'x, y', True) + p = Point(x=10, y=20) + assert p == loads(dumps(p)) + + # test and demonstrate ability to override methods + class Point(namedtuple('Point', 'x y')): + __slots__ = () + @property + def hypot(self): + return (self.x ** 2 + self.y ** 2) ** 0.5 + def __str__(self): + return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot) + + for p in Point(3, 4), Point(14, 5/7.): + print p + + class Point(namedtuple('Point', 'x y')): + 'Point class with optimized _make() and _replace() without error-checking' + __slots__ = () + _make = classmethod(tuple.__new__) + def _replace(self, _map=map, **kwds): + return self._make(_map(kwds.get, ('x', 'y'), self)) + + print Point(11, 22)._replace(x=100) + + Point3D = namedtuple('Point3D', Point._fields + ('z',)) + print Point3D.__doc__ + + import doctest + TestResults = namedtuple('TestResults', 'failed attempted') + print TestResults(*doctest.testmod()) diff --git a/PythonHome/Lib/collections.pyc b/PythonHome/Lib/collections.pyc index 54d3ae98b552a6a01368061d0051c7b6bf1f79be..c947e2e5e010908d4f6230e319d5b39bd8ac0266 100644 GIT binary patch delta 3073 zcmaF7pYilr#tjDSh7Jr245?Nz>6s-NrAaa2`4xIz!Tx?h0nRc0r6mQWB{43kNu}vA z0hJ{g`FS4sxv7&Kr6e|ovr99Qu61)GhXNVeCO2|OO+LkWigXJ>Zk@cF>pU4c8#zQK zujPJ4mQLZxJ9(PO(kU`Ij&}l?ItBR_ld1DM-$XKWg2J|+e+d~nL17yvu!nS=n-vA; zlb3*mCqEK8M!JQ-q$jfZwD1ISEWH>dvAIb!k{qp|EXE}6Nsd-f*yc%0BFn47lkfYo zZdRA%CdXn&DJw>{%{5X%5T5)&x|A$ei%jm2Sw@CVQ2Gs(T||aXP#8g}*$EER!YloF`}MYLa39Lfta3{v@*WDsEn-C&xsd*2zB%wvwlF z^Iby?ax4X=smn-kfM8PNqNC$fu7-r&r(`9235PRYpz zT&J*Tl%DLyeFlrT$mDRIS6IY_C%5u8VG$RZ?87$!tGFWnVyxnv0u!-_OH6(&ump=Z z(1TJelP?JFz$Ul(tWY;Lj|)$pBXSIz29RN!SBv&wYBEfe*xVo!oukhrRrhJpl3`4=Hl5nZm>|i9vgiCVr z29vGWf#Wt0ou5C~Ve?sK%yNdh*vu9faClK(+pxtD;IU)dCBe&BigaF(p72 zO2*B?=FZLE<1{cefQqb?ggF=*3=^|4#1h$op_~|i#gODWY>Fp8NMzltk-~^A9Z5_s HN{a*lFxZ5m diff --git a/PythonHome/Lib/colorsys.py b/PythonHome/Lib/colorsys.py new file mode 100644 index 0000000000..a6c0cf6a46 --- /dev/null +++ b/PythonHome/Lib/colorsys.py @@ -0,0 +1,156 @@ +"""Conversion functions between RGB and other color systems. + +This modules provides two functions for each color system ABC: + + rgb_to_abc(r, g, b) --> a, b, c + abc_to_rgb(a, b, c) --> r, g, b + +All inputs and outputs are triples of floats in the range [0.0...1.0] +(with the exception of I and Q, which covers a slightly larger range). +Inputs outside the valid range may cause exceptions or invalid outputs. + +Supported color systems: +RGB: Red, Green, Blue components +YIQ: Luminance, Chrominance (used by composite video signals) +HLS: Hue, Luminance, Saturation +HSV: Hue, Saturation, Value +""" + +# References: +# http://en.wikipedia.org/wiki/YIQ +# http://en.wikipedia.org/wiki/HLS_color_space +# http://en.wikipedia.org/wiki/HSV_color_space + +__all__ = ["rgb_to_yiq","yiq_to_rgb","rgb_to_hls","hls_to_rgb", + "rgb_to_hsv","hsv_to_rgb"] + +# Some floating point constants + +ONE_THIRD = 1.0/3.0 +ONE_SIXTH = 1.0/6.0 +TWO_THIRD = 2.0/3.0 + +# YIQ: used by composite video signals (linear combinations of RGB) +# Y: perceived grey level (0.0 == black, 1.0 == white) +# I, Q: color components + +def rgb_to_yiq(r, g, b): + y = 0.30*r + 0.59*g + 0.11*b + i = 0.60*r - 0.28*g - 0.32*b + q = 0.21*r - 0.52*g + 0.31*b + return (y, i, q) + +def yiq_to_rgb(y, i, q): + r = y + 0.948262*i + 0.624013*q + g = y - 0.276066*i - 0.639810*q + b = y - 1.105450*i + 1.729860*q + if r < 0.0: + r = 0.0 + if g < 0.0: + g = 0.0 + if b < 0.0: + b = 0.0 + if r > 1.0: + r = 1.0 + if g > 1.0: + g = 1.0 + if b > 1.0: + b = 1.0 + return (r, g, b) + + +# HLS: Hue, Luminance, Saturation +# H: position in the spectrum +# L: color lightness +# S: color saturation + +def rgb_to_hls(r, g, b): + maxc = max(r, g, b) + minc = min(r, g, b) + # XXX Can optimize (maxc+minc) and (maxc-minc) + l = (minc+maxc)/2.0 + if minc == maxc: + return 0.0, l, 0.0 + if l <= 0.5: + s = (maxc-minc) / (maxc+minc) + else: + s = (maxc-minc) / (2.0-maxc-minc) + rc = (maxc-r) / (maxc-minc) + gc = (maxc-g) / (maxc-minc) + bc = (maxc-b) / (maxc-minc) + if r == maxc: + h = bc-gc + elif g == maxc: + h = 2.0+rc-bc + else: + h = 4.0+gc-rc + h = (h/6.0) % 1.0 + return h, l, s + +def hls_to_rgb(h, l, s): + if s == 0.0: + return l, l, l + if l <= 0.5: + m2 = l * (1.0+s) + else: + m2 = l+s-(l*s) + m1 = 2.0*l - m2 + return (_v(m1, m2, h+ONE_THIRD), _v(m1, m2, h), _v(m1, m2, h-ONE_THIRD)) + +def _v(m1, m2, hue): + hue = hue % 1.0 + if hue < ONE_SIXTH: + return m1 + (m2-m1)*hue*6.0 + if hue < 0.5: + return m2 + if hue < TWO_THIRD: + return m1 + (m2-m1)*(TWO_THIRD-hue)*6.0 + return m1 + + +# HSV: Hue, Saturation, Value +# H: position in the spectrum +# S: color saturation ("purity") +# V: color brightness + +def rgb_to_hsv(r, g, b): + maxc = max(r, g, b) + minc = min(r, g, b) + v = maxc + if minc == maxc: + return 0.0, 0.0, v + s = (maxc-minc) / maxc + rc = (maxc-r) / (maxc-minc) + gc = (maxc-g) / (maxc-minc) + bc = (maxc-b) / (maxc-minc) + if r == maxc: + h = bc-gc + elif g == maxc: + h = 2.0+rc-bc + else: + h = 4.0+gc-rc + h = (h/6.0) % 1.0 + return h, s, v + +def hsv_to_rgb(h, s, v): + if s == 0.0: + return v, v, v + i = int(h*6.0) # XXX assume int() truncates! + f = (h*6.0) - i + p = v*(1.0 - s) + q = v*(1.0 - s*f) + t = v*(1.0 - s*(1.0-f)) + i = i%6 + if i == 0: + return v, t, p + if i == 1: + return q, v, p + if i == 2: + return p, v, t + if i == 3: + return p, q, v + if i == 4: + return t, p, v + if i == 5: + return v, p, q + # Cannot get here diff --git a/PythonHome/Lib/colorsys.pyc b/PythonHome/Lib/colorsys.pyc deleted file mode 100644 index 72e9df8edf3c5af6a6ba466c703673f8b5f5b434..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3871 zcmb_fO>87b6|V7&$DUr>@j7GAB>bojK^hZhv-TCZODZo8+_Um4G{Xz}+UT&1o;7L+@o+@f+z%AHhh zS@~sk70M~)POHVMu%TB$4=$F`!Sj^*0j9%$MmlBX&PoTqbJCes?mg0}D0f~un0#6~ zrxUkCR6FRc=pH;^q6ZussnU3)?w0k~V4#C=G)`i(({W<@k*AX=7;$UE zExk1uI`9ZWjg#oe34KpLb*6cy*=#=CJo9a7$yi!1tiKaevp zRNB$;An^OiU{4R6$VX&k!R4m4VKy?vZV(GuZ`TaqQ{*E!bUzZ5c1j zMk}x|2RlIP0WTm4*bv=#LL$Dh4!jmA7kE;CE89hjvU6sT5n%Y z?T5-0ec8b#ti(c2rHJkYPsu*CRWLyMn+K!NQmRYj5Q7gV)|O52~n^FS(2ER$lXqx5L0AE3OZ%$(`eQc35) z6Vpp-e^PA~Q9?ZKrvD}Rz1i~LdA9oU`FH-_@|Ul@@cMrmzip+af3*CY7k~ZvAHMfS z%l{r-p8ZSa{D+qR%hA`Yw_bd^<-heJdvCTHSXDK6kfZ<+iS$KwMed0VL_Tf2IVC;~ z(Y$sc=w6dLMVU57dp1p9pn00T!u|4hd#wHlBf`OONt_U`G)~mw*wEHpoIQ;ZwZ|h@ zJCOJwc-z?Z6-E(J4za96l*)l9OQHmM8PDfLIVnn@GOe~tD*72ahtrMnhA8vtM){g3 zv*}0Bso+GLe(~|&|77{e_gjAZX8*JA{ufw$wAKC1{0(67^Y^~|XM69TE&s-!{(AZ5 zEB|i!yFY&SrRQGyUzTM`<#~4qip_OxLT{g|^Y4R$fk@nVE$ZGTD>`?$s?)gp>@33D;R3HHmT90|f^ikQlI zA;S0TzRNpTt$_ zS)i6L4MP1D8VnKEs;sevG<9kwgTR4?9Z~WCjEu;XlNAw23(2}g2+ zIViVbkrTQ)Yan10I=cyL?1{~0Ypjcb3FFd%&>)Vw4P3vN6&X_>G>96i*4p$$^1{B#FmjCZbNrnn{!qbC z&*muH9(-RGnLG}8PQIPyWEP3`#*>%UB`%k)JdwtQySDG6s6$BF_Q&3d!B~Q`ixxAQ zs$d};RkRXX-DDLLKM%*hF!)rI11dU7HET>n5{J1h$p@ehJpLaH@{7AM$nS*Ujxz|} ze4If_V35h2LBMC}g-$NdAj!!;r;@u8hdqON_AJDmD8pvX+4n#o36$EE{IwUTs4YbDNnK};iI6+3n9~xR)8|Kaw&klm$(`TWl~t_r}PDxA7%x(oOJao@;GgI zy72n|hS#YwlZ402Hv$ZQ6N6033>BI2Vfq40$_$nmW((#8>5YLRXbWPuVV;-atyaLK z2+&kO_yRIiz{(2&1', 'r') + text = pipe.read() + sts = pipe.close() + + [Note: it would be nice to add functions to interpret the exit status.] +""" +from warnings import warnpy3k +warnpy3k("the commands module has been removed in Python 3.0; " + "use the subprocess module instead", stacklevel=2) +del warnpy3k + +__all__ = ["getstatusoutput","getoutput","getstatus"] + +# Module 'commands' +# +# Various tools for executing commands and looking at their output and status. +# +# NB This only works (and is only relevant) for UNIX. + + +# Get 'ls -l' status for an object into a string +# +def getstatus(file): + """Return output of "ls -ld " in a string.""" + import warnings + warnings.warn("commands.getstatus() is deprecated", DeprecationWarning, 2) + return getoutput('ls -ld' + mkarg(file)) + + +# Get the output from a shell command into a string. +# The exit status is ignored; a trailing newline is stripped. +# Assume the command will work with '{ ... ; } 2>&1' around it.. +# +def getoutput(cmd): + """Return output (stdout or stderr) of executing cmd in a shell.""" + return getstatusoutput(cmd)[1] + + +# Ditto but preserving the exit status. +# Returns a pair (sts, output) +# +def getstatusoutput(cmd): + """Return (status, output) of executing cmd in a shell.""" + import os + pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r') + text = pipe.read() + sts = pipe.close() + if sts is None: sts = 0 + if text[-1:] == '\n': text = text[:-1] + return sts, text + + +# Make command argument from directory and pathname (prefix space, add quotes). +# +def mk2arg(head, x): + import os + return mkarg(os.path.join(head, x)) + + +# Make a shell command argument from a string. +# Return a string beginning with a space followed by a shell-quoted +# version of the argument. +# Two strategies: enclose in single quotes if it contains none; +# otherwise, enclose in double quotes and prefix quotable characters +# with backslash. +# +def mkarg(x): + if '\'' not in x: + return ' \'' + x + '\'' + s = ' "' + for c in x: + if c in '\\$"`': + s = s + '\\' + s = s + c + s = s + '"' + return s diff --git a/PythonHome/Lib/commands.pyc b/PythonHome/Lib/commands.pyc deleted file mode 100644 index f8bc8ba7f050dd9c34a1b417bae8d94ef65d9c96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2379 zcmah~+iu%N5S^ub6Ky5w1#sGzF4U%?&{#;~J`}kaEn+_uD1=r*VZd=<)8yKsMUg6Z z=}Tijxu4WO>j$)FhLq|S1}uZi;q1)r%$YOe#$PS}&)vgeMD=e0@9**01WQb`hgDJR zQL1R-(Vj=jcoa7%UZ8l9Zj@5*@V!LwGQ}%&(x5%;HR%ty!on9}k>XVmV74X#j9VhC zQ2c;~!9%`s!z0?cFj47@wj-0KI?5-LFpI4|OG2I7-ZY<@Ea+ds;e7Wkm3eTSq^7I&mvvgU&PV6Rx}93Rk;a-$+P?pTc14(^Np_+$ zbB?#siG|xFKQk~Y@`-jMGxN8ufF)qr$)a#-%QSSxiosE6lSl*5B6LZf%~6^rQ-hS| zXm>v7j{Zgi2CSV|`dYu(`uch2sqPe=889_^?Aj|#7zeWr>nzR^eU#?bV8hq%`nfYN zwN9Kq&r4)>WOSCGU@q5Tj2y}=;*bz$t`jcj6vdXH8UMQEz4w0dH-3Qvciak=^RURK zmz!hzD{FwkoIaC0E>ojNp~YP$o1>Lv`sYhG$}_#$d-h6~7BRrjmPgYfkBqgt_DnMC zkeBnBr!I`fsW~%g0>YAG?t(72>+YJBu42LLtFnkVUUuYGdyB_zVyT;q=vvX0qEqx- zgB&_*fo>Y49GYs8+yY$@dXCod41*G2I!3MJ|VycjLA4Ax#JyE?~R09Ts279pEWE>VJ zfk4JS9NK{O0iJ5HA3^Hv|CAi<&qJGD4%qq$9*KjzHT8)S5NALNh!0@ksKy6qem0b= z>>KF+i%(!(45)No0Fu}gMVBEnGI+SFnCTT@JcD`(Un3+NaO@S`I4RiO8#>!P!(-W% zJPDg~X1#>{JA^xHk3z4b`0G4mJ-YVj%A-?{ZorU+$PJOf2#i^e#w%0|c@AGMPzD&l z7e!xSD33iVruDamD{sQ7LB}2_#BF20#Zp5AY;KR!dywJw>q}}MwB@5_)4?%j1^){n z%c5WLhC#@!kU=K7aEIrGsANEhs-I^@JO(u`Lsn z>GQc-<3DPuN7Pag@AFyneq^q3O+b2}?Gdu6z&{1@fKPEnqyyQtUrizQmPiK-L=|r6 zMk1W%Nfz)G@-^aw8I=pMzb}5r-8UJ(K=bTCvV0LCe&G@y%FkOo_7Dr=Mu_8ODjqW} zghiMaLrfD)mW$`C*?!-x2?c_Um#En0oItd7m@q#iU;g;*3GMRMl59a52FtjlFGcN0 z<#qjPOJMt7wGU-;Uovc0$#H~(bu6N^vPSpiEja!Hr>bsJvnAESyQLl|U-bhXvX0|9 zIEeG;;6SFy0N*ohn5NK5Wh4YH*WfWPT%&&j5b5sWBeU*x^ 0 and \ + name != os.curdir and name != os.pardir and \ + os.path.isdir(fullname) and \ + not os.path.islink(fullname): + if not compile_dir(fullname, maxlevels - 1, dfile, force, rx, + quiet): + success = 0 + return success + +def compile_file(fullname, ddir=None, force=0, rx=None, quiet=0): + """Byte-compile one file. + + Arguments (only fullname is required): + + fullname: the file to byte-compile + ddir: if given, the directory name compiled in to the + byte-code file. + force: if 1, force compilation, even if timestamps are up-to-date + quiet: if 1, be quiet during compilation + """ + success = 1 + name = os.path.basename(fullname) + if ddir is not None: + dfile = os.path.join(ddir, name) + else: + dfile = None + if rx is not None: + mo = rx.search(fullname) + if mo: + return success + if os.path.isfile(fullname): + head, tail = name[:-3], name[-3:] + if tail == '.py': + if not force: + try: + mtime = int(os.stat(fullname).st_mtime) + expect = struct.pack('<4sl', imp.get_magic(), mtime) + cfile = fullname + (__debug__ and 'c' or 'o') + with open(cfile, 'rb') as chandle: + actual = chandle.read(8) + if expect == actual: + return success + except IOError: + pass + if not quiet: + print 'Compiling', fullname, '...' + try: + ok = py_compile.compile(fullname, None, dfile, True) + except py_compile.PyCompileError,err: + if quiet: + print 'Compiling', fullname, '...' + print err.msg + success = 0 + except IOError, e: + print "Sorry", e + success = 0 + else: + if ok == 0: + success = 0 + return success + +def compile_path(skip_curdir=1, maxlevels=0, force=0, quiet=0): + """Byte-compile all module on sys.path. + + Arguments (all optional): + + skip_curdir: if true, skip current directory (default true) + maxlevels: max recursion level (default 0) + force: as for compile_dir() (default 0) + quiet: as for compile_dir() (default 0) + """ + success = 1 + for dir in sys.path: + if (not dir or dir == os.curdir) and skip_curdir: + print 'Skipping current directory' + else: + success = success and compile_dir(dir, maxlevels, None, + force, quiet=quiet) + return success + +def expand_args(args, flist): + """read names in flist and append to args""" + expanded = args[:] + if flist: + try: + if flist == '-': + fd = sys.stdin + else: + fd = open(flist) + while 1: + line = fd.readline() + if not line: + break + expanded.append(line[:-1]) + except IOError: + print "Error reading file list %s" % flist + raise + return expanded + +def main(): + """Script main program.""" + import getopt + try: + opts, args = getopt.getopt(sys.argv[1:], 'lfqd:x:i:') + except getopt.error, msg: + print msg + print "usage: python compileall.py [-l] [-f] [-q] [-d destdir] " \ + "[-x regexp] [-i list] [directory|file ...]" + print + print "arguments: zero or more file and directory names to compile; " \ + "if no arguments given, " + print " defaults to the equivalent of -l sys.path" + print + print "options:" + print "-l: don't recurse into subdirectories" + print "-f: force rebuild even if timestamps are up-to-date" + print "-q: output only error messages" + print "-d destdir: directory to prepend to file paths for use in " \ + "compile-time tracebacks and in" + print " runtime tracebacks in cases where the source " \ + "file is unavailable" + print "-x regexp: skip files matching the regular expression regexp; " \ + "the regexp is searched for" + print " in the full path of each file considered for " \ + "compilation" + print "-i file: add all the files and directories listed in file to " \ + "the list considered for" + print ' compilation; if "-", names are read from stdin' + + sys.exit(2) + maxlevels = 10 + ddir = None + force = 0 + quiet = 0 + rx = None + flist = None + for o, a in opts: + if o == '-l': maxlevels = 0 + if o == '-d': ddir = a + if o == '-f': force = 1 + if o == '-q': quiet = 1 + if o == '-x': + import re + rx = re.compile(a) + if o == '-i': flist = a + if ddir: + if len(args) != 1 and not os.path.isdir(args[0]): + print "-d destdir require exactly one directory argument" + sys.exit(2) + success = 1 + try: + if args or flist: + try: + if flist: + args = expand_args(args, flist) + except IOError: + success = 0 + if success: + for arg in args: + if os.path.isdir(arg): + if not compile_dir(arg, maxlevels, ddir, + force, rx, quiet): + success = 0 + else: + if not compile_file(arg, ddir, force, rx, quiet): + success = 0 + else: + success = compile_path() + except KeyboardInterrupt: + print "\n[interrupted]" + success = 0 + return success + +if __name__ == '__main__': + exit_status = int(not main()) + sys.exit(exit_status) diff --git a/PythonHome/Lib/compileall.pyc b/PythonHome/Lib/compileall.pyc deleted file mode 100644 index 128f347593b88d42fec40f55d077d8797e6c12a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6986 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 J!0ZJZ3jnU4RILC2 delta 505 zcmYk1O-{ow5QWE1o1{rA6@;f^7Hu3=kfU9y#+hxdk}ohA7(imql^0uF8z$c01{LJjDjSP5a0w}C@=@O z1FQqA3-6Q=OSm9AP;?>bLg7N_HJg5FjAJ4j5BCLG#0PCOZ?@vdQw5h?_x&|BwSw0END9&j0`b diff --git a/PythonHome/Lib/compiler/ast.py b/PythonHome/Lib/compiler/ast.py new file mode 100644 index 0000000000..4c3fc161d3 --- /dev/null +++ b/PythonHome/Lib/compiler/ast.py @@ -0,0 +1,1419 @@ +"""Python abstract syntax node definitions + +This file is automatically generated by Tools/compiler/astgen.py +""" +from compiler.consts import CO_VARARGS, CO_VARKEYWORDS + +def flatten(seq): + l = [] + for elt in seq: + t = type(elt) + if t is tuple or t is list: + for elt2 in flatten(elt): + l.append(elt2) + else: + l.append(elt) + return l + +def flatten_nodes(seq): + return [n for n in flatten(seq) if isinstance(n, Node)] + +nodes = {} + +class Node: + """Abstract base class for ast nodes.""" + def getChildren(self): + pass # implemented by subclasses + def __iter__(self): + for n in self.getChildren(): + yield n + def asList(self): # for backwards compatibility + return self.getChildren() + def getChildNodes(self): + pass # implemented by subclasses + +class EmptyNode(Node): + pass + +class Expression(Node): + # Expression is an artificial node class to support "eval" + nodes["expression"] = "Expression" + def __init__(self, node): + self.node = node + + def getChildren(self): + return self.node, + + def getChildNodes(self): + return self.node, + + def __repr__(self): + return "Expression(%s)" % (repr(self.node)) + +class Add(Node): + def __init__(self, leftright, lineno=None): + self.left = leftright[0] + self.right = leftright[1] + self.lineno = lineno + + def getChildren(self): + return self.left, self.right + + def getChildNodes(self): + return self.left, self.right + + def __repr__(self): + return "Add((%s, %s))" % (repr(self.left), repr(self.right)) + +class And(Node): + def __init__(self, nodes, lineno=None): + self.nodes = nodes + self.lineno = lineno + + def getChildren(self): + return tuple(flatten(self.nodes)) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.nodes)) + return tuple(nodelist) + + def __repr__(self): + return "And(%s)" % (repr(self.nodes),) + +class AssAttr(Node): + def __init__(self, expr, attrname, flags, lineno=None): + self.expr = expr + self.attrname = attrname + self.flags = flags + self.lineno = lineno + + def getChildren(self): + return self.expr, self.attrname, self.flags + + def getChildNodes(self): + return self.expr, + + def __repr__(self): + return "AssAttr(%s, %s, %s)" % (repr(self.expr), repr(self.attrname), repr(self.flags)) + +class AssList(Node): + def __init__(self, nodes, lineno=None): + self.nodes = nodes + self.lineno = lineno + + def getChildren(self): + return tuple(flatten(self.nodes)) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.nodes)) + return tuple(nodelist) + + def __repr__(self): + return "AssList(%s)" % (repr(self.nodes),) + +class AssName(Node): + def __init__(self, name, flags, lineno=None): + self.name = name + self.flags = flags + self.lineno = lineno + + def getChildren(self): + return self.name, self.flags + + def getChildNodes(self): + return () + + def __repr__(self): + return "AssName(%s, %s)" % (repr(self.name), repr(self.flags)) + +class AssTuple(Node): + def __init__(self, nodes, lineno=None): + self.nodes = nodes + self.lineno = lineno + + def getChildren(self): + return tuple(flatten(self.nodes)) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.nodes)) + return tuple(nodelist) + + def __repr__(self): + return "AssTuple(%s)" % (repr(self.nodes),) + +class Assert(Node): + def __init__(self, test, fail, lineno=None): + self.test = test + self.fail = fail + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.test) + children.append(self.fail) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.test) + if self.fail is not None: + nodelist.append(self.fail) + return tuple(nodelist) + + def __repr__(self): + return "Assert(%s, %s)" % (repr(self.test), repr(self.fail)) + +class Assign(Node): + def __init__(self, nodes, expr, lineno=None): + self.nodes = nodes + self.expr = expr + self.lineno = lineno + + def getChildren(self): + children = [] + children.extend(flatten(self.nodes)) + children.append(self.expr) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.nodes)) + nodelist.append(self.expr) + return tuple(nodelist) + + def __repr__(self): + return "Assign(%s, %s)" % (repr(self.nodes), repr(self.expr)) + +class AugAssign(Node): + def __init__(self, node, op, expr, lineno=None): + self.node = node + self.op = op + self.expr = expr + self.lineno = lineno + + def getChildren(self): + return self.node, self.op, self.expr + + def getChildNodes(self): + return self.node, self.expr + + def __repr__(self): + return "AugAssign(%s, %s, %s)" % (repr(self.node), repr(self.op), repr(self.expr)) + +class Backquote(Node): + def __init__(self, expr, lineno=None): + self.expr = expr + self.lineno = lineno + + def getChildren(self): + return self.expr, + + def getChildNodes(self): + return self.expr, + + def __repr__(self): + return "Backquote(%s)" % (repr(self.expr),) + +class Bitand(Node): + def __init__(self, nodes, lineno=None): + self.nodes = nodes + self.lineno = lineno + + def getChildren(self): + return tuple(flatten(self.nodes)) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.nodes)) + return tuple(nodelist) + + def __repr__(self): + return "Bitand(%s)" % (repr(self.nodes),) + +class Bitor(Node): + def __init__(self, nodes, lineno=None): + self.nodes = nodes + self.lineno = lineno + + def getChildren(self): + return tuple(flatten(self.nodes)) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.nodes)) + return tuple(nodelist) + + def __repr__(self): + return "Bitor(%s)" % (repr(self.nodes),) + +class Bitxor(Node): + def __init__(self, nodes, lineno=None): + self.nodes = nodes + self.lineno = lineno + + def getChildren(self): + return tuple(flatten(self.nodes)) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.nodes)) + return tuple(nodelist) + + def __repr__(self): + return "Bitxor(%s)" % (repr(self.nodes),) + +class Break(Node): + def __init__(self, lineno=None): + self.lineno = lineno + + def getChildren(self): + return () + + def getChildNodes(self): + return () + + def __repr__(self): + return "Break()" + +class CallFunc(Node): + def __init__(self, node, args, star_args = None, dstar_args = None, lineno=None): + self.node = node + self.args = args + self.star_args = star_args + self.dstar_args = dstar_args + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.node) + children.extend(flatten(self.args)) + children.append(self.star_args) + children.append(self.dstar_args) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.node) + nodelist.extend(flatten_nodes(self.args)) + if self.star_args is not None: + nodelist.append(self.star_args) + if self.dstar_args is not None: + nodelist.append(self.dstar_args) + return tuple(nodelist) + + def __repr__(self): + return "CallFunc(%s, %s, %s, %s)" % (repr(self.node), repr(self.args), repr(self.star_args), repr(self.dstar_args)) + +class Class(Node): + def __init__(self, name, bases, doc, code, decorators = None, lineno=None): + self.name = name + self.bases = bases + self.doc = doc + self.code = code + self.decorators = decorators + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.name) + children.extend(flatten(self.bases)) + children.append(self.doc) + children.append(self.code) + children.append(self.decorators) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.bases)) + nodelist.append(self.code) + if self.decorators is not None: + nodelist.append(self.decorators) + return tuple(nodelist) + + def __repr__(self): + return "Class(%s, %s, %s, %s, %s)" % (repr(self.name), repr(self.bases), repr(self.doc), repr(self.code), repr(self.decorators)) + +class Compare(Node): + def __init__(self, expr, ops, lineno=None): + self.expr = expr + self.ops = ops + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.expr) + children.extend(flatten(self.ops)) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.expr) + nodelist.extend(flatten_nodes(self.ops)) + return tuple(nodelist) + + def __repr__(self): + return "Compare(%s, %s)" % (repr(self.expr), repr(self.ops)) + +class Const(Node): + def __init__(self, value, lineno=None): + self.value = value + self.lineno = lineno + + def getChildren(self): + return self.value, + + def getChildNodes(self): + return () + + def __repr__(self): + return "Const(%s)" % (repr(self.value),) + +class Continue(Node): + def __init__(self, lineno=None): + self.lineno = lineno + + def getChildren(self): + return () + + def getChildNodes(self): + return () + + def __repr__(self): + return "Continue()" + +class Decorators(Node): + def __init__(self, nodes, lineno=None): + self.nodes = nodes + self.lineno = lineno + + def getChildren(self): + return tuple(flatten(self.nodes)) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.nodes)) + return tuple(nodelist) + + def __repr__(self): + return "Decorators(%s)" % (repr(self.nodes),) + +class Dict(Node): + def __init__(self, items, lineno=None): + self.items = items + self.lineno = lineno + + def getChildren(self): + return tuple(flatten(self.items)) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.items)) + return tuple(nodelist) + + def __repr__(self): + return "Dict(%s)" % (repr(self.items),) + +class Discard(Node): + def __init__(self, expr, lineno=None): + self.expr = expr + self.lineno = lineno + + def getChildren(self): + return self.expr, + + def getChildNodes(self): + return self.expr, + + def __repr__(self): + return "Discard(%s)" % (repr(self.expr),) + +class Div(Node): + def __init__(self, leftright, lineno=None): + self.left = leftright[0] + self.right = leftright[1] + self.lineno = lineno + + def getChildren(self): + return self.left, self.right + + def getChildNodes(self): + return self.left, self.right + + def __repr__(self): + return "Div((%s, %s))" % (repr(self.left), repr(self.right)) + +class Ellipsis(Node): + def __init__(self, lineno=None): + self.lineno = lineno + + def getChildren(self): + return () + + def getChildNodes(self): + return () + + def __repr__(self): + return "Ellipsis()" + +class Exec(Node): + def __init__(self, expr, locals, globals, lineno=None): + self.expr = expr + self.locals = locals + self.globals = globals + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.expr) + children.append(self.locals) + children.append(self.globals) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.expr) + if self.locals is not None: + nodelist.append(self.locals) + if self.globals is not None: + nodelist.append(self.globals) + return tuple(nodelist) + + def __repr__(self): + return "Exec(%s, %s, %s)" % (repr(self.expr), repr(self.locals), repr(self.globals)) + +class FloorDiv(Node): + def __init__(self, leftright, lineno=None): + self.left = leftright[0] + self.right = leftright[1] + self.lineno = lineno + + def getChildren(self): + return self.left, self.right + + def getChildNodes(self): + return self.left, self.right + + def __repr__(self): + return "FloorDiv((%s, %s))" % (repr(self.left), repr(self.right)) + +class For(Node): + def __init__(self, assign, list, body, else_, lineno=None): + self.assign = assign + self.list = list + self.body = body + self.else_ = else_ + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.assign) + children.append(self.list) + children.append(self.body) + children.append(self.else_) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.assign) + nodelist.append(self.list) + nodelist.append(self.body) + if self.else_ is not None: + nodelist.append(self.else_) + return tuple(nodelist) + + def __repr__(self): + return "For(%s, %s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.body), repr(self.else_)) + +class From(Node): + def __init__(self, modname, names, level, lineno=None): + self.modname = modname + self.names = names + self.level = level + self.lineno = lineno + + def getChildren(self): + return self.modname, self.names, self.level + + def getChildNodes(self): + return () + + def __repr__(self): + return "From(%s, %s, %s)" % (repr(self.modname), repr(self.names), repr(self.level)) + +class Function(Node): + def __init__(self, decorators, name, argnames, defaults, flags, doc, code, lineno=None): + self.decorators = decorators + self.name = name + self.argnames = argnames + self.defaults = defaults + self.flags = flags + self.doc = doc + self.code = code + self.lineno = lineno + self.varargs = self.kwargs = None + if flags & CO_VARARGS: + self.varargs = 1 + if flags & CO_VARKEYWORDS: + self.kwargs = 1 + + + def getChildren(self): + children = [] + children.append(self.decorators) + children.append(self.name) + children.append(self.argnames) + children.extend(flatten(self.defaults)) + children.append(self.flags) + children.append(self.doc) + children.append(self.code) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + if self.decorators is not None: + nodelist.append(self.decorators) + nodelist.extend(flatten_nodes(self.defaults)) + nodelist.append(self.code) + return tuple(nodelist) + + def __repr__(self): + return "Function(%s, %s, %s, %s, %s, %s, %s)" % (repr(self.decorators), repr(self.name), repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.doc), repr(self.code)) + +class GenExpr(Node): + def __init__(self, code, lineno=None): + self.code = code + self.lineno = lineno + self.argnames = ['.0'] + self.varargs = self.kwargs = None + + + def getChildren(self): + return self.code, + + def getChildNodes(self): + return self.code, + + def __repr__(self): + return "GenExpr(%s)" % (repr(self.code),) + +class GenExprFor(Node): + def __init__(self, assign, iter, ifs, lineno=None): + self.assign = assign + self.iter = iter + self.ifs = ifs + self.lineno = lineno + self.is_outmost = False + + def getChildren(self): + children = [] + children.append(self.assign) + children.append(self.iter) + children.extend(flatten(self.ifs)) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.assign) + nodelist.append(self.iter) + nodelist.extend(flatten_nodes(self.ifs)) + return tuple(nodelist) + + def __repr__(self): + return "GenExprFor(%s, %s, %s)" % (repr(self.assign), repr(self.iter), repr(self.ifs)) + +class GenExprIf(Node): + def __init__(self, test, lineno=None): + self.test = test + self.lineno = lineno + + def getChildren(self): + return self.test, + + def getChildNodes(self): + return self.test, + + def __repr__(self): + return "GenExprIf(%s)" % (repr(self.test),) + +class GenExprInner(Node): + def __init__(self, expr, quals, lineno=None): + self.expr = expr + self.quals = quals + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.expr) + children.extend(flatten(self.quals)) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.expr) + nodelist.extend(flatten_nodes(self.quals)) + return tuple(nodelist) + + def __repr__(self): + return "GenExprInner(%s, %s)" % (repr(self.expr), repr(self.quals)) + +class Getattr(Node): + def __init__(self, expr, attrname, lineno=None): + self.expr = expr + self.attrname = attrname + self.lineno = lineno + + def getChildren(self): + return self.expr, self.attrname + + def getChildNodes(self): + return self.expr, + + def __repr__(self): + return "Getattr(%s, %s)" % (repr(self.expr), repr(self.attrname)) + +class Global(Node): + def __init__(self, names, lineno=None): + self.names = names + self.lineno = lineno + + def getChildren(self): + return self.names, + + def getChildNodes(self): + return () + + def __repr__(self): + return "Global(%s)" % (repr(self.names),) + +class If(Node): + def __init__(self, tests, else_, lineno=None): + self.tests = tests + self.else_ = else_ + self.lineno = lineno + + def getChildren(self): + children = [] + children.extend(flatten(self.tests)) + children.append(self.else_) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.tests)) + if self.else_ is not None: + nodelist.append(self.else_) + return tuple(nodelist) + + def __repr__(self): + return "If(%s, %s)" % (repr(self.tests), repr(self.else_)) + +class IfExp(Node): + def __init__(self, test, then, else_, lineno=None): + self.test = test + self.then = then + self.else_ = else_ + self.lineno = lineno + + def getChildren(self): + return self.test, self.then, self.else_ + + def getChildNodes(self): + return self.test, self.then, self.else_ + + def __repr__(self): + return "IfExp(%s, %s, %s)" % (repr(self.test), repr(self.then), repr(self.else_)) + +class Import(Node): + def __init__(self, names, lineno=None): + self.names = names + self.lineno = lineno + + def getChildren(self): + return self.names, + + def getChildNodes(self): + return () + + def __repr__(self): + return "Import(%s)" % (repr(self.names),) + +class Invert(Node): + def __init__(self, expr, lineno=None): + self.expr = expr + self.lineno = lineno + + def getChildren(self): + return self.expr, + + def getChildNodes(self): + return self.expr, + + def __repr__(self): + return "Invert(%s)" % (repr(self.expr),) + +class Keyword(Node): + def __init__(self, name, expr, lineno=None): + self.name = name + self.expr = expr + self.lineno = lineno + + def getChildren(self): + return self.name, self.expr + + def getChildNodes(self): + return self.expr, + + def __repr__(self): + return "Keyword(%s, %s)" % (repr(self.name), repr(self.expr)) + +class Lambda(Node): + def __init__(self, argnames, defaults, flags, code, lineno=None): + self.argnames = argnames + self.defaults = defaults + self.flags = flags + self.code = code + self.lineno = lineno + self.varargs = self.kwargs = None + if flags & CO_VARARGS: + self.varargs = 1 + if flags & CO_VARKEYWORDS: + self.kwargs = 1 + + + def getChildren(self): + children = [] + children.append(self.argnames) + children.extend(flatten(self.defaults)) + children.append(self.flags) + children.append(self.code) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.defaults)) + nodelist.append(self.code) + return tuple(nodelist) + + def __repr__(self): + return "Lambda(%s, %s, %s, %s)" % (repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.code)) + +class LeftShift(Node): + def __init__(self, leftright, lineno=None): + self.left = leftright[0] + self.right = leftright[1] + self.lineno = lineno + + def getChildren(self): + return self.left, self.right + + def getChildNodes(self): + return self.left, self.right + + def __repr__(self): + return "LeftShift((%s, %s))" % (repr(self.left), repr(self.right)) + +class List(Node): + def __init__(self, nodes, lineno=None): + self.nodes = nodes + self.lineno = lineno + + def getChildren(self): + return tuple(flatten(self.nodes)) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.nodes)) + return tuple(nodelist) + + def __repr__(self): + return "List(%s)" % (repr(self.nodes),) + +class ListComp(Node): + def __init__(self, expr, quals, lineno=None): + self.expr = expr + self.quals = quals + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.expr) + children.extend(flatten(self.quals)) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.expr) + nodelist.extend(flatten_nodes(self.quals)) + return tuple(nodelist) + + def __repr__(self): + return "ListComp(%s, %s)" % (repr(self.expr), repr(self.quals)) + +class ListCompFor(Node): + def __init__(self, assign, list, ifs, lineno=None): + self.assign = assign + self.list = list + self.ifs = ifs + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.assign) + children.append(self.list) + children.extend(flatten(self.ifs)) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.assign) + nodelist.append(self.list) + nodelist.extend(flatten_nodes(self.ifs)) + return tuple(nodelist) + + def __repr__(self): + return "ListCompFor(%s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.ifs)) + +class ListCompIf(Node): + def __init__(self, test, lineno=None): + self.test = test + self.lineno = lineno + + def getChildren(self): + return self.test, + + def getChildNodes(self): + return self.test, + + def __repr__(self): + return "ListCompIf(%s)" % (repr(self.test),) + +class SetComp(Node): + def __init__(self, expr, quals, lineno=None): + self.expr = expr + self.quals = quals + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.expr) + children.extend(flatten(self.quals)) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.expr) + nodelist.extend(flatten_nodes(self.quals)) + return tuple(nodelist) + + def __repr__(self): + return "SetComp(%s, %s)" % (repr(self.expr), repr(self.quals)) + +class DictComp(Node): + def __init__(self, key, value, quals, lineno=None): + self.key = key + self.value = value + self.quals = quals + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.key) + children.append(self.value) + children.extend(flatten(self.quals)) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.key) + nodelist.append(self.value) + nodelist.extend(flatten_nodes(self.quals)) + return tuple(nodelist) + + def __repr__(self): + return "DictComp(%s, %s, %s)" % (repr(self.key), repr(self.value), repr(self.quals)) + +class Mod(Node): + def __init__(self, leftright, lineno=None): + self.left = leftright[0] + self.right = leftright[1] + self.lineno = lineno + + def getChildren(self): + return self.left, self.right + + def getChildNodes(self): + return self.left, self.right + + def __repr__(self): + return "Mod((%s, %s))" % (repr(self.left), repr(self.right)) + +class Module(Node): + def __init__(self, doc, node, lineno=None): + self.doc = doc + self.node = node + self.lineno = lineno + + def getChildren(self): + return self.doc, self.node + + def getChildNodes(self): + return self.node, + + def __repr__(self): + return "Module(%s, %s)" % (repr(self.doc), repr(self.node)) + +class Mul(Node): + def __init__(self, leftright, lineno=None): + self.left = leftright[0] + self.right = leftright[1] + self.lineno = lineno + + def getChildren(self): + return self.left, self.right + + def getChildNodes(self): + return self.left, self.right + + def __repr__(self): + return "Mul((%s, %s))" % (repr(self.left), repr(self.right)) + +class Name(Node): + def __init__(self, name, lineno=None): + self.name = name + self.lineno = lineno + + def getChildren(self): + return self.name, + + def getChildNodes(self): + return () + + def __repr__(self): + return "Name(%s)" % (repr(self.name),) + +class Not(Node): + def __init__(self, expr, lineno=None): + self.expr = expr + self.lineno = lineno + + def getChildren(self): + return self.expr, + + def getChildNodes(self): + return self.expr, + + def __repr__(self): + return "Not(%s)" % (repr(self.expr),) + +class Or(Node): + def __init__(self, nodes, lineno=None): + self.nodes = nodes + self.lineno = lineno + + def getChildren(self): + return tuple(flatten(self.nodes)) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.nodes)) + return tuple(nodelist) + + def __repr__(self): + return "Or(%s)" % (repr(self.nodes),) + +class Pass(Node): + def __init__(self, lineno=None): + self.lineno = lineno + + def getChildren(self): + return () + + def getChildNodes(self): + return () + + def __repr__(self): + return "Pass()" + +class Power(Node): + def __init__(self, leftright, lineno=None): + self.left = leftright[0] + self.right = leftright[1] + self.lineno = lineno + + def getChildren(self): + return self.left, self.right + + def getChildNodes(self): + return self.left, self.right + + def __repr__(self): + return "Power((%s, %s))" % (repr(self.left), repr(self.right)) + +class Print(Node): + def __init__(self, nodes, dest, lineno=None): + self.nodes = nodes + self.dest = dest + self.lineno = lineno + + def getChildren(self): + children = [] + children.extend(flatten(self.nodes)) + children.append(self.dest) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.nodes)) + if self.dest is not None: + nodelist.append(self.dest) + return tuple(nodelist) + + def __repr__(self): + return "Print(%s, %s)" % (repr(self.nodes), repr(self.dest)) + +class Printnl(Node): + def __init__(self, nodes, dest, lineno=None): + self.nodes = nodes + self.dest = dest + self.lineno = lineno + + def getChildren(self): + children = [] + children.extend(flatten(self.nodes)) + children.append(self.dest) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.nodes)) + if self.dest is not None: + nodelist.append(self.dest) + return tuple(nodelist) + + def __repr__(self): + return "Printnl(%s, %s)" % (repr(self.nodes), repr(self.dest)) + +class Raise(Node): + def __init__(self, expr1, expr2, expr3, lineno=None): + self.expr1 = expr1 + self.expr2 = expr2 + self.expr3 = expr3 + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.expr1) + children.append(self.expr2) + children.append(self.expr3) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + if self.expr1 is not None: + nodelist.append(self.expr1) + if self.expr2 is not None: + nodelist.append(self.expr2) + if self.expr3 is not None: + nodelist.append(self.expr3) + return tuple(nodelist) + + def __repr__(self): + return "Raise(%s, %s, %s)" % (repr(self.expr1), repr(self.expr2), repr(self.expr3)) + +class Return(Node): + def __init__(self, value, lineno=None): + self.value = value + self.lineno = lineno + + def getChildren(self): + return self.value, + + def getChildNodes(self): + return self.value, + + def __repr__(self): + return "Return(%s)" % (repr(self.value),) + +class RightShift(Node): + def __init__(self, leftright, lineno=None): + self.left = leftright[0] + self.right = leftright[1] + self.lineno = lineno + + def getChildren(self): + return self.left, self.right + + def getChildNodes(self): + return self.left, self.right + + def __repr__(self): + return "RightShift((%s, %s))" % (repr(self.left), repr(self.right)) + +class Set(Node): + def __init__(self, nodes, lineno=None): + self.nodes = nodes + self.lineno = lineno + + def getChildren(self): + return tuple(flatten(self.nodes)) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.nodes)) + return tuple(nodelist) + + def __repr__(self): + return "Set(%s)" % (repr(self.nodes),) + +class Slice(Node): + def __init__(self, expr, flags, lower, upper, lineno=None): + self.expr = expr + self.flags = flags + self.lower = lower + self.upper = upper + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.expr) + children.append(self.flags) + children.append(self.lower) + children.append(self.upper) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.expr) + if self.lower is not None: + nodelist.append(self.lower) + if self.upper is not None: + nodelist.append(self.upper) + return tuple(nodelist) + + def __repr__(self): + return "Slice(%s, %s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.lower), repr(self.upper)) + +class Sliceobj(Node): + def __init__(self, nodes, lineno=None): + self.nodes = nodes + self.lineno = lineno + + def getChildren(self): + return tuple(flatten(self.nodes)) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.nodes)) + return tuple(nodelist) + + def __repr__(self): + return "Sliceobj(%s)" % (repr(self.nodes),) + +class Stmt(Node): + def __init__(self, nodes, lineno=None): + self.nodes = nodes + self.lineno = lineno + + def getChildren(self): + return tuple(flatten(self.nodes)) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.nodes)) + return tuple(nodelist) + + def __repr__(self): + return "Stmt(%s)" % (repr(self.nodes),) + +class Sub(Node): + def __init__(self, leftright, lineno=None): + self.left = leftright[0] + self.right = leftright[1] + self.lineno = lineno + + def getChildren(self): + return self.left, self.right + + def getChildNodes(self): + return self.left, self.right + + def __repr__(self): + return "Sub((%s, %s))" % (repr(self.left), repr(self.right)) + +class Subscript(Node): + def __init__(self, expr, flags, subs, lineno=None): + self.expr = expr + self.flags = flags + self.subs = subs + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.expr) + children.append(self.flags) + children.extend(flatten(self.subs)) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.expr) + nodelist.extend(flatten_nodes(self.subs)) + return tuple(nodelist) + + def __repr__(self): + return "Subscript(%s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.subs)) + +class TryExcept(Node): + def __init__(self, body, handlers, else_, lineno=None): + self.body = body + self.handlers = handlers + self.else_ = else_ + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.body) + children.extend(flatten(self.handlers)) + children.append(self.else_) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.body) + nodelist.extend(flatten_nodes(self.handlers)) + if self.else_ is not None: + nodelist.append(self.else_) + return tuple(nodelist) + + def __repr__(self): + return "TryExcept(%s, %s, %s)" % (repr(self.body), repr(self.handlers), repr(self.else_)) + +class TryFinally(Node): + def __init__(self, body, final, lineno=None): + self.body = body + self.final = final + self.lineno = lineno + + def getChildren(self): + return self.body, self.final + + def getChildNodes(self): + return self.body, self.final + + def __repr__(self): + return "TryFinally(%s, %s)" % (repr(self.body), repr(self.final)) + +class Tuple(Node): + def __init__(self, nodes, lineno=None): + self.nodes = nodes + self.lineno = lineno + + def getChildren(self): + return tuple(flatten(self.nodes)) + + def getChildNodes(self): + nodelist = [] + nodelist.extend(flatten_nodes(self.nodes)) + return tuple(nodelist) + + def __repr__(self): + return "Tuple(%s)" % (repr(self.nodes),) + +class UnaryAdd(Node): + def __init__(self, expr, lineno=None): + self.expr = expr + self.lineno = lineno + + def getChildren(self): + return self.expr, + + def getChildNodes(self): + return self.expr, + + def __repr__(self): + return "UnaryAdd(%s)" % (repr(self.expr),) + +class UnarySub(Node): + def __init__(self, expr, lineno=None): + self.expr = expr + self.lineno = lineno + + def getChildren(self): + return self.expr, + + def getChildNodes(self): + return self.expr, + + def __repr__(self): + return "UnarySub(%s)" % (repr(self.expr),) + +class While(Node): + def __init__(self, test, body, else_, lineno=None): + self.test = test + self.body = body + self.else_ = else_ + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.test) + children.append(self.body) + children.append(self.else_) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.test) + nodelist.append(self.body) + if self.else_ is not None: + nodelist.append(self.else_) + return tuple(nodelist) + + def __repr__(self): + return "While(%s, %s, %s)" % (repr(self.test), repr(self.body), repr(self.else_)) + +class With(Node): + def __init__(self, expr, vars, body, lineno=None): + self.expr = expr + self.vars = vars + self.body = body + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.expr) + children.append(self.vars) + children.append(self.body) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.expr) + if self.vars is not None: + nodelist.append(self.vars) + nodelist.append(self.body) + return tuple(nodelist) + + def __repr__(self): + return "With(%s, %s, %s)" % (repr(self.expr), repr(self.vars), repr(self.body)) + +class Yield(Node): + def __init__(self, value, lineno=None): + self.value = value + self.lineno = lineno + + def getChildren(self): + return self.value, + + def getChildNodes(self): + return self.value, + + def __repr__(self): + return "Yield(%s)" % (repr(self.value),) + +for name, obj in globals().items(): + if isinstance(obj, type) and issubclass(obj, Node): + nodes[name.lower()] = obj diff --git a/PythonHome/Lib/compiler/ast.pyc b/PythonHome/Lib/compiler/ast.pyc deleted file mode 100644 index b7b05c104232696bc77de0b09cb6f93e529d0d14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66290 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 E1N;v)9{>OV diff --git a/PythonHome/Lib/compiler/consts.py b/PythonHome/Lib/compiler/consts.py new file mode 100644 index 0000000000..c60b1d0b4f --- /dev/null +++ b/PythonHome/Lib/compiler/consts.py @@ -0,0 +1,23 @@ +# operation flags +OP_ASSIGN = 'OP_ASSIGN' +OP_DELETE = 'OP_DELETE' +OP_APPLY = 'OP_APPLY' + +SC_LOCAL = 1 +SC_GLOBAL_IMPLICIT = 2 +SC_GLOBAL_EXPLICIT = 3 +SC_FREE = 4 +SC_CELL = 5 +SC_UNKNOWN = 6 + +CO_OPTIMIZED = 0x0001 +CO_NEWLOCALS = 0x0002 +CO_VARARGS = 0x0004 +CO_VARKEYWORDS = 0x0008 +CO_NESTED = 0x0010 +CO_GENERATOR = 0x0020 +CO_GENERATOR_ALLOWED = 0 +CO_FUTURE_DIVISION = 0x2000 +CO_FUTURE_ABSIMPORT = 0x4000 +CO_FUTURE_WITH_STATEMENT = 0x8000 +CO_FUTURE_PRINT_FUNCTION = 0x10000 diff --git a/PythonHome/Lib/compiler/consts.pyc b/PythonHome/Lib/compiler/consts.pyc deleted file mode 100644 index 4e2ce9ae2ddc3652a3384421704d6a654d29bcb7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 722 zcmZ9J$!^;)5Qcy6OKitUdg!sI!lyhzQB;u`mk3P?Bpo$G02K{$5ReTOdnnLDAF6NG z7wC|78aNX8Y384W9IEqoI{s6BH8bAf$zd~;d^jB z_&!`8egHRsAHoe&&M4)KQ}h6S1UG>n!%g82;AZd>xI_3U+#G%ecLaY3cMLy=JAprf zSsc>=!ib=XDl>+!SAf>{=ZyI4_(t2&;$Zbx(?x)HsIend>I=MnEBXc5S)WB-jb(1Bzl{>r~2;pI~fm6XilGgrYrw&|LA|*-F}S! Spm|T|x9DvrMr+^RD#U+1L5S1< diff --git a/PythonHome/Lib/compiler/future.py b/PythonHome/Lib/compiler/future.py new file mode 100644 index 0000000000..fd5e5dfb37 --- /dev/null +++ b/PythonHome/Lib/compiler/future.py @@ -0,0 +1,74 @@ +"""Parser for future statements + +""" + +from compiler import ast, walk + +def is_future(stmt): + """Return true if statement is a well-formed future statement""" + if not isinstance(stmt, ast.From): + return 0 + if stmt.modname == "__future__": + return 1 + else: + return 0 + +class FutureParser: + + features = ("nested_scopes", "generators", "division", + "absolute_import", "with_statement", "print_function", + "unicode_literals") + + def __init__(self): + self.found = {} # set + + def visitModule(self, node): + stmt = node.node + for s in stmt.nodes: + if not self.check_stmt(s): + break + + def check_stmt(self, stmt): + if is_future(stmt): + for name, asname in stmt.names: + if name in self.features: + self.found[name] = 1 + else: + raise SyntaxError, \ + "future feature %s is not defined" % name + stmt.valid_future = 1 + return 1 + return 0 + + def get_features(self): + """Return list of features enabled by future statements""" + return self.found.keys() + +class BadFutureParser: + """Check for invalid future statements""" + + def visitFrom(self, node): + if hasattr(node, 'valid_future'): + return + if node.modname != "__future__": + return + raise SyntaxError, "invalid future statement " + repr(node) + +def find_futures(node): + p1 = FutureParser() + p2 = BadFutureParser() + walk(node, p1) + walk(node, p2) + return p1.get_features() + +if __name__ == "__main__": + import sys + from compiler import parseFile, walk + + for file in sys.argv[1:]: + print file + tree = parseFile(file) + v = FutureParser() + walk(tree, v) + print v.found + print diff --git a/PythonHome/Lib/compiler/future.pyc b/PythonHome/Lib/compiler/future.pyc deleted file mode 100644 index 096d74185b49cc1ba24ad21f093e730cf30dfcd3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2806 zcma)8?QYye6uq{SO}yEprGb=!M9oL5tq?`6Pz9(UXiMo28dbADB37x4vz~38?Alw; zY??^vAHoChFuVpocorT2&bi)ADixw^;_I35jPJc?&bj00@74AnTfg)MGW#vy{v9s& z7fdeFhYchTWfaIblzu4VNcxckc_hE#@q*;|UzL23-D8oT`-_sdBwv$!>0}7~Wu3kx zc3JXR_Cl%u)HkW&y^Q3Yg!hAD!1vV@Ob;kop68*Q4TN~ zYzHJbAG$_}|I}Tx>YQ_b3ZW~@657<%HdR3` zfy-H87}`t=#5G4rmX%L(J1k0@tNywKz>v}nWYAN?z1cEn$RN+8dxxdZ4t}U>u#X(x z&qhT)6VPk0Dx%Dt+Vt#YPGySLIfQB6!L+Nm+$AmuI>81&y%U zLWO@IJST)Boo2;pR5+hh!(^UQV#{o2gp#y#_(oN7S~r`lnZ=$xbjmO#&3Q>ee4bh8 zumRtFihe`Uuj~>aYZcZwHIG6M^O6U*tX-E&u=k diff --git a/PythonHome/Lib/compiler/misc.py b/PythonHome/Lib/compiler/misc.py new file mode 100644 index 0000000000..588c7fbd5a --- /dev/null +++ b/PythonHome/Lib/compiler/misc.py @@ -0,0 +1,73 @@ + +def flatten(tup): + elts = [] + for elt in tup: + if isinstance(elt, tuple): + elts = elts + flatten(elt) + else: + elts.append(elt) + return elts + +class Set: + def __init__(self): + self.elts = {} + def __len__(self): + return len(self.elts) + def __contains__(self, elt): + return elt in self.elts + def add(self, elt): + self.elts[elt] = elt + def elements(self): + return self.elts.keys() + def has_elt(self, elt): + return elt in self.elts + def remove(self, elt): + del self.elts[elt] + def copy(self): + c = Set() + c.elts.update(self.elts) + return c + +class Stack: + def __init__(self): + self.stack = [] + self.pop = self.stack.pop + def __len__(self): + return len(self.stack) + def push(self, elt): + self.stack.append(elt) + def top(self): + return self.stack[-1] + def __getitem__(self, index): # needed by visitContinue() + return self.stack[index] + +MANGLE_LEN = 256 # magic constant from compile.c + +def mangle(name, klass): + if not name.startswith('__'): + return name + if len(name) + 2 >= MANGLE_LEN: + return name + if name.endswith('__'): + return name + try: + i = 0 + while klass[i] == '_': + i = i + 1 + except IndexError: + return name + klass = klass[i:] + + tlen = len(klass) + len(name) + if tlen > MANGLE_LEN: + klass = klass[:MANGLE_LEN-tlen] + + return "_%s%s" % (klass, name) + +def set_filename(filename, tree): + """Set the filename attribute to filename on every node in tree""" + worklist = [tree] + while worklist: + node = worklist.pop(0) + node.filename = filename + worklist.extend(node.getChildNodes()) diff --git a/PythonHome/Lib/compiler/misc.pyc b/PythonHome/Lib/compiler/misc.pyc deleted file mode 100644 index 94c2cfa64cbe2129cde70d50f8b522158306dc52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3448 zcmb_eU2hvj6uq-{+&DCpCT-I2RRfAJLWHNjwWu^i2nZHhKLnzp!Szm(jqSCwGiej4 z6%Xl8;+0>(&*2BaIoDaQ)zFYcO*FGJv*Y`5&b@bURy zG5q(Kc12zoIeH+^MZWpUoPLB-sTR3Pp zDZkaE^e~4h^=alqC+oT}!?VLt--T;f?ese#xGdDL?uj4%` z>_sQPgw@*P&GgCR?r<qqt=7w2}ZWy;ob(2l>$gbd%H%YU*cES3b1Dju z6Btx#!c8nDCSY+NoS$XkDrQhcCrK8jw9~I*lmMvrWT4cn`ZPTl^*wj&H4rXA0m*WG zH$X!9TT>M_Uxk07o#8R2AJ{*5W7soTayJ-0b$6z;6Z*n` z^}T@uBmjU%0fPY`VIMWE$OnU?A{HvR8q+IH2rW{FqofmDlM&%xI2DcWH&L z&a04giUK_))J#2^{?{7a4xMhVi?{kmFCSs}dzh|JCs7O;*=Nhq`#9Y#is3jYKnNCA zD{;XD@m90&73uc0PK}16OXi2-*nlKYCJ6pndx-7p%41BTVg}b`6%*=DFkYJyq_6Z| z3$vL@3=KCbjv10=^j)Gr(&f>i-&@7AFrz3-6u-`M+Br4@AHS8hDr%+w;BV~l6?|8& z!f^EIlwRs9#w&V}eb7t8T2m_3e^xh*fiz3pQ5o###Cf1Y*6zBH1~;(wGi*qYw3i7RgFdl^%Mvlr0&$lV!X- z*p#iUY(c8%DSC5~|1QQD>iQXIB@t!K)VS#NJKn3pRJ*5uW~8L=yf9%g9(1zZzFVWA zA7c`9oa(pjZ+0}H^kYm^eS%OCiy5Tsu-cZB9U2`qZZk@dZ_pR^#rE4VSUWeg;Q>5rcc z^IkvoK~JgbV(@B1>VhqFD_BetiR!4rH!xbIq$b(W9)A4oWm?4_apIl$OH5Ojv6J(t aoyGh6<1gt~BubOBUSGVmIA4qExBmq%d?)_^ diff --git a/PythonHome/Lib/compiler/pyassem.py b/PythonHome/Lib/compiler/pyassem.py new file mode 100644 index 0000000000..f52f7d079f --- /dev/null +++ b/PythonHome/Lib/compiler/pyassem.py @@ -0,0 +1,763 @@ +"""A flow graph representation for Python bytecode""" + +import dis +import types +import sys + +from compiler import misc +from compiler.consts \ + import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS + +class FlowGraph: + def __init__(self): + self.current = self.entry = Block() + self.exit = Block("exit") + self.blocks = misc.Set() + self.blocks.add(self.entry) + self.blocks.add(self.exit) + + def startBlock(self, block): + if self._debug: + if self.current: + print "end", repr(self.current) + print " next", self.current.next + print " prev", self.current.prev + print " ", self.current.get_children() + print repr(block) + self.current = block + + def nextBlock(self, block=None): + # XXX think we need to specify when there is implicit transfer + # from one block to the next. might be better to represent this + # with explicit JUMP_ABSOLUTE instructions that are optimized + # out when they are unnecessary. + # + # I think this strategy works: each block has a child + # designated as "next" which is returned as the last of the + # children. because the nodes in a graph are emitted in + # reverse post order, the "next" block will always be emitted + # immediately after its parent. + # Worry: maintaining this invariant could be tricky + if block is None: + block = self.newBlock() + + # Note: If the current block ends with an unconditional control + # transfer, then it is techically incorrect to add an implicit + # transfer to the block graph. Doing so results in code generation + # for unreachable blocks. That doesn't appear to be very common + # with Python code and since the built-in compiler doesn't optimize + # it out we don't either. + self.current.addNext(block) + self.startBlock(block) + + def newBlock(self): + b = Block() + self.blocks.add(b) + return b + + def startExitBlock(self): + self.startBlock(self.exit) + + _debug = 0 + + def _enable_debug(self): + self._debug = 1 + + def _disable_debug(self): + self._debug = 0 + + def emit(self, *inst): + if self._debug: + print "\t", inst + if len(inst) == 2 and isinstance(inst[1], Block): + self.current.addOutEdge(inst[1]) + self.current.emit(inst) + + def getBlocksInOrder(self): + """Return the blocks in reverse postorder + + i.e. each node appears before all of its successors + """ + order = order_blocks(self.entry, self.exit) + return order + + def getBlocks(self): + return self.blocks.elements() + + def getRoot(self): + """Return nodes appropriate for use with dominator""" + return self.entry + + def getContainedGraphs(self): + l = [] + for b in self.getBlocks(): + l.extend(b.getContainedGraphs()) + return l + + +def order_blocks(start_block, exit_block): + """Order blocks so that they are emitted in the right order""" + # Rules: + # - when a block has a next block, the next block must be emitted just after + # - when a block has followers (relative jumps), it must be emitted before + # them + # - all reachable blocks must be emitted + order = [] + + # Find all the blocks to be emitted. + remaining = set() + todo = [start_block] + while todo: + b = todo.pop() + if b in remaining: + continue + remaining.add(b) + for c in b.get_children(): + if c not in remaining: + todo.append(c) + + # A block is dominated by another block if that block must be emitted + # before it. + dominators = {} + for b in remaining: + if __debug__ and b.next: + assert b is b.next[0].prev[0], (b, b.next) + # Make sure every block appears in dominators, even if no + # other block must precede it. + dominators.setdefault(b, set()) + # preceding blocks dominate following blocks + for c in b.get_followers(): + while 1: + dominators.setdefault(c, set()).add(b) + # Any block that has a next pointer leading to c is also + # dominated because the whole chain will be emitted at once. + # Walk backwards and add them all. + if c.prev and c.prev[0] is not b: + c = c.prev[0] + else: + break + + def find_next(): + # Find a block that can be emitted next. + for b in remaining: + for c in dominators[b]: + if c in remaining: + break # can't emit yet, dominated by a remaining block + else: + return b + assert 0, 'circular dependency, cannot find next block' + + b = start_block + while 1: + order.append(b) + remaining.discard(b) + if b.next: + b = b.next[0] + continue + elif b is not exit_block and not b.has_unconditional_transfer(): + order.append(exit_block) + if not remaining: + break + b = find_next() + return order + + +class Block: + _count = 0 + + def __init__(self, label=''): + self.insts = [] + self.outEdges = set() + self.label = label + self.bid = Block._count + self.next = [] + self.prev = [] + Block._count = Block._count + 1 + + def __repr__(self): + if self.label: + return "" % (self.label, self.bid) + else: + return "" % (self.bid) + + def __str__(self): + insts = map(str, self.insts) + return "" % (self.label, self.bid, + '\n'.join(insts)) + + def emit(self, inst): + op = inst[0] + self.insts.append(inst) + + def getInstructions(self): + return self.insts + + def addOutEdge(self, block): + self.outEdges.add(block) + + def addNext(self, block): + self.next.append(block) + assert len(self.next) == 1, map(str, self.next) + block.prev.append(self) + assert len(block.prev) == 1, map(str, block.prev) + + _uncond_transfer = ('RETURN_VALUE', 'RAISE_VARARGS', + 'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'CONTINUE_LOOP', + ) + + def has_unconditional_transfer(self): + """Returns True if there is an unconditional transfer to an other block + at the end of this block. This means there is no risk for the bytecode + executer to go past this block's bytecode.""" + try: + op, arg = self.insts[-1] + except (IndexError, ValueError): + return + return op in self._uncond_transfer + + def get_children(self): + return list(self.outEdges) + self.next + + def get_followers(self): + """Get the whole list of followers, including the next block.""" + followers = set(self.next) + # Blocks that must be emitted *after* this one, because of + # bytecode offsets (e.g. relative jumps) pointing to them. + for inst in self.insts: + if inst[0] in PyFlowGraph.hasjrel: + followers.add(inst[1]) + return followers + + def getContainedGraphs(self): + """Return all graphs contained within this block. + + For example, a MAKE_FUNCTION block will contain a reference to + the graph for the function body. + """ + contained = [] + for inst in self.insts: + if len(inst) == 1: + continue + op = inst[1] + if hasattr(op, 'graph'): + contained.append(op.graph) + return contained + +# flags for code objects + +# the FlowGraph is transformed in place; it exists in one of these states +RAW = "RAW" +FLAT = "FLAT" +CONV = "CONV" +DONE = "DONE" + +class PyFlowGraph(FlowGraph): + super_init = FlowGraph.__init__ + + def __init__(self, name, filename, args=(), optimized=0, klass=None): + self.super_init() + self.name = name + self.filename = filename + self.docstring = None + self.args = args # XXX + self.argcount = getArgCount(args) + self.klass = klass + if optimized: + self.flags = CO_OPTIMIZED | CO_NEWLOCALS + else: + self.flags = 0 + self.consts = [] + self.names = [] + # Free variables found by the symbol table scan, including + # variables used only in nested scopes, are included here. + self.freevars = [] + self.cellvars = [] + # The closure list is used to track the order of cell + # variables and free variables in the resulting code object. + # The offsets used by LOAD_CLOSURE/LOAD_DEREF refer to both + # kinds of variables. + self.closure = [] + self.varnames = list(args) or [] + for i in range(len(self.varnames)): + var = self.varnames[i] + if isinstance(var, TupleArg): + self.varnames[i] = var.getName() + self.stage = RAW + + def setDocstring(self, doc): + self.docstring = doc + + def setFlag(self, flag): + self.flags = self.flags | flag + if flag == CO_VARARGS: + self.argcount = self.argcount - 1 + + def checkFlag(self, flag): + if self.flags & flag: + return 1 + + def setFreeVars(self, names): + self.freevars = list(names) + + def setCellVars(self, names): + self.cellvars = names + + def getCode(self): + """Get a Python code object""" + assert self.stage == RAW + self.computeStackDepth() + self.flattenGraph() + assert self.stage == FLAT + self.convertArgs() + assert self.stage == CONV + self.makeByteCode() + assert self.stage == DONE + return self.newCodeObject() + + def dump(self, io=None): + if io: + save = sys.stdout + sys.stdout = io + pc = 0 + for t in self.insts: + opname = t[0] + if opname == "SET_LINENO": + print + if len(t) == 1: + print "\t", "%3d" % pc, opname + pc = pc + 1 + else: + print "\t", "%3d" % pc, opname, t[1] + pc = pc + 3 + if io: + sys.stdout = save + + def computeStackDepth(self): + """Compute the max stack depth. + + Approach is to compute the stack effect of each basic block. + Then find the path through the code with the largest total + effect. + """ + depth = {} + exit = None + for b in self.getBlocks(): + depth[b] = findDepth(b.getInstructions()) + + seen = {} + + def max_depth(b, d): + if b in seen: + return d + seen[b] = 1 + d = d + depth[b] + children = b.get_children() + if children: + return max([max_depth(c, d) for c in children]) + else: + if not b.label == "exit": + return max_depth(self.exit, d) + else: + return d + + self.stacksize = max_depth(self.entry, 0) + + def flattenGraph(self): + """Arrange the blocks in order and resolve jumps""" + assert self.stage == RAW + self.insts = insts = [] + pc = 0 + begin = {} + end = {} + for b in self.getBlocksInOrder(): + begin[b] = pc + for inst in b.getInstructions(): + insts.append(inst) + if len(inst) == 1: + pc = pc + 1 + elif inst[0] != "SET_LINENO": + # arg takes 2 bytes + pc = pc + 3 + end[b] = pc + pc = 0 + for i in range(len(insts)): + inst = insts[i] + if len(inst) == 1: + pc = pc + 1 + elif inst[0] != "SET_LINENO": + pc = pc + 3 + opname = inst[0] + if opname in self.hasjrel: + oparg = inst[1] + offset = begin[oparg] - pc + insts[i] = opname, offset + elif opname in self.hasjabs: + insts[i] = opname, begin[inst[1]] + self.stage = FLAT + + hasjrel = set() + for i in dis.hasjrel: + hasjrel.add(dis.opname[i]) + hasjabs = set() + for i in dis.hasjabs: + hasjabs.add(dis.opname[i]) + + def convertArgs(self): + """Convert arguments from symbolic to concrete form""" + assert self.stage == FLAT + self.consts.insert(0, self.docstring) + self.sort_cellvars() + for i in range(len(self.insts)): + t = self.insts[i] + if len(t) == 2: + opname, oparg = t + conv = self._converters.get(opname, None) + if conv: + self.insts[i] = opname, conv(self, oparg) + self.stage = CONV + + def sort_cellvars(self): + """Sort cellvars in the order of varnames and prune from freevars. + """ + cells = {} + for name in self.cellvars: + cells[name] = 1 + self.cellvars = [name for name in self.varnames + if name in cells] + for name in self.cellvars: + del cells[name] + self.cellvars = self.cellvars + cells.keys() + self.closure = self.cellvars + self.freevars + + def _lookupName(self, name, list): + """Return index of name in list, appending if necessary + + This routine uses a list instead of a dictionary, because a + dictionary can't store two different keys if the keys have the + same value but different types, e.g. 2 and 2L. The compiler + must treat these two separately, so it does an explicit type + comparison before comparing the values. + """ + t = type(name) + for i in range(len(list)): + if t == type(list[i]) and list[i] == name: + return i + end = len(list) + list.append(name) + return end + + _converters = {} + def _convert_LOAD_CONST(self, arg): + if hasattr(arg, 'getCode'): + arg = arg.getCode() + return self._lookupName(arg, self.consts) + + def _convert_LOAD_FAST(self, arg): + self._lookupName(arg, self.names) + return self._lookupName(arg, self.varnames) + _convert_STORE_FAST = _convert_LOAD_FAST + _convert_DELETE_FAST = _convert_LOAD_FAST + + def _convert_LOAD_NAME(self, arg): + if self.klass is None: + self._lookupName(arg, self.varnames) + return self._lookupName(arg, self.names) + + def _convert_NAME(self, arg): + if self.klass is None: + self._lookupName(arg, self.varnames) + return self._lookupName(arg, self.names) + _convert_STORE_NAME = _convert_NAME + _convert_DELETE_NAME = _convert_NAME + _convert_IMPORT_NAME = _convert_NAME + _convert_IMPORT_FROM = _convert_NAME + _convert_STORE_ATTR = _convert_NAME + _convert_LOAD_ATTR = _convert_NAME + _convert_DELETE_ATTR = _convert_NAME + _convert_LOAD_GLOBAL = _convert_NAME + _convert_STORE_GLOBAL = _convert_NAME + _convert_DELETE_GLOBAL = _convert_NAME + + def _convert_DEREF(self, arg): + self._lookupName(arg, self.names) + self._lookupName(arg, self.varnames) + return self._lookupName(arg, self.closure) + _convert_LOAD_DEREF = _convert_DEREF + _convert_STORE_DEREF = _convert_DEREF + + def _convert_LOAD_CLOSURE(self, arg): + self._lookupName(arg, self.varnames) + return self._lookupName(arg, self.closure) + + _cmp = list(dis.cmp_op) + def _convert_COMPARE_OP(self, arg): + return self._cmp.index(arg) + + # similarly for other opcodes... + + for name, obj in locals().items(): + if name[:9] == "_convert_": + opname = name[9:] + _converters[opname] = obj + del name, obj, opname + + def makeByteCode(self): + assert self.stage == CONV + self.lnotab = lnotab = LineAddrTable() + for t in self.insts: + opname = t[0] + if len(t) == 1: + lnotab.addCode(self.opnum[opname]) + else: + oparg = t[1] + if opname == "SET_LINENO": + lnotab.nextLine(oparg) + continue + hi, lo = twobyte(oparg) + try: + lnotab.addCode(self.opnum[opname], lo, hi) + except ValueError: + print opname, oparg + print self.opnum[opname], lo, hi + raise + self.stage = DONE + + opnum = {} + for num in range(len(dis.opname)): + opnum[dis.opname[num]] = num + del num + + def newCodeObject(self): + assert self.stage == DONE + if (self.flags & CO_NEWLOCALS) == 0: + nlocals = 0 + else: + nlocals = len(self.varnames) + argcount = self.argcount + if self.flags & CO_VARKEYWORDS: + argcount = argcount - 1 + return types.CodeType(argcount, nlocals, self.stacksize, self.flags, + self.lnotab.getCode(), self.getConsts(), + tuple(self.names), tuple(self.varnames), + self.filename, self.name, self.lnotab.firstline, + self.lnotab.getTable(), tuple(self.freevars), + tuple(self.cellvars)) + + def getConsts(self): + """Return a tuple for the const slot of the code object + + Must convert references to code (MAKE_FUNCTION) to code + objects recursively. + """ + l = [] + for elt in self.consts: + if isinstance(elt, PyFlowGraph): + elt = elt.getCode() + l.append(elt) + return tuple(l) + +def isJump(opname): + if opname[:4] == 'JUMP': + return 1 + +class TupleArg: + """Helper for marking func defs with nested tuples in arglist""" + def __init__(self, count, names): + self.count = count + self.names = names + def __repr__(self): + return "TupleArg(%s, %s)" % (self.count, self.names) + def getName(self): + return ".%d" % self.count + +def getArgCount(args): + argcount = len(args) + if args: + for arg in args: + if isinstance(arg, TupleArg): + numNames = len(misc.flatten(arg.names)) + argcount = argcount - numNames + return argcount + +def twobyte(val): + """Convert an int argument into high and low bytes""" + assert isinstance(val, int) + return divmod(val, 256) + +class LineAddrTable: + """lnotab + + This class builds the lnotab, which is documented in compile.c. + Here's a brief recap: + + For each SET_LINENO instruction after the first one, two bytes are + added to lnotab. (In some cases, multiple two-byte entries are + added.) The first byte is the distance in bytes between the + instruction for the last SET_LINENO and the current SET_LINENO. + The second byte is offset in line numbers. If either offset is + greater than 255, multiple two-byte entries are added -- see + compile.c for the delicate details. + """ + + def __init__(self): + self.code = [] + self.codeOffset = 0 + self.firstline = 0 + self.lastline = 0 + self.lastoff = 0 + self.lnotab = [] + + def addCode(self, *args): + for arg in args: + self.code.append(chr(arg)) + self.codeOffset = self.codeOffset + len(args) + + def nextLine(self, lineno): + if self.firstline == 0: + self.firstline = lineno + self.lastline = lineno + else: + # compute deltas + addr = self.codeOffset - self.lastoff + line = lineno - self.lastline + # Python assumes that lineno always increases with + # increasing bytecode address (lnotab is unsigned char). + # Depending on when SET_LINENO instructions are emitted + # this is not always true. Consider the code: + # a = (1, + # b) + # In the bytecode stream, the assignment to "a" occurs + # after the loading of "b". This works with the C Python + # compiler because it only generates a SET_LINENO instruction + # for the assignment. + if line >= 0: + push = self.lnotab.append + while addr > 255: + push(255); push(0) + addr -= 255 + while line > 255: + push(addr); push(255) + line -= 255 + addr = 0 + if addr > 0 or line > 0: + push(addr); push(line) + self.lastline = lineno + self.lastoff = self.codeOffset + + def getCode(self): + return ''.join(self.code) + + def getTable(self): + return ''.join(map(chr, self.lnotab)) + +class StackDepthTracker: + # XXX 1. need to keep track of stack depth on jumps + # XXX 2. at least partly as a result, this code is broken + + def findDepth(self, insts, debug=0): + depth = 0 + maxDepth = 0 + for i in insts: + opname = i[0] + if debug: + print i, + delta = self.effect.get(opname, None) + if delta is not None: + depth = depth + delta + else: + # now check patterns + for pat, pat_delta in self.patterns: + if opname[:len(pat)] == pat: + delta = pat_delta + depth = depth + delta + break + # if we still haven't found a match + if delta is None: + meth = getattr(self, opname, None) + if meth is not None: + depth = depth + meth(i[1]) + if depth > maxDepth: + maxDepth = depth + if debug: + print depth, maxDepth + return maxDepth + + effect = { + 'POP_TOP': -1, + 'DUP_TOP': 1, + 'LIST_APPEND': -1, + 'SET_ADD': -1, + 'MAP_ADD': -2, + 'SLICE+1': -1, + 'SLICE+2': -1, + 'SLICE+3': -2, + 'STORE_SLICE+0': -1, + 'STORE_SLICE+1': -2, + 'STORE_SLICE+2': -2, + 'STORE_SLICE+3': -3, + 'DELETE_SLICE+0': -1, + 'DELETE_SLICE+1': -2, + 'DELETE_SLICE+2': -2, + 'DELETE_SLICE+3': -3, + 'STORE_SUBSCR': -3, + 'DELETE_SUBSCR': -2, + # PRINT_EXPR? + 'PRINT_ITEM': -1, + 'RETURN_VALUE': -1, + 'YIELD_VALUE': -1, + 'EXEC_STMT': -3, + 'BUILD_CLASS': -2, + 'STORE_NAME': -1, + 'STORE_ATTR': -2, + 'DELETE_ATTR': -1, + 'STORE_GLOBAL': -1, + 'BUILD_MAP': 1, + 'COMPARE_OP': -1, + 'STORE_FAST': -1, + 'IMPORT_STAR': -1, + 'IMPORT_NAME': -1, + 'IMPORT_FROM': 1, + 'LOAD_ATTR': 0, # unlike other loads + # close enough... + 'SETUP_EXCEPT': 3, + 'SETUP_FINALLY': 3, + 'FOR_ITER': 1, + 'WITH_CLEANUP': -1, + } + # use pattern match + patterns = [ + ('BINARY_', -1), + ('LOAD_', 1), + ] + + def UNPACK_SEQUENCE(self, count): + return count-1 + def BUILD_TUPLE(self, count): + return -count+1 + def BUILD_LIST(self, count): + return -count+1 + def BUILD_SET(self, count): + return -count+1 + def CALL_FUNCTION(self, argc): + hi, lo = divmod(argc, 256) + return -(lo + hi * 2) + def CALL_FUNCTION_VAR(self, argc): + return self.CALL_FUNCTION(argc)-1 + def CALL_FUNCTION_KW(self, argc): + return self.CALL_FUNCTION(argc)-1 + def CALL_FUNCTION_VAR_KW(self, argc): + return self.CALL_FUNCTION(argc)-2 + def MAKE_FUNCTION(self, argc): + return -argc + def MAKE_CLOSURE(self, argc): + # XXX need to account for free variables too! + return -argc + def BUILD_SLICE(self, argc): + if argc == 2: + return -1 + elif argc == 3: + return -2 + def DUP_TOPX(self, argc): + return argc + +findDepth = StackDepthTracker().findDepth diff --git a/PythonHome/Lib/compiler/pyassem.pyc b/PythonHome/Lib/compiler/pyassem.pyc deleted file mode 100644 index 0d32efb0ded9d1d854c0d88a5d26a9b0370169ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24734 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 diff --git a/PythonHome/Lib/compiler/symbols.py b/PythonHome/Lib/compiler/symbols.py new file mode 100644 index 0000000000..afeec50153 --- /dev/null +++ b/PythonHome/Lib/compiler/symbols.py @@ -0,0 +1,462 @@ +"""Module symbol-table generator""" + +from compiler import ast +from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICIT, \ + SC_FREE, SC_CELL, SC_UNKNOWN +from compiler.misc import mangle +import types + + +import sys + +MANGLE_LEN = 256 + +class Scope: + # XXX how much information do I need about each name? + def __init__(self, name, module, klass=None): + self.name = name + self.module = module + self.defs = {} + self.uses = {} + self.globals = {} + self.params = {} + self.frees = {} + self.cells = {} + self.children = [] + # nested is true if the class could contain free variables, + # i.e. if it is nested within another function. + self.nested = None + self.generator = None + self.klass = None + if klass is not None: + for i in range(len(klass)): + if klass[i] != '_': + self.klass = klass[i:] + break + + def __repr__(self): + return "<%s: %s>" % (self.__class__.__name__, self.name) + + def mangle(self, name): + if self.klass is None: + return name + return mangle(name, self.klass) + + def add_def(self, name): + self.defs[self.mangle(name)] = 1 + + def add_use(self, name): + self.uses[self.mangle(name)] = 1 + + def add_global(self, name): + name = self.mangle(name) + if name in self.uses or name in self.defs: + pass # XXX warn about global following def/use + if name in self.params: + raise SyntaxError, "%s in %s is global and parameter" % \ + (name, self.name) + self.globals[name] = 1 + self.module.add_def(name) + + def add_param(self, name): + name = self.mangle(name) + self.defs[name] = 1 + self.params[name] = 1 + + def get_names(self): + d = {} + d.update(self.defs) + d.update(self.uses) + d.update(self.globals) + return d.keys() + + def add_child(self, child): + self.children.append(child) + + def get_children(self): + return self.children + + def DEBUG(self): + print >> sys.stderr, self.name, self.nested and "nested" or "" + print >> sys.stderr, "\tglobals: ", self.globals + print >> sys.stderr, "\tcells: ", self.cells + print >> sys.stderr, "\tdefs: ", self.defs + print >> sys.stderr, "\tuses: ", self.uses + print >> sys.stderr, "\tfrees:", self.frees + + def check_name(self, name): + """Return scope of name. + + The scope of a name could be LOCAL, GLOBAL, FREE, or CELL. + """ + if name in self.globals: + return SC_GLOBAL_EXPLICIT + if name in self.cells: + return SC_CELL + if name in self.defs: + return SC_LOCAL + if self.nested and (name in self.frees or name in self.uses): + return SC_FREE + if self.nested: + return SC_UNKNOWN + else: + return SC_GLOBAL_IMPLICIT + + def get_free_vars(self): + if not self.nested: + return () + free = {} + free.update(self.frees) + for name in self.uses.keys(): + if name not in self.defs and name not in self.globals: + free[name] = 1 + return free.keys() + + def handle_children(self): + for child in self.children: + frees = child.get_free_vars() + globals = self.add_frees(frees) + for name in globals: + child.force_global(name) + + def force_global(self, name): + """Force name to be global in scope. + + Some child of the current node had a free reference to name. + When the child was processed, it was labelled a free + variable. Now that all its enclosing scope have been + processed, the name is known to be a global or builtin. So + walk back down the child chain and set the name to be global + rather than free. + + Be careful to stop if a child does not think the name is + free. + """ + self.globals[name] = 1 + if name in self.frees: + del self.frees[name] + for child in self.children: + if child.check_name(name) == SC_FREE: + child.force_global(name) + + def add_frees(self, names): + """Process list of free vars from nested scope. + + Returns a list of names that are either 1) declared global in the + parent or 2) undefined in a top-level parent. In either case, + the nested scope should treat them as globals. + """ + child_globals = [] + for name in names: + sc = self.check_name(name) + if self.nested: + if sc == SC_UNKNOWN or sc == SC_FREE \ + or isinstance(self, ClassScope): + self.frees[name] = 1 + elif sc == SC_GLOBAL_IMPLICIT: + child_globals.append(name) + elif isinstance(self, FunctionScope) and sc == SC_LOCAL: + self.cells[name] = 1 + elif sc != SC_CELL: + child_globals.append(name) + else: + if sc == SC_LOCAL: + self.cells[name] = 1 + elif sc != SC_CELL: + child_globals.append(name) + return child_globals + + def get_cell_vars(self): + return self.cells.keys() + +class ModuleScope(Scope): + __super_init = Scope.__init__ + + def __init__(self): + self.__super_init("global", self) + +class FunctionScope(Scope): + pass + +class GenExprScope(Scope): + __super_init = Scope.__init__ + + __counter = 1 + + def __init__(self, module, klass=None): + i = self.__counter + self.__counter += 1 + self.__super_init("generator expression<%d>"%i, module, klass) + self.add_param('.0') + + def get_names(self): + keys = Scope.get_names(self) + return keys + +class LambdaScope(FunctionScope): + __super_init = Scope.__init__ + + __counter = 1 + + def __init__(self, module, klass=None): + i = self.__counter + self.__counter += 1 + self.__super_init("lambda.%d" % i, module, klass) + +class ClassScope(Scope): + __super_init = Scope.__init__ + + def __init__(self, name, module): + self.__super_init(name, module, name) + +class SymbolVisitor: + def __init__(self): + self.scopes = {} + self.klass = None + + # node that define new scopes + + def visitModule(self, node): + scope = self.module = self.scopes[node] = ModuleScope() + self.visit(node.node, scope) + + visitExpression = visitModule + + def visitFunction(self, node, parent): + if node.decorators: + self.visit(node.decorators, parent) + parent.add_def(node.name) + for n in node.defaults: + self.visit(n, parent) + scope = FunctionScope(node.name, self.module, self.klass) + if parent.nested or isinstance(parent, FunctionScope): + scope.nested = 1 + self.scopes[node] = scope + self._do_args(scope, node.argnames) + self.visit(node.code, scope) + self.handle_free_vars(scope, parent) + + def visitGenExpr(self, node, parent): + scope = GenExprScope(self.module, self.klass); + if parent.nested or isinstance(parent, FunctionScope) \ + or isinstance(parent, GenExprScope): + scope.nested = 1 + + self.scopes[node] = scope + self.visit(node.code, scope) + + self.handle_free_vars(scope, parent) + + def visitGenExprInner(self, node, scope): + for genfor in node.quals: + self.visit(genfor, scope) + + self.visit(node.expr, scope) + + def visitGenExprFor(self, node, scope): + self.visit(node.assign, scope, 1) + self.visit(node.iter, scope) + for if_ in node.ifs: + self.visit(if_, scope) + + def visitGenExprIf(self, node, scope): + self.visit(node.test, scope) + + def visitLambda(self, node, parent, assign=0): + # Lambda is an expression, so it could appear in an expression + # context where assign is passed. The transformer should catch + # any code that has a lambda on the left-hand side. + assert not assign + + for n in node.defaults: + self.visit(n, parent) + scope = LambdaScope(self.module, self.klass) + if parent.nested or isinstance(parent, FunctionScope): + scope.nested = 1 + self.scopes[node] = scope + self._do_args(scope, node.argnames) + self.visit(node.code, scope) + self.handle_free_vars(scope, parent) + + def _do_args(self, scope, args): + for name in args: + if type(name) == types.TupleType: + self._do_args(scope, name) + else: + scope.add_param(name) + + def handle_free_vars(self, scope, parent): + parent.add_child(scope) + scope.handle_children() + + def visitClass(self, node, parent): + parent.add_def(node.name) + for n in node.bases: + self.visit(n, parent) + scope = ClassScope(node.name, self.module) + if parent.nested or isinstance(parent, FunctionScope): + scope.nested = 1 + if node.doc is not None: + scope.add_def('__doc__') + scope.add_def('__module__') + self.scopes[node] = scope + prev = self.klass + self.klass = node.name + self.visit(node.code, scope) + self.klass = prev + self.handle_free_vars(scope, parent) + + # name can be a def or a use + + # XXX a few calls and nodes expect a third "assign" arg that is + # true if the name is being used as an assignment. only + # expressions contained within statements may have the assign arg. + + def visitName(self, node, scope, assign=0): + if assign: + scope.add_def(node.name) + else: + scope.add_use(node.name) + + # operations that bind new names + + def visitFor(self, node, scope): + self.visit(node.assign, scope, 1) + self.visit(node.list, scope) + self.visit(node.body, scope) + if node.else_: + self.visit(node.else_, scope) + + def visitFrom(self, node, scope): + for name, asname in node.names: + if name == "*": + continue + scope.add_def(asname or name) + + def visitImport(self, node, scope): + for name, asname in node.names: + i = name.find(".") + if i > -1: + name = name[:i] + scope.add_def(asname or name) + + def visitGlobal(self, node, scope): + for name in node.names: + scope.add_global(name) + + def visitAssign(self, node, scope): + """Propagate assignment flag down to child nodes. + + The Assign node doesn't itself contains the variables being + assigned to. Instead, the children in node.nodes are visited + with the assign flag set to true. When the names occur in + those nodes, they are marked as defs. + + Some names that occur in an assignment target are not bound by + the assignment, e.g. a name occurring inside a slice. The + visitor handles these nodes specially; they do not propagate + the assign flag to their children. + """ + for n in node.nodes: + self.visit(n, scope, 1) + self.visit(node.expr, scope) + + def visitAssName(self, node, scope, assign=1): + scope.add_def(node.name) + + def visitAssAttr(self, node, scope, assign=0): + self.visit(node.expr, scope, 0) + + def visitSubscript(self, node, scope, assign=0): + self.visit(node.expr, scope, 0) + for n in node.subs: + self.visit(n, scope, 0) + + def visitSlice(self, node, scope, assign=0): + self.visit(node.expr, scope, 0) + if node.lower: + self.visit(node.lower, scope, 0) + if node.upper: + self.visit(node.upper, scope, 0) + + def visitAugAssign(self, node, scope): + # If the LHS is a name, then this counts as assignment. + # Otherwise, it's just use. + self.visit(node.node, scope) + if isinstance(node.node, ast.Name): + self.visit(node.node, scope, 1) # XXX worry about this + self.visit(node.expr, scope) + + # prune if statements if tests are false + + _const_types = types.StringType, types.IntType, types.FloatType + + def visitIf(self, node, scope): + for test, body in node.tests: + if isinstance(test, ast.Const): + if type(test.value) in self._const_types: + if not test.value: + continue + self.visit(test, scope) + self.visit(body, scope) + if node.else_: + self.visit(node.else_, scope) + + # a yield statement signals a generator + + def visitYield(self, node, scope): + scope.generator = 1 + self.visit(node.value, scope) + +def list_eq(l1, l2): + return sorted(l1) == sorted(l2) + +if __name__ == "__main__": + import sys + from compiler import parseFile, walk + import symtable + + def get_names(syms): + return [s for s in [s.get_name() for s in syms.get_symbols()] + if not (s.startswith('_[') or s.startswith('.'))] + + for file in sys.argv[1:]: + print file + f = open(file) + buf = f.read() + f.close() + syms = symtable.symtable(buf, file, "exec") + mod_names = get_names(syms) + tree = parseFile(file) + s = SymbolVisitor() + walk(tree, s) + + # compare module-level symbols + names2 = s.scopes[tree].get_names() + + if not list_eq(mod_names, names2): + print + print "oops", file + print sorted(mod_names) + print sorted(names2) + sys.exit(-1) + + d = {} + d.update(s.scopes) + del d[tree] + scopes = d.values() + del d + + for s in syms.get_symbols(): + if s.is_namespace(): + l = [sc for sc in scopes + if sc.name == s.get_name()] + if len(l) > 1: + print "skipping", s.get_name() + else: + if not list_eq(get_names(s.get_namespace()), + l[0].get_names()): + print s.get_name() + print sorted(get_names(s.get_namespace())) + print sorted(l[0].get_names()) + sys.exit(-1) diff --git a/PythonHome/Lib/compiler/symbols.pyc b/PythonHome/Lib/compiler/symbols.pyc deleted file mode 100644 index 7326d1cff55d85199a283c495dee6bdbeee89ee2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16837 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 AST +parseFile(path) -> AST +""" + +# Original version written by Greg Stein (gstein@lyra.org) +# and Bill Tutt (rassilon@lima.mudlib.org) +# February 1997. +# +# Modifications and improvements for Python 2.0 by Jeremy Hylton and +# Mark Hammond +# +# Some fixes to try to have correct line number on almost all nodes +# (except Module, Discard and Stmt) added by Sylvain Thenault +# +# Portions of this file are: +# Copyright (C) 1997-1998 Greg Stein. All Rights Reserved. +# +# This module is provided under a BSD-ish license. See +# http://www.opensource.org/licenses/bsd-license.html +# and replace OWNER, ORGANIZATION, and YEAR as appropriate. + +from compiler.ast import * +import parser +import symbol +import token + +class WalkerError(StandardError): + pass + +from compiler.consts import CO_VARARGS, CO_VARKEYWORDS +from compiler.consts import OP_ASSIGN, OP_DELETE, OP_APPLY + +def parseFile(path): + f = open(path, "U") + # XXX The parser API tolerates files without a trailing newline, + # but not strings without a trailing newline. Always add an extra + # newline to the file contents, since we're going through the string + # version of the API. + src = f.read() + "\n" + f.close() + return parse(src) + +def parse(buf, mode="exec"): + if mode == "exec" or mode == "single": + return Transformer().parsesuite(buf) + elif mode == "eval": + return Transformer().parseexpr(buf) + else: + raise ValueError("compile() arg 3 must be" + " 'exec' or 'eval' or 'single'") + +def asList(nodes): + l = [] + for item in nodes: + if hasattr(item, "asList"): + l.append(item.asList()) + else: + if type(item) is type( (None, None) ): + l.append(tuple(asList(item))) + elif type(item) is type( [] ): + l.append(asList(item)) + else: + l.append(item) + return l + +def extractLineNo(ast): + if not isinstance(ast[1], tuple): + # get a terminal node + return ast[2] + for child in ast[1:]: + if isinstance(child, tuple): + lineno = extractLineNo(child) + if lineno is not None: + return lineno + +def Node(*args): + kind = args[0] + if kind in nodes: + try: + return nodes[kind](*args[1:]) + except TypeError: + print nodes[kind], len(args), args + raise + else: + raise WalkerError, "Can't find appropriate Node type: %s" % str(args) + #return apply(ast.Node, args) + +class Transformer: + """Utility object for transforming Python parse trees. + + Exposes the following methods: + tree = transform(ast_tree) + tree = parsesuite(text) + tree = parseexpr(text) + tree = parsefile(fileob | filename) + """ + + def __init__(self): + self._dispatch = {} + for value, name in symbol.sym_name.items(): + if hasattr(self, name): + self._dispatch[value] = getattr(self, name) + self._dispatch[token.NEWLINE] = self.com_NEWLINE + self._atom_dispatch = {token.LPAR: self.atom_lpar, + token.LSQB: self.atom_lsqb, + token.LBRACE: self.atom_lbrace, + token.BACKQUOTE: self.atom_backquote, + token.NUMBER: self.atom_number, + token.STRING: self.atom_string, + token.NAME: self.atom_name, + } + self.encoding = None + + def transform(self, tree): + """Transform an AST into a modified parse tree.""" + if not (isinstance(tree, tuple) or isinstance(tree, list)): + tree = parser.st2tuple(tree, line_info=1) + return self.compile_node(tree) + + def parsesuite(self, text): + """Return a modified parse tree for the given suite text.""" + return self.transform(parser.suite(text)) + + def parseexpr(self, text): + """Return a modified parse tree for the given expression text.""" + return self.transform(parser.expr(text)) + + def parsefile(self, file): + """Return a modified parse tree for the contents of the given file.""" + if type(file) == type(''): + file = open(file) + return self.parsesuite(file.read()) + + # -------------------------------------------------------------- + # + # PRIVATE METHODS + # + + def compile_node(self, node): + ### emit a line-number node? + n = node[0] + + if n == symbol.encoding_decl: + self.encoding = node[2] + node = node[1] + n = node[0] + + if n == symbol.single_input: + return self.single_input(node[1:]) + if n == symbol.file_input: + return self.file_input(node[1:]) + if n == symbol.eval_input: + return self.eval_input(node[1:]) + if n == symbol.lambdef: + return self.lambdef(node[1:]) + if n == symbol.funcdef: + return self.funcdef(node[1:]) + if n == symbol.classdef: + return self.classdef(node[1:]) + + raise WalkerError, ('unexpected node type', n) + + def single_input(self, node): + ### do we want to do anything about being "interactive" ? + + # NEWLINE | simple_stmt | compound_stmt NEWLINE + n = node[0][0] + if n != token.NEWLINE: + return self.com_stmt(node[0]) + + return Pass() + + def file_input(self, nodelist): + doc = self.get_docstring(nodelist, symbol.file_input) + if doc is not None: + i = 1 + else: + i = 0 + stmts = [] + for node in nodelist[i:]: + if node[0] != token.ENDMARKER and node[0] != token.NEWLINE: + self.com_append_stmt(stmts, node) + return Module(doc, Stmt(stmts)) + + def eval_input(self, nodelist): + # from the built-in function input() + ### is this sufficient? + return Expression(self.com_node(nodelist[0])) + + def decorator_name(self, nodelist): + listlen = len(nodelist) + assert listlen >= 1 and listlen % 2 == 1 + + item = self.atom_name(nodelist) + i = 1 + while i < listlen: + assert nodelist[i][0] == token.DOT + assert nodelist[i + 1][0] == token.NAME + item = Getattr(item, nodelist[i + 1][1]) + i += 2 + + return item + + def decorator(self, nodelist): + # '@' dotted_name [ '(' [arglist] ')' ] + assert len(nodelist) in (3, 5, 6) + assert nodelist[0][0] == token.AT + assert nodelist[-1][0] == token.NEWLINE + + assert nodelist[1][0] == symbol.dotted_name + funcname = self.decorator_name(nodelist[1][1:]) + + if len(nodelist) > 3: + assert nodelist[2][0] == token.LPAR + expr = self.com_call_function(funcname, nodelist[3]) + else: + expr = funcname + + return expr + + def decorators(self, nodelist): + # decorators: decorator ([NEWLINE] decorator)* NEWLINE + items = [] + for dec_nodelist in nodelist: + assert dec_nodelist[0] == symbol.decorator + items.append(self.decorator(dec_nodelist[1:])) + return Decorators(items) + + def decorated(self, nodelist): + assert nodelist[0][0] == symbol.decorators + if nodelist[1][0] == symbol.funcdef: + n = [nodelist[0]] + list(nodelist[1][1:]) + return self.funcdef(n) + elif nodelist[1][0] == symbol.classdef: + decorators = self.decorators(nodelist[0][1:]) + cls = self.classdef(nodelist[1][1:]) + cls.decorators = decorators + return cls + raise WalkerError() + + def funcdef(self, nodelist): + # -6 -5 -4 -3 -2 -1 + # funcdef: [decorators] 'def' NAME parameters ':' suite + # parameters: '(' [varargslist] ')' + + if len(nodelist) == 6: + assert nodelist[0][0] == symbol.decorators + decorators = self.decorators(nodelist[0][1:]) + else: + assert len(nodelist) == 5 + decorators = None + + lineno = nodelist[-4][2] + name = nodelist[-4][1] + args = nodelist[-3][2] + + if args[0] == symbol.varargslist: + names, defaults, flags = self.com_arglist(args[1:]) + else: + names = defaults = () + flags = 0 + doc = self.get_docstring(nodelist[-1]) + + # code for function + code = self.com_node(nodelist[-1]) + + if doc is not None: + assert isinstance(code, Stmt) + assert isinstance(code.nodes[0], Discard) + del code.nodes[0] + return Function(decorators, name, names, defaults, flags, doc, code, + lineno=lineno) + + def lambdef(self, nodelist): + # lambdef: 'lambda' [varargslist] ':' test + if nodelist[2][0] == symbol.varargslist: + names, defaults, flags = self.com_arglist(nodelist[2][1:]) + else: + names = defaults = () + flags = 0 + + # code for lambda + code = self.com_node(nodelist[-1]) + + return Lambda(names, defaults, flags, code, lineno=nodelist[1][2]) + old_lambdef = lambdef + + def classdef(self, nodelist): + # classdef: 'class' NAME ['(' [testlist] ')'] ':' suite + + name = nodelist[1][1] + doc = self.get_docstring(nodelist[-1]) + if nodelist[2][0] == token.COLON: + bases = [] + elif nodelist[3][0] == token.RPAR: + bases = [] + else: + bases = self.com_bases(nodelist[3]) + + # code for class + code = self.com_node(nodelist[-1]) + + if doc is not None: + assert isinstance(code, Stmt) + assert isinstance(code.nodes[0], Discard) + del code.nodes[0] + + return Class(name, bases, doc, code, lineno=nodelist[1][2]) + + def stmt(self, nodelist): + return self.com_stmt(nodelist[0]) + + small_stmt = stmt + flow_stmt = stmt + compound_stmt = stmt + + def simple_stmt(self, nodelist): + # small_stmt (';' small_stmt)* [';'] NEWLINE + stmts = [] + for i in range(0, len(nodelist), 2): + self.com_append_stmt(stmts, nodelist[i]) + return Stmt(stmts) + + def parameters(self, nodelist): + raise WalkerError + + def varargslist(self, nodelist): + raise WalkerError + + def fpdef(self, nodelist): + raise WalkerError + + def fplist(self, nodelist): + raise WalkerError + + def dotted_name(self, nodelist): + raise WalkerError + + def comp_op(self, nodelist): + raise WalkerError + + def trailer(self, nodelist): + raise WalkerError + + def sliceop(self, nodelist): + raise WalkerError + + def argument(self, nodelist): + raise WalkerError + + # -------------------------------------------------------------- + # + # STATEMENT NODES (invoked by com_node()) + # + + def expr_stmt(self, nodelist): + # augassign testlist | testlist ('=' testlist)* + en = nodelist[-1] + exprNode = self.lookup_node(en)(en[1:]) + if len(nodelist) == 1: + return Discard(exprNode, lineno=exprNode.lineno) + if nodelist[1][0] == token.EQUAL: + nodesl = [] + for i in range(0, len(nodelist) - 2, 2): + nodesl.append(self.com_assign(nodelist[i], OP_ASSIGN)) + return Assign(nodesl, exprNode, lineno=nodelist[1][2]) + else: + lval = self.com_augassign(nodelist[0]) + op = self.com_augassign_op(nodelist[1]) + return AugAssign(lval, op[1], exprNode, lineno=op[2]) + raise WalkerError, "can't get here" + + def print_stmt(self, nodelist): + # print ([ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ]) + items = [] + if len(nodelist) == 1: + start = 1 + dest = None + elif nodelist[1][0] == token.RIGHTSHIFT: + assert len(nodelist) == 3 \ + or nodelist[3][0] == token.COMMA + dest = self.com_node(nodelist[2]) + start = 4 + else: + dest = None + start = 1 + for i in range(start, len(nodelist), 2): + items.append(self.com_node(nodelist[i])) + if nodelist[-1][0] == token.COMMA: + return Print(items, dest, lineno=nodelist[0][2]) + return Printnl(items, dest, lineno=nodelist[0][2]) + + def del_stmt(self, nodelist): + return self.com_assign(nodelist[1], OP_DELETE) + + def pass_stmt(self, nodelist): + return Pass(lineno=nodelist[0][2]) + + def break_stmt(self, nodelist): + return Break(lineno=nodelist[0][2]) + + def continue_stmt(self, nodelist): + return Continue(lineno=nodelist[0][2]) + + def return_stmt(self, nodelist): + # return: [testlist] + if len(nodelist) < 2: + return Return(Const(None), lineno=nodelist[0][2]) + return Return(self.com_node(nodelist[1]), lineno=nodelist[0][2]) + + def yield_stmt(self, nodelist): + expr = self.com_node(nodelist[0]) + return Discard(expr, lineno=expr.lineno) + + def yield_expr(self, nodelist): + if len(nodelist) > 1: + value = self.com_node(nodelist[1]) + else: + value = Const(None) + return Yield(value, lineno=nodelist[0][2]) + + def raise_stmt(self, nodelist): + # raise: [test [',' test [',' test]]] + if len(nodelist) > 5: + expr3 = self.com_node(nodelist[5]) + else: + expr3 = None + if len(nodelist) > 3: + expr2 = self.com_node(nodelist[3]) + else: + expr2 = None + if len(nodelist) > 1: + expr1 = self.com_node(nodelist[1]) + else: + expr1 = None + return Raise(expr1, expr2, expr3, lineno=nodelist[0][2]) + + def import_stmt(self, nodelist): + # import_stmt: import_name | import_from + assert len(nodelist) == 1 + return self.com_node(nodelist[0]) + + def import_name(self, nodelist): + # import_name: 'import' dotted_as_names + return Import(self.com_dotted_as_names(nodelist[1]), + lineno=nodelist[0][2]) + + def import_from(self, nodelist): + # import_from: 'from' ('.'* dotted_name | '.') 'import' ('*' | + # '(' import_as_names ')' | import_as_names) + assert nodelist[0][1] == 'from' + idx = 1 + while nodelist[idx][1] == '.': + idx += 1 + level = idx - 1 + if nodelist[idx][0] == symbol.dotted_name: + fromname = self.com_dotted_name(nodelist[idx]) + idx += 1 + else: + fromname = "" + assert nodelist[idx][1] == 'import' + if nodelist[idx + 1][0] == token.STAR: + return From(fromname, [('*', None)], level, + lineno=nodelist[0][2]) + else: + node = nodelist[idx + 1 + (nodelist[idx + 1][0] == token.LPAR)] + return From(fromname, self.com_import_as_names(node), level, + lineno=nodelist[0][2]) + + def global_stmt(self, nodelist): + # global: NAME (',' NAME)* + names = [] + for i in range(1, len(nodelist), 2): + names.append(nodelist[i][1]) + return Global(names, lineno=nodelist[0][2]) + + def exec_stmt(self, nodelist): + # exec_stmt: 'exec' expr ['in' expr [',' expr]] + expr1 = self.com_node(nodelist[1]) + if len(nodelist) >= 4: + expr2 = self.com_node(nodelist[3]) + if len(nodelist) >= 6: + expr3 = self.com_node(nodelist[5]) + else: + expr3 = None + else: + expr2 = expr3 = None + + return Exec(expr1, expr2, expr3, lineno=nodelist[0][2]) + + def assert_stmt(self, nodelist): + # 'assert': test, [',' test] + expr1 = self.com_node(nodelist[1]) + if (len(nodelist) == 4): + expr2 = self.com_node(nodelist[3]) + else: + expr2 = None + return Assert(expr1, expr2, lineno=nodelist[0][2]) + + def if_stmt(self, nodelist): + # if: test ':' suite ('elif' test ':' suite)* ['else' ':' suite] + tests = [] + for i in range(0, len(nodelist) - 3, 4): + testNode = self.com_node(nodelist[i + 1]) + suiteNode = self.com_node(nodelist[i + 3]) + tests.append((testNode, suiteNode)) + + if len(nodelist) % 4 == 3: + elseNode = self.com_node(nodelist[-1]) +## elseNode.lineno = nodelist[-1][1][2] + else: + elseNode = None + return If(tests, elseNode, lineno=nodelist[0][2]) + + def while_stmt(self, nodelist): + # 'while' test ':' suite ['else' ':' suite] + + testNode = self.com_node(nodelist[1]) + bodyNode = self.com_node(nodelist[3]) + + if len(nodelist) > 4: + elseNode = self.com_node(nodelist[6]) + else: + elseNode = None + + return While(testNode, bodyNode, elseNode, lineno=nodelist[0][2]) + + def for_stmt(self, nodelist): + # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] + + assignNode = self.com_assign(nodelist[1], OP_ASSIGN) + listNode = self.com_node(nodelist[3]) + bodyNode = self.com_node(nodelist[5]) + + if len(nodelist) > 8: + elseNode = self.com_node(nodelist[8]) + else: + elseNode = None + + return For(assignNode, listNode, bodyNode, elseNode, + lineno=nodelist[0][2]) + + def try_stmt(self, nodelist): + return self.com_try_except_finally(nodelist) + + def with_stmt(self, nodelist): + return self.com_with(nodelist) + + def with_var(self, nodelist): + return self.com_with_var(nodelist) + + def suite(self, nodelist): + # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT + if len(nodelist) == 1: + return self.com_stmt(nodelist[0]) + + stmts = [] + for node in nodelist: + if node[0] == symbol.stmt: + self.com_append_stmt(stmts, node) + return Stmt(stmts) + + # -------------------------------------------------------------- + # + # EXPRESSION NODES (invoked by com_node()) + # + + def testlist(self, nodelist): + # testlist: expr (',' expr)* [','] + # testlist_safe: test [(',' test)+ [',']] + # exprlist: expr (',' expr)* [','] + return self.com_binary(Tuple, nodelist) + + testlist_safe = testlist # XXX + testlist1 = testlist + exprlist = testlist + + def testlist_comp(self, nodelist): + # test ( comp_for | (',' test)* [','] ) + assert nodelist[0][0] == symbol.test + if len(nodelist) == 2 and nodelist[1][0] == symbol.comp_for: + test = self.com_node(nodelist[0]) + return self.com_generator_expression(test, nodelist[1]) + return self.testlist(nodelist) + + def test(self, nodelist): + # or_test ['if' or_test 'else' test] | lambdef + if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef: + return self.lambdef(nodelist[0]) + then = self.com_node(nodelist[0]) + if len(nodelist) > 1: + assert len(nodelist) == 5 + assert nodelist[1][1] == 'if' + assert nodelist[3][1] == 'else' + test = self.com_node(nodelist[2]) + else_ = self.com_node(nodelist[4]) + return IfExp(test, then, else_, lineno=nodelist[1][2]) + return then + + def or_test(self, nodelist): + # and_test ('or' and_test)* | lambdef + if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef: + return self.lambdef(nodelist[0]) + return self.com_binary(Or, nodelist) + old_test = or_test + + def and_test(self, nodelist): + # not_test ('and' not_test)* + return self.com_binary(And, nodelist) + + def not_test(self, nodelist): + # 'not' not_test | comparison + result = self.com_node(nodelist[-1]) + if len(nodelist) == 2: + return Not(result, lineno=nodelist[0][2]) + return result + + def comparison(self, nodelist): + # comparison: expr (comp_op expr)* + node = self.com_node(nodelist[0]) + if len(nodelist) == 1: + return node + + results = [] + for i in range(2, len(nodelist), 2): + nl = nodelist[i-1] + + # comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '==' + # | 'in' | 'not' 'in' | 'is' | 'is' 'not' + n = nl[1] + if n[0] == token.NAME: + type = n[1] + if len(nl) == 3: + if type == 'not': + type = 'not in' + else: + type = 'is not' + else: + type = _cmp_types[n[0]] + + lineno = nl[1][2] + results.append((type, self.com_node(nodelist[i]))) + + # we need a special "compare" node so that we can distinguish + # 3 < x < 5 from (3 < x) < 5 + # the two have very different semantics and results (note that the + # latter form is always true) + + return Compare(node, results, lineno=lineno) + + def expr(self, nodelist): + # xor_expr ('|' xor_expr)* + return self.com_binary(Bitor, nodelist) + + def xor_expr(self, nodelist): + # xor_expr ('^' xor_expr)* + return self.com_binary(Bitxor, nodelist) + + def and_expr(self, nodelist): + # xor_expr ('&' xor_expr)* + return self.com_binary(Bitand, nodelist) + + def shift_expr(self, nodelist): + # shift_expr ('<<'|'>>' shift_expr)* + node = self.com_node(nodelist[0]) + for i in range(2, len(nodelist), 2): + right = self.com_node(nodelist[i]) + if nodelist[i-1][0] == token.LEFTSHIFT: + node = LeftShift([node, right], lineno=nodelist[1][2]) + elif nodelist[i-1][0] == token.RIGHTSHIFT: + node = RightShift([node, right], lineno=nodelist[1][2]) + else: + raise ValueError, "unexpected token: %s" % nodelist[i-1][0] + return node + + def arith_expr(self, nodelist): + node = self.com_node(nodelist[0]) + for i in range(2, len(nodelist), 2): + right = self.com_node(nodelist[i]) + if nodelist[i-1][0] == token.PLUS: + node = Add([node, right], lineno=nodelist[1][2]) + elif nodelist[i-1][0] == token.MINUS: + node = Sub([node, right], lineno=nodelist[1][2]) + else: + raise ValueError, "unexpected token: %s" % nodelist[i-1][0] + return node + + def term(self, nodelist): + node = self.com_node(nodelist[0]) + for i in range(2, len(nodelist), 2): + right = self.com_node(nodelist[i]) + t = nodelist[i-1][0] + if t == token.STAR: + node = Mul([node, right]) + elif t == token.SLASH: + node = Div([node, right]) + elif t == token.PERCENT: + node = Mod([node, right]) + elif t == token.DOUBLESLASH: + node = FloorDiv([node, right]) + else: + raise ValueError, "unexpected token: %s" % t + node.lineno = nodelist[1][2] + return node + + def factor(self, nodelist): + elt = nodelist[0] + t = elt[0] + node = self.lookup_node(nodelist[-1])(nodelist[-1][1:]) + # need to handle (unary op)constant here... + if t == token.PLUS: + return UnaryAdd(node, lineno=elt[2]) + elif t == token.MINUS: + return UnarySub(node, lineno=elt[2]) + elif t == token.TILDE: + node = Invert(node, lineno=elt[2]) + return node + + def power(self, nodelist): + # power: atom trailer* ('**' factor)* + node = self.com_node(nodelist[0]) + for i in range(1, len(nodelist)): + elt = nodelist[i] + if elt[0] == token.DOUBLESTAR: + return Power([node, self.com_node(nodelist[i+1])], + lineno=elt[2]) + + node = self.com_apply_trailer(node, elt) + + return node + + def atom(self, nodelist): + return self._atom_dispatch[nodelist[0][0]](nodelist) + + def atom_lpar(self, nodelist): + if nodelist[1][0] == token.RPAR: + return Tuple((), lineno=nodelist[0][2]) + return self.com_node(nodelist[1]) + + def atom_lsqb(self, nodelist): + if nodelist[1][0] == token.RSQB: + return List((), lineno=nodelist[0][2]) + return self.com_list_constructor(nodelist[1]) + + def atom_lbrace(self, nodelist): + if nodelist[1][0] == token.RBRACE: + return Dict((), lineno=nodelist[0][2]) + return self.com_dictorsetmaker(nodelist[1]) + + def atom_backquote(self, nodelist): + return Backquote(self.com_node(nodelist[1])) + + def atom_number(self, nodelist): + ### need to verify this matches compile.c + k = eval(nodelist[0][1]) + return Const(k, lineno=nodelist[0][2]) + + def decode_literal(self, lit): + if self.encoding: + # this is particularly fragile & a bit of a + # hack... changes in compile.c:parsestr and + # tokenizer.c must be reflected here. + if self.encoding not in ['utf-8', 'iso-8859-1']: + lit = unicode(lit, 'utf-8').encode(self.encoding) + return eval("# coding: %s\n%s" % (self.encoding, lit)) + else: + return eval(lit) + + def atom_string(self, nodelist): + k = '' + for node in nodelist: + k += self.decode_literal(node[1]) + return Const(k, lineno=nodelist[0][2]) + + def atom_name(self, nodelist): + return Name(nodelist[0][1], lineno=nodelist[0][2]) + + # -------------------------------------------------------------- + # + # INTERNAL PARSING UTILITIES + # + + # The use of com_node() introduces a lot of extra stack frames, + # enough to cause a stack overflow compiling test.test_parser with + # the standard interpreter recursionlimit. The com_node() is a + # convenience function that hides the dispatch details, but comes + # at a very high cost. It is more efficient to dispatch directly + # in the callers. In these cases, use lookup_node() and call the + # dispatched node directly. + + def lookup_node(self, node): + return self._dispatch[node[0]] + + def com_node(self, node): + # Note: compile.c has handling in com_node for del_stmt, pass_stmt, + # break_stmt, stmt, small_stmt, flow_stmt, simple_stmt, + # and compound_stmt. + # We'll just dispatch them. + return self._dispatch[node[0]](node[1:]) + + def com_NEWLINE(self, *args): + # A ';' at the end of a line can make a NEWLINE token appear + # here, Render it harmless. (genc discards ('discard', + # ('const', xxxx)) Nodes) + return Discard(Const(None)) + + def com_arglist(self, nodelist): + # varargslist: + # (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME) + # | fpdef ['=' test] (',' fpdef ['=' test])* [','] + # fpdef: NAME | '(' fplist ')' + # fplist: fpdef (',' fpdef)* [','] + names = [] + defaults = [] + flags = 0 + + i = 0 + while i < len(nodelist): + node = nodelist[i] + if node[0] == token.STAR or node[0] == token.DOUBLESTAR: + if node[0] == token.STAR: + node = nodelist[i+1] + if node[0] == token.NAME: + names.append(node[1]) + flags = flags | CO_VARARGS + i = i + 3 + + if i < len(nodelist): + # should be DOUBLESTAR + t = nodelist[i][0] + if t == token.DOUBLESTAR: + node = nodelist[i+1] + else: + raise ValueError, "unexpected token: %s" % t + names.append(node[1]) + flags = flags | CO_VARKEYWORDS + + break + + # fpdef: NAME | '(' fplist ')' + names.append(self.com_fpdef(node)) + + i = i + 1 + if i < len(nodelist) and nodelist[i][0] == token.EQUAL: + defaults.append(self.com_node(nodelist[i + 1])) + i = i + 2 + elif len(defaults): + # we have already seen an argument with default, but here + # came one without + raise SyntaxError, "non-default argument follows default argument" + + # skip the comma + i = i + 1 + + return names, defaults, flags + + def com_fpdef(self, node): + # fpdef: NAME | '(' fplist ')' + if node[1][0] == token.LPAR: + return self.com_fplist(node[2]) + return node[1][1] + + def com_fplist(self, node): + # fplist: fpdef (',' fpdef)* [','] + if len(node) == 2: + return self.com_fpdef(node[1]) + list = [] + for i in range(1, len(node), 2): + list.append(self.com_fpdef(node[i])) + return tuple(list) + + def com_dotted_name(self, node): + # String together the dotted names and return the string + name = "" + for n in node: + if type(n) == type(()) and n[0] == 1: + name = name + n[1] + '.' + return name[:-1] + + def com_dotted_as_name(self, node): + assert node[0] == symbol.dotted_as_name + node = node[1:] + dot = self.com_dotted_name(node[0][1:]) + if len(node) == 1: + return dot, None + assert node[1][1] == 'as' + assert node[2][0] == token.NAME + return dot, node[2][1] + + def com_dotted_as_names(self, node): + assert node[0] == symbol.dotted_as_names + node = node[1:] + names = [self.com_dotted_as_name(node[0])] + for i in range(2, len(node), 2): + names.append(self.com_dotted_as_name(node[i])) + return names + + def com_import_as_name(self, node): + assert node[0] == symbol.import_as_name + node = node[1:] + assert node[0][0] == token.NAME + if len(node) == 1: + return node[0][1], None + assert node[1][1] == 'as', node + assert node[2][0] == token.NAME + return node[0][1], node[2][1] + + def com_import_as_names(self, node): + assert node[0] == symbol.import_as_names + node = node[1:] + names = [self.com_import_as_name(node[0])] + for i in range(2, len(node), 2): + names.append(self.com_import_as_name(node[i])) + return names + + def com_bases(self, node): + bases = [] + for i in range(1, len(node), 2): + bases.append(self.com_node(node[i])) + return bases + + def com_try_except_finally(self, nodelist): + # ('try' ':' suite + # ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite] + # | 'finally' ':' suite)) + + if nodelist[3][0] == token.NAME: + # first clause is a finally clause: only try-finally + return TryFinally(self.com_node(nodelist[2]), + self.com_node(nodelist[5]), + lineno=nodelist[0][2]) + + #tryexcept: [TryNode, [except_clauses], elseNode)] + clauses = [] + elseNode = None + finallyNode = None + for i in range(3, len(nodelist), 3): + node = nodelist[i] + if node[0] == symbol.except_clause: + # except_clause: 'except' [expr [(',' | 'as') expr]] */ + if len(node) > 2: + expr1 = self.com_node(node[2]) + if len(node) > 4: + expr2 = self.com_assign(node[4], OP_ASSIGN) + else: + expr2 = None + else: + expr1 = expr2 = None + clauses.append((expr1, expr2, self.com_node(nodelist[i+2]))) + + if node[0] == token.NAME: + if node[1] == 'else': + elseNode = self.com_node(nodelist[i+2]) + elif node[1] == 'finally': + finallyNode = self.com_node(nodelist[i+2]) + try_except = TryExcept(self.com_node(nodelist[2]), clauses, elseNode, + lineno=nodelist[0][2]) + if finallyNode: + return TryFinally(try_except, finallyNode, lineno=nodelist[0][2]) + else: + return try_except + + def com_with(self, nodelist): + # with_stmt: 'with' with_item (',' with_item)* ':' suite + body = self.com_node(nodelist[-1]) + for i in range(len(nodelist) - 3, 0, -2): + ret = self.com_with_item(nodelist[i], body, nodelist[0][2]) + if i == 1: + return ret + body = ret + + def com_with_item(self, nodelist, body, lineno): + # with_item: test ['as' expr] + if len(nodelist) == 4: + var = self.com_assign(nodelist[3], OP_ASSIGN) + else: + var = None + expr = self.com_node(nodelist[1]) + return With(expr, var, body, lineno=lineno) + + def com_augassign_op(self, node): + assert node[0] == symbol.augassign + return node[1] + + def com_augassign(self, node): + """Return node suitable for lvalue of augmented assignment + + Names, slices, and attributes are the only allowable nodes. + """ + l = self.com_node(node) + if l.__class__ in (Name, Slice, Subscript, Getattr): + return l + raise SyntaxError, "can't assign to %s" % l.__class__.__name__ + + def com_assign(self, node, assigning): + # return a node suitable for use as an "lvalue" + # loop to avoid trivial recursion + while 1: + t = node[0] + if t in (symbol.exprlist, symbol.testlist, symbol.testlist_safe, symbol.testlist_comp): + if len(node) > 2: + return self.com_assign_tuple(node, assigning) + node = node[1] + elif t in _assign_types: + if len(node) > 2: + raise SyntaxError, "can't assign to operator" + node = node[1] + elif t == symbol.power: + if node[1][0] != symbol.atom: + raise SyntaxError, "can't assign to operator" + if len(node) > 2: + primary = self.com_node(node[1]) + for i in range(2, len(node)-1): + ch = node[i] + if ch[0] == token.DOUBLESTAR: + raise SyntaxError, "can't assign to operator" + primary = self.com_apply_trailer(primary, ch) + return self.com_assign_trailer(primary, node[-1], + assigning) + node = node[1] + elif t == symbol.atom: + t = node[1][0] + if t == token.LPAR: + node = node[2] + if node[0] == token.RPAR: + raise SyntaxError, "can't assign to ()" + elif t == token.LSQB: + node = node[2] + if node[0] == token.RSQB: + raise SyntaxError, "can't assign to []" + return self.com_assign_list(node, assigning) + elif t == token.NAME: + return self.com_assign_name(node[1], assigning) + else: + raise SyntaxError, "can't assign to literal" + else: + raise SyntaxError, "bad assignment (%s)" % t + + def com_assign_tuple(self, node, assigning): + assigns = [] + for i in range(1, len(node), 2): + assigns.append(self.com_assign(node[i], assigning)) + return AssTuple(assigns, lineno=extractLineNo(node)) + + def com_assign_list(self, node, assigning): + assigns = [] + for i in range(1, len(node), 2): + if i + 1 < len(node): + if node[i + 1][0] == symbol.list_for: + raise SyntaxError, "can't assign to list comprehension" + assert node[i + 1][0] == token.COMMA, node[i + 1] + assigns.append(self.com_assign(node[i], assigning)) + return AssList(assigns, lineno=extractLineNo(node)) + + def com_assign_name(self, node, assigning): + return AssName(node[1], assigning, lineno=node[2]) + + def com_assign_trailer(self, primary, node, assigning): + t = node[1][0] + if t == token.DOT: + return self.com_assign_attr(primary, node[2], assigning) + if t == token.LSQB: + return self.com_subscriptlist(primary, node[2], assigning) + if t == token.LPAR: + raise SyntaxError, "can't assign to function call" + raise SyntaxError, "unknown trailer type: %s" % t + + def com_assign_attr(self, primary, node, assigning): + return AssAttr(primary, node[1], assigning, lineno=node[-1]) + + def com_binary(self, constructor, nodelist): + "Compile 'NODE (OP NODE)*' into (type, [ node1, ..., nodeN ])." + l = len(nodelist) + if l == 1: + n = nodelist[0] + return self.lookup_node(n)(n[1:]) + items = [] + for i in range(0, l, 2): + n = nodelist[i] + items.append(self.lookup_node(n)(n[1:])) + return constructor(items, lineno=extractLineNo(nodelist)) + + def com_stmt(self, node): + result = self.lookup_node(node)(node[1:]) + assert result is not None + if isinstance(result, Stmt): + return result + return Stmt([result]) + + def com_append_stmt(self, stmts, node): + result = self.lookup_node(node)(node[1:]) + assert result is not None + if isinstance(result, Stmt): + stmts.extend(result.nodes) + else: + stmts.append(result) + + def com_list_constructor(self, nodelist): + # listmaker: test ( list_for | (',' test)* [','] ) + values = [] + for i in range(1, len(nodelist)): + if nodelist[i][0] == symbol.list_for: + assert len(nodelist[i:]) == 1 + return self.com_list_comprehension(values[0], + nodelist[i]) + elif nodelist[i][0] == token.COMMA: + continue + values.append(self.com_node(nodelist[i])) + return List(values, lineno=values[0].lineno) + + def com_list_comprehension(self, expr, node): + return self.com_comprehension(expr, None, node, 'list') + + def com_comprehension(self, expr1, expr2, node, type): + # list_iter: list_for | list_if + # list_for: 'for' exprlist 'in' testlist [list_iter] + # list_if: 'if' test [list_iter] + + # XXX should raise SyntaxError for assignment + # XXX(avassalotti) Set and dict comprehensions should have generator + # semantics. In other words, they shouldn't leak + # variables outside of the comprehension's scope. + + lineno = node[1][2] + fors = [] + while node: + t = node[1][1] + if t == 'for': + assignNode = self.com_assign(node[2], OP_ASSIGN) + compNode = self.com_node(node[4]) + newfor = ListCompFor(assignNode, compNode, []) + newfor.lineno = node[1][2] + fors.append(newfor) + if len(node) == 5: + node = None + elif type == 'list': + node = self.com_list_iter(node[5]) + else: + node = self.com_comp_iter(node[5]) + elif t == 'if': + test = self.com_node(node[2]) + newif = ListCompIf(test, lineno=node[1][2]) + newfor.ifs.append(newif) + if len(node) == 3: + node = None + elif type == 'list': + node = self.com_list_iter(node[3]) + else: + node = self.com_comp_iter(node[3]) + else: + raise SyntaxError, \ + ("unexpected comprehension element: %s %d" + % (node, lineno)) + if type == 'list': + return ListComp(expr1, fors, lineno=lineno) + elif type == 'set': + return SetComp(expr1, fors, lineno=lineno) + elif type == 'dict': + return DictComp(expr1, expr2, fors, lineno=lineno) + else: + raise ValueError("unexpected comprehension type: " + repr(type)) + + def com_list_iter(self, node): + assert node[0] == symbol.list_iter + return node[1] + + def com_comp_iter(self, node): + assert node[0] == symbol.comp_iter + return node[1] + + def com_generator_expression(self, expr, node): + # comp_iter: comp_for | comp_if + # comp_for: 'for' exprlist 'in' test [comp_iter] + # comp_if: 'if' test [comp_iter] + + lineno = node[1][2] + fors = [] + while node: + t = node[1][1] + if t == 'for': + assignNode = self.com_assign(node[2], OP_ASSIGN) + genNode = self.com_node(node[4]) + newfor = GenExprFor(assignNode, genNode, [], + lineno=node[1][2]) + fors.append(newfor) + if (len(node)) == 5: + node = None + else: + node = self.com_comp_iter(node[5]) + elif t == 'if': + test = self.com_node(node[2]) + newif = GenExprIf(test, lineno=node[1][2]) + newfor.ifs.append(newif) + if len(node) == 3: + node = None + else: + node = self.com_comp_iter(node[3]) + else: + raise SyntaxError, \ + ("unexpected generator expression element: %s %d" + % (node, lineno)) + fors[0].is_outmost = True + return GenExpr(GenExprInner(expr, fors), lineno=lineno) + + def com_dictorsetmaker(self, nodelist): + # dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) | + # (test (comp_for | (',' test)* [','])) ) + assert nodelist[0] == symbol.dictorsetmaker + nodelist = nodelist[1:] + if len(nodelist) == 1 or nodelist[1][0] == token.COMMA: + # set literal + items = [] + for i in range(0, len(nodelist), 2): + items.append(self.com_node(nodelist[i])) + return Set(items, lineno=items[0].lineno) + elif nodelist[1][0] == symbol.comp_for: + # set comprehension + expr = self.com_node(nodelist[0]) + return self.com_comprehension(expr, None, nodelist[1], 'set') + elif len(nodelist) > 3 and nodelist[3][0] == symbol.comp_for: + # dict comprehension + assert nodelist[1][0] == token.COLON + key = self.com_node(nodelist[0]) + value = self.com_node(nodelist[2]) + return self.com_comprehension(key, value, nodelist[3], 'dict') + else: + # dict literal + items = [] + for i in range(0, len(nodelist), 4): + items.append((self.com_node(nodelist[i]), + self.com_node(nodelist[i+2]))) + return Dict(items, lineno=items[0][0].lineno) + + def com_apply_trailer(self, primaryNode, nodelist): + t = nodelist[1][0] + if t == token.LPAR: + return self.com_call_function(primaryNode, nodelist[2]) + if t == token.DOT: + return self.com_select_member(primaryNode, nodelist[2]) + if t == token.LSQB: + return self.com_subscriptlist(primaryNode, nodelist[2], OP_APPLY) + + raise SyntaxError, 'unknown node type: %s' % t + + def com_select_member(self, primaryNode, nodelist): + if nodelist[0] != token.NAME: + raise SyntaxError, "member must be a name" + return Getattr(primaryNode, nodelist[1], lineno=nodelist[2]) + + def com_call_function(self, primaryNode, nodelist): + if nodelist[0] == token.RPAR: + return CallFunc(primaryNode, [], lineno=extractLineNo(nodelist)) + args = [] + kw = 0 + star_node = dstar_node = None + len_nodelist = len(nodelist) + i = 1 + while i < len_nodelist: + node = nodelist[i] + + if node[0]==token.STAR: + if star_node is not None: + raise SyntaxError, 'already have the varargs indentifier' + star_node = self.com_node(nodelist[i+1]) + i = i + 3 + continue + elif node[0]==token.DOUBLESTAR: + if dstar_node is not None: + raise SyntaxError, 'already have the kwargs indentifier' + dstar_node = self.com_node(nodelist[i+1]) + i = i + 3 + continue + + # positional or named parameters + kw, result = self.com_argument(node, kw, star_node) + + if len_nodelist != 2 and isinstance(result, GenExpr) \ + and len(node) == 3 and node[2][0] == symbol.comp_for: + # allow f(x for x in y), but reject f(x for x in y, 1) + # should use f((x for x in y), 1) instead of f(x for x in y, 1) + raise SyntaxError, 'generator expression needs parenthesis' + + args.append(result) + i = i + 2 + + return CallFunc(primaryNode, args, star_node, dstar_node, + lineno=extractLineNo(nodelist)) + + def com_argument(self, nodelist, kw, star_node): + if len(nodelist) == 3 and nodelist[2][0] == symbol.comp_for: + test = self.com_node(nodelist[1]) + return 0, self.com_generator_expression(test, nodelist[2]) + if len(nodelist) == 2: + if kw: + raise SyntaxError, "non-keyword arg after keyword arg" + if star_node: + raise SyntaxError, "only named arguments may follow *expression" + return 0, self.com_node(nodelist[1]) + result = self.com_node(nodelist[3]) + n = nodelist[1] + while len(n) == 2 and n[0] != token.NAME: + n = n[1] + if n[0] != token.NAME: + raise SyntaxError, "keyword can't be an expression (%s)"%n[0] + node = Keyword(n[1], result, lineno=n[2]) + return 1, node + + def com_subscriptlist(self, primary, nodelist, assigning): + # slicing: simple_slicing | extended_slicing + # simple_slicing: primary "[" short_slice "]" + # extended_slicing: primary "[" slice_list "]" + # slice_list: slice_item ("," slice_item)* [","] + + # backwards compat slice for '[i:j]' + if len(nodelist) == 2: + sub = nodelist[1] + if (sub[1][0] == token.COLON or \ + (len(sub) > 2 and sub[2][0] == token.COLON)) and \ + sub[-1][0] != symbol.sliceop: + return self.com_slice(primary, sub, assigning) + + subscripts = [] + for i in range(1, len(nodelist), 2): + subscripts.append(self.com_subscript(nodelist[i])) + return Subscript(primary, assigning, subscripts, + lineno=extractLineNo(nodelist)) + + def com_subscript(self, node): + # slice_item: expression | proper_slice | ellipsis + ch = node[1] + t = ch[0] + if t == token.DOT and node[2][0] == token.DOT: + return Ellipsis() + if t == token.COLON or len(node) > 2: + return self.com_sliceobj(node) + return self.com_node(ch) + + def com_sliceobj(self, node): + # proper_slice: short_slice | long_slice + # short_slice: [lower_bound] ":" [upper_bound] + # long_slice: short_slice ":" [stride] + # lower_bound: expression + # upper_bound: expression + # stride: expression + # + # Note: a stride may be further slicing... + + items = [] + + if node[1][0] == token.COLON: + items.append(Const(None)) + i = 2 + else: + items.append(self.com_node(node[1])) + # i == 2 is a COLON + i = 3 + + if i < len(node) and node[i][0] == symbol.test: + items.append(self.com_node(node[i])) + i = i + 1 + else: + items.append(Const(None)) + + # a short_slice has been built. look for long_slice now by looking + # for strides... + for j in range(i, len(node)): + ch = node[j] + if len(ch) == 2: + items.append(Const(None)) + else: + items.append(self.com_node(ch[2])) + return Sliceobj(items, lineno=extractLineNo(node)) + + def com_slice(self, primary, node, assigning): + # short_slice: [lower_bound] ":" [upper_bound] + lower = upper = None + if len(node) == 3: + if node[1][0] == token.COLON: + upper = self.com_node(node[2]) + else: + lower = self.com_node(node[1]) + elif len(node) == 4: + lower = self.com_node(node[1]) + upper = self.com_node(node[3]) + return Slice(primary, assigning, lower, upper, + lineno=extractLineNo(node)) + + def get_docstring(self, node, n=None): + if n is None: + n = node[0] + node = node[1:] + if n == symbol.suite: + if len(node) == 1: + return self.get_docstring(node[0]) + for sub in node: + if sub[0] == symbol.stmt: + return self.get_docstring(sub) + return None + if n == symbol.file_input: + for sub in node: + if sub[0] == symbol.stmt: + return self.get_docstring(sub) + return None + if n == symbol.atom: + if node[0][0] == token.STRING: + s = '' + for t in node: + s = s + eval(t[1]) + return s + return None + if n == symbol.stmt or n == symbol.simple_stmt \ + or n == symbol.small_stmt: + return self.get_docstring(node[0]) + if n in _doc_nodes and len(node) == 1: + return self.get_docstring(node[0]) + return None + + +_doc_nodes = [ + symbol.expr_stmt, + symbol.testlist, + symbol.testlist_safe, + symbol.test, + symbol.or_test, + symbol.and_test, + symbol.not_test, + symbol.comparison, + symbol.expr, + symbol.xor_expr, + symbol.and_expr, + symbol.shift_expr, + symbol.arith_expr, + symbol.term, + symbol.factor, + symbol.power, + ] + +# comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '==' +# | 'in' | 'not' 'in' | 'is' | 'is' 'not' +_cmp_types = { + token.LESS : '<', + token.GREATER : '>', + token.EQEQUAL : '==', + token.EQUAL : '==', + token.LESSEQUAL : '<=', + token.GREATEREQUAL : '>=', + token.NOTEQUAL : '!=', + } + +_legal_node_types = [ + symbol.funcdef, + symbol.classdef, + symbol.stmt, + symbol.small_stmt, + symbol.flow_stmt, + symbol.simple_stmt, + symbol.compound_stmt, + symbol.expr_stmt, + symbol.print_stmt, + symbol.del_stmt, + symbol.pass_stmt, + symbol.break_stmt, + symbol.continue_stmt, + symbol.return_stmt, + symbol.raise_stmt, + symbol.import_stmt, + symbol.global_stmt, + symbol.exec_stmt, + symbol.assert_stmt, + symbol.if_stmt, + symbol.while_stmt, + symbol.for_stmt, + symbol.try_stmt, + symbol.with_stmt, + symbol.suite, + symbol.testlist, + symbol.testlist_safe, + symbol.test, + symbol.and_test, + symbol.not_test, + symbol.comparison, + symbol.exprlist, + symbol.expr, + symbol.xor_expr, + symbol.and_expr, + symbol.shift_expr, + symbol.arith_expr, + symbol.term, + symbol.factor, + symbol.power, + symbol.atom, + ] + +if hasattr(symbol, 'yield_stmt'): + _legal_node_types.append(symbol.yield_stmt) +if hasattr(symbol, 'yield_expr'): + _legal_node_types.append(symbol.yield_expr) + +_assign_types = [ + symbol.test, + symbol.or_test, + symbol.and_test, + symbol.not_test, + symbol.comparison, + symbol.expr, + symbol.xor_expr, + symbol.and_expr, + symbol.shift_expr, + symbol.arith_expr, + symbol.term, + symbol.factor, + ] + +_names = {} +for k, v in symbol.sym_name.items(): + _names[k] = v +for k, v in token.tok_name.items(): + _names[k] = v + +def debug_tree(tree): + l = [] + for elt in tree: + if isinstance(elt, int): + l.append(_names.get(elt, elt)) + elif isinstance(elt, str): + l.append(elt) + else: + l.append(debug_tree(elt)) + return l diff --git a/PythonHome/Lib/compiler/transformer.pyc b/PythonHome/Lib/compiler/transformer.pyc deleted file mode 100644 index 83c70307ff5360273b0b8719d417758590754edf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45754 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 O?ewF32O>%M75)!Zwv#vj diff --git a/PythonHome/Lib/compiler/visitor.py b/PythonHome/Lib/compiler/visitor.py new file mode 100644 index 0000000000..f10f56011a --- /dev/null +++ b/PythonHome/Lib/compiler/visitor.py @@ -0,0 +1,113 @@ +from compiler import ast + +# XXX should probably rename ASTVisitor to ASTWalker +# XXX can it be made even more generic? + +class ASTVisitor: + """Performs a depth-first walk of the AST + + The ASTVisitor will walk the AST, performing either a preorder or + postorder traversal depending on which method is called. + + methods: + preorder(tree, visitor) + postorder(tree, visitor) + tree: an instance of ast.Node + visitor: an instance with visitXXX methods + + The ASTVisitor is responsible for walking over the tree in the + correct order. For each node, it checks the visitor argument for + a method named 'visitNodeType' where NodeType is the name of the + node's class, e.g. Class. If the method exists, it is called + with the node as its sole argument. + + The visitor method for a particular node type can control how + child nodes are visited during a preorder walk. (It can't control + the order during a postorder walk, because it is called _after_ + the walk has occurred.) The ASTVisitor modifies the visitor + argument by adding a visit method to the visitor; this method can + be used to visit a child node of arbitrary type. + """ + + VERBOSE = 0 + + def __init__(self): + self.node = None + self._cache = {} + + def default(self, node, *args): + for child in node.getChildNodes(): + self.dispatch(child, *args) + + def dispatch(self, node, *args): + self.node = node + klass = node.__class__ + meth = self._cache.get(klass, None) + if meth is None: + className = klass.__name__ + meth = getattr(self.visitor, 'visit' + className, self.default) + self._cache[klass] = meth +## if self.VERBOSE > 0: +## className = klass.__name__ +## if self.VERBOSE == 1: +## if meth == 0: +## print "dispatch", className +## else: +## print "dispatch", className, (meth and meth.__name__ or '') + return meth(node, *args) + + def preorder(self, tree, visitor, *args): + """Do preorder walk of tree using visitor""" + self.visitor = visitor + visitor.visit = self.dispatch + self.dispatch(tree, *args) # XXX *args make sense? + +class ExampleASTVisitor(ASTVisitor): + """Prints examples of the nodes that aren't visited + + This visitor-driver is only useful for development, when it's + helpful to develop a visitor incrementally, and get feedback on what + you still have to do. + """ + examples = {} + + def dispatch(self, node, *args): + self.node = node + meth = self._cache.get(node.__class__, None) + className = node.__class__.__name__ + if meth is None: + meth = getattr(self.visitor, 'visit' + className, 0) + self._cache[node.__class__] = meth + if self.VERBOSE > 1: + print "dispatch", className, (meth and meth.__name__ or '') + if meth: + meth(node, *args) + elif self.VERBOSE > 0: + klass = node.__class__ + if klass not in self.examples: + self.examples[klass] = klass + print + print self.visitor + print klass + for attr in dir(node): + if attr[0] != '_': + print "\t", "%-12.12s" % attr, getattr(node, attr) + print + return self.default(node, *args) + +# XXX this is an API change + +_walker = ASTVisitor +def walk(tree, visitor, walker=None, verbose=None): + if walker is None: + walker = _walker() + if verbose is not None: + walker.VERBOSE = verbose + walker.preorder(tree, visitor) + return walker.visitor + +def dumpNode(node): + print node.__class__ + for attr in dir(node): + if attr[0] != '_': + print "\t", "%-10.10s" % attr, getattr(node, attr) diff --git a/PythonHome/Lib/compiler/visitor.pyc b/PythonHome/Lib/compiler/visitor.pyc deleted file mode 100644 index 16f36584a6b17fcd1070fe91876f47cbe76b8cf1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4037 zcma)9U2_|^6$MC&5*52v;>sVLv_YG+qFb3`Coi4Y)2So7bUGcyv+~5Q>dbbv3z};! zcj*OaSu@s?^VUvZ`qqEY_x_vyjK1WpJ?COcT2020On?9gT-=X?bFbU~Ilum|M}OW+ zRrA-z_ixeMpU`FaXjLdR(Q02SowZcfQ(0Smt<-C!{xEE7x((>ke~k-e|?RS=e>#Zp38Uk9)6j-+*kENE$;aY&HWmkg%n(f z9`{4Dwt`|5jVndB{T1rP72GO%;nrxc-=&22I!ZmT^{A>R&Lk$YQ$M~w%4_G%QBoY5 zYGnM_8Yr>8Zt(XoOd5^MQC<{bW3y}9OoOz%d}?ft)f!@_wXNz5!>Sf3)5^gfF8Dfm zVQZHZyxNu-k5#2P8t3WQOspSQnaQ0=lcKQMAm|X5-KRlRBf9TvYq!md;HqnhfWSR`kADDI-A(i z^9qrY%sp5p6PuYW*+|nK9#8ESoNQ}r=5xB4LFC>h>>`9WZXp6i;@q~egQo+t!!fk_ zJbR!<{CGFeTeJl#xz3dE#N1qeV)#Wq!tGl z5B-6O(xg@C>#8v0>L~baoEMqw0h(c)NQ3Fwtfs%;KqAo%6Z)USl}WjUK8O-AR5svq zd2j()p4>JEHce&@L3_hm6DK2Y>v$nUp3oQ;S7|y!M6yP?$uw~a_}V~k+~I67 z>f>8U=dNNjc=Ct*;7M9drg>rOCk+w?(__DeU*kA0b05b)!`M-R(mkD0H%{1wXzo|& zUVfxrY4uEK`R-Sj)JdDFKGW(I1}*hhkoWWR>QS~-oMQZWbWg3{p?ml$oZOq`ZkqUX z+~*b13cH1w2$Az#5|^IYoK>92>?oNP{udZF)?5tM&{+#>W|+VfI$8#>p)sbVp1~N9 zJ*;f0la6`?zE|pSP1R$rKU+~JD+;cs<;XG+vZ5|?vZh|Qn**G-xchbq@sNRC;-9@f zJ+dpdNgVn;%!A<^#j)@~97j}D@)bN6i5o+(NF#CVX)1n6ysu^41T}gG>ym+%9*rni zZagHv2z&@;&vm(O7c$T4426N z;Y}aGE%>wrIq+ogj$`cZR?FnJNSGw^nIqve=7yIMy^8~)S9A`eC7{Gqrhu@6_MX*D zf#^KF-oimg{HRtBruONA=mI(^B;puUGb`p%iQ}wFn+Sb*FZ%3@y?YVQN@#+XeD6y| zWc2oj8j%Jl#L>X+m2Rus>UHq%T~FKZy-X(4!oIDd`7yS=S<&PuTL5z1R5U1Ch%xtX zbPqu3NF+801;>VLM8+YRCY~99%q~H&**rOeBb%^X&+42R7%Np-9Fr(VvqCa-W?$H% znlhbkGf|>M@LNvEacqkzw}DZcU8dn>g#o8wE zBIvl98RuC+jZp-Nyejao&>Ei(Au8}3!m~>v5J>Xng5?$z06LHTp%npXkLDgWLD{%POQ|GQ9ut4l#>^ueG}S)hFr%JcjDE zrLJaOb%;y9VF5iv?TqD1L(&`+=#mPD_n&{G@OdQqLFhY6<@UgkdqQQq@&th{)ZGNF z0N!)zIgK6rp5qJp`SqJ04{m=&s(tcMt8n z)_P5^V0}aXRCjb=vKomZy3FnhJHABm%JP00eUB19!m&GO!b9C|S9e<}Eny?s?(jE4 z8gM~02+%9^`D>+4S}H(_>pfN95MT)jb3J4{c?Jlx=DdSwGElq00!csgY)mS)b;KY< zWHE_JAl%LQRLYXDF{CD2A5`wl2}a^0$01PoPKmqe@(nG;6ZN6pV)FwGh;ck=1+shXy2nfVE|S-yYjg4$UT07Dp3aN5m;Wi9p&7Vz?w5=XG4fJ(3tAVk0u_ m=$Yt4b|0ZzDj=gXXmLBFvfnWHZXMmm%EeokKJ4lXYySfb)pxc4 diff --git a/PythonHome/Lib/contextlib.py b/PythonHome/Lib/contextlib.py new file mode 100644 index 0000000000..f05205b01c --- /dev/null +++ b/PythonHome/Lib/contextlib.py @@ -0,0 +1,154 @@ +"""Utilities for with-statement contexts. See PEP 343.""" + +import sys +from functools import wraps +from warnings import warn + +__all__ = ["contextmanager", "nested", "closing"] + +class GeneratorContextManager(object): + """Helper for @contextmanager decorator.""" + + def __init__(self, gen): + self.gen = gen + + def __enter__(self): + try: + return self.gen.next() + except StopIteration: + raise RuntimeError("generator didn't yield") + + def __exit__(self, type, value, traceback): + if type is None: + try: + self.gen.next() + except StopIteration: + return + else: + raise RuntimeError("generator didn't stop") + else: + if value is None: + # Need to force instantiation so we can reliably + # tell if we get the same exception back + value = type() + try: + self.gen.throw(type, value, traceback) + raise RuntimeError("generator didn't stop after throw()") + except StopIteration, exc: + # Suppress the exception *unless* it's the same exception that + # was passed to throw(). This prevents a StopIteration + # raised inside the "with" statement from being suppressed + return exc is not value + except: + # only re-raise if it's *not* the exception that was + # passed to throw(), because __exit__() must not raise + # an exception unless __exit__() itself failed. But throw() + # has to raise the exception to signal propagation, so this + # fixes the impedance mismatch between the throw() protocol + # and the __exit__() protocol. + # + if sys.exc_info()[1] is not value: + raise + + +def contextmanager(func): + """@contextmanager decorator. + + Typical usage: + + @contextmanager + def some_generator(): + + try: + yield + finally: + + + This makes this: + + with some_generator() as : + + + equivalent to this: + + + try: + = + + finally: + + + """ + @wraps(func) + def helper(*args, **kwds): + return GeneratorContextManager(func(*args, **kwds)) + return helper + + +@contextmanager +def nested(*managers): + """Combine multiple context managers into a single nested context manager. + + This function has been deprecated in favour of the multiple manager form + of the with statement. + + The one advantage of this function over the multiple manager form of the + with statement is that argument unpacking allows it to be + used with a variable number of context managers as follows: + + with nested(*managers): + do_something() + + """ + warn("With-statements now directly support multiple context managers", + DeprecationWarning, 3) + exits = [] + vars = [] + exc = (None, None, None) + try: + for mgr in managers: + exit = mgr.__exit__ + enter = mgr.__enter__ + vars.append(enter()) + exits.append(exit) + yield vars + except: + exc = sys.exc_info() + finally: + while exits: + exit = exits.pop() + try: + if exit(*exc): + exc = (None, None, None) + except: + exc = sys.exc_info() + if exc != (None, None, None): + # Don't rely on sys.exc_info() still containing + # the right information. Another exception may + # have been raised and caught by an exit method + raise exc[0], exc[1], exc[2] + + +class closing(object): + """Context to automatically close something at the end of a block. + + Code like this: + + with closing(.open()) as f: + + + is equivalent to this: + + f = .open() + try: + + finally: + f.close() + + """ + def __init__(self, thing): + self.thing = thing + def __enter__(self): + return self.thing + def __exit__(self, *exc_info): + self.thing.close() diff --git a/PythonHome/Lib/contextlib.pyc b/PythonHome/Lib/contextlib.pyc deleted file mode 100644 index 61b31a5fcfe9f683df6e62860ad74a2891b091ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4394 zcmbtX-EJgD6+S&Z9(%lA>`lVLDv2n82xCM{$PY*>#|m*)As1Myc3?KvqM>KH#%{Z( zd$y})?LqdM-6m)kv=JRyGHL36)Dmx%134md zWL|dh9)kt3^U}wrrhFpuvB*a|3z95yveOjXl;noK0P#g0o9tdX-F<_+w_7)Pr8m+2 z%%@rEQ|nB>D9vH&_g-~A_I6-%Z+b=U?U8qD#%x<_?%%s_-gxtkwe)j5Tde@c{T#Z( zG9J2WTIVz_bN>|#CdUVH9`D-HH?Wjj=WXKW`8F$Dn(z9rVf?<$Z5jKb+^jhMv^sK% zB3ZqQ=2p>J$O;6|*N7iQ4=EJ~b;8NPoJ8BLI*)uC-A`;bw55vp&g`vBVta+MUhCDc zbJ{j}lqeksaxBtOIarkP zH3@>i0|~qe`Vug zYs-BV{UseZ!0f(t)f*G{0hRH4WpUVAO=%J>BBrX^DsroeiwJA9$nFMT5rC7sj|aBX@sy|285GGVv3=tTAaQCkt@XIv9Wge$jn%uS8@YMi zSw9+X%&hrxJiCb-)#c5)>Uws2Kh5JTd&-gZUS{K*)GImmQfCJ70g{Ht@SG&fA76H5 z6FYJ))3}@2joG`ccZ*~^;b0$)Qe2QZ$QKuxT$J>ZlxG~w+fNmA!is3{d8*tOWbVNb zG&#_bX%+5ybd_l!B*PH?s77%Lkk{f(j3+s8RJ-A8N+8hyJSlS-Su>`bCKYm<{ zN>lXV5$D)W*s;19&_5^dD_@+}a#J?eAZ3_1c^u~+QK;H{o_FzBv&|LsC&bBSmc9WE zzZZKm4Nzv350O70xA6nPZ7 z;x~lVgriC}us^y6z@rt#rkfSLgUa;HW|3Hvr3dz6K2bxOe2ui$t7>Cot$+$<((Njf zSN~$pB7;fNf(LwQ-s&?OT}fUuD?GzoPG>5`S*m_&y6Uef7E?37=C@2$F49eC%UT&m zuV8d7TUo$?KT*r1aqbI-+TY|ltrz(KpD#06QW= EPOCH_YEAR) and (1 <= month <= 12) and (1 <= mday <= 31) and + (0 <= hour <= 24) and (0 <= min <= 59) and (0 <= sec <= 61)): + return timegm(tt) + else: + return None + +DAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] +MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] +MONTHS_LOWER = [] +for month in MONTHS: MONTHS_LOWER.append(month.lower()) + +def time2isoz(t=None): + """Return a string representing time in seconds since epoch, t. + + If the function is called without an argument, it will use the current + time. + + The format of the returned string is like "YYYY-MM-DD hh:mm:ssZ", + representing Universal Time (UTC, aka GMT). An example of this format is: + + 1994-11-24 08:49:37Z + + """ + if t is None: t = time.time() + year, mon, mday, hour, min, sec = time.gmtime(t)[:6] + return "%04d-%02d-%02d %02d:%02d:%02dZ" % ( + year, mon, mday, hour, min, sec) + +def time2netscape(t=None): + """Return a string representing time in seconds since epoch, t. + + If the function is called without an argument, it will use the current + time. + + The format of the returned string is like this: + + Wed, DD-Mon-YYYY HH:MM:SS GMT + + """ + if t is None: t = time.time() + year, mon, mday, hour, min, sec, wday = time.gmtime(t)[:7] + return "%s %02d-%s-%04d %02d:%02d:%02d GMT" % ( + DAYS[wday], mday, MONTHS[mon-1], year, hour, min, sec) + + +UTC_ZONES = {"GMT": None, "UTC": None, "UT": None, "Z": None} + +TIMEZONE_RE = re.compile(r"^([-+])?(\d\d?):?(\d\d)?$") +def offset_from_tz_string(tz): + offset = None + if tz in UTC_ZONES: + offset = 0 + else: + m = TIMEZONE_RE.search(tz) + if m: + offset = 3600 * int(m.group(2)) + if m.group(3): + offset = offset + 60 * int(m.group(3)) + if m.group(1) == '-': + offset = -offset + return offset + +def _str2time(day, mon, yr, hr, min, sec, tz): + # translate month name to number + # month numbers start with 1 (January) + try: + mon = MONTHS_LOWER.index(mon.lower())+1 + except ValueError: + # maybe it's already a number + try: + imon = int(mon) + except ValueError: + return None + if 1 <= imon <= 12: + mon = imon + else: + return None + + # make sure clock elements are defined + if hr is None: hr = 0 + if min is None: min = 0 + if sec is None: sec = 0 + + yr = int(yr) + day = int(day) + hr = int(hr) + min = int(min) + sec = int(sec) + + if yr < 1000: + # find "obvious" year + cur_yr = time.localtime(time.time())[0] + m = cur_yr % 100 + tmp = yr + yr = yr + cur_yr - m + m = m - tmp + if abs(m) > 50: + if m > 0: yr = yr + 100 + else: yr = yr - 100 + + # convert UTC time tuple to seconds since epoch (not timezone-adjusted) + t = _timegm((yr, mon, day, hr, min, sec, tz)) + + if t is not None: + # adjust time using timezone string, to get absolute time since epoch + if tz is None: + tz = "UTC" + tz = tz.upper() + offset = offset_from_tz_string(tz) + if offset is None: + return None + t = t - offset + + return t + +STRICT_DATE_RE = re.compile( + r"^[SMTWF][a-z][a-z], (\d\d) ([JFMASOND][a-z][a-z]) " + "(\d\d\d\d) (\d\d):(\d\d):(\d\d) GMT$") +WEEKDAY_RE = re.compile( + r"^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[a-z]*,?\s*", re.I) +LOOSE_HTTP_DATE_RE = re.compile( + r"""^ + (\d\d?) # day + (?:\s+|[-\/]) + (\w+) # month + (?:\s+|[-\/]) + (\d+) # year + (?: + (?:\s+|:) # separator before clock + (\d\d?):(\d\d) # hour:min + (?::(\d\d))? # optional seconds + )? # optional clock + \s* + ([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+)? # timezone + \s* + (?:\(\w+\))? # ASCII representation of timezone in parens. + \s*$""", re.X) +def http2time(text): + """Returns time in seconds since epoch of time represented by a string. + + Return value is an integer. + + None is returned if the format of str is unrecognized, the time is outside + the representable range, or the timezone string is not recognized. If the + string contains no timezone, UTC is assumed. + + The timezone in the string may be numerical (like "-0800" or "+0100") or a + string timezone (like "UTC", "GMT", "BST" or "EST"). Currently, only the + timezone strings equivalent to UTC (zero offset) are known to the function. + + The function loosely parses the following formats: + + Wed, 09 Feb 1994 22:23:32 GMT -- HTTP format + Tuesday, 08-Feb-94 14:15:29 GMT -- old rfc850 HTTP format + Tuesday, 08-Feb-1994 14:15:29 GMT -- broken rfc850 HTTP format + 09 Feb 1994 22:23:32 GMT -- HTTP format (no weekday) + 08-Feb-94 14:15:29 GMT -- rfc850 format (no weekday) + 08-Feb-1994 14:15:29 GMT -- broken rfc850 format (no weekday) + + The parser ignores leading and trailing whitespace. The time may be + absent. + + If the year is given with only 2 digits, the function will select the + century that makes the year closest to the current date. + + """ + # fast exit for strictly conforming string + m = STRICT_DATE_RE.search(text) + if m: + g = m.groups() + mon = MONTHS_LOWER.index(g[1].lower()) + 1 + tt = (int(g[2]), mon, int(g[0]), + int(g[3]), int(g[4]), float(g[5])) + return _timegm(tt) + + # No, we need some messy parsing... + + # clean up + text = text.lstrip() + text = WEEKDAY_RE.sub("", text, 1) # Useless weekday + + # tz is time zone specifier string + day, mon, yr, hr, min, sec, tz = [None]*7 + + # loose regexp parse + m = LOOSE_HTTP_DATE_RE.search(text) + if m is not None: + day, mon, yr, hr, min, sec, tz = m.groups() + else: + return None # bad format + + return _str2time(day, mon, yr, hr, min, sec, tz) + +ISO_DATE_RE = re.compile( + """^ + (\d{4}) # year + [-\/]? + (\d\d?) # numerical month + [-\/]? + (\d\d?) # day + (?: + (?:\s+|[-:Tt]) # separator before clock + (\d\d?):?(\d\d) # hour:min + (?::?(\d\d(?:\.\d*)?))? # optional seconds (and fractional) + )? # optional clock + \s* + ([-+]?\d\d?:?(:?\d\d)? + |Z|z)? # timezone (Z is "zero meridian", i.e. GMT) + \s*$""", re.X) +def iso2time(text): + """ + As for http2time, but parses the ISO 8601 formats: + + 1994-02-03 14:15:29 -0100 -- ISO 8601 format + 1994-02-03 14:15:29 -- zone is optional + 1994-02-03 -- only date + 1994-02-03T14:15:29 -- Use T as separator + 19940203T141529Z -- ISO 8601 compact format + 19940203 -- only date + + """ + # clean up + text = text.lstrip() + + # tz is time zone specifier string + day, mon, yr, hr, min, sec, tz = [None]*7 + + # loose regexp parse + m = ISO_DATE_RE.search(text) + if m is not None: + # XXX there's an extra bit of the timezone I'm ignoring here: is + # this the right thing to do? + yr, mon, day, hr, min, sec, tz, _ = m.groups() + else: + return None # bad format + + return _str2time(day, mon, yr, hr, min, sec, tz) + + +# Header parsing +# ----------------------------------------------------------------------------- + +def unmatched(match): + """Return unmatched part of re.Match object.""" + start, end = match.span(0) + return match.string[:start]+match.string[end:] + +HEADER_TOKEN_RE = re.compile(r"^\s*([^=\s;,]+)") +HEADER_QUOTED_VALUE_RE = re.compile(r"^\s*=\s*\"([^\"\\]*(?:\\.[^\"\\]*)*)\"") +HEADER_VALUE_RE = re.compile(r"^\s*=\s*([^\s;,]*)") +HEADER_ESCAPE_RE = re.compile(r"\\(.)") +def split_header_words(header_values): + r"""Parse header values into a list of lists containing key,value pairs. + + The function knows how to deal with ",", ";" and "=" as well as quoted + values after "=". A list of space separated tokens are parsed as if they + were separated by ";". + + If the header_values passed as argument contains multiple values, then they + are treated as if they were a single value separated by comma ",". + + This means that this function is useful for parsing header fields that + follow this syntax (BNF as from the HTTP/1.1 specification, but we relax + the requirement for tokens). + + headers = #header + header = (token | parameter) *( [";"] (token | parameter)) + + token = 1* + separators = "(" | ")" | "<" | ">" | "@" + | "," | ";" | ":" | "\" | <"> + | "/" | "[" | "]" | "?" | "=" + | "{" | "}" | SP | HT + + quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) + qdtext = > + quoted-pair = "\" CHAR + + parameter = attribute "=" value + attribute = token + value = token | quoted-string + + Each header is represented by a list of key/value pairs. The value for a + simple token (not part of a parameter) is None. Syntactically incorrect + headers will not necessarily be parsed as you would want. + + This is easier to describe with some examples: + + >>> split_header_words(['foo="bar"; port="80,81"; discard, bar=baz']) + [[('foo', 'bar'), ('port', '80,81'), ('discard', None)], [('bar', 'baz')]] + >>> split_header_words(['text/html; charset="iso-8859-1"']) + [[('text/html', None), ('charset', 'iso-8859-1')]] + >>> split_header_words([r'Basic realm="\"foo\bar\""']) + [[('Basic', None), ('realm', '"foobar"')]] + + """ + assert not isinstance(header_values, basestring) + result = [] + for text in header_values: + orig_text = text + pairs = [] + while text: + m = HEADER_TOKEN_RE.search(text) + if m: + text = unmatched(m) + name = m.group(1) + m = HEADER_QUOTED_VALUE_RE.search(text) + if m: # quoted value + text = unmatched(m) + value = m.group(1) + value = HEADER_ESCAPE_RE.sub(r"\1", value) + else: + m = HEADER_VALUE_RE.search(text) + if m: # unquoted value + text = unmatched(m) + value = m.group(1) + value = value.rstrip() + else: + # no value, a lone token + value = None + pairs.append((name, value)) + elif text.lstrip().startswith(","): + # concatenated headers, as per RFC 2616 section 4.2 + text = text.lstrip()[1:] + if pairs: result.append(pairs) + pairs = [] + else: + # skip junk + non_junk, nr_junk_chars = re.subn("^[=\s;]*", "", text) + assert nr_junk_chars > 0, ( + "split_header_words bug: '%s', '%s', %s" % + (orig_text, text, pairs)) + text = non_junk + if pairs: result.append(pairs) + return result + +HEADER_JOIN_ESCAPE_RE = re.compile(r"([\"\\])") +def join_header_words(lists): + """Do the inverse (almost) of the conversion done by split_header_words. + + Takes a list of lists of (key, value) pairs and produces a single header + value. Attribute values are quoted if needed. + + >>> join_header_words([[("text/plain", None), ("charset", "iso-8859/1")]]) + 'text/plain; charset="iso-8859/1"' + >>> join_header_words([[("text/plain", None)], [("charset", "iso-8859/1")]]) + 'text/plain, charset="iso-8859/1"' + + """ + headers = [] + for pairs in lists: + attr = [] + for k, v in pairs: + if v is not None: + if not re.search(r"^\w+$", v): + v = HEADER_JOIN_ESCAPE_RE.sub(r"\\\1", v) # escape " and \ + v = '"%s"' % v + k = "%s=%s" % (k, v) + attr.append(k) + if attr: headers.append("; ".join(attr)) + return ", ".join(headers) + +def _strip_quotes(text): + if text.startswith('"'): + text = text[1:] + if text.endswith('"'): + text = text[:-1] + return text + +def parse_ns_headers(ns_headers): + """Ad-hoc parser for Netscape protocol cookie-attributes. + + The old Netscape cookie format for Set-Cookie can for instance contain + an unquoted "," in the expires field, so we have to use this ad-hoc + parser instead of split_header_words. + + XXX This may not make the best possible effort to parse all the crap + that Netscape Cookie headers contain. Ronald Tschalar's HTTPClient + parser is probably better, so could do worse than following that if + this ever gives any trouble. + + Currently, this is also used for parsing RFC 2109 cookies. + + """ + known_attrs = ("expires", "domain", "path", "secure", + # RFC 2109 attrs (may turn up in Netscape cookies, too) + "version", "port", "max-age") + + result = [] + for ns_header in ns_headers: + pairs = [] + version_set = False + for ii, param in enumerate(re.split(r";\s*", ns_header)): + param = param.rstrip() + if param == "": continue + if "=" not in param: + k, v = param, None + else: + k, v = re.split(r"\s*=\s*", param, 1) + k = k.lstrip() + if ii != 0: + lc = k.lower() + if lc in known_attrs: + k = lc + if k == "version": + # This is an RFC 2109 cookie. + v = _strip_quotes(v) + version_set = True + if k == "expires": + # convert expires date to seconds since epoch + v = http2time(_strip_quotes(v)) # None if invalid + pairs.append((k, v)) + + if pairs: + if not version_set: + pairs.append(("version", "0")) + result.append(pairs) + + return result + + +IPV4_RE = re.compile(r"\.\d+$") +def is_HDN(text): + """Return True if text is a host domain name.""" + # XXX + # This may well be wrong. Which RFC is HDN defined in, if any (for + # the purposes of RFC 2965)? + # For the current implementation, what about IPv6? Remember to look + # at other uses of IPV4_RE also, if change this. + if IPV4_RE.search(text): + return False + if text == "": + return False + if text[0] == "." or text[-1] == ".": + return False + return True + +def domain_match(A, B): + """Return True if domain A domain-matches domain B, according to RFC 2965. + + A and B may be host domain names or IP addresses. + + RFC 2965, section 1: + + Host names can be specified either as an IP address or a HDN string. + Sometimes we compare one host name with another. (Such comparisons SHALL + be case-insensitive.) Host A's name domain-matches host B's if + + * their host name strings string-compare equal; or + + * A is a HDN string and has the form NB, where N is a non-empty + name string, B has the form .B', and B' is a HDN string. (So, + x.y.com domain-matches .Y.com but not Y.com.) + + Note that domain-match is not a commutative operation: a.b.c.com + domain-matches .c.com, but not the reverse. + + """ + # Note that, if A or B are IP addresses, the only relevant part of the + # definition of the domain-match algorithm is the direct string-compare. + A = A.lower() + B = B.lower() + if A == B: + return True + if not is_HDN(A): + return False + i = A.rfind(B) + if i == -1 or i == 0: + # A does not have form NB, or N is the empty string + return False + if not B.startswith("."): + return False + if not is_HDN(B[1:]): + return False + return True + +def liberal_is_HDN(text): + """Return True if text is a sort-of-like a host domain name. + + For accepting/blocking domains. + + """ + if IPV4_RE.search(text): + return False + return True + +def user_domain_match(A, B): + """For blocking/accepting domains. + + A and B may be host domain names or IP addresses. + + """ + A = A.lower() + B = B.lower() + if not (liberal_is_HDN(A) and liberal_is_HDN(B)): + if A == B: + # equal IP addresses + return True + return False + initial_dot = B.startswith(".") + if initial_dot and A.endswith(B): + return True + if not initial_dot and A == B: + return True + return False + +cut_port_re = re.compile(r":\d+$") +def request_host(request): + """Return request-host, as defined by RFC 2965. + + Variation from RFC: returned value is lowercased, for convenient + comparison. + + """ + url = request.get_full_url() + host = urlparse.urlparse(url)[1] + if host == "": + host = request.get_header("Host", "") + + # remove port, if present + host = cut_port_re.sub("", host, 1) + return host.lower() + +def eff_request_host(request): + """Return a tuple (request-host, effective request-host name). + + As defined by RFC 2965, except both are lowercased. + + """ + erhn = req_host = request_host(request) + if req_host.find(".") == -1 and not IPV4_RE.search(req_host): + erhn = req_host + ".local" + return req_host, erhn + +def request_path(request): + """Path component of request-URI, as defined by RFC 2965.""" + url = request.get_full_url() + parts = urlparse.urlsplit(url) + path = escape_path(parts.path) + if not path.startswith("/"): + # fix bad RFC 2396 absoluteURI + path = "/" + path + return path + +def request_port(request): + host = request.get_host() + i = host.find(':') + if i >= 0: + port = host[i+1:] + try: + int(port) + except ValueError: + _debug("nonnumeric port: '%s'", port) + return None + else: + port = DEFAULT_HTTP_PORT + return port + +# Characters in addition to A-Z, a-z, 0-9, '_', '.', and '-' that don't +# need to be escaped to form a valid HTTP URL (RFCs 2396 and 1738). +HTTP_PATH_SAFE = "%/;:@&=+$,!~*'()" +ESCAPED_CHAR_RE = re.compile(r"%([0-9a-fA-F][0-9a-fA-F])") +def uppercase_escaped_char(match): + return "%%%s" % match.group(1).upper() +def escape_path(path): + """Escape any invalid characters in HTTP URL, and uppercase all escapes.""" + # There's no knowing what character encoding was used to create URLs + # containing %-escapes, but since we have to pick one to escape invalid + # path characters, we pick UTF-8, as recommended in the HTML 4.0 + # specification: + # http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.2.1 + # And here, kind of: draft-fielding-uri-rfc2396bis-03 + # (And in draft IRI specification: draft-duerst-iri-05) + # (And here, for new URI schemes: RFC 2718) + if isinstance(path, unicode): + path = path.encode("utf-8") + path = urllib.quote(path, HTTP_PATH_SAFE) + path = ESCAPED_CHAR_RE.sub(uppercase_escaped_char, path) + return path + +def reach(h): + """Return reach of host h, as defined by RFC 2965, section 1. + + The reach R of a host name H is defined as follows: + + * If + + - H is the host domain name of a host; and, + + - H has the form A.B; and + + - A has no embedded (that is, interior) dots; and + + - B has at least one embedded dot, or B is the string "local". + then the reach of H is .B. + + * Otherwise, the reach of H is H. + + >>> reach("www.acme.com") + '.acme.com' + >>> reach("acme.com") + 'acme.com' + >>> reach("acme.local") + '.local' + + """ + i = h.find(".") + if i >= 0: + #a = h[:i] # this line is only here to show what a is + b = h[i+1:] + i = b.find(".") + if is_HDN(h) and (i >= 0 or b == "local"): + return "."+b + return h + +def is_third_party(request): + """ + + RFC 2965, section 3.3.6: + + An unverifiable transaction is to a third-party host if its request- + host U does not domain-match the reach R of the request-host O in the + origin transaction. + + """ + req_host = request_host(request) + if not domain_match(req_host, reach(request.get_origin_req_host())): + return True + else: + return False + + +class Cookie: + """HTTP Cookie. + + This class represents both Netscape and RFC 2965 cookies. + + This is deliberately a very simple class. It just holds attributes. It's + possible to construct Cookie instances that don't comply with the cookie + standards. CookieJar.make_cookies is the factory function for Cookie + objects -- it deals with cookie parsing, supplying defaults, and + normalising to the representation used in this class. CookiePolicy is + responsible for checking them to see whether they should be accepted from + and returned to the server. + + Note that the port may be present in the headers, but unspecified ("Port" + rather than"Port=80", for example); if this is the case, port is None. + + """ + + def __init__(self, version, name, value, + port, port_specified, + domain, domain_specified, domain_initial_dot, + path, path_specified, + secure, + expires, + discard, + comment, + comment_url, + rest, + rfc2109=False, + ): + + if version is not None: version = int(version) + if expires is not None: expires = int(expires) + if port is None and port_specified is True: + raise ValueError("if port is None, port_specified must be false") + + self.version = version + self.name = name + self.value = value + self.port = port + self.port_specified = port_specified + # normalise case, as per RFC 2965 section 3.3.3 + self.domain = domain.lower() + self.domain_specified = domain_specified + # Sigh. We need to know whether the domain given in the + # cookie-attribute had an initial dot, in order to follow RFC 2965 + # (as clarified in draft errata). Needed for the returned $Domain + # value. + self.domain_initial_dot = domain_initial_dot + self.path = path + self.path_specified = path_specified + self.secure = secure + self.expires = expires + self.discard = discard + self.comment = comment + self.comment_url = comment_url + self.rfc2109 = rfc2109 + + self._rest = copy.copy(rest) + + def has_nonstandard_attr(self, name): + return name in self._rest + def get_nonstandard_attr(self, name, default=None): + return self._rest.get(name, default) + def set_nonstandard_attr(self, name, value): + self._rest[name] = value + + def is_expired(self, now=None): + if now is None: now = time.time() + if (self.expires is not None) and (self.expires <= now): + return True + return False + + def __str__(self): + if self.port is None: p = "" + else: p = ":"+self.port + limit = self.domain + p + self.path + if self.value is not None: + namevalue = "%s=%s" % (self.name, self.value) + else: + namevalue = self.name + return "" % (namevalue, limit) + + def __repr__(self): + args = [] + for name in ("version", "name", "value", + "port", "port_specified", + "domain", "domain_specified", "domain_initial_dot", + "path", "path_specified", + "secure", "expires", "discard", "comment", "comment_url", + ): + attr = getattr(self, name) + args.append("%s=%s" % (name, repr(attr))) + args.append("rest=%s" % repr(self._rest)) + args.append("rfc2109=%s" % repr(self.rfc2109)) + return "Cookie(%s)" % ", ".join(args) + + +class CookiePolicy: + """Defines which cookies get accepted from and returned to server. + + May also modify cookies, though this is probably a bad idea. + + The subclass DefaultCookiePolicy defines the standard rules for Netscape + and RFC 2965 cookies -- override that if you want a customised policy. + + """ + def set_ok(self, cookie, request): + """Return true if (and only if) cookie should be accepted from server. + + Currently, pre-expired cookies never get this far -- the CookieJar + class deletes such cookies itself. + + """ + raise NotImplementedError() + + def return_ok(self, cookie, request): + """Return true if (and only if) cookie should be returned to server.""" + raise NotImplementedError() + + def domain_return_ok(self, domain, request): + """Return false if cookies should not be returned, given cookie domain. + """ + return True + + def path_return_ok(self, path, request): + """Return false if cookies should not be returned, given cookie path. + """ + return True + + +class DefaultCookiePolicy(CookiePolicy): + """Implements the standard rules for accepting and returning cookies.""" + + DomainStrictNoDots = 1 + DomainStrictNonDomain = 2 + DomainRFC2965Match = 4 + + DomainLiberal = 0 + DomainStrict = DomainStrictNoDots|DomainStrictNonDomain + + def __init__(self, + blocked_domains=None, allowed_domains=None, + netscape=True, rfc2965=False, + rfc2109_as_netscape=None, + hide_cookie2=False, + strict_domain=False, + strict_rfc2965_unverifiable=True, + strict_ns_unverifiable=False, + strict_ns_domain=DomainLiberal, + strict_ns_set_initial_dollar=False, + strict_ns_set_path=False, + ): + """Constructor arguments should be passed as keyword arguments only.""" + self.netscape = netscape + self.rfc2965 = rfc2965 + self.rfc2109_as_netscape = rfc2109_as_netscape + self.hide_cookie2 = hide_cookie2 + self.strict_domain = strict_domain + self.strict_rfc2965_unverifiable = strict_rfc2965_unverifiable + self.strict_ns_unverifiable = strict_ns_unverifiable + self.strict_ns_domain = strict_ns_domain + self.strict_ns_set_initial_dollar = strict_ns_set_initial_dollar + self.strict_ns_set_path = strict_ns_set_path + + if blocked_domains is not None: + self._blocked_domains = tuple(blocked_domains) + else: + self._blocked_domains = () + + if allowed_domains is not None: + allowed_domains = tuple(allowed_domains) + self._allowed_domains = allowed_domains + + def blocked_domains(self): + """Return the sequence of blocked domains (as a tuple).""" + return self._blocked_domains + def set_blocked_domains(self, blocked_domains): + """Set the sequence of blocked domains.""" + self._blocked_domains = tuple(blocked_domains) + + def is_blocked(self, domain): + for blocked_domain in self._blocked_domains: + if user_domain_match(domain, blocked_domain): + return True + return False + + def allowed_domains(self): + """Return None, or the sequence of allowed domains (as a tuple).""" + return self._allowed_domains + def set_allowed_domains(self, allowed_domains): + """Set the sequence of allowed domains, or None.""" + if allowed_domains is not None: + allowed_domains = tuple(allowed_domains) + self._allowed_domains = allowed_domains + + def is_not_allowed(self, domain): + if self._allowed_domains is None: + return False + for allowed_domain in self._allowed_domains: + if user_domain_match(domain, allowed_domain): + return False + return True + + def set_ok(self, cookie, request): + """ + If you override .set_ok(), be sure to call this method. If it returns + false, so should your subclass (assuming your subclass wants to be more + strict about which cookies to accept). + + """ + _debug(" - checking cookie %s=%s", cookie.name, cookie.value) + + assert cookie.name is not None + + for n in "version", "verifiability", "name", "path", "domain", "port": + fn_name = "set_ok_"+n + fn = getattr(self, fn_name) + if not fn(cookie, request): + return False + + return True + + def set_ok_version(self, cookie, request): + if cookie.version is None: + # Version is always set to 0 by parse_ns_headers if it's a Netscape + # cookie, so this must be an invalid RFC 2965 cookie. + _debug(" Set-Cookie2 without version attribute (%s=%s)", + cookie.name, cookie.value) + return False + if cookie.version > 0 and not self.rfc2965: + _debug(" RFC 2965 cookies are switched off") + return False + elif cookie.version == 0 and not self.netscape: + _debug(" Netscape cookies are switched off") + return False + return True + + def set_ok_verifiability(self, cookie, request): + if request.is_unverifiable() and is_third_party(request): + if cookie.version > 0 and self.strict_rfc2965_unverifiable: + _debug(" third-party RFC 2965 cookie during " + "unverifiable transaction") + return False + elif cookie.version == 0 and self.strict_ns_unverifiable: + _debug(" third-party Netscape cookie during " + "unverifiable transaction") + return False + return True + + def set_ok_name(self, cookie, request): + # Try and stop servers setting V0 cookies designed to hack other + # servers that know both V0 and V1 protocols. + if (cookie.version == 0 and self.strict_ns_set_initial_dollar and + cookie.name.startswith("$")): + _debug(" illegal name (starts with '$'): '%s'", cookie.name) + return False + return True + + def set_ok_path(self, cookie, request): + if cookie.path_specified: + req_path = request_path(request) + if ((cookie.version > 0 or + (cookie.version == 0 and self.strict_ns_set_path)) and + not req_path.startswith(cookie.path)): + _debug(" path attribute %s is not a prefix of request " + "path %s", cookie.path, req_path) + return False + return True + + def set_ok_domain(self, cookie, request): + if self.is_blocked(cookie.domain): + _debug(" domain %s is in user block-list", cookie.domain) + return False + if self.is_not_allowed(cookie.domain): + _debug(" domain %s is not in user allow-list", cookie.domain) + return False + if cookie.domain_specified: + req_host, erhn = eff_request_host(request) + domain = cookie.domain + if self.strict_domain and (domain.count(".") >= 2): + # XXX This should probably be compared with the Konqueror + # (kcookiejar.cpp) and Mozilla implementations, but it's a + # losing battle. + i = domain.rfind(".") + j = domain.rfind(".", 0, i) + if j == 0: # domain like .foo.bar + tld = domain[i+1:] + sld = domain[j+1:i] + if sld.lower() in ("co", "ac", "com", "edu", "org", "net", + "gov", "mil", "int", "aero", "biz", "cat", "coop", + "info", "jobs", "mobi", "museum", "name", "pro", + "travel", "eu") and len(tld) == 2: + # domain like .co.uk + _debug(" country-code second level domain %s", domain) + return False + if domain.startswith("."): + undotted_domain = domain[1:] + else: + undotted_domain = domain + embedded_dots = (undotted_domain.find(".") >= 0) + if not embedded_dots and domain != ".local": + _debug(" non-local domain %s contains no embedded dot", + domain) + return False + if cookie.version == 0: + if (not erhn.endswith(domain) and + (not erhn.startswith(".") and + not ("."+erhn).endswith(domain))): + _debug(" effective request-host %s (even with added " + "initial dot) does not end with %s", + erhn, domain) + return False + if (cookie.version > 0 or + (self.strict_ns_domain & self.DomainRFC2965Match)): + if not domain_match(erhn, domain): + _debug(" effective request-host %s does not domain-match " + "%s", erhn, domain) + return False + if (cookie.version > 0 or + (self.strict_ns_domain & self.DomainStrictNoDots)): + host_prefix = req_host[:-len(domain)] + if (host_prefix.find(".") >= 0 and + not IPV4_RE.search(req_host)): + _debug(" host prefix %s for domain %s contains a dot", + host_prefix, domain) + return False + return True + + def set_ok_port(self, cookie, request): + if cookie.port_specified: + req_port = request_port(request) + if req_port is None: + req_port = "80" + else: + req_port = str(req_port) + for p in cookie.port.split(","): + try: + int(p) + except ValueError: + _debug(" bad port %s (not numeric)", p) + return False + if p == req_port: + break + else: + _debug(" request port (%s) not found in %s", + req_port, cookie.port) + return False + return True + + def return_ok(self, cookie, request): + """ + If you override .return_ok(), be sure to call this method. If it + returns false, so should your subclass (assuming your subclass wants to + be more strict about which cookies to return). + + """ + # Path has already been checked by .path_return_ok(), and domain + # blocking done by .domain_return_ok(). + _debug(" - checking cookie %s=%s", cookie.name, cookie.value) + + for n in "version", "verifiability", "secure", "expires", "port", "domain": + fn_name = "return_ok_"+n + fn = getattr(self, fn_name) + if not fn(cookie, request): + return False + return True + + def return_ok_version(self, cookie, request): + if cookie.version > 0 and not self.rfc2965: + _debug(" RFC 2965 cookies are switched off") + return False + elif cookie.version == 0 and not self.netscape: + _debug(" Netscape cookies are switched off") + return False + return True + + def return_ok_verifiability(self, cookie, request): + if request.is_unverifiable() and is_third_party(request): + if cookie.version > 0 and self.strict_rfc2965_unverifiable: + _debug(" third-party RFC 2965 cookie during unverifiable " + "transaction") + return False + elif cookie.version == 0 and self.strict_ns_unverifiable: + _debug(" third-party Netscape cookie during unverifiable " + "transaction") + return False + return True + + def return_ok_secure(self, cookie, request): + if cookie.secure and request.get_type() != "https": + _debug(" secure cookie with non-secure request") + return False + return True + + def return_ok_expires(self, cookie, request): + if cookie.is_expired(self._now): + _debug(" cookie expired") + return False + return True + + def return_ok_port(self, cookie, request): + if cookie.port: + req_port = request_port(request) + if req_port is None: + req_port = "80" + for p in cookie.port.split(","): + if p == req_port: + break + else: + _debug(" request port %s does not match cookie port %s", + req_port, cookie.port) + return False + return True + + def return_ok_domain(self, cookie, request): + req_host, erhn = eff_request_host(request) + domain = cookie.domain + + # strict check of non-domain cookies: Mozilla does this, MSIE5 doesn't + if (cookie.version == 0 and + (self.strict_ns_domain & self.DomainStrictNonDomain) and + not cookie.domain_specified and domain != erhn): + _debug(" cookie with unspecified domain does not string-compare " + "equal to request domain") + return False + + if cookie.version > 0 and not domain_match(erhn, domain): + _debug(" effective request-host name %s does not domain-match " + "RFC 2965 cookie domain %s", erhn, domain) + return False + if cookie.version == 0 and not ("."+erhn).endswith(domain): + _debug(" request-host %s does not match Netscape cookie domain " + "%s", req_host, domain) + return False + return True + + def domain_return_ok(self, domain, request): + # Liberal check of. This is here as an optimization to avoid + # having to load lots of MSIE cookie files unless necessary. + req_host, erhn = eff_request_host(request) + if not req_host.startswith("."): + req_host = "."+req_host + if not erhn.startswith("."): + erhn = "."+erhn + if not (req_host.endswith(domain) or erhn.endswith(domain)): + #_debug(" request domain %s does not match cookie domain %s", + # req_host, domain) + return False + + if self.is_blocked(domain): + _debug(" domain %s is in user block-list", domain) + return False + if self.is_not_allowed(domain): + _debug(" domain %s is not in user allow-list", domain) + return False + + return True + + def path_return_ok(self, path, request): + _debug("- checking cookie path=%s", path) + req_path = request_path(request) + if not req_path.startswith(path): + _debug(" %s does not path-match %s", req_path, path) + return False + return True + + +def vals_sorted_by_key(adict): + keys = adict.keys() + keys.sort() + return map(adict.get, keys) + +def deepvalues(mapping): + """Iterates over nested mapping, depth-first, in sorted order by key.""" + values = vals_sorted_by_key(mapping) + for obj in values: + mapping = False + try: + obj.items + except AttributeError: + pass + else: + mapping = True + for subobj in deepvalues(obj): + yield subobj + if not mapping: + yield obj + + +# Used as second parameter to dict.get() method, to distinguish absent +# dict key from one with a None value. +class Absent: pass + +class CookieJar: + """Collection of HTTP cookies. + + You may not need to know about this class: try + urllib2.build_opener(HTTPCookieProcessor).open(url). + + """ + + non_word_re = re.compile(r"\W") + quote_re = re.compile(r"([\"\\])") + strict_domain_re = re.compile(r"\.?[^.]*") + domain_re = re.compile(r"[^.]*") + dots_re = re.compile(r"^\.+") + + magic_re = r"^\#LWP-Cookies-(\d+\.\d+)" + + def __init__(self, policy=None): + if policy is None: + policy = DefaultCookiePolicy() + self._policy = policy + + self._cookies_lock = _threading.RLock() + self._cookies = {} + + def set_policy(self, policy): + self._policy = policy + + def _cookies_for_domain(self, domain, request): + cookies = [] + if not self._policy.domain_return_ok(domain, request): + return [] + _debug("Checking %s for cookies to return", domain) + cookies_by_path = self._cookies[domain] + for path in cookies_by_path.keys(): + if not self._policy.path_return_ok(path, request): + continue + cookies_by_name = cookies_by_path[path] + for cookie in cookies_by_name.values(): + if not self._policy.return_ok(cookie, request): + _debug(" not returning cookie") + continue + _debug(" it's a match") + cookies.append(cookie) + return cookies + + def _cookies_for_request(self, request): + """Return a list of cookies to be returned to server.""" + cookies = [] + for domain in self._cookies.keys(): + cookies.extend(self._cookies_for_domain(domain, request)) + return cookies + + def _cookie_attrs(self, cookies): + """Return a list of cookie-attributes to be returned to server. + + like ['foo="bar"; $Path="/"', ...] + + The $Version attribute is also added when appropriate (currently only + once per request). + + """ + # add cookies in order of most specific (ie. longest) path first + cookies.sort(key=lambda arg: len(arg.path), reverse=True) + + version_set = False + + attrs = [] + for cookie in cookies: + # set version of Cookie header + # XXX + # What should it be if multiple matching Set-Cookie headers have + # different versions themselves? + # Answer: there is no answer; was supposed to be settled by + # RFC 2965 errata, but that may never appear... + version = cookie.version + if not version_set: + version_set = True + if version > 0: + attrs.append("$Version=%s" % version) + + # quote cookie value if necessary + # (not for Netscape protocol, which already has any quotes + # intact, due to the poorly-specified Netscape Cookie: syntax) + if ((cookie.value is not None) and + self.non_word_re.search(cookie.value) and version > 0): + value = self.quote_re.sub(r"\\\1", cookie.value) + else: + value = cookie.value + + # add cookie-attributes to be returned in Cookie header + if cookie.value is None: + attrs.append(cookie.name) + else: + attrs.append("%s=%s" % (cookie.name, value)) + if version > 0: + if cookie.path_specified: + attrs.append('$Path="%s"' % cookie.path) + if cookie.domain.startswith("."): + domain = cookie.domain + if (not cookie.domain_initial_dot and + domain.startswith(".")): + domain = domain[1:] + attrs.append('$Domain="%s"' % domain) + if cookie.port is not None: + p = "$Port" + if cookie.port_specified: + p = p + ('="%s"' % cookie.port) + attrs.append(p) + + return attrs + + def add_cookie_header(self, request): + """Add correct Cookie: header to request (urllib2.Request object). + + The Cookie2 header is also added unless policy.hide_cookie2 is true. + + """ + _debug("add_cookie_header") + self._cookies_lock.acquire() + try: + + self._policy._now = self._now = int(time.time()) + + cookies = self._cookies_for_request(request) + + attrs = self._cookie_attrs(cookies) + if attrs: + if not request.has_header("Cookie"): + request.add_unredirected_header( + "Cookie", "; ".join(attrs)) + + # if necessary, advertise that we know RFC 2965 + if (self._policy.rfc2965 and not self._policy.hide_cookie2 and + not request.has_header("Cookie2")): + for cookie in cookies: + if cookie.version != 1: + request.add_unredirected_header("Cookie2", '$Version="1"') + break + + finally: + self._cookies_lock.release() + + self.clear_expired_cookies() + + def _normalized_cookie_tuples(self, attrs_set): + """Return list of tuples containing normalised cookie information. + + attrs_set is the list of lists of key,value pairs extracted from + the Set-Cookie or Set-Cookie2 headers. + + Tuples are name, value, standard, rest, where name and value are the + cookie name and value, standard is a dictionary containing the standard + cookie-attributes (discard, secure, version, expires or max-age, + domain, path and port) and rest is a dictionary containing the rest of + the cookie-attributes. + + """ + cookie_tuples = [] + + boolean_attrs = "discard", "secure" + value_attrs = ("version", + "expires", "max-age", + "domain", "path", "port", + "comment", "commenturl") + + for cookie_attrs in attrs_set: + name, value = cookie_attrs[0] + + # Build dictionary of standard cookie-attributes (standard) and + # dictionary of other cookie-attributes (rest). + + # Note: expiry time is normalised to seconds since epoch. V0 + # cookies should have the Expires cookie-attribute, and V1 cookies + # should have Max-Age, but since V1 includes RFC 2109 cookies (and + # since V0 cookies may be a mish-mash of Netscape and RFC 2109), we + # accept either (but prefer Max-Age). + max_age_set = False + + bad_cookie = False + + standard = {} + rest = {} + for k, v in cookie_attrs[1:]: + lc = k.lower() + # don't lose case distinction for unknown fields + if lc in value_attrs or lc in boolean_attrs: + k = lc + if k in boolean_attrs and v is None: + # boolean cookie-attribute is present, but has no value + # (like "discard", rather than "port=80") + v = True + if k in standard: + # only first value is significant + continue + if k == "domain": + if v is None: + _debug(" missing value for domain attribute") + bad_cookie = True + break + # RFC 2965 section 3.3.3 + v = v.lower() + if k == "expires": + if max_age_set: + # Prefer max-age to expires (like Mozilla) + continue + if v is None: + _debug(" missing or invalid value for expires " + "attribute: treating as session cookie") + continue + if k == "max-age": + max_age_set = True + try: + v = int(v) + except ValueError: + _debug(" missing or invalid (non-numeric) value for " + "max-age attribute") + bad_cookie = True + break + # convert RFC 2965 Max-Age to seconds since epoch + # XXX Strictly you're supposed to follow RFC 2616 + # age-calculation rules. Remember that zero Max-Age is a + # is a request to discard (old and new) cookie, though. + k = "expires" + v = self._now + v + if (k in value_attrs) or (k in boolean_attrs): + if (v is None and + k not in ("port", "comment", "commenturl")): + _debug(" missing value for %s attribute" % k) + bad_cookie = True + break + standard[k] = v + else: + rest[k] = v + + if bad_cookie: + continue + + cookie_tuples.append((name, value, standard, rest)) + + return cookie_tuples + + def _cookie_from_cookie_tuple(self, tup, request): + # standard is dict of standard cookie-attributes, rest is dict of the + # rest of them + name, value, standard, rest = tup + + domain = standard.get("domain", Absent) + path = standard.get("path", Absent) + port = standard.get("port", Absent) + expires = standard.get("expires", Absent) + + # set the easy defaults + version = standard.get("version", None) + if version is not None: + try: + version = int(version) + except ValueError: + return None # invalid version, ignore cookie + secure = standard.get("secure", False) + # (discard is also set if expires is Absent) + discard = standard.get("discard", False) + comment = standard.get("comment", None) + comment_url = standard.get("commenturl", None) + + # set default path + if path is not Absent and path != "": + path_specified = True + path = escape_path(path) + else: + path_specified = False + path = request_path(request) + i = path.rfind("/") + if i != -1: + if version == 0: + # Netscape spec parts company from reality here + path = path[:i] + else: + path = path[:i+1] + if len(path) == 0: path = "/" + + # set default domain + domain_specified = domain is not Absent + # but first we have to remember whether it starts with a dot + domain_initial_dot = False + if domain_specified: + domain_initial_dot = bool(domain.startswith(".")) + if domain is Absent: + req_host, erhn = eff_request_host(request) + domain = erhn + elif not domain.startswith("."): + domain = "."+domain + + # set default port + port_specified = False + if port is not Absent: + if port is None: + # Port attr present, but has no value: default to request port. + # Cookie should then only be sent back on that port. + port = request_port(request) + else: + port_specified = True + port = re.sub(r"\s+", "", port) + else: + # No port attr present. Cookie can be sent back on any port. + port = None + + # set default expires and discard + if expires is Absent: + expires = None + discard = True + elif expires <= self._now: + # Expiry date in past is request to delete cookie. This can't be + # in DefaultCookiePolicy, because can't delete cookies there. + try: + self.clear(domain, path, name) + except KeyError: + pass + _debug("Expiring cookie, domain='%s', path='%s', name='%s'", + domain, path, name) + return None + + return Cookie(version, + name, value, + port, port_specified, + domain, domain_specified, domain_initial_dot, + path, path_specified, + secure, + expires, + discard, + comment, + comment_url, + rest) + + def _cookies_from_attrs_set(self, attrs_set, request): + cookie_tuples = self._normalized_cookie_tuples(attrs_set) + + cookies = [] + for tup in cookie_tuples: + cookie = self._cookie_from_cookie_tuple(tup, request) + if cookie: cookies.append(cookie) + return cookies + + def _process_rfc2109_cookies(self, cookies): + rfc2109_as_ns = getattr(self._policy, 'rfc2109_as_netscape', None) + if rfc2109_as_ns is None: + rfc2109_as_ns = not self._policy.rfc2965 + for cookie in cookies: + if cookie.version == 1: + cookie.rfc2109 = True + if rfc2109_as_ns: + # treat 2109 cookies as Netscape cookies rather than + # as RFC2965 cookies + cookie.version = 0 + + def make_cookies(self, response, request): + """Return sequence of Cookie objects extracted from response object.""" + # get cookie-attributes for RFC 2965 and Netscape protocols + headers = response.info() + rfc2965_hdrs = headers.getheaders("Set-Cookie2") + ns_hdrs = headers.getheaders("Set-Cookie") + + rfc2965 = self._policy.rfc2965 + netscape = self._policy.netscape + + if ((not rfc2965_hdrs and not ns_hdrs) or + (not ns_hdrs and not rfc2965) or + (not rfc2965_hdrs and not netscape) or + (not netscape and not rfc2965)): + return [] # no relevant cookie headers: quick exit + + try: + cookies = self._cookies_from_attrs_set( + split_header_words(rfc2965_hdrs), request) + except Exception: + _warn_unhandled_exception() + cookies = [] + + if ns_hdrs and netscape: + try: + # RFC 2109 and Netscape cookies + ns_cookies = self._cookies_from_attrs_set( + parse_ns_headers(ns_hdrs), request) + except Exception: + _warn_unhandled_exception() + ns_cookies = [] + self._process_rfc2109_cookies(ns_cookies) + + # Look for Netscape cookies (from Set-Cookie headers) that match + # corresponding RFC 2965 cookies (from Set-Cookie2 headers). + # For each match, keep the RFC 2965 cookie and ignore the Netscape + # cookie (RFC 2965 section 9.1). Actually, RFC 2109 cookies are + # bundled in with the Netscape cookies for this purpose, which is + # reasonable behaviour. + if rfc2965: + lookup = {} + for cookie in cookies: + lookup[(cookie.domain, cookie.path, cookie.name)] = None + + def no_matching_rfc2965(ns_cookie, lookup=lookup): + key = ns_cookie.domain, ns_cookie.path, ns_cookie.name + return key not in lookup + ns_cookies = filter(no_matching_rfc2965, ns_cookies) + + if ns_cookies: + cookies.extend(ns_cookies) + + return cookies + + def set_cookie_if_ok(self, cookie, request): + """Set a cookie if policy says it's OK to do so.""" + self._cookies_lock.acquire() + try: + self._policy._now = self._now = int(time.time()) + + if self._policy.set_ok(cookie, request): + self.set_cookie(cookie) + + + finally: + self._cookies_lock.release() + + def set_cookie(self, cookie): + """Set a cookie, without checking whether or not it should be set.""" + c = self._cookies + self._cookies_lock.acquire() + try: + if cookie.domain not in c: c[cookie.domain] = {} + c2 = c[cookie.domain] + if cookie.path not in c2: c2[cookie.path] = {} + c3 = c2[cookie.path] + c3[cookie.name] = cookie + finally: + self._cookies_lock.release() + + def extract_cookies(self, response, request): + """Extract cookies from response, where allowable given the request.""" + _debug("extract_cookies: %s", response.info()) + self._cookies_lock.acquire() + try: + self._policy._now = self._now = int(time.time()) + + for cookie in self.make_cookies(response, request): + if self._policy.set_ok(cookie, request): + _debug(" setting cookie: %s", cookie) + self.set_cookie(cookie) + finally: + self._cookies_lock.release() + + def clear(self, domain=None, path=None, name=None): + """Clear some cookies. + + Invoking this method without arguments will clear all cookies. If + given a single argument, only cookies belonging to that domain will be + removed. If given two arguments, cookies belonging to the specified + path within that domain are removed. If given three arguments, then + the cookie with the specified name, path and domain is removed. + + Raises KeyError if no matching cookie exists. + + """ + if name is not None: + if (domain is None) or (path is None): + raise ValueError( + "domain and path must be given to remove a cookie by name") + del self._cookies[domain][path][name] + elif path is not None: + if domain is None: + raise ValueError( + "domain must be given to remove cookies by path") + del self._cookies[domain][path] + elif domain is not None: + del self._cookies[domain] + else: + self._cookies = {} + + def clear_session_cookies(self): + """Discard all session cookies. + + Note that the .save() method won't save session cookies anyway, unless + you ask otherwise by passing a true ignore_discard argument. + + """ + self._cookies_lock.acquire() + try: + for cookie in self: + if cookie.discard: + self.clear(cookie.domain, cookie.path, cookie.name) + finally: + self._cookies_lock.release() + + def clear_expired_cookies(self): + """Discard all expired cookies. + + You probably don't need to call this method: expired cookies are never + sent back to the server (provided you're using DefaultCookiePolicy), + this method is called by CookieJar itself every so often, and the + .save() method won't save expired cookies anyway (unless you ask + otherwise by passing a true ignore_expires argument). + + """ + self._cookies_lock.acquire() + try: + now = time.time() + for cookie in self: + if cookie.is_expired(now): + self.clear(cookie.domain, cookie.path, cookie.name) + finally: + self._cookies_lock.release() + + def __iter__(self): + return deepvalues(self._cookies) + + def __len__(self): + """Return number of contained cookies.""" + i = 0 + for cookie in self: i = i + 1 + return i + + def __repr__(self): + r = [] + for cookie in self: r.append(repr(cookie)) + return "<%s[%s]>" % (self.__class__, ", ".join(r)) + + def __str__(self): + r = [] + for cookie in self: r.append(str(cookie)) + return "<%s[%s]>" % (self.__class__, ", ".join(r)) + + +# derives from IOError for backwards-compatibility with Python 2.4.0 +class LoadError(IOError): pass + +class FileCookieJar(CookieJar): + """CookieJar that can be loaded from and saved to a file.""" + + def __init__(self, filename=None, delayload=False, policy=None): + """ + Cookies are NOT loaded from the named file until either the .load() or + .revert() method is called. + + """ + CookieJar.__init__(self, policy) + if filename is not None: + try: + filename+"" + except: + raise ValueError("filename must be string-like") + self.filename = filename + self.delayload = bool(delayload) + + def save(self, filename=None, ignore_discard=False, ignore_expires=False): + """Save cookies to a file.""" + raise NotImplementedError() + + def load(self, filename=None, ignore_discard=False, ignore_expires=False): + """Load cookies from a file.""" + if filename is None: + if self.filename is not None: filename = self.filename + else: raise ValueError(MISSING_FILENAME_TEXT) + + f = open(filename) + try: + self._really_load(f, filename, ignore_discard, ignore_expires) + finally: + f.close() + + def revert(self, filename=None, + ignore_discard=False, ignore_expires=False): + """Clear all cookies and reload cookies from a saved file. + + Raises LoadError (or IOError) if reversion is not successful; the + object's state will not be altered if this happens. + + """ + if filename is None: + if self.filename is not None: filename = self.filename + else: raise ValueError(MISSING_FILENAME_TEXT) + + self._cookies_lock.acquire() + try: + + old_state = copy.deepcopy(self._cookies) + self._cookies = {} + try: + self.load(filename, ignore_discard, ignore_expires) + except (LoadError, IOError): + self._cookies = old_state + raise + + finally: + self._cookies_lock.release() + +from _LWPCookieJar import LWPCookieJar, lwp_cookie_str +from _MozillaCookieJar import MozillaCookieJar diff --git a/PythonHome/Lib/cookielib.pyc b/PythonHome/Lib/cookielib.pyc index 80d09bb80b1e3adbcdb6d3f3159be676675243ec..f5c6f10e3e23bf143bb8ec498eb6db8bbf5fd4c3 100644 GIT binary patch delta 5615 zcmbW5>q}H&5XL>N7OPe!bymAbL1_?3`9U$$A`LY+*W9RVH}KN7rmHJ?)+-^AWfq$4 z2$@1^Mi--So9>FSwW~!JOY>7D1O-u0b|FH#z3YE)o20r$RtLpP!CVwngnXdRtK+HQuQLGcXCmy7kZ1&T$H`m}dL9WlY`#&_vTeRr z1BTqL`v#m5`LcB_Yx4(GT^^ZABi{g|PqZvb2~v;p_n1+{p_j1}fS5b(Vt{&#x-Bv_ zCt4*9{Y)HJ&x?CQlSz@1KkL^2Ly{dyl_?>4O1(0rq^y$y_+Ux~P{RCb(|Z7;k<<;6 zhC|Zg5m;EwrRk9fI+7Z}?#;0vO3U^A>J8@4`eH<|Ff&G!Lq}#XP!4=^>oq`=D~!O0IGVgRXxRD_L`8sms5O4y%;UCodqaEyG$Q! zmjSZY98Ucu9RO)5^#YVHQiFY1J;^J|2q;P(-rs}VyJ|%*THKIQfWV!mg_KgwwMj!#asM;jySXW&&6Hxb!r`PM|0%nWABY5)QJ_IeSkCptX zv;Ged@s`G=^!RYp^nuNmoDHeKH~L&M*&5=-`+mLwXxY=#TuoCTwH&>wUY)lz<{;;M ztnLphK zM0CYI$qR2m|6zRl*`?cdK$WBJjsX~H2hzpXVjPGCDw*5v^#hum@4kf`$x2U+`p1D> z9%LG?^S%SL_79Dzr+C}&JitX#9-aoo7C*{BysvmX2#6&=L3TZEf4T#R(fJ%{RP?+Y M&=OT8)2cDoe?YnBlK=n! delta 2376 zcmZveYfQ~?7{~i}PDl+kvf{->!~=RB{wGQ)G& z7&kY!In$S0w{A*ZpB*}l>`s;QJ?j)OBzswv0qpQfN0Xt=ms1RV?%?AHQMr8hBrx!g z5set8cT|Ehh{Jq5buI%H`hCT6wG7Qc<$CZiC#zIx?2$P;LW;ZqrcG_foJy%m`C(5$ zygj_eLxyEBDy5s(4R+V2DSo#3bShG%KJyJ(sSTJu%?eg@>|^-@SvfLtI8MfrtJ2B2 z!T-bWqX5fjem~cUT2VG9Mm^Sm{yDc}y zzv41bTpk}PI(-&D1Uns+cn$TITz}RlW#~ke88dI}dcCGZ&c>B%U!quBfX38XSxjP; z>0+8g=GtmirL&Al+ldny@iOPJnal7tI676jyP;YZ6K%wCPQIs7Ud{#3im_0(%?>X7Ddvt;@@%%Qc45Kf4{N6 z1sC_|(SbPOs2*&P9kmnpE4d|OR!Wy(AKIL%%1olouCfHEP79TDc=ll3zjx^hy)9Gu z#bGN%;>4rA2rJ6<0IB`h7bx!A@gfvDPVNEW>Ixrt3#flTD^oyht@?>k#d7h%>Y-@R z9)jL8lN1jgd3FRQ5uXIktcgIs?pm9e--5aaFh81eDMoygN-lke6`^D=UuwC2MDga; z^@s4v2{W5-FNSRVq+td?ntDh3y6(NR9ZKNI_X0uB`OUilio@pU`|E-8hX)-1>Eokl zv6<5zn_y6Ef7$?gE^4_6wNcLVZSt9kC)%G(t>=In+IoQnwRgyjgFCz-JEguj2Ex#n j^RXgFXA=l3x}qQ=tKCWHZFl0rCiK`)sQtY#yt(=p8L-bv diff --git a/PythonHome/Lib/copy.py b/PythonHome/Lib/copy.py new file mode 100644 index 0000000000..c227a2e5c7 --- /dev/null +++ b/PythonHome/Lib/copy.py @@ -0,0 +1,433 @@ +"""Generic (shallow and deep) copying operations. + +Interface summary: + + import copy + + x = copy.copy(y) # make a shallow copy of y + x = copy.deepcopy(y) # make a deep copy of y + +For module specific errors, copy.Error is raised. + +The difference between shallow and deep copying is only relevant for +compound objects (objects that contain other objects, like lists or +class instances). + +- A shallow copy constructs a new compound object and then (to the + extent possible) inserts *the same objects* into it that the + original contains. + +- A deep copy constructs a new compound object and then, recursively, + inserts *copies* into it of the objects found in the original. + +Two problems often exist with deep copy operations that don't exist +with shallow copy operations: + + a) recursive objects (compound objects that, directly or indirectly, + contain a reference to themselves) may cause a recursive loop + + b) because deep copy copies *everything* it may copy too much, e.g. + administrative data structures that should be shared even between + copies + +Python's deep copy operation avoids these problems by: + + a) keeping a table of objects already copied during the current + copying pass + + b) letting user-defined classes override the copying operation or the + set of components copied + +This version does not copy types like module, class, function, method, +nor stack trace, stack frame, nor file, socket, window, nor array, nor +any similar types. + +Classes can use the same interfaces to control copying that they use +to control pickling: they can define methods called __getinitargs__(), +__getstate__() and __setstate__(). See the documentation for module +"pickle" for information on these methods. +""" + +import types +import weakref +from copy_reg import dispatch_table + +class Error(Exception): + pass +error = Error # backward compatibility + +try: + from org.python.core import PyStringMap +except ImportError: + PyStringMap = None + +__all__ = ["Error", "copy", "deepcopy"] + +def copy(x): + """Shallow copy operation on arbitrary Python objects. + + See the module's __doc__ string for more info. + """ + + cls = type(x) + + copier = _copy_dispatch.get(cls) + if copier: + return copier(x) + + copier = getattr(cls, "__copy__", None) + if copier: + return copier(x) + + reductor = dispatch_table.get(cls) + if reductor: + rv = reductor(x) + else: + reductor = getattr(x, "__reduce_ex__", None) + if reductor: + rv = reductor(2) + else: + reductor = getattr(x, "__reduce__", None) + if reductor: + rv = reductor() + else: + raise Error("un(shallow)copyable object of type %s" % cls) + + return _reconstruct(x, rv, 0) + + +_copy_dispatch = d = {} + +def _copy_immutable(x): + return x +for t in (type(None), int, long, float, bool, str, tuple, + frozenset, type, xrange, types.ClassType, + types.BuiltinFunctionType, type(Ellipsis), + types.FunctionType, weakref.ref): + d[t] = _copy_immutable +for name in ("ComplexType", "UnicodeType", "CodeType"): + t = getattr(types, name, None) + if t is not None: + d[t] = _copy_immutable + +def _copy_with_constructor(x): + return type(x)(x) +for t in (list, dict, set): + d[t] = _copy_with_constructor + +def _copy_with_copy_method(x): + return x.copy() +if PyStringMap is not None: + d[PyStringMap] = _copy_with_copy_method + +def _copy_inst(x): + if hasattr(x, '__copy__'): + return x.__copy__() + if hasattr(x, '__getinitargs__'): + args = x.__getinitargs__() + y = x.__class__(*args) + else: + y = _EmptyClass() + y.__class__ = x.__class__ + if hasattr(x, '__getstate__'): + state = x.__getstate__() + else: + state = x.__dict__ + if hasattr(y, '__setstate__'): + y.__setstate__(state) + else: + y.__dict__.update(state) + return y +d[types.InstanceType] = _copy_inst + +del d + +def deepcopy(x, memo=None, _nil=[]): + """Deep copy operation on arbitrary Python objects. + + See the module's __doc__ string for more info. + """ + + if memo is None: + memo = {} + + d = id(x) + y = memo.get(d, _nil) + if y is not _nil: + return y + + cls = type(x) + + copier = _deepcopy_dispatch.get(cls) + if copier: + y = copier(x, memo) + else: + try: + issc = issubclass(cls, type) + except TypeError: # cls is not a class (old Boost; see SF #502085) + issc = 0 + if issc: + y = _deepcopy_atomic(x, memo) + else: + copier = getattr(x, "__deepcopy__", None) + if copier: + y = copier(memo) + else: + reductor = dispatch_table.get(cls) + if reductor: + rv = reductor(x) + else: + reductor = getattr(x, "__reduce_ex__", None) + if reductor: + rv = reductor(2) + else: + reductor = getattr(x, "__reduce__", None) + if reductor: + rv = reductor() + else: + raise Error( + "un(deep)copyable object of type %s" % cls) + y = _reconstruct(x, rv, 1, memo) + + memo[d] = y + _keep_alive(x, memo) # Make sure x lives at least as long as d + return y + +_deepcopy_dispatch = d = {} + +def _deepcopy_atomic(x, memo): + return x +d[type(None)] = _deepcopy_atomic +d[type(Ellipsis)] = _deepcopy_atomic +d[int] = _deepcopy_atomic +d[long] = _deepcopy_atomic +d[float] = _deepcopy_atomic +d[bool] = _deepcopy_atomic +try: + d[complex] = _deepcopy_atomic +except NameError: + pass +d[str] = _deepcopy_atomic +try: + d[unicode] = _deepcopy_atomic +except NameError: + pass +try: + d[types.CodeType] = _deepcopy_atomic +except AttributeError: + pass +d[type] = _deepcopy_atomic +d[xrange] = _deepcopy_atomic +d[types.ClassType] = _deepcopy_atomic +d[types.BuiltinFunctionType] = _deepcopy_atomic +d[types.FunctionType] = _deepcopy_atomic +d[weakref.ref] = _deepcopy_atomic + +def _deepcopy_list(x, memo): + y = [] + memo[id(x)] = y + for a in x: + y.append(deepcopy(a, memo)) + return y +d[list] = _deepcopy_list + +def _deepcopy_tuple(x, memo): + y = [] + for a in x: + y.append(deepcopy(a, memo)) + d = id(x) + try: + return memo[d] + except KeyError: + pass + for i in range(len(x)): + if x[i] is not y[i]: + y = tuple(y) + break + else: + y = x + memo[d] = y + return y +d[tuple] = _deepcopy_tuple + +def _deepcopy_dict(x, memo): + y = {} + memo[id(x)] = y + for key, value in x.iteritems(): + y[deepcopy(key, memo)] = deepcopy(value, memo) + return y +d[dict] = _deepcopy_dict +if PyStringMap is not None: + d[PyStringMap] = _deepcopy_dict + +def _deepcopy_method(x, memo): # Copy instance methods + return type(x)(x.im_func, deepcopy(x.im_self, memo), x.im_class) +_deepcopy_dispatch[types.MethodType] = _deepcopy_method + +def _keep_alive(x, memo): + """Keeps a reference to the object x in the memo. + + Because we remember objects by their id, we have + to assure that possibly temporary objects are kept + alive by referencing them. + We store a reference at the id of the memo, which should + normally not be used unless someone tries to deepcopy + the memo itself... + """ + try: + memo[id(memo)].append(x) + except KeyError: + # aha, this is the first one :-) + memo[id(memo)]=[x] + +def _deepcopy_inst(x, memo): + if hasattr(x, '__deepcopy__'): + return x.__deepcopy__(memo) + if hasattr(x, '__getinitargs__'): + args = x.__getinitargs__() + args = deepcopy(args, memo) + y = x.__class__(*args) + else: + y = _EmptyClass() + y.__class__ = x.__class__ + memo[id(x)] = y + if hasattr(x, '__getstate__'): + state = x.__getstate__() + else: + state = x.__dict__ + state = deepcopy(state, memo) + if hasattr(y, '__setstate__'): + y.__setstate__(state) + else: + y.__dict__.update(state) + return y +d[types.InstanceType] = _deepcopy_inst + +def _reconstruct(x, info, deep, memo=None): + if isinstance(info, str): + return x + assert isinstance(info, tuple) + if memo is None: + memo = {} + n = len(info) + assert n in (2, 3, 4, 5) + callable, args = info[:2] + if n > 2: + state = info[2] + else: + state = {} + if n > 3: + listiter = info[3] + else: + listiter = None + if n > 4: + dictiter = info[4] + else: + dictiter = None + if deep: + args = deepcopy(args, memo) + y = callable(*args) + memo[id(x)] = y + + if state: + if deep: + state = deepcopy(state, memo) + if hasattr(y, '__setstate__'): + y.__setstate__(state) + else: + if isinstance(state, tuple) and len(state) == 2: + state, slotstate = state + else: + slotstate = None + if state is not None: + y.__dict__.update(state) + if slotstate is not None: + for key, value in slotstate.iteritems(): + setattr(y, key, value) + + if listiter is not None: + for item in listiter: + if deep: + item = deepcopy(item, memo) + y.append(item) + if dictiter is not None: + for key, value in dictiter: + if deep: + key = deepcopy(key, memo) + value = deepcopy(value, memo) + y[key] = value + return y + +del d + +del types + +# Helper for instance creation without calling __init__ +class _EmptyClass: + pass + +def _test(): + l = [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'], + {'abc': 'ABC'}, (), [], {}] + l1 = copy(l) + print l1==l + l1 = map(copy, l) + print l1==l + l1 = deepcopy(l) + print l1==l + class C: + def __init__(self, arg=None): + self.a = 1 + self.arg = arg + if __name__ == '__main__': + import sys + file = sys.argv[0] + else: + file = __file__ + self.fp = open(file) + self.fp.close() + def __getstate__(self): + return {'a': self.a, 'arg': self.arg} + def __setstate__(self, state): + for key, value in state.iteritems(): + setattr(self, key, value) + def __deepcopy__(self, memo=None): + new = self.__class__(deepcopy(self.arg, memo)) + new.a = self.a + return new + c = C('argument sketch') + l.append(c) + l2 = copy(l) + print l == l2 + print l + print l2 + l2 = deepcopy(l) + print l == l2 + print l + print l2 + l.append({l[1]: l, 'xyz': l[2]}) + l3 = copy(l) + import repr + print map(repr.repr, l) + print map(repr.repr, l1) + print map(repr.repr, l2) + print map(repr.repr, l3) + l3 = deepcopy(l) + import repr + print map(repr.repr, l) + print map(repr.repr, l1) + print map(repr.repr, l2) + print map(repr.repr, l3) + class odict(dict): + def __init__(self, d = {}): + self.a = 99 + dict.__init__(self, d) + def __setitem__(self, k, i): + dict.__setitem__(self, k, i) + self.a + o = odict({"A" : "B"}) + x = deepcopy(o) + print(o, x) + +if __name__ == '__main__': + _test() diff --git a/PythonHome/Lib/copy.pyc b/PythonHome/Lib/copy.pyc index 399329ff24dbd685fe862f74dcc2f194c349226e..fbe4e76689fd2a02855601c7887d75681c1cf3a4 100644 GIT binary patch delta 1439 zcmZ1wHzjog54WKu0|P^On82Uo>#EHUr>N^jDKlKL1{^hOKMVSdQ3oN zNk)F2M}BVVW@+vfOr&d@e2KS$3|*0Yi^^h)1 eoeW)RTJB`%+M~6fbX}Xfw2zaKmM16Z9RL6bbNy=o delta 551 zcmbP|x*%=?4>!L!0|SGzRZKu-Nk)F2k@;p@?iEbvf|JGgDlo+M^DV{@vlft>ypcZ= zU3{~(z;Q+lL1Uq2W^}>H&qe2Ah;0?yfiAXro_GePiRO|l7=n}MiAzszms*KoLZUPu zhDSFqke!QZLY{muBkSfv@@p`iJ70M(hQYlm*Dw`M(U^j+aB`&P91Jlvtpylj-?cD8 mbaJEiFAQ~Sbf#m7mFT)-h`rI>k1n?Pj^1&M(3pJ1@Bjcxew`cu diff --git a/PythonHome/Lib/copy_reg.py b/PythonHome/Lib/copy_reg.py new file mode 100644 index 0000000000..db1715092c --- /dev/null +++ b/PythonHome/Lib/copy_reg.py @@ -0,0 +1,201 @@ +"""Helper to provide extensibility for pickle/cPickle. + +This is only useful to add pickle support for extension types defined in +C, not for instances of user-defined classes. +""" + +from types import ClassType as _ClassType + +__all__ = ["pickle", "constructor", + "add_extension", "remove_extension", "clear_extension_cache"] + +dispatch_table = {} + +def pickle(ob_type, pickle_function, constructor_ob=None): + if type(ob_type) is _ClassType: + raise TypeError("copy_reg is not intended for use with classes") + + if not hasattr(pickle_function, '__call__'): + raise TypeError("reduction functions must be callable") + dispatch_table[ob_type] = pickle_function + + # The constructor_ob function is a vestige of safe for unpickling. + # There is no reason for the caller to pass it anymore. + if constructor_ob is not None: + constructor(constructor_ob) + +def constructor(object): + if not hasattr(object, '__call__'): + raise TypeError("constructors must be callable") + +# Example: provide pickling support for complex numbers. + +try: + complex +except NameError: + pass +else: + + def pickle_complex(c): + return complex, (c.real, c.imag) + + pickle(complex, pickle_complex, complex) + +# Support for pickling new-style objects + +def _reconstructor(cls, base, state): + if base is object: + obj = object.__new__(cls) + else: + obj = base.__new__(cls, state) + if base.__init__ != object.__init__: + base.__init__(obj, state) + return obj + +_HEAPTYPE = 1<<9 + +# Python code for object.__reduce_ex__ for protocols 0 and 1 + +def _reduce_ex(self, proto): + assert proto < 2 + for base in self.__class__.__mro__: + if hasattr(base, '__flags__') and not base.__flags__ & _HEAPTYPE: + break + else: + base = object # not really reachable + if base is object: + state = None + else: + if base is self.__class__: + raise TypeError, "can't pickle %s objects" % base.__name__ + state = base(self) + args = (self.__class__, base, state) + try: + getstate = self.__getstate__ + except AttributeError: + if getattr(self, "__slots__", None): + raise TypeError("a class that defines __slots__ without " + "defining __getstate__ cannot be pickled") + try: + dict = self.__dict__ + except AttributeError: + dict = None + else: + dict = getstate() + if dict: + return _reconstructor, args, dict + else: + return _reconstructor, args + +# Helper for __reduce_ex__ protocol 2 + +def __newobj__(cls, *args): + return cls.__new__(cls, *args) + +def _slotnames(cls): + """Return a list of slot names for a given class. + + This needs to find slots defined by the class and its bases, so we + can't simply return the __slots__ attribute. We must walk down + the Method Resolution Order and concatenate the __slots__ of each + class found there. (This assumes classes don't modify their + __slots__ attribute to misrepresent their slots after the class is + defined.) + """ + + # Get the value from a cache in the class if possible + names = cls.__dict__.get("__slotnames__") + if names is not None: + return names + + # Not cached -- calculate the value + names = [] + if not hasattr(cls, "__slots__"): + # This class has no slots + pass + else: + # Slots found -- gather slot names from all base classes + for c in cls.__mro__: + if "__slots__" in c.__dict__: + slots = c.__dict__['__slots__'] + # if class has a single slot, it can be given as a string + if isinstance(slots, basestring): + slots = (slots,) + for name in slots: + # special descriptors + if name in ("__dict__", "__weakref__"): + continue + # mangled names + elif name.startswith('__') and not name.endswith('__'): + names.append('_%s%s' % (c.__name__, name)) + else: + names.append(name) + + # Cache the outcome in the class if at all possible + try: + cls.__slotnames__ = names + except: + pass # But don't die if we can't + + return names + +# A registry of extension codes. This is an ad-hoc compression +# mechanism. Whenever a global reference to , is about +# to be pickled, the (, ) tuple is looked up here to see +# if it is a registered extension code for it. Extension codes are +# universal, so that the meaning of a pickle does not depend on +# context. (There are also some codes reserved for local use that +# don't have this restriction.) Codes are positive ints; 0 is +# reserved. + +_extension_registry = {} # key -> code +_inverted_registry = {} # code -> key +_extension_cache = {} # code -> object +# Don't ever rebind those names: cPickle grabs a reference to them when +# it's initialized, and won't see a rebinding. + +def add_extension(module, name, code): + """Register an extension code.""" + code = int(code) + if not 1 <= code <= 0x7fffffff: + raise ValueError, "code out of range" + key = (module, name) + if (_extension_registry.get(key) == code and + _inverted_registry.get(code) == key): + return # Redundant registrations are benign + if key in _extension_registry: + raise ValueError("key %s is already registered with code %s" % + (key, _extension_registry[key])) + if code in _inverted_registry: + raise ValueError("code %s is already in use for key %s" % + (code, _inverted_registry[code])) + _extension_registry[key] = code + _inverted_registry[code] = key + +def remove_extension(module, name, code): + """Unregister an extension code. For testing only.""" + key = (module, name) + if (_extension_registry.get(key) != code or + _inverted_registry.get(code) != key): + raise ValueError("key %s is not registered with code %s" % + (key, code)) + del _extension_registry[key] + del _inverted_registry[code] + if code in _extension_cache: + del _extension_cache[code] + +def clear_extension_cache(): + _extension_cache.clear() + +# Standard extension code assignments + +# Reserved ranges + +# First Last Count Purpose +# 1 127 127 Reserved for Python standard library +# 128 191 64 Reserved for Zope +# 192 239 48 Reserved for 3rd parties +# 240 255 16 Reserved for private use (will never be assigned) +# 256 Inf Inf Reserved for future assignment + +# Extension codes are assigned by the Python Software Foundation. diff --git a/PythonHome/Lib/copy_reg.pyc b/PythonHome/Lib/copy_reg.pyc index 40c56234274fef21ca21f87d548445ae7327d9be..5c64c10d9134f645a922a7a3d560f020b20dd452 100644 GIT binary patch delta 632 zcmX@4zC&xnVrD~I1_lOKtC;l6l8n-%nDG1xJ+EMYzn}o;82{3eg3^*0m(--v^q7Fk zl8pR3kNn)!$(xvWlcB4IrI!p{3T&d2by=T~u5+^jn-m$Io5UqHIi7P8>GnfGZ>G=KTUzjAUr$5UL|X*HocXWa!Eh4gmo1C)e8m delta 248 zcmdm?bx3`~VrG761_lOatC)bwl8pR3BlF2un0I4{9boCj5UXSTi7vKz1)CJ6fuA{7 zpevkwhRc|dZ4>u#Ow~X5Vi{RChw(EpVQA_UbY*1Od|uFs5ktyKxDG??rSK^Xu_q!S E0NbudMgRZ+ diff --git a/PythonHome/Lib/csv.py b/PythonHome/Lib/csv.py new file mode 100644 index 0000000000..c155ada794 --- /dev/null +++ b/PythonHome/Lib/csv.py @@ -0,0 +1,456 @@ + +""" +csv.py - read/write/investigate CSV files +""" + +import re +from functools import reduce +from _csv import Error, __version__, writer, reader, register_dialect, \ + unregister_dialect, get_dialect, list_dialects, \ + field_size_limit, \ + QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE, \ + __doc__ +from _csv import Dialect as _Dialect + +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + +__all__ = [ "QUOTE_MINIMAL", "QUOTE_ALL", "QUOTE_NONNUMERIC", "QUOTE_NONE", + "Error", "Dialect", "__doc__", "excel", "excel_tab", + "field_size_limit", "reader", "writer", + "register_dialect", "get_dialect", "list_dialects", "Sniffer", + "unregister_dialect", "__version__", "DictReader", "DictWriter" ] + +class Dialect: + """Describe an Excel dialect. + + This must be subclassed (see csv.excel). Valid attributes are: + delimiter, quotechar, escapechar, doublequote, skipinitialspace, + lineterminator, quoting. + + """ + _name = "" + _valid = False + # placeholders + delimiter = None + quotechar = None + escapechar = None + doublequote = None + skipinitialspace = None + lineterminator = None + quoting = None + + def __init__(self): + if self.__class__ != Dialect: + self._valid = True + self._validate() + + def _validate(self): + try: + _Dialect(self) + except TypeError, e: + # We do this for compatibility with py2.3 + raise Error(str(e)) + +class excel(Dialect): + """Describe the usual properties of Excel-generated CSV files.""" + delimiter = ',' + quotechar = '"' + doublequote = True + skipinitialspace = False + lineterminator = '\r\n' + quoting = QUOTE_MINIMAL +register_dialect("excel", excel) + +class excel_tab(excel): + """Describe the usual properties of Excel-generated TAB-delimited files.""" + delimiter = '\t' +register_dialect("excel-tab", excel_tab) + + +class DictReader: + def __init__(self, f, fieldnames=None, restkey=None, restval=None, + dialect="excel", *args, **kwds): + self._fieldnames = fieldnames # list of keys for the dict + self.restkey = restkey # key to catch long rows + self.restval = restval # default value for short rows + self.reader = reader(f, dialect, *args, **kwds) + self.dialect = dialect + self.line_num = 0 + + def __iter__(self): + return self + + @property + def fieldnames(self): + if self._fieldnames is None: + try: + self._fieldnames = self.reader.next() + except StopIteration: + pass + self.line_num = self.reader.line_num + return self._fieldnames + + # Issue 20004: Because DictReader is a classic class, this setter is + # ignored. At this point in 2.7's lifecycle, it is too late to change the + # base class for fear of breaking working code. If you want to change + # fieldnames without overwriting the getter, set _fieldnames directly. + @fieldnames.setter + def fieldnames(self, value): + self._fieldnames = value + + def next(self): + if self.line_num == 0: + # Used only for its side effect. + self.fieldnames + row = self.reader.next() + self.line_num = self.reader.line_num + + # unlike the basic reader, we prefer not to return blanks, + # because we will typically wind up with a dict full of None + # values + while row == []: + row = self.reader.next() + d = dict(zip(self.fieldnames, row)) + lf = len(self.fieldnames) + lr = len(row) + if lf < lr: + d[self.restkey] = row[lf:] + elif lf > lr: + for key in self.fieldnames[lr:]: + d[key] = self.restval + return d + + +class DictWriter: + def __init__(self, f, fieldnames, restval="", extrasaction="raise", + dialect="excel", *args, **kwds): + self.fieldnames = fieldnames # list of keys for the dict + self.restval = restval # for writing short dicts + if extrasaction.lower() not in ("raise", "ignore"): + raise ValueError, \ + ("extrasaction (%s) must be 'raise' or 'ignore'" % + extrasaction) + self.extrasaction = extrasaction + self.writer = writer(f, dialect, *args, **kwds) + + def writeheader(self): + header = dict(zip(self.fieldnames, self.fieldnames)) + self.writerow(header) + + def _dict_to_list(self, rowdict): + if self.extrasaction == "raise": + wrong_fields = [k for k in rowdict if k not in self.fieldnames] + if wrong_fields: + raise ValueError("dict contains fields not in fieldnames: " + + ", ".join([repr(x) for x in wrong_fields])) + return [rowdict.get(key, self.restval) for key in self.fieldnames] + + def writerow(self, rowdict): + return self.writer.writerow(self._dict_to_list(rowdict)) + + def writerows(self, rowdicts): + rows = [] + for rowdict in rowdicts: + rows.append(self._dict_to_list(rowdict)) + return self.writer.writerows(rows) + +# Guard Sniffer's type checking against builds that exclude complex() +try: + complex +except NameError: + complex = float + +class Sniffer: + ''' + "Sniffs" the format of a CSV file (i.e. delimiter, quotechar) + Returns a Dialect object. + ''' + def __init__(self): + # in case there is more than one possible delimiter + self.preferred = [',', '\t', ';', ' ', ':'] + + + def sniff(self, sample, delimiters=None): + """ + Returns a dialect (or None) corresponding to the sample + """ + + quotechar, doublequote, delimiter, skipinitialspace = \ + self._guess_quote_and_delimiter(sample, delimiters) + if not delimiter: + delimiter, skipinitialspace = self._guess_delimiter(sample, + delimiters) + + if not delimiter: + raise Error, "Could not determine delimiter" + + class dialect(Dialect): + _name = "sniffed" + lineterminator = '\r\n' + quoting = QUOTE_MINIMAL + # escapechar = '' + + dialect.doublequote = doublequote + dialect.delimiter = delimiter + # _csv.reader won't accept a quotechar of '' + dialect.quotechar = quotechar or '"' + dialect.skipinitialspace = skipinitialspace + + return dialect + + + def _guess_quote_and_delimiter(self, data, delimiters): + """ + Looks for text enclosed between two identical quotes + (the probable quotechar) which are preceded and followed + by the same character (the probable delimiter). + For example: + ,'some text', + The quote with the most wins, same with the delimiter. + If there is no quotechar the delimiter can't be determined + this way. + """ + + matches = [] + for restr in ('(?P[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?P=delim)', # ,".*?", + '(?:^|\n)(?P["\']).*?(?P=quote)(?P[^\w\n"\'])(?P ?)', # ".*?", + '(?P>[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?:$|\n)', # ,".*?" + '(?:^|\n)(?P["\']).*?(?P=quote)(?:$|\n)'): # ".*?" (no delim, no space) + regexp = re.compile(restr, re.DOTALL | re.MULTILINE) + matches = regexp.findall(data) + if matches: + break + + if not matches: + # (quotechar, doublequote, delimiter, skipinitialspace) + return ('', False, None, 0) + quotes = {} + delims = {} + spaces = 0 + for m in matches: + n = regexp.groupindex['quote'] - 1 + key = m[n] + if key: + quotes[key] = quotes.get(key, 0) + 1 + try: + n = regexp.groupindex['delim'] - 1 + key = m[n] + except KeyError: + continue + if key and (delimiters is None or key in delimiters): + delims[key] = delims.get(key, 0) + 1 + try: + n = regexp.groupindex['space'] - 1 + except KeyError: + continue + if m[n]: + spaces += 1 + + quotechar = reduce(lambda a, b, quotes = quotes: + (quotes[a] > quotes[b]) and a or b, quotes.keys()) + + if delims: + delim = reduce(lambda a, b, delims = delims: + (delims[a] > delims[b]) and a or b, delims.keys()) + skipinitialspace = delims[delim] == spaces + if delim == '\n': # most likely a file with a single column + delim = '' + else: + # there is *no* delimiter, it's a single column of quoted data + delim = '' + skipinitialspace = 0 + + # if we see an extra quote between delimiters, we've got a + # double quoted format + dq_regexp = re.compile( + r"((%(delim)s)|^)\W*%(quote)s[^%(delim)s\n]*%(quote)s[^%(delim)s\n]*%(quote)s\W*((%(delim)s)|$)" % \ + {'delim':re.escape(delim), 'quote':quotechar}, re.MULTILINE) + + + + if dq_regexp.search(data): + doublequote = True + else: + doublequote = False + + return (quotechar, doublequote, delim, skipinitialspace) + + + def _guess_delimiter(self, data, delimiters): + """ + The delimiter /should/ occur the same number of times on + each row. However, due to malformed data, it may not. We don't want + an all or nothing approach, so we allow for small variations in this + number. + 1) build a table of the frequency of each character on every line. + 2) build a table of frequencies of this frequency (meta-frequency?), + e.g. 'x occurred 5 times in 10 rows, 6 times in 1000 rows, + 7 times in 2 rows' + 3) use the mode of the meta-frequency to determine the /expected/ + frequency for that character + 4) find out how often the character actually meets that goal + 5) the character that best meets its goal is the delimiter + For performance reasons, the data is evaluated in chunks, so it can + try and evaluate the smallest portion of the data possible, evaluating + additional chunks as necessary. + """ + + data = filter(None, data.split('\n')) + + ascii = [chr(c) for c in range(127)] # 7-bit ASCII + + # build frequency tables + chunkLength = min(10, len(data)) + iteration = 0 + charFrequency = {} + modes = {} + delims = {} + start, end = 0, min(chunkLength, len(data)) + while start < len(data): + iteration += 1 + for line in data[start:end]: + for char in ascii: + metaFrequency = charFrequency.get(char, {}) + # must count even if frequency is 0 + freq = line.count(char) + # value is the mode + metaFrequency[freq] = metaFrequency.get(freq, 0) + 1 + charFrequency[char] = metaFrequency + + for char in charFrequency.keys(): + items = charFrequency[char].items() + if len(items) == 1 and items[0][0] == 0: + continue + # get the mode of the frequencies + if len(items) > 1: + modes[char] = reduce(lambda a, b: a[1] > b[1] and a or b, + items) + # adjust the mode - subtract the sum of all + # other frequencies + items.remove(modes[char]) + modes[char] = (modes[char][0], modes[char][1] + - reduce(lambda a, b: (0, a[1] + b[1]), + items)[1]) + else: + modes[char] = items[0] + + # build a list of possible delimiters + modeList = modes.items() + total = float(chunkLength * iteration) + # (rows of consistent data) / (number of rows) = 100% + consistency = 1.0 + # minimum consistency threshold + threshold = 0.9 + while len(delims) == 0 and consistency >= threshold: + for k, v in modeList: + if v[0] > 0 and v[1] > 0: + if ((v[1]/total) >= consistency and + (delimiters is None or k in delimiters)): + delims[k] = v + consistency -= 0.01 + + if len(delims) == 1: + delim = delims.keys()[0] + skipinitialspace = (data[0].count(delim) == + data[0].count("%c " % delim)) + return (delim, skipinitialspace) + + # analyze another chunkLength lines + start = end + end += chunkLength + + if not delims: + return ('', 0) + + # if there's more than one, fall back to a 'preferred' list + if len(delims) > 1: + for d in self.preferred: + if d in delims.keys(): + skipinitialspace = (data[0].count(d) == + data[0].count("%c " % d)) + return (d, skipinitialspace) + + # nothing else indicates a preference, pick the character that + # dominates(?) + items = [(v,k) for (k,v) in delims.items()] + items.sort() + delim = items[-1][1] + + skipinitialspace = (data[0].count(delim) == + data[0].count("%c " % delim)) + return (delim, skipinitialspace) + + + def has_header(self, sample): + # Creates a dictionary of types of data in each column. If any + # column is of a single type (say, integers), *except* for the first + # row, then the first row is presumed to be labels. If the type + # can't be determined, it is assumed to be a string in which case + # the length of the string is the determining factor: if all of the + # rows except for the first are the same length, it's a header. + # Finally, a 'vote' is taken at the end for each column, adding or + # subtracting from the likelihood of the first row being a header. + + rdr = reader(StringIO(sample), self.sniff(sample)) + + header = rdr.next() # assume first row is header + + columns = len(header) + columnTypes = {} + for i in range(columns): columnTypes[i] = None + + checked = 0 + for row in rdr: + # arbitrary number of rows to check, to keep it sane + if checked > 20: + break + checked += 1 + + if len(row) != columns: + continue # skip rows that have irregular number of columns + + for col in columnTypes.keys(): + + for thisType in [int, long, float, complex]: + try: + thisType(row[col]) + break + except (ValueError, OverflowError): + pass + else: + # fallback to length of string + thisType = len(row[col]) + + # treat longs as ints + if thisType == long: + thisType = int + + if thisType != columnTypes[col]: + if columnTypes[col] is None: # add new column type + columnTypes[col] = thisType + else: + # type is inconsistent, remove column from + # consideration + del columnTypes[col] + + # finally, compare results against first row and "vote" + # on whether it's a header + hasHeader = 0 + for col, colType in columnTypes.items(): + if type(colType) == type(0): # it's a length + if len(header[col]) != colType: + hasHeader += 1 + else: + hasHeader -= 1 + else: # attempt typecast + try: + colType(header[col]) + except (ValueError, TypeError): + hasHeader += 1 + else: + hasHeader -= 1 + + return hasHeader > 0 diff --git a/PythonHome/Lib/csv.pyc b/PythonHome/Lib/csv.pyc deleted file mode 100644 index d5f1b2b6a6c73e68c96e6ad1f7a22ca138f7751a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13375 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 P HRESULT +WINOLEAPI_(type) + +STDMETHODCALLTYPE + +STDMETHOD(name) +STDMETHOD_(type, name) + +STDAPICALLTYPE +""" + +def create_string_buffer(init, size=None): + """create_string_buffer(aString) -> character array + create_string_buffer(anInteger) -> character array + create_string_buffer(aString, anInteger) -> character array + """ + if isinstance(init, (str, unicode)): + if size is None: + size = len(init)+1 + buftype = c_char * size + buf = buftype() + buf.value = init + return buf + elif isinstance(init, (int, long)): + buftype = c_char * init + buf = buftype() + return buf + raise TypeError(init) + +def c_buffer(init, size=None): +## "deprecated, use create_string_buffer instead" +## import warnings +## warnings.warn("c_buffer is deprecated, use create_string_buffer instead", +## DeprecationWarning, stacklevel=2) + return create_string_buffer(init, size) + +_c_functype_cache = {} +def CFUNCTYPE(restype, *argtypes, **kw): + """CFUNCTYPE(restype, *argtypes, + use_errno=False, use_last_error=False) -> function prototype. + + restype: the result type + argtypes: a sequence specifying the argument types + + The function prototype can be called in different ways to create a + callable object: + + prototype(integer address) -> foreign function + prototype(callable) -> create and return a C callable function from callable + prototype(integer index, method name[, paramflags]) -> foreign function calling a COM method + prototype((ordinal number, dll object)[, paramflags]) -> foreign function exported by ordinal + prototype((function name, dll object)[, paramflags]) -> foreign function exported by name + """ + flags = _FUNCFLAG_CDECL + if kw.pop("use_errno", False): + flags |= _FUNCFLAG_USE_ERRNO + if kw.pop("use_last_error", False): + flags |= _FUNCFLAG_USE_LASTERROR + if kw: + raise ValueError("unexpected keyword argument(s) %s" % kw.keys()) + try: + return _c_functype_cache[(restype, argtypes, flags)] + except KeyError: + class CFunctionType(_CFuncPtr): + _argtypes_ = argtypes + _restype_ = restype + _flags_ = flags + _c_functype_cache[(restype, argtypes, flags)] = CFunctionType + return CFunctionType + +if _os.name in ("nt", "ce"): + from _ctypes import LoadLibrary as _dlopen + from _ctypes import FUNCFLAG_STDCALL as _FUNCFLAG_STDCALL + if _os.name == "ce": + # 'ce' doesn't have the stdcall calling convention + _FUNCFLAG_STDCALL = _FUNCFLAG_CDECL + + _win_functype_cache = {} + def WINFUNCTYPE(restype, *argtypes, **kw): + # docstring set later (very similar to CFUNCTYPE.__doc__) + flags = _FUNCFLAG_STDCALL + if kw.pop("use_errno", False): + flags |= _FUNCFLAG_USE_ERRNO + if kw.pop("use_last_error", False): + flags |= _FUNCFLAG_USE_LASTERROR + if kw: + raise ValueError("unexpected keyword argument(s) %s" % kw.keys()) + try: + return _win_functype_cache[(restype, argtypes, flags)] + except KeyError: + class WinFunctionType(_CFuncPtr): + _argtypes_ = argtypes + _restype_ = restype + _flags_ = flags + _win_functype_cache[(restype, argtypes, flags)] = WinFunctionType + return WinFunctionType + if WINFUNCTYPE.__doc__: + WINFUNCTYPE.__doc__ = CFUNCTYPE.__doc__.replace("CFUNCTYPE", "WINFUNCTYPE") + +elif _os.name == "posix": + from _ctypes import dlopen as _dlopen + +from _ctypes import sizeof, byref, addressof, alignment, resize +from _ctypes import get_errno, set_errno +from _ctypes import _SimpleCData + +def _check_size(typ, typecode=None): + # Check if sizeof(ctypes_type) against struct.calcsize. This + # should protect somewhat against a misconfigured libffi. + from struct import calcsize + if typecode is None: + # Most _type_ codes are the same as used in struct + typecode = typ._type_ + actual, required = sizeof(typ), calcsize(typecode) + if actual != required: + raise SystemError("sizeof(%s) wrong: %d instead of %d" % \ + (typ, actual, required)) + +class py_object(_SimpleCData): + _type_ = "O" + def __repr__(self): + try: + return super(py_object, self).__repr__() + except ValueError: + return "%s()" % type(self).__name__ +_check_size(py_object, "P") + +class c_short(_SimpleCData): + _type_ = "h" +_check_size(c_short) + +class c_ushort(_SimpleCData): + _type_ = "H" +_check_size(c_ushort) + +class c_long(_SimpleCData): + _type_ = "l" +_check_size(c_long) + +class c_ulong(_SimpleCData): + _type_ = "L" +_check_size(c_ulong) + +if _calcsize("i") == _calcsize("l"): + # if int and long have the same size, make c_int an alias for c_long + c_int = c_long + c_uint = c_ulong +else: + class c_int(_SimpleCData): + _type_ = "i" + _check_size(c_int) + + class c_uint(_SimpleCData): + _type_ = "I" + _check_size(c_uint) + +class c_float(_SimpleCData): + _type_ = "f" +_check_size(c_float) + +class c_double(_SimpleCData): + _type_ = "d" +_check_size(c_double) + +class c_longdouble(_SimpleCData): + _type_ = "g" +if sizeof(c_longdouble) == sizeof(c_double): + c_longdouble = c_double + +if _calcsize("l") == _calcsize("q"): + # if long and long long have the same size, make c_longlong an alias for c_long + c_longlong = c_long + c_ulonglong = c_ulong +else: + class c_longlong(_SimpleCData): + _type_ = "q" + _check_size(c_longlong) + + class c_ulonglong(_SimpleCData): + _type_ = "Q" + ## def from_param(cls, val): + ## return ('d', float(val), val) + ## from_param = classmethod(from_param) + _check_size(c_ulonglong) + +class c_ubyte(_SimpleCData): + _type_ = "B" +c_ubyte.__ctype_le__ = c_ubyte.__ctype_be__ = c_ubyte +# backward compatibility: +##c_uchar = c_ubyte +_check_size(c_ubyte) + +class c_byte(_SimpleCData): + _type_ = "b" +c_byte.__ctype_le__ = c_byte.__ctype_be__ = c_byte +_check_size(c_byte) + +class c_char(_SimpleCData): + _type_ = "c" +c_char.__ctype_le__ = c_char.__ctype_be__ = c_char +_check_size(c_char) + +class c_char_p(_SimpleCData): + _type_ = "z" + if _os.name == "nt": + def __repr__(self): + if not windll.kernel32.IsBadStringPtrA(self, -1): + return "%s(%r)" % (self.__class__.__name__, self.value) + return "%s(%s)" % (self.__class__.__name__, cast(self, c_void_p).value) + else: + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, cast(self, c_void_p).value) +_check_size(c_char_p, "P") + +class c_void_p(_SimpleCData): + _type_ = "P" +c_voidp = c_void_p # backwards compatibility (to a bug) +_check_size(c_void_p) + +class c_bool(_SimpleCData): + _type_ = "?" + +from _ctypes import POINTER, pointer, _pointer_type_cache + +def _reset_cache(): + _pointer_type_cache.clear() + _c_functype_cache.clear() + if _os.name in ("nt", "ce"): + _win_functype_cache.clear() + # _SimpleCData.c_wchar_p_from_param + POINTER(c_wchar).from_param = c_wchar_p.from_param + # _SimpleCData.c_char_p_from_param + POINTER(c_char).from_param = c_char_p.from_param + _pointer_type_cache[None] = c_void_p + # XXX for whatever reasons, creating the first instance of a callback + # function is needed for the unittests on Win64 to succeed. This MAY + # be a compiler bug, since the problem occurs only when _ctypes is + # compiled with the MS SDK compiler. Or an uninitialized variable? + CFUNCTYPE(c_int)(lambda: None) + +try: + from _ctypes import set_conversion_mode +except ImportError: + pass +else: + if _os.name in ("nt", "ce"): + set_conversion_mode("mbcs", "ignore") + else: + set_conversion_mode("ascii", "strict") + + class c_wchar_p(_SimpleCData): + _type_ = "Z" + + class c_wchar(_SimpleCData): + _type_ = "u" + + def create_unicode_buffer(init, size=None): + """create_unicode_buffer(aString) -> character array + create_unicode_buffer(anInteger) -> character array + create_unicode_buffer(aString, anInteger) -> character array + """ + if isinstance(init, (str, unicode)): + if size is None: + size = len(init)+1 + buftype = c_wchar * size + buf = buftype() + buf.value = init + return buf + elif isinstance(init, (int, long)): + buftype = c_wchar * init + buf = buftype() + return buf + raise TypeError(init) + +# XXX Deprecated +def SetPointerType(pointer, cls): + if _pointer_type_cache.get(cls, None) is not None: + raise RuntimeError("This type already exists in the cache") + if id(pointer) not in _pointer_type_cache: + raise RuntimeError("What's this???") + pointer.set_type(cls) + _pointer_type_cache[cls] = pointer + del _pointer_type_cache[id(pointer)] + +# XXX Deprecated +def ARRAY(typ, len): + return typ * len + +################################################################ + + +class CDLL(object): + """An instance of this class represents a loaded dll/shared + library, exporting functions using the standard C calling + convention (named 'cdecl' on Windows). + + The exported functions can be accessed as attributes, or by + indexing with the function name. Examples: + + .qsort -> callable object + ['qsort'] -> callable object + + Calling the functions releases the Python GIL during the call and + reacquires it afterwards. + """ + _func_flags_ = _FUNCFLAG_CDECL + _func_restype_ = c_int + + def __init__(self, name, mode=DEFAULT_MODE, handle=None, + use_errno=False, + use_last_error=False): + self._name = name + flags = self._func_flags_ + if use_errno: + flags |= _FUNCFLAG_USE_ERRNO + if use_last_error: + flags |= _FUNCFLAG_USE_LASTERROR + + class _FuncPtr(_CFuncPtr): + _flags_ = flags + _restype_ = self._func_restype_ + self._FuncPtr = _FuncPtr + + if handle is None: + self._handle = _dlopen(self._name, mode) + else: + self._handle = handle + + def __repr__(self): + return "<%s '%s', handle %x at %x>" % \ + (self.__class__.__name__, self._name, + (self._handle & (_sys.maxint*2 + 1)), + id(self) & (_sys.maxint*2 + 1)) + + def __getattr__(self, name): + if name.startswith('__') and name.endswith('__'): + raise AttributeError(name) + func = self.__getitem__(name) + setattr(self, name, func) + return func + + def __getitem__(self, name_or_ordinal): + func = self._FuncPtr((name_or_ordinal, self)) + if not isinstance(name_or_ordinal, (int, long)): + func.__name__ = name_or_ordinal + return func + +class PyDLL(CDLL): + """This class represents the Python library itself. It allows to + access Python API functions. The GIL is not released, and + Python exceptions are handled correctly. + """ + _func_flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI + +if _os.name in ("nt", "ce"): + + class WinDLL(CDLL): + """This class represents a dll exporting functions using the + Windows stdcall calling convention. + """ + _func_flags_ = _FUNCFLAG_STDCALL + + # XXX Hm, what about HRESULT as normal parameter? + # Mustn't it derive from c_long then? + from _ctypes import _check_HRESULT, _SimpleCData + class HRESULT(_SimpleCData): + _type_ = "l" + # _check_retval_ is called with the function's result when it + # is used as restype. It checks for the FAILED bit, and + # raises a WindowsError if it is set. + # + # The _check_retval_ method is implemented in C, so that the + # method definition itself is not included in the traceback + # when it raises an error - that is what we want (and Python + # doesn't have a way to raise an exception in the caller's + # frame). + _check_retval_ = _check_HRESULT + + class OleDLL(CDLL): + """This class represents a dll exporting functions using the + Windows stdcall calling convention, and returning HRESULT. + HRESULT error values are automatically raised as WindowsError + exceptions. + """ + _func_flags_ = _FUNCFLAG_STDCALL + _func_restype_ = HRESULT + +class LibraryLoader(object): + def __init__(self, dlltype): + self._dlltype = dlltype + + def __getattr__(self, name): + if name[0] == '_': + raise AttributeError(name) + dll = self._dlltype(name) + setattr(self, name, dll) + return dll + + def __getitem__(self, name): + return getattr(self, name) + + def LoadLibrary(self, name): + return self._dlltype(name) + +cdll = LibraryLoader(CDLL) +pydll = LibraryLoader(PyDLL) + +if _os.name in ("nt", "ce"): + pythonapi = PyDLL("python dll", None, _sys.dllhandle) +elif _sys.platform == "cygwin": + pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2]) +else: + pythonapi = PyDLL(None) + + +if _os.name in ("nt", "ce"): + windll = LibraryLoader(WinDLL) + oledll = LibraryLoader(OleDLL) + + if _os.name == "nt": + GetLastError = windll.kernel32.GetLastError + else: + GetLastError = windll.coredll.GetLastError + from _ctypes import get_last_error, set_last_error + + def WinError(code=None, descr=None): + if code is None: + code = GetLastError() + if descr is None: + descr = FormatError(code).strip() + return WindowsError(code, descr) + +if sizeof(c_uint) == sizeof(c_void_p): + c_size_t = c_uint + c_ssize_t = c_int +elif sizeof(c_ulong) == sizeof(c_void_p): + c_size_t = c_ulong + c_ssize_t = c_long +elif sizeof(c_ulonglong) == sizeof(c_void_p): + c_size_t = c_ulonglong + c_ssize_t = c_longlong + +# functions + +from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr + +## void *memmove(void *, const void *, size_t); +memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr) + +## void *memset(void *, int, size_t) +memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr) + +def PYFUNCTYPE(restype, *argtypes): + class CFunctionType(_CFuncPtr): + _argtypes_ = argtypes + _restype_ = restype + _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI + return CFunctionType + +_cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr) +def cast(obj, typ): + return _cast(obj, obj, typ) + +_string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr) +def string_at(ptr, size=-1): + """string_at(addr[, size]) -> string + + Return the string at addr.""" + return _string_at(ptr, size) + +try: + from _ctypes import _wstring_at_addr +except ImportError: + pass +else: + _wstring_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr) + def wstring_at(ptr, size=-1): + """wstring_at(addr[, size]) -> string + + Return the string at addr.""" + return _wstring_at(ptr, size) + + +if _os.name in ("nt", "ce"): # COM stuff + def DllGetClassObject(rclsid, riid, ppv): + try: + ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*']) + except ImportError: + return -2147221231 # CLASS_E_CLASSNOTAVAILABLE + else: + return ccom.DllGetClassObject(rclsid, riid, ppv) + + def DllCanUnloadNow(): + try: + ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*']) + except ImportError: + return 0 # S_OK + return ccom.DllCanUnloadNow() + +from ctypes._endian import BigEndianStructure, LittleEndianStructure + +# Fill in specifically-sized types +c_int8 = c_byte +c_uint8 = c_ubyte +for kind in [c_short, c_int, c_long, c_longlong]: + if sizeof(kind) == 2: c_int16 = kind + elif sizeof(kind) == 4: c_int32 = kind + elif sizeof(kind) == 8: c_int64 = kind +for kind in [c_ushort, c_uint, c_ulong, c_ulonglong]: + if sizeof(kind) == 2: c_uint16 = kind + elif sizeof(kind) == 4: c_uint32 = kind + elif sizeof(kind) == 8: c_uint64 = kind +del(kind) + +_reset_cache() diff --git a/PythonHome/Lib/ctypes/__init__.pyc b/PythonHome/Lib/ctypes/__init__.pyc index 854774443a48718bd3971c50538d3a79c1ded320..3de5e99b57a1e71cfbf7c72b8cd5e97e9762f428 100644 GIT binary patch delta 3453 zcmbW4-z!657{{HM3x%TD*xAM~Z3~^)WPZ&yBMGB6<&;bO#I`3HQ@-MRSm{XXC4ectDsvmI{ZkSof5&(Aycj}K2} z{XMxSMfw84op}q`#o&xQ9i0^Y(sEtz@Ie32pi3Nx%5za!bO$D*L2+?WugtLU4Rs9JpERs5mCXWrN%NILA@Fu z;FVQ*t62oe5HEowrwxN-TpIyNvktBET8FwF)uV3T^k}wg{YKrqCD{%yC70cE{(Gw>8k<5rO!2`NJMP2m`w+OT}Gx& z*8q8EjsaBW&ZJA02cSqgQ7Z%3@7DdSLt4oe;AVX+8!MAo8}_n+P!Q$2Fb1V z5J;LkM36k{aAG7aaR^AbY)T`YCIn^2=)&m%{IV&vxX@39D;LsHrn&7-U~Xx=%Zf&n V@+AK+N|W8U$o~p!=Y8K8_X8hiw8sDd delta 1458 zcmeBP!?<-0qY(3FUal?S3Bkz>P{6uTNS=>h3CMG{iV3JJ$;i($GM{Y7FEP1_uMJ&% zvmyUW7IeYMi82zClSMvahyxATJXiEPBZdS>!(H)(7~&ue$0hz_Y5+;_ODkeZB+7(g zm;y9?l580^;mP}D^RbGT%jIGf*Okx1D*i+syZMV1FwJpP#0W-khzTfRcgqQ-Vyt$y zC}X$NS)~Z8`hP0e-M&>7(~Y1A$yQ6pX3l15^=xe6E;ISEMkf{xGLu(ox?&NRm~5_< zgH`;E7FGvsUZgFFX|W-{%w!JTWf%s566|-~;~3%~pRwy>_t|#++t@6S*nHbC2CKy6 z24hSwfYPR^Nj)=GtN)s>#1IF0;j_he4Dm!6naSo>Qj9El+#(F=7 z9LSR`HZ9o1HwW5=VfqE6;e*{9Y#Ju3I;_GbzFERC7rQ~{oK9fVF!{doI;`T?T(Yr> zce%!371wuj!Y00XmzyD`gMfj%*}_8=Qv&4WWu9&rCV|4$)C+r-`{;$~1CaU`-dC`h gvzgV`6uZUEeh)D;03Eb>t^YR6;uPeC4I$Bt0GgtlK>z>% diff --git a/PythonHome/Lib/ctypes/_endian.py b/PythonHome/Lib/ctypes/_endian.py new file mode 100644 index 0000000000..f80e675aaf --- /dev/null +++ b/PythonHome/Lib/ctypes/_endian.py @@ -0,0 +1,64 @@ +###################################################################### +# This file should be kept compatible with Python 2.3, see PEP 291. # +###################################################################### +import sys +from ctypes import * + +_array_type = type(Array) + +def _other_endian(typ): + """Return the type with the 'other' byte order. Simple types like + c_int and so on already have __ctype_be__ and __ctype_le__ + attributes which contain the types, for more complicated types + arrays and structures are supported. + """ + # check _OTHER_ENDIAN attribute (present if typ is primitive type) + if hasattr(typ, _OTHER_ENDIAN): + return getattr(typ, _OTHER_ENDIAN) + # if typ is array + if isinstance(typ, _array_type): + return _other_endian(typ._type_) * typ._length_ + # if typ is structure + if issubclass(typ, Structure): + return typ + raise TypeError("This type does not support other endian: %s" % typ) + +class _swapped_meta(type(Structure)): + def __setattr__(self, attrname, value): + if attrname == "_fields_": + fields = [] + for desc in value: + name = desc[0] + typ = desc[1] + rest = desc[2:] + fields.append((name, _other_endian(typ)) + rest) + value = fields + super(_swapped_meta, self).__setattr__(attrname, value) + +################################################################ + +# Note: The Structure metaclass checks for the *presence* (not the +# value!) of a _swapped_bytes_ attribute to determine the bit order in +# structures containing bit fields. + +if sys.byteorder == "little": + _OTHER_ENDIAN = "__ctype_be__" + + LittleEndianStructure = Structure + + class BigEndianStructure(Structure): + """Structure with big endian byte order""" + __metaclass__ = _swapped_meta + _swappedbytes_ = None + +elif sys.byteorder == "big": + _OTHER_ENDIAN = "__ctype_le__" + + BigEndianStructure = Structure + class LittleEndianStructure(Structure): + """Structure with little endian byte order""" + __metaclass__ = _swapped_meta + _swappedbytes_ = None + +else: + raise RuntimeError("Invalid byteorder") diff --git a/PythonHome/Lib/ctypes/_endian.pyc b/PythonHome/Lib/ctypes/_endian.pyc index f135dabc1102c051e38766eb039cf496cbd05695..0a6da991a04664225d176b682c5b8271ca7d98dc 100644 GIT binary patch delta 352 zcmaDVxKVgR2(zIx0|P^On82Uo>#EHUr>N^jDKlKL1{^hOKMVSdQ3oN yNk)F2M}BVVzkLVWRXr8N^wT1v_9xPPQ*#2Dz@SXx@22-Pwt~LX&#Zf encs`uu$7bQk|UG5)uW zZ`YdA{VC!9ZG85w5eY>$Q5p#g(l)XQ0)Itm7i706n?*6Km!w^i-Lh$6pHcipdEVAZl@jO zahi_*ShY^NS4t<<%TqaD-Y#y}e$##EmS-4(68+x3P8#9mlm_V*6^8lbPfCXV|}XVDo7AxbCv<2c|8LHQ%w> zd^>Fh?RhrQ%9I%E^~H@Q`Q%r`w}{VrC~}eKD2=>?TxUsdLlvkRSwm&5R^UhuUrlo_ zXt%wz<$ZN~t3W; z@?53zq9D&9Avf&0Jb{c*-!2^rO$D}!*&;V;)RG>0HBF+Nd!<&-86{8SEKPE<@C1V4 zK)ctDb0--#V~BP?4KiIKdm6Ndk^q%YY1FY2C)z3sF;)Cd;wzb+Mf8Ml4FldRgsy3H zPk9>Sm%dq9s^7i0@S8jJwTH{gcfYPt%RV>rCs@!x{Yez6N}qFvItM4{IpW>mNmRF; zRx95B42@2odZ6A>C^^+9w|2%&mI)F(12(iiuS^4JsW%H1#g1^=6O!(mU3a1)|bo&0_NHvG+El9S=W%E}iD zi(l5?u`s!T6DAO+5j1z|uS@mUZ^Jba^>wb_sd%~k>pTz2`PKl(Gza=f&klZ$3T<@| zUD^M#CSO4qoXsrvq!0NZ0BZf4C+oLpCEavQ8g~{QHbY39nN1R$2`M! z8Ye#8K^5ExY@`#}<$uJ2a@FLj=hZ$Z4<%qiwF)>zijl=30)qvFPQ|3x( z%7uHnT~EBXQNdyRR(+Gw2@%#I;hPjMB0eOFMhruIcGiAHMFW9i4kLr2+ec%oMA-_V=0EU(fhnlx2TTo|iEX zR`~k7W36yYHn^Ts%=g@}ntji`VO&49_g{5yY-UfG{h!g~{@-2yr8E0VR=cecI0j6A zmQ_u0`s%#QHfk)_aC2vQ;o-`If$+H8jhH$8W~tkK7>5o!)p+`@;(yHbrctzx4~ObK z`MJRXgRy5Q1M1~5Vblsb?YwI^$aBT=aAL{@I#v|`dIkR{%!h?3rAJUUix^SDN6cNs zXa9tvZ%vMNan8v81I7{f8Z-~HgP!4DfDqD(Lh!p@`%48j3|M+RtN1k{+oQblG8`Jo z?vq&i?!Ih5&+t}EY#BL^u0O!BnE;YEdjrL|ho5C!;Jm==3d%zW?V*v^!L8(pM?dO^ zNu6Z7{uMX8Yu0O~9gIkDF=|9!E5#*f)!B#|$~B%`U27`R74)`NB@x|3yT<{}Yc!T*$nhNG*XhEb@`Q{x)ruBcL?<|>*q^B#1@j5(c=PeQ>W zNB$GV!Aw7WCNk=^=cOsEZ6s4tg4%Y*C7TxmATWuMuOV*U990+a>*u%-mGrV6cD2he zrmDr5>+W6!RU=|;BQQZyj@A%_$({>C821K7rhAP1LyR%dKU7U-!ZOs&iHV<|p4BPAEp6xWZyujYjPMVav3?He^^|t)M zj`?+5p7C5^=NCI!h9pi$_LZ*5LVum^qsADHrrPy+$xutn^i{%R#}Qnj$++t%!(c1v zFRoWrXL_yOXM7k5qy3>QjQ;*-e3psXL#WO(ts@}lkI9!&Y0}4y6uY0wAoe5hzTclPbDt9v;J`)7M0|!NqSnnm!UOSQ}-0esW&SBM*P;<*hl7Y+l!BPQCsGEt*1$ z88H`(CRg?PF0iFuug!9}Cc5=7ZPx2f{|p=&u+%!RQrytzDowtaU*~Dsb}th3I${gv zUFAZ=uV{Y{&p90&#h>Fc^DGqD&XUsPPm^ZN0I7PPO!yiBiG4>AkMi+pD?YDpUG|w7 zf_*d$g=#wc=588x+R-g_^qW{=1o7w;e#eU=raCeSyDOSXsr$cJ8L5m_%hh7{_hj{S Qb+meZa&mIIQm&f+0?cV)@Bjb+ diff --git a/PythonHome/Lib/ctypes/macholib/dylib.py b/PythonHome/Lib/ctypes/macholib/dylib.py new file mode 100644 index 0000000000..ea3dd38bdf --- /dev/null +++ b/PythonHome/Lib/ctypes/macholib/dylib.py @@ -0,0 +1,66 @@ +###################################################################### +# This file should be kept compatible with Python 2.3, see PEP 291. # +###################################################################### +""" +Generic dylib path manipulation +""" + +import re + +__all__ = ['dylib_info'] + +DYLIB_RE = re.compile(r"""(?x) +(?P^.*)(?:^|/) +(?P + (?P\w+?) + (?:\.(?P[^._]+))? + (?:_(?P[^._]+))? + \.dylib$ +) +""") + +def dylib_info(filename): + """ + A dylib name can take one of the following four forms: + Location/Name.SomeVersion_Suffix.dylib + Location/Name.SomeVersion.dylib + Location/Name_Suffix.dylib + Location/Name.dylib + + returns None if not found or a mapping equivalent to: + dict( + location='Location', + name='Name.SomeVersion_Suffix.dylib', + shortname='Name', + version='SomeVersion', + suffix='Suffix', + ) + + Note that SomeVersion and Suffix are optional and may be None + if not present. + """ + is_dylib = DYLIB_RE.match(filename) + if not is_dylib: + return None + return is_dylib.groupdict() + + +def test_dylib_info(): + def d(location=None, name=None, shortname=None, version=None, suffix=None): + return dict( + location=location, + name=name, + shortname=shortname, + version=version, + suffix=suffix + ) + assert dylib_info('completely/invalid') is None + assert dylib_info('completely/invalide_debug') is None + assert dylib_info('P/Foo.dylib') == d('P', 'Foo.dylib', 'Foo') + assert dylib_info('P/Foo_debug.dylib') == d('P', 'Foo_debug.dylib', 'Foo', suffix='debug') + assert dylib_info('P/Foo.A.dylib') == d('P', 'Foo.A.dylib', 'Foo', 'A') + assert dylib_info('P/Foo_debug.A.dylib') == d('P', 'Foo_debug.A.dylib', 'Foo_debug', 'A') + assert dylib_info('P/Foo.A_debug.dylib') == d('P', 'Foo.A_debug.dylib', 'Foo', 'A', 'debug') + +if __name__ == '__main__': + test_dylib_info() diff --git a/PythonHome/Lib/ctypes/macholib/dylib.pyc b/PythonHome/Lib/ctypes/macholib/dylib.pyc deleted file mode 100644 index 05973c2ae4b7c43843ddebca4dc95649bbbbcf9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2255 zcmb7F&2HO95FXN!Y$^VUouF`gC|ERwsHBjSs}b9E)AR>01cL%nBvsAQ-6cN%6NuI~Dph$LI?-7YA3Kx4jGS?h#*=9hm^e#Y@!$CLOpASCh##lJO#h0d zyZ5Hka`z4&Cs`=i-J|aPj=Q&gbiP$=q`_G2wj6vIrbk(BL^XK*V6Ri^w+CI`e5G=Y z>vn%Q>iR!E=ydjG+rF4ihr{^Iwar0S9J<%)v_cF1FmF7bVCYXF4AD!A&WQ!L8bwp$j) zPP;v&g9UR2RgV3B!lpc(OaFpTw4FuVpoOulX07J72ba%~aST!r;IlqQQj3*d+ z11ofqD}NTftJ7P!B7FtV1G}e7q#u&8=@(1%cp!8Aw-vqg8$2rX8*~~pn2QDOF*>PW zme{t$G#L}MD7pot#mL_($mI%hMUbm>QIiAzsKC}Lu-g=^Q#6PDS%Ga-V0X&X_};o4 zxM~&AA=tiq7u@thP8g3{7<~-=83g(Ux&*s#bJIY>J-4~fo}=5==^O-5z3(=F>`D4& zZ$gqTN#&%^%i3@%$}%==Rn)7?SrQYe4EDlfq{r#>_ymueuE(z3s4$RJxc&%2FGCRO zV)oS=Sclnok|?8+v#mJAqmLuB#eY*PKT^lj6U`nRZhf6)MPHKh4>fyusaq&kdVPj1 zYzqs$R_s=F5|=!f;*yn_VRyeY;%oVWaxK^H>pL@CdDsli7Xy7&E3a>^y|nG_S6vaO z<)*6E<&ZoPn2=e8*w9`H@+Vv2~<4i6r;g-TnW-AJTCY0EUr+T k1;q{h=E8hD&Z23ecBPKl;fB3zH|@q!({6s$Twk{S0dJHNi~s-t diff --git a/PythonHome/Lib/ctypes/macholib/framework.py b/PythonHome/Lib/ctypes/macholib/framework.py new file mode 100644 index 0000000000..dd7fb2f296 --- /dev/null +++ b/PythonHome/Lib/ctypes/macholib/framework.py @@ -0,0 +1,68 @@ +###################################################################### +# This file should be kept compatible with Python 2.3, see PEP 291. # +###################################################################### +""" +Generic framework path manipulation +""" + +import re + +__all__ = ['framework_info'] + +STRICT_FRAMEWORK_RE = re.compile(r"""(?x) +(?P^.*)(?:^|/) +(?P + (?P\w+).framework/ + (?:Versions/(?P[^/]+)/)? + (?P=shortname) + (?:_(?P[^_]+))? +)$ +""") + +def framework_info(filename): + """ + A framework name can take one of the following four forms: + Location/Name.framework/Versions/SomeVersion/Name_Suffix + Location/Name.framework/Versions/SomeVersion/Name + Location/Name.framework/Name_Suffix + Location/Name.framework/Name + + returns None if not found, or a mapping equivalent to: + dict( + location='Location', + name='Name.framework/Versions/SomeVersion/Name_Suffix', + shortname='Name', + version='SomeVersion', + suffix='Suffix', + ) + + Note that SomeVersion and Suffix are optional and may be None + if not present + """ + is_framework = STRICT_FRAMEWORK_RE.match(filename) + if not is_framework: + return None + return is_framework.groupdict() + +def test_framework_info(): + def d(location=None, name=None, shortname=None, version=None, suffix=None): + return dict( + location=location, + name=name, + shortname=shortname, + version=version, + suffix=suffix + ) + assert framework_info('completely/invalid') is None + assert framework_info('completely/invalid/_debug') is None + assert framework_info('P/F.framework') is None + assert framework_info('P/F.framework/_debug') is None + assert framework_info('P/F.framework/F') == d('P', 'F.framework/F', 'F') + assert framework_info('P/F.framework/F_debug') == d('P', 'F.framework/F_debug', 'F', suffix='debug') + assert framework_info('P/F.framework/Versions') is None + assert framework_info('P/F.framework/Versions/A') is None + assert framework_info('P/F.framework/Versions/A/F') == d('P', 'F.framework/Versions/A/F', 'F', 'A') + assert framework_info('P/F.framework/Versions/A/F_debug') == d('P', 'F.framework/Versions/A/F_debug', 'F', 'A', 'debug') + +if __name__ == '__main__': + test_framework_info() diff --git a/PythonHome/Lib/ctypes/macholib/framework.pyc b/PythonHome/Lib/ctypes/macholib/framework.pyc deleted file mode 100644 index 17ece65d9f9650fbc57df92ebc55139d83d80883..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2565 zcmbVO;Z7Sz5S}yGfCC{-XhkZuI<=`dClQz5C_pWQ(<-Tp&QT(zl*@6qh70FA_jVmX zfL!vAyfr*>7iOXTO=di9hG+zde81390y0@c%WM zeuge0dV$`es6vTFFCa|N9)t=hi(XAoG)ZR|PEu5*Hvm^Ds)2~3=&_4sdm+U7d&W0)VO z-Aw-qm9u`-s5|Rh50fku{Myd)-G;NivUB1NCsLSRtK0Z6Oz&s85!LqLy~gs`qFW$V zo~c}8TkSIX^>DEE!;bsoy@uOZAK6(Q+i8pz`eJ_2?Z!vI`@jRDwIX4kQE?;p#ZNK%b(QEt;h$@d4~GNNp1wC_78hy0+O@b~j6s z>@ZIEAPsVKc~7s%at^?gB1Uc->q}=JpShFuR51{Y-;witxPkYsWKaI@E{v^<#ax*| zo@%?zM~}O9ni)QD8r`?E+zvpXexHM&ej3EDgG8mqHraU`qBu0p*foyKh&`)IqZlpS zzX0HfuP$9NZkKF~IWshLX|~|n>Qd11`zUJnrsZi($0(m4FY4AY}i2>*~1lf zkb^0GPOBgheJ?n+ca_9Zj$6dCpDT@^iK^{PGGA|@>pb;~Oq?c+};9r*X)e`=wq(|A497iFHrYV}Cvk9(<`j-->Ucy{s zOf*Z;9FP_xe=i}gmv;H1q@OS8|0?Nklq`QFmT%J8q&V=Ib$-}eCD=j%V+X2&d{iKD z>W=d!3*~M?FLJLOnx;M+w7o;-tclhZ8&`s&sv#Rf!{%?Eg}`ex!B>dwLGDTW;&T(CUTDnh|vVUlT2HXG@HfOt?dR zOY>b^Fz&XBZ8=jftQhJgD3Y#2?>K)h8W=qW^x|8m+@}8Y9g}WL)|Pi48Fib5>rHLH z(?W5I&jEUyogu`T0K}6H0?8XfQ)`uTecR0QEEl?Xd<|D814q#)ZO+S-ymYuwYYrV* zi_?qN@O#I)E7FoB-1hxm5U0K`FFL|x-;c7;_mOl&cy=*meLqMNs90uZp*VU>K&fq> t?9Qb2eNGP8g8TueU=t5}Su{x0nxxSUC~B42%1os;JyV&vJ+m-t{R66ydaVEe diff --git a/PythonHome/Lib/ctypes/util.py b/PythonHome/Lib/ctypes/util.py new file mode 100644 index 0000000000..fe0ed0a085 --- /dev/null +++ b/PythonHome/Lib/ctypes/util.py @@ -0,0 +1,276 @@ +###################################################################### +# This file should be kept compatible with Python 2.3, see PEP 291. # +###################################################################### +import sys, os + +# find_library(name) returns the pathname of a library, or None. +if os.name == "nt": + + def _get_build_version(): + """Return the version of MSVC that was used to build Python. + + For Python 2.3 and up, the version number is included in + sys.version. For earlier versions, assume the compiler is MSVC 6. + """ + # This function was copied from Lib/distutils/msvccompiler.py + prefix = "MSC v." + i = sys.version.find(prefix) + if i == -1: + return 6 + i = i + len(prefix) + s, rest = sys.version[i:].split(" ", 1) + majorVersion = int(s[:-2]) - 6 + minorVersion = int(s[2:3]) / 10.0 + # I don't think paths are affected by minor version in version 6 + if majorVersion == 6: + minorVersion = 0 + if majorVersion >= 6: + return majorVersion + minorVersion + # else we don't know what version of the compiler this is + return None + + def find_msvcrt(): + """Return the name of the VC runtime dll""" + version = _get_build_version() + if version is None: + # better be safe than sorry + return None + if version <= 6: + clibname = 'msvcrt' + else: + clibname = 'msvcr%d' % (version * 10) + + # If python was built with in debug mode + import imp + if imp.get_suffixes()[0][0] == '_d.pyd': + clibname += 'd' + return clibname+'.dll' + + def find_library(name): + if name in ('c', 'm'): + return find_msvcrt() + # See MSDN for the REAL search order. + for directory in os.environ['PATH'].split(os.pathsep): + fname = os.path.join(directory, name) + if os.path.isfile(fname): + return fname + if fname.lower().endswith(".dll"): + continue + fname = fname + ".dll" + if os.path.isfile(fname): + return fname + return None + +if os.name == "ce": + # search path according to MSDN: + # - absolute path specified by filename + # - The .exe launch directory + # - the Windows directory + # - ROM dll files (where are they?) + # - OEM specified search path: HKLM\Loader\SystemPath + def find_library(name): + return name + +if os.name == "posix" and sys.platform == "darwin": + from ctypes.macholib.dyld import dyld_find as _dyld_find + def find_library(name): + possible = ['lib%s.dylib' % name, + '%s.dylib' % name, + '%s.framework/%s' % (name, name)] + for name in possible: + try: + return _dyld_find(name) + except ValueError: + continue + return None + +elif os.name == "posix": + # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump + import re, tempfile, errno + + def _findLib_gcc(name): + expr = r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name) + fdout, ccout = tempfile.mkstemp() + os.close(fdout) + cmd = 'if type gcc >/dev/null 2>&1; then CC=gcc; elif type cc >/dev/null 2>&1; then CC=cc;else exit 10; fi;' \ + 'LANG=C LC_ALL=C $CC -Wl,-t -o ' + ccout + ' 2>&1 -l' + name + try: + f = os.popen(cmd) + try: + trace = f.read() + finally: + rv = f.close() + finally: + try: + os.unlink(ccout) + except OSError, e: + if e.errno != errno.ENOENT: + raise + if rv == 10: + raise OSError, 'gcc or cc command not found' + res = re.search(expr, trace) + if not res: + return None + return res.group(0) + + + if sys.platform == "sunos5": + # use /usr/ccs/bin/dump on solaris + def _get_soname(f): + if not f: + return None + cmd = "/usr/ccs/bin/dump -Lpv 2>/dev/null " + f + f = os.popen(cmd) + try: + data = f.read() + finally: + f.close() + res = re.search(r'\[.*\]\sSONAME\s+([^\s]+)', data) + if not res: + return None + return res.group(1) + else: + def _get_soname(f): + # assuming GNU binutils / ELF + if not f: + return None + cmd = 'if ! type objdump >/dev/null 2>&1; then exit 10; fi;' \ + "objdump -p -j .dynamic 2>/dev/null " + f + f = os.popen(cmd) + dump = f.read() + rv = f.close() + if rv == 10: + raise OSError, 'objdump command not found' + f = os.popen(cmd) + try: + data = f.read() + finally: + f.close() + res = re.search(r'\sSONAME\s+([^\s]+)', data) + if not res: + return None + return res.group(1) + + if (sys.platform.startswith("freebsd") + or sys.platform.startswith("openbsd") + or sys.platform.startswith("dragonfly")): + + def _num_version(libname): + # "libxyz.so.MAJOR.MINOR" => [ MAJOR, MINOR ] + parts = libname.split(".") + nums = [] + try: + while parts: + nums.insert(0, int(parts.pop())) + except ValueError: + pass + return nums or [ sys.maxint ] + + def find_library(name): + ename = re.escape(name) + expr = r':-l%s\.\S+ => \S*/(lib%s\.\S+)' % (ename, ename) + f = os.popen('/sbin/ldconfig -r 2>/dev/null') + try: + data = f.read() + finally: + f.close() + res = re.findall(expr, data) + if not res: + return _get_soname(_findLib_gcc(name)) + res.sort(cmp= lambda x,y: cmp(_num_version(x), _num_version(y))) + return res[-1] + + elif sys.platform == "sunos5": + + def _findLib_crle(name, is64): + if not os.path.exists('/usr/bin/crle'): + return None + + if is64: + cmd = 'env LC_ALL=C /usr/bin/crle -64 2>/dev/null' + else: + cmd = 'env LC_ALL=C /usr/bin/crle 2>/dev/null' + + for line in os.popen(cmd).readlines(): + line = line.strip() + if line.startswith('Default Library Path (ELF):'): + paths = line.split()[4] + + if not paths: + return None + + for dir in paths.split(":"): + libfile = os.path.join(dir, "lib%s.so" % name) + if os.path.exists(libfile): + return libfile + + return None + + def find_library(name, is64 = False): + return _get_soname(_findLib_crle(name, is64) or _findLib_gcc(name)) + + else: + + def _findSoname_ldconfig(name): + import struct + if struct.calcsize('l') == 4: + machine = os.uname()[4] + '-32' + else: + machine = os.uname()[4] + '-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', + } + abi_type = mach_map.get(machine, 'libc6') + + # XXX assuming GLIBC's ldconfig (with option -p) + expr = r'\s+(lib%s\.[^\s]+)\s+\(%s' % (re.escape(name), abi_type) + f = os.popen('/sbin/ldconfig -p 2>/dev/null') + try: + data = f.read() + finally: + f.close() + res = re.search(expr, data) + if not res: + return None + return res.group(1) + + def find_library(name): + return _findSoname_ldconfig(name) or _get_soname(_findLib_gcc(name)) + +################################################################ +# test code + +def test(): + from ctypes import cdll + if os.name == "nt": + print cdll.msvcrt + print cdll.load("msvcrt") + print find_library("msvcrt") + + if os.name == "posix": + # find and load_version + print find_library("m") + print find_library("c") + print find_library("bz2") + + # getattr +## print cdll.m +## print cdll.bz2 + + # load + if sys.platform == "darwin": + print cdll.LoadLibrary("libm.dylib") + print cdll.LoadLibrary("libcrypto.dylib") + print cdll.LoadLibrary("libSystem.dylib") + print cdll.LoadLibrary("System.framework/System") + else: + print cdll.LoadLibrary("libm.so") + print cdll.LoadLibrary("libcrypt.so") + print find_library("crypt") + +if __name__ == "__main__": + test() diff --git a/PythonHome/Lib/ctypes/util.pyc b/PythonHome/Lib/ctypes/util.pyc index b5a3040a50fd6d2dca1d3e8c588153d7da2a27aa..89129a4d683ac1008d023f9e77cfe5f3345d41fc 100644 GIT binary patch delta 1026 zcmaE5yT(a~`7 znaI*AGWmwsVzP7!Z=Nf@l{`z+7+EHtkP0W$T1ROk@~jn^JWciqS(b`So-5}I0I14f AFaQ7m delta 448 zcmZ4E^vYI<`7EpIa|d9RF-7q=NXw#{wN}{xre2T5vxQr z+d8Zgll?e~&^2uS$YF~`F^9zFaxQjebk!hxC)*3NZa%@Ai$xdEQC0k(u}E-;Y~Cd3 zfkgtS!(O-%o5W&FyMd0nE9%FDDFJj;fdqC9F_IgwYY3DHVq~7YL?#^5IG{Z)vbxx{ QZIge3sX;_?@)HFQ0Ej7q;s5{u diff --git a/PythonHome/Lib/ctypes/wintypes.py b/PythonHome/Lib/ctypes/wintypes.py new file mode 100644 index 0000000000..dafbb78b78 --- /dev/null +++ b/PythonHome/Lib/ctypes/wintypes.py @@ -0,0 +1,185 @@ +###################################################################### +# This file should be kept compatible with Python 2.3, see PEP 291. # +###################################################################### + +# The most useful windows datatypes +from ctypes import * + +BYTE = c_byte +WORD = c_ushort +DWORD = c_ulong + +WCHAR = c_wchar +UINT = c_uint +INT = c_int + +DOUBLE = c_double +FLOAT = c_float + +BOOLEAN = BYTE +BOOL = c_long + +from ctypes import _SimpleCData +class VARIANT_BOOL(_SimpleCData): + _type_ = "v" + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self.value) + +ULONG = c_ulong +LONG = c_long + +USHORT = c_ushort +SHORT = c_short + +# in the windows header files, these are structures. +_LARGE_INTEGER = LARGE_INTEGER = c_longlong +_ULARGE_INTEGER = ULARGE_INTEGER = c_ulonglong + +LPCOLESTR = LPOLESTR = OLESTR = c_wchar_p +LPCWSTR = LPWSTR = c_wchar_p +LPCSTR = LPSTR = c_char_p +LPCVOID = LPVOID = c_void_p + +# WPARAM is defined as UINT_PTR (unsigned type) +# LPARAM is defined as LONG_PTR (signed type) +if sizeof(c_long) == sizeof(c_void_p): + WPARAM = c_ulong + LPARAM = c_long +elif sizeof(c_longlong) == sizeof(c_void_p): + WPARAM = c_ulonglong + LPARAM = c_longlong + +ATOM = WORD +LANGID = WORD + +COLORREF = DWORD +LGRPID = DWORD +LCTYPE = DWORD + +LCID = DWORD + +################################################################ +# HANDLE types +HANDLE = c_void_p # in the header files: void * + +HACCEL = HANDLE +HBITMAP = HANDLE +HBRUSH = HANDLE +HCOLORSPACE = HANDLE +HDC = HANDLE +HDESK = HANDLE +HDWP = HANDLE +HENHMETAFILE = HANDLE +HFONT = HANDLE +HGDIOBJ = HANDLE +HGLOBAL = HANDLE +HHOOK = HANDLE +HICON = HANDLE +HINSTANCE = HANDLE +HKEY = HANDLE +HKL = HANDLE +HLOCAL = HANDLE +HMENU = HANDLE +HMETAFILE = HANDLE +HMODULE = HANDLE +HMONITOR = HANDLE +HPALETTE = HANDLE +HPEN = HANDLE +HRGN = HANDLE +HRSRC = HANDLE +HSTR = HANDLE +HTASK = HANDLE +HWINSTA = HANDLE +HWND = HANDLE +SC_HANDLE = HANDLE +SERVICE_STATUS_HANDLE = HANDLE + +################################################################ +# Some important structure definitions + +class RECT(Structure): + _fields_ = [("left", c_long), + ("top", c_long), + ("right", c_long), + ("bottom", c_long)] +tagRECT = _RECTL = RECTL = RECT + +class _SMALL_RECT(Structure): + _fields_ = [('Left', c_short), + ('Top', c_short), + ('Right', c_short), + ('Bottom', c_short)] +SMALL_RECT = _SMALL_RECT + +class _COORD(Structure): + _fields_ = [('X', c_short), + ('Y', c_short)] + +class POINT(Structure): + _fields_ = [("x", c_long), + ("y", c_long)] +tagPOINT = _POINTL = POINTL = POINT + +class SIZE(Structure): + _fields_ = [("cx", c_long), + ("cy", c_long)] +tagSIZE = SIZEL = SIZE + +def RGB(red, green, blue): + return red + (green << 8) + (blue << 16) + +class FILETIME(Structure): + _fields_ = [("dwLowDateTime", DWORD), + ("dwHighDateTime", DWORD)] +_FILETIME = FILETIME + +class MSG(Structure): + _fields_ = [("hWnd", HWND), + ("message", c_uint), + ("wParam", WPARAM), + ("lParam", LPARAM), + ("time", DWORD), + ("pt", POINT)] +tagMSG = MSG +MAX_PATH = 260 + +class WIN32_FIND_DATAA(Structure): + _fields_ = [("dwFileAttributes", DWORD), + ("ftCreationTime", FILETIME), + ("ftLastAccessTime", FILETIME), + ("ftLastWriteTime", FILETIME), + ("nFileSizeHigh", DWORD), + ("nFileSizeLow", DWORD), + ("dwReserved0", DWORD), + ("dwReserved1", DWORD), + ("cFileName", c_char * MAX_PATH), + ("cAlternateFileName", c_char * 14)] + +class WIN32_FIND_DATAW(Structure): + _fields_ = [("dwFileAttributes", DWORD), + ("ftCreationTime", FILETIME), + ("ftLastAccessTime", FILETIME), + ("ftLastWriteTime", FILETIME), + ("nFileSizeHigh", DWORD), + ("nFileSizeLow", DWORD), + ("dwReserved0", DWORD), + ("dwReserved1", DWORD), + ("cFileName", c_wchar * MAX_PATH), + ("cAlternateFileName", c_wchar * 14)] + +__all__ = ['ATOM', 'BOOL', 'BOOLEAN', 'BYTE', 'COLORREF', 'DOUBLE', 'DWORD', + 'FILETIME', 'FLOAT', 'HACCEL', 'HANDLE', 'HBITMAP', 'HBRUSH', + 'HCOLORSPACE', 'HDC', 'HDESK', 'HDWP', 'HENHMETAFILE', 'HFONT', + 'HGDIOBJ', 'HGLOBAL', 'HHOOK', 'HICON', 'HINSTANCE', 'HKEY', + 'HKL', 'HLOCAL', 'HMENU', 'HMETAFILE', 'HMODULE', 'HMONITOR', + 'HPALETTE', 'HPEN', 'HRGN', 'HRSRC', 'HSTR', 'HTASK', 'HWINSTA', + 'HWND', 'INT', 'LANGID', 'LARGE_INTEGER', 'LCID', 'LCTYPE', + 'LGRPID', 'LONG', 'LPARAM', 'LPCOLESTR', 'LPCSTR', 'LPCVOID', + 'LPCWSTR', 'LPOLESTR', 'LPSTR', 'LPVOID', 'LPWSTR', 'MAX_PATH', + 'MSG', 'OLESTR', 'POINT', 'POINTL', 'RECT', 'RECTL', 'RGB', + 'SC_HANDLE', 'SERVICE_STATUS_HANDLE', 'SHORT', 'SIZE', 'SIZEL', + 'SMALL_RECT', 'UINT', 'ULARGE_INTEGER', 'ULONG', 'USHORT', + 'VARIANT_BOOL', 'WCHAR', 'WIN32_FIND_DATAA', 'WIN32_FIND_DATAW', + 'WORD', 'WPARAM', '_COORD', '_FILETIME', '_LARGE_INTEGER', + '_POINTL', '_RECTL', '_SMALL_RECT', '_ULARGE_INTEGER', 'tagMSG', + 'tagPOINT', 'tagRECT', 'tagSIZE'] diff --git a/PythonHome/Lib/ctypes/wintypes.pyc b/PythonHome/Lib/ctypes/wintypes.pyc deleted file mode 100644 index e4e184ba5d99339308bc2ed04d7f7192f915e697..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5890 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 diff --git a/PythonHome/Lib/curses/ascii.py b/PythonHome/Lib/curses/ascii.py new file mode 100644 index 0000000000..800fd8b4b7 --- /dev/null +++ b/PythonHome/Lib/curses/ascii.py @@ -0,0 +1,99 @@ +"""Constants and membership tests for ASCII characters""" + +NUL = 0x00 # ^@ +SOH = 0x01 # ^A +STX = 0x02 # ^B +ETX = 0x03 # ^C +EOT = 0x04 # ^D +ENQ = 0x05 # ^E +ACK = 0x06 # ^F +BEL = 0x07 # ^G +BS = 0x08 # ^H +TAB = 0x09 # ^I +HT = 0x09 # ^I +LF = 0x0a # ^J +NL = 0x0a # ^J +VT = 0x0b # ^K +FF = 0x0c # ^L +CR = 0x0d # ^M +SO = 0x0e # ^N +SI = 0x0f # ^O +DLE = 0x10 # ^P +DC1 = 0x11 # ^Q +DC2 = 0x12 # ^R +DC3 = 0x13 # ^S +DC4 = 0x14 # ^T +NAK = 0x15 # ^U +SYN = 0x16 # ^V +ETB = 0x17 # ^W +CAN = 0x18 # ^X +EM = 0x19 # ^Y +SUB = 0x1a # ^Z +ESC = 0x1b # ^[ +FS = 0x1c # ^\ +GS = 0x1d # ^] +RS = 0x1e # ^^ +US = 0x1f # ^_ +SP = 0x20 # space +DEL = 0x7f # delete + +controlnames = [ +"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", +"BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", +"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", +"CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US", +"SP" +] + +def _ctoi(c): + if type(c) == type(""): + return ord(c) + else: + return c + +def isalnum(c): return isalpha(c) or isdigit(c) +def isalpha(c): return isupper(c) or islower(c) +def isascii(c): return _ctoi(c) <= 127 # ? +def isblank(c): return _ctoi(c) in (8,32) +def iscntrl(c): return _ctoi(c) <= 31 +def isdigit(c): return _ctoi(c) >= 48 and _ctoi(c) <= 57 +def isgraph(c): return _ctoi(c) >= 33 and _ctoi(c) <= 126 +def islower(c): return _ctoi(c) >= 97 and _ctoi(c) <= 122 +def isprint(c): return _ctoi(c) >= 32 and _ctoi(c) <= 126 +def ispunct(c): return _ctoi(c) != 32 and not isalnum(c) +def isspace(c): return _ctoi(c) in (9, 10, 11, 12, 13, 32) +def isupper(c): return _ctoi(c) >= 65 and _ctoi(c) <= 90 +def isxdigit(c): return isdigit(c) or \ + (_ctoi(c) >= 65 and _ctoi(c) <= 70) or (_ctoi(c) >= 97 and _ctoi(c) <= 102) +def isctrl(c): return _ctoi(c) < 32 +def ismeta(c): return _ctoi(c) > 127 + +def ascii(c): + if type(c) == type(""): + return chr(_ctoi(c) & 0x7f) + else: + return _ctoi(c) & 0x7f + +def ctrl(c): + if type(c) == type(""): + return chr(_ctoi(c) & 0x1f) + else: + return _ctoi(c) & 0x1f + +def alt(c): + if type(c) == type(""): + return chr(_ctoi(c) | 0x80) + else: + return _ctoi(c) | 0x80 + +def unctrl(c): + bits = _ctoi(c) + if bits == 0x7f: + rep = "^?" + elif isprint(bits & 0x7f): + rep = chr(bits & 0x7f) + else: + rep = "^" + chr(((bits & 0x7f) | 0x20) + 0x20) + if bits & 0x80: + return "!" + rep + return rep diff --git a/PythonHome/Lib/curses/ascii.pyc b/PythonHome/Lib/curses/ascii.pyc deleted file mode 100644 index f1040e365166628405b75ce29c9cf55e95b9f27f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4775 zcmcIn30D+H5dLNt5D-sLP*E4-vEFBHqp%C85m)WOtDjG@Zmlv;*xffXlYkRJFR$Ts+GkY4y+NFRJ3q#wTDa64o>{D9#O$N>CK$PV~jke%?m zA-mxBKz76Lh3tVJgzSYMf(*j%gABp%hwOtNhU|wQfegbRfQ-N&gdBiB1UU#l3ONLS z7%~cf1acVuDC7uy0df?63{rqU1{s6@0CEieI79`-6OfaTQ;;I$G~^8AEaV*IJmdo8 zBIFX}GUN*6D&!jEL&!&vk0GBxK81V+`5bZ`@&)7u(?J0>WHFHKM;cTG?}GbSjjdnPEiiV4c_z6r|nfeFg?p$W>_ znV`%=6O{j~2|9~MCg@xqo1im#VuH@=DZ=72I>J?ja7%6F|TP0gg7Un#Wa_N+BC)7CuB?xwT5va`JaOgW;LT#>%ma4$@Qo;(s<#s^|c?jo?K=hu3yC*KjKt2O3Izmk3ZLIowax`He)(Y^wTETv|Z+PTy4!?-y%{~lKOrV zq#UE%7hA-ppyO=C61C!}k=|IJ6i=^JUX(|3bUEw|w1aWBow&PfJ2?ip4ej#QQlpmM zT*HU4&;s!4J+&>{<=oJf^$+ucJ}%nHzwUW&uWT+FB&}+#KCY^^Vh2pC#h+~ouqob-f2H7(1sD=nzTHMe3ew%n1WRdy7(F&!v7uX*n* za8s(y#~WEWdW0R_w^ZolRzu6V)&DdDJ7GIBa369m8#w8iK+x>>wvc`4@9SS$v;M!R zy5i>9bA;+b8oq-(A8~SJKKojs<2*lV!mWk3ZXV6QwSvvz#~d0rEg)Dw{U@F@m+IW} z6|IHyD|)31CB26A?O}b)F}pDy$E@9d$YD5C2#bvD74tXS)GuyY-u}Y2YxE0wanFur zi$Mdriv-#;>pQNJRRAxeG_eXGuD6QX`LAg|_Z5$uc)==8)^`X7^xqfk4hD0hL4VL2 zREo^8ETNd2lV)vhj-eCIB8eS%W+pDBqpv%T>NqRMsAYs^CrXY-k7KE61yW_kvEp>B zI2|ia$BNUj;&conjuodPBR5DGBCvpQtUw$qPREMVvEpiF-=_x1FtmEZZ# KX>U%S>;Eq-TgKG@ diff --git a/PythonHome/Lib/curses/has_key.py b/PythonHome/Lib/curses/has_key.py new file mode 100644 index 0000000000..1dd5a3bd4a --- /dev/null +++ b/PythonHome/Lib/curses/has_key.py @@ -0,0 +1,192 @@ + +# +# Emulation of has_key() function for platforms that don't use ncurses +# + +import _curses + +# Table mapping curses keys to the terminfo capability name + +_capability_names = { + _curses.KEY_A1: 'ka1', + _curses.KEY_A3: 'ka3', + _curses.KEY_B2: 'kb2', + _curses.KEY_BACKSPACE: 'kbs', + _curses.KEY_BEG: 'kbeg', + _curses.KEY_BTAB: 'kcbt', + _curses.KEY_C1: 'kc1', + _curses.KEY_C3: 'kc3', + _curses.KEY_CANCEL: 'kcan', + _curses.KEY_CATAB: 'ktbc', + _curses.KEY_CLEAR: 'kclr', + _curses.KEY_CLOSE: 'kclo', + _curses.KEY_COMMAND: 'kcmd', + _curses.KEY_COPY: 'kcpy', + _curses.KEY_CREATE: 'kcrt', + _curses.KEY_CTAB: 'kctab', + _curses.KEY_DC: 'kdch1', + _curses.KEY_DL: 'kdl1', + _curses.KEY_DOWN: 'kcud1', + _curses.KEY_EIC: 'krmir', + _curses.KEY_END: 'kend', + _curses.KEY_ENTER: 'kent', + _curses.KEY_EOL: 'kel', + _curses.KEY_EOS: 'ked', + _curses.KEY_EXIT: 'kext', + _curses.KEY_F0: 'kf0', + _curses.KEY_F1: 'kf1', + _curses.KEY_F10: 'kf10', + _curses.KEY_F11: 'kf11', + _curses.KEY_F12: 'kf12', + _curses.KEY_F13: 'kf13', + _curses.KEY_F14: 'kf14', + _curses.KEY_F15: 'kf15', + _curses.KEY_F16: 'kf16', + _curses.KEY_F17: 'kf17', + _curses.KEY_F18: 'kf18', + _curses.KEY_F19: 'kf19', + _curses.KEY_F2: 'kf2', + _curses.KEY_F20: 'kf20', + _curses.KEY_F21: 'kf21', + _curses.KEY_F22: 'kf22', + _curses.KEY_F23: 'kf23', + _curses.KEY_F24: 'kf24', + _curses.KEY_F25: 'kf25', + _curses.KEY_F26: 'kf26', + _curses.KEY_F27: 'kf27', + _curses.KEY_F28: 'kf28', + _curses.KEY_F29: 'kf29', + _curses.KEY_F3: 'kf3', + _curses.KEY_F30: 'kf30', + _curses.KEY_F31: 'kf31', + _curses.KEY_F32: 'kf32', + _curses.KEY_F33: 'kf33', + _curses.KEY_F34: 'kf34', + _curses.KEY_F35: 'kf35', + _curses.KEY_F36: 'kf36', + _curses.KEY_F37: 'kf37', + _curses.KEY_F38: 'kf38', + _curses.KEY_F39: 'kf39', + _curses.KEY_F4: 'kf4', + _curses.KEY_F40: 'kf40', + _curses.KEY_F41: 'kf41', + _curses.KEY_F42: 'kf42', + _curses.KEY_F43: 'kf43', + _curses.KEY_F44: 'kf44', + _curses.KEY_F45: 'kf45', + _curses.KEY_F46: 'kf46', + _curses.KEY_F47: 'kf47', + _curses.KEY_F48: 'kf48', + _curses.KEY_F49: 'kf49', + _curses.KEY_F5: 'kf5', + _curses.KEY_F50: 'kf50', + _curses.KEY_F51: 'kf51', + _curses.KEY_F52: 'kf52', + _curses.KEY_F53: 'kf53', + _curses.KEY_F54: 'kf54', + _curses.KEY_F55: 'kf55', + _curses.KEY_F56: 'kf56', + _curses.KEY_F57: 'kf57', + _curses.KEY_F58: 'kf58', + _curses.KEY_F59: 'kf59', + _curses.KEY_F6: 'kf6', + _curses.KEY_F60: 'kf60', + _curses.KEY_F61: 'kf61', + _curses.KEY_F62: 'kf62', + _curses.KEY_F63: 'kf63', + _curses.KEY_F7: 'kf7', + _curses.KEY_F8: 'kf8', + _curses.KEY_F9: 'kf9', + _curses.KEY_FIND: 'kfnd', + _curses.KEY_HELP: 'khlp', + _curses.KEY_HOME: 'khome', + _curses.KEY_IC: 'kich1', + _curses.KEY_IL: 'kil1', + _curses.KEY_LEFT: 'kcub1', + _curses.KEY_LL: 'kll', + _curses.KEY_MARK: 'kmrk', + _curses.KEY_MESSAGE: 'kmsg', + _curses.KEY_MOVE: 'kmov', + _curses.KEY_NEXT: 'knxt', + _curses.KEY_NPAGE: 'knp', + _curses.KEY_OPEN: 'kopn', + _curses.KEY_OPTIONS: 'kopt', + _curses.KEY_PPAGE: 'kpp', + _curses.KEY_PREVIOUS: 'kprv', + _curses.KEY_PRINT: 'kprt', + _curses.KEY_REDO: 'krdo', + _curses.KEY_REFERENCE: 'kref', + _curses.KEY_REFRESH: 'krfr', + _curses.KEY_REPLACE: 'krpl', + _curses.KEY_RESTART: 'krst', + _curses.KEY_RESUME: 'kres', + _curses.KEY_RIGHT: 'kcuf1', + _curses.KEY_SAVE: 'ksav', + _curses.KEY_SBEG: 'kBEG', + _curses.KEY_SCANCEL: 'kCAN', + _curses.KEY_SCOMMAND: 'kCMD', + _curses.KEY_SCOPY: 'kCPY', + _curses.KEY_SCREATE: 'kCRT', + _curses.KEY_SDC: 'kDC', + _curses.KEY_SDL: 'kDL', + _curses.KEY_SELECT: 'kslt', + _curses.KEY_SEND: 'kEND', + _curses.KEY_SEOL: 'kEOL', + _curses.KEY_SEXIT: 'kEXT', + _curses.KEY_SF: 'kind', + _curses.KEY_SFIND: 'kFND', + _curses.KEY_SHELP: 'kHLP', + _curses.KEY_SHOME: 'kHOM', + _curses.KEY_SIC: 'kIC', + _curses.KEY_SLEFT: 'kLFT', + _curses.KEY_SMESSAGE: 'kMSG', + _curses.KEY_SMOVE: 'kMOV', + _curses.KEY_SNEXT: 'kNXT', + _curses.KEY_SOPTIONS: 'kOPT', + _curses.KEY_SPREVIOUS: 'kPRV', + _curses.KEY_SPRINT: 'kPRT', + _curses.KEY_SR: 'kri', + _curses.KEY_SREDO: 'kRDO', + _curses.KEY_SREPLACE: 'kRPL', + _curses.KEY_SRIGHT: 'kRIT', + _curses.KEY_SRSUME: 'kRES', + _curses.KEY_SSAVE: 'kSAV', + _curses.KEY_SSUSPEND: 'kSPD', + _curses.KEY_STAB: 'khts', + _curses.KEY_SUNDO: 'kUND', + _curses.KEY_SUSPEND: 'kspd', + _curses.KEY_UNDO: 'kund', + _curses.KEY_UP: 'kcuu1' + } + +def has_key(ch): + if isinstance(ch, str): + ch = ord(ch) + + # Figure out the correct capability name for the keycode. + capability_name = _capability_names.get(ch) + if capability_name is None: + return False + + #Check the current terminal description for that capability; + #if present, return true, else return false. + if _curses.tigetstr( capability_name ): + return True + else: + return False + +if __name__ == '__main__': + # Compare the output of this implementation and the ncurses has_key, + # on platforms where has_key is already available + try: + L = [] + _curses.initscr() + for key in _capability_names.keys(): + system = key in _curses + python = has_key(key) + if system != python: + L.append( 'Mismatch for key %s, system=%i, Python=%i' + % (_curses.keyname( key ), system, python) ) + finally: + _curses.endwin() + for i in L: print i diff --git a/PythonHome/Lib/curses/has_key.pyc b/PythonHome/Lib/curses/has_key.pyc deleted file mode 100644 index 09d506b9c4a3200900977b5daa33212b8822bdb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5907 zcmeI#`F_(@8V2CwBm@Xa1Eq!1HC<>!ODW#6v_NqjIZ1JB*Gfo8p~kUg;=~)40)#>r zp!>c+p=CN#<`(A8<^pD3y*i&H=8yT!1q?~-M`!zvbaeEI-hU1a{A207SyB35KfX`m z&%Os$@f%SMrB;-x-&WNgWhu2DQDfC!st4+$dZBGpAJk86gSJ!s&<<)lw3FHa4NyCw zUDNcg&wCKgZ5F6L;IK{Q_wV(h74*N%1{P0LuH^@Y6hC4W}$beIp`Gi4wR)%LGx4=%2D%Bp2|T5Di6I& z6`&&ZE@VU4PB%z?O9Ox3Y30U>Qm@*>NDsI>T~Ez>I>*A>PzTr z>MQ6Q>TBp*>Ko`g>Raf0>O1HM>U-!%>Idj2>PP5j>L=(I>SyRS^$T=|x~;}m?x^ao z>J}dGzbfmls@_!_J*s=V|LUf?fWmuh_nW$@ROAY7vO8-1clTiWTtTheR~CMi+UQp+ ze^C|&xUX(T)XE>q!r>okqgQng^jr7T`d?Mm8|iPljn|;otM;Ko9 zPcPhFg|5@*cBz#I%6gz?W-s38Us`T4BblSWAw|{yg?~Ax7u+aE^>^I+UXAH*+v#)b zSFH;kDyxoHQ_(#taa~bvd2m)Mx}?z+v^APljn0-v*KxMF0V+;;)l;>y7WFEtji|2N ztZH?ebv>xn(qmaIJtM2(&CHUDE4rd~)T^lJacj||UVvKEFNsNsKAl=LAtgz{m|$Em zA(+$=WSE#lh)IN)UnLP@5+NoLViF-H5n>V{CK04}Tq49JLR=!m{WcOIE)n7qAubW( z5+N=Tq*Fp7BqTyYA|xb2!fz}Q5)vUH5fTz1ArYi)QX(WJLQ*0mB|=gnB>i3zAt@1( z5+NxOq{)~>7?TKN5@Af=>a}sbb`$!0QZK69U~7$zcN?y?o0g}#e~;FKdvsOrh(^O3 zpxNEfu=VC?wl8@lEx9#Y9j~C>(YvSJ(Kl^J*L1qNPX}9td$C*9+o@~SbV;qN(b2KH zwlubE*+X*s+hslClriIVOQ&)g^V1rIGaAJO@3Ks%^>@~*up2spk<)#Qysk2q7rZug zxr7;MGn*}VRkQhdZ@js*SCGx*3KyQKa}` z?}v_@&DK}XdIO$aE8C?FYwHM}@@^b`_yDwb<3mM;Bg4JJk-~jJ{U+1-rJR2b z1~!s=vE8BEEh+OcatlT=sKFlfTjfoEC}SDBL_%ba28{a6Gsv3KHG{+%I2Lj|}n*`-Y}~R2{SlO#ulz zC=X2`)D@ZAZ-V3>`eC&E5n%j z0V+@(2~GFq#2@~lr=6JzDtHh0 z&3F?8NA6wV$Hi^n*KqOulaW>StGUen5!cyoEUPJNV)_dx*BB-43d+4@2D!!LYWhPJ z4R5jhj^1(vhYzh4?nEq)-`QL=ag&9vS2(4acq_^W%kdvgSt-+7EEMnJRxJLB4_^Ed zUqwnKyd5d!<(_)0?${Om#%dv{yRRuo@;pZ`$&+|{K$0iRosRqeJ@@LPq5E>fVw7F3 zw>Wft6m{PF2=!lIO5D5RShHQ-Y*;7UncK6N-C$pDWZ?fl|I-y1>fO0}u(vnTkJfwf Q9_Rk-j2!G4hzzNJ1JJUpZvX%Q diff --git a/PythonHome/Lib/curses/panel.py b/PythonHome/Lib/curses/panel.py new file mode 100644 index 0000000000..aacca85151 --- /dev/null +++ b/PythonHome/Lib/curses/panel.py @@ -0,0 +1,8 @@ +"""curses.panel + +Module for using panels with curses. +""" + +__revision__ = "$Id$" + +from _curses_panel import * diff --git a/PythonHome/Lib/curses/panel.pyc b/PythonHome/Lib/curses/panel.pyc deleted file mode 100644 index 84e334c45dfb0fe98acad123dd475fc26e67a5bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 262 zcmZSn%*(YUJRvxl0ScIav;z 0: + self.win.move(y, x-1) + elif y == 0: + pass + elif self.stripspaces: + self.win.move(y-1, self._end_of_line(y-1)) + else: + self.win.move(y-1, self.maxx) + if ch in (curses.ascii.BS, curses.KEY_BACKSPACE): + self.win.delch() + elif ch == curses.ascii.EOT: # ^d + self.win.delch() + elif ch == curses.ascii.ENQ: # ^e + if self.stripspaces: + self.win.move(y, self._end_of_line(y)) + else: + self.win.move(y, self.maxx) + elif ch in (curses.ascii.ACK, curses.KEY_RIGHT): # ^f + if x < self.maxx: + self.win.move(y, x+1) + elif y == self.maxy: + pass + else: + self.win.move(y+1, 0) + elif ch == curses.ascii.BEL: # ^g + return 0 + elif ch == curses.ascii.NL: # ^j + if self.maxy == 0: + return 0 + elif y < self.maxy: + self.win.move(y+1, 0) + elif ch == curses.ascii.VT: # ^k + if x == 0 and self._end_of_line(y) == 0: + self.win.deleteln() + else: + # first undo the effect of self._end_of_line + self.win.move(y, x) + self.win.clrtoeol() + elif ch == curses.ascii.FF: # ^l + self.win.refresh() + elif ch in (curses.ascii.SO, curses.KEY_DOWN): # ^n + if y < self.maxy: + self.win.move(y+1, x) + if x > self._end_of_line(y+1): + self.win.move(y+1, self._end_of_line(y+1)) + elif ch == curses.ascii.SI: # ^o + self.win.insertln() + elif ch in (curses.ascii.DLE, curses.KEY_UP): # ^p + if y > 0: + self.win.move(y-1, x) + if x > self._end_of_line(y-1): + self.win.move(y-1, self._end_of_line(y-1)) + return 1 + + def gather(self): + "Collect and return the contents of the window." + result = "" + for y in range(self.maxy+1): + self.win.move(y, 0) + stop = self._end_of_line(y) + if stop == 0 and self.stripspaces: + continue + for x in range(self.maxx+1): + if self.stripspaces and x > stop: + break + result = result + chr(curses.ascii.ascii(self.win.inch(y, x))) + if self.maxy > 0: + result = result + "\n" + return result + + def edit(self, validate=None): + "Edit in the widget window and collect the results." + while 1: + ch = self.win.getch() + if validate: + ch = validate(ch) + if not ch: + continue + if not self.do_command(ch): + break + self.win.refresh() + return self.gather() + +if __name__ == '__main__': + def test_editbox(stdscr): + ncols, nlines = 9, 4 + uly, ulx = 15, 20 + stdscr.addstr(uly-2, ulx, "Use Ctrl-G to end editing.") + win = curses.newwin(nlines, ncols, uly, ulx) + rectangle(stdscr, uly-1, ulx-1, uly + nlines, ulx + ncols) + stdscr.refresh() + return Textbox(win).edit() + + str = curses.wrapper(test_editbox) + print 'Contents of text box:', repr(str) diff --git a/PythonHome/Lib/curses/textpad.pyc b/PythonHome/Lib/curses/textpad.pyc deleted file mode 100644 index 6c771eda8d19681e8598a95b4338313923f13785..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6719 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 NJ|rBejc&19{04-6J0bu8 diff --git a/PythonHome/Lib/dbhash.py b/PythonHome/Lib/dbhash.py new file mode 100644 index 0000000000..a5d5375ba9 --- /dev/null +++ b/PythonHome/Lib/dbhash.py @@ -0,0 +1,18 @@ +"""Provide a (g)dbm-compatible interface to bsddb.hashopen.""" + +import sys +import warnings +warnings.warnpy3k("in 3.x, the dbhash module has been removed", stacklevel=2) +try: + import bsddb +except ImportError: + # prevent a second import of this module from spuriously succeeding + del sys.modules[__name__] + raise + +__all__ = ["error","open"] + +error = bsddb.error # Exported for anydbm + +def open(file, flag = 'r', mode=0666): + return bsddb.hashopen(file, flag, mode) diff --git a/PythonHome/Lib/dbhash.pyc b/PythonHome/Lib/dbhash.pyc deleted file mode 100644 index 0ab5b9558e3a3af2a4e021b2915ac279e736ab81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 688 zcmZ`#%Wl*#6g_q_uP_xwl~^J#1A=V2VF48q>H-N>Xu2qhDupDzo$*W_qu2}`sVmBg z??L<+9{|@0r7JAo<{l=gh)eNG*1xH2%8994!$RW^%yk4>#sl~@KKMUCs?xH6cl1TLpp<= zLNiAA#^;ewejY#Yo?bG1=-Qppq;eH6pX#E1QMUCqcc!RFnZ{9fm6xPks|u@ik*spN zYPZxR<~NTs`-~+_qmGm7=gO@}>B7HIb*n$K0CQCkHL9b!-H~>YPwVn>Q_+qpBYEq5 zi>T|`&V|gpxD!k|^OKh{VCuu)z2&e+3=UWe+yFO>61M?YZpw#umSZo| z=eRNz4W!DKJz>8T^EG;~51A#G?@e(z)RS!Y3$Of$!+HYIchF6kW|?lwEOTDo?rop* zOWrl6S>A89`{T{R*Wi5T-_=_#_p~qCOAPHAUT0a8*Ti~*c3xFkw(!OE4(?6<*J*Fy d)gXD|KibC(V>uUdaU=q9C=O&KCUP!k@()1Aj$;4- diff --git a/PythonHome/Lib/decimal.py b/PythonHome/Lib/decimal.py new file mode 100644 index 0000000000..04bf5c2660 --- /dev/null +++ b/PythonHome/Lib/decimal.py @@ -0,0 +1,6198 @@ +# Copyright (c) 2004 Python Software Foundation. +# All rights reserved. + +# Written by Eric Price +# and Facundo Batista +# and Raymond Hettinger +# and Aahz +# and Tim Peters + +# This module is currently Py2.3 compatible and should be kept that way +# unless a major compelling advantage arises. IOW, 2.3 compatibility is +# strongly preferred, but not guaranteed. + +# Also, this module should be kept in sync with the latest updates of +# the IBM specification as it evolves. Those updates will be treated +# as bug fixes (deviation from the spec is a compatibility, usability +# bug) and will be backported. At this point the spec is stabilizing +# and the updates are becoming fewer, smaller, and less significant. + +""" +This is a Py2.3 implementation of decimal floating point arithmetic based on +the General Decimal Arithmetic Specification: + + http://speleotrove.com/decimal/decarith.html + +and IEEE standard 854-1987: + + http://en.wikipedia.org/wiki/IEEE_854-1987 + +Decimal floating point has finite precision with arbitrarily large bounds. + +The purpose of this module is to support arithmetic using familiar +"schoolhouse" rules and to avoid some of the tricky representation +issues associated with binary floating point. The package is especially +useful for financial applications or for contexts where users have +expectations that are at odds with binary floating point (for instance, +in binary floating point, 1.00 % 0.1 gives 0.09999999999999995 instead +of the expected Decimal('0.00') returned by decimal floating point). + +Here are some examples of using the decimal module: + +>>> from decimal import * +>>> setcontext(ExtendedContext) +>>> Decimal(0) +Decimal('0') +>>> Decimal('1') +Decimal('1') +>>> Decimal('-.0123') +Decimal('-0.0123') +>>> Decimal(123456) +Decimal('123456') +>>> Decimal('123.45e12345678901234567890') +Decimal('1.2345E+12345678901234567892') +>>> Decimal('1.33') + Decimal('1.27') +Decimal('2.60') +>>> Decimal('12.34') + Decimal('3.87') - Decimal('18.41') +Decimal('-2.20') +>>> dig = Decimal(1) +>>> print dig / Decimal(3) +0.333333333 +>>> getcontext().prec = 18 +>>> print dig / Decimal(3) +0.333333333333333333 +>>> print dig.sqrt() +1 +>>> print Decimal(3).sqrt() +1.73205080756887729 +>>> print Decimal(3) ** 123 +4.85192780976896427E+58 +>>> inf = Decimal(1) / Decimal(0) +>>> print inf +Infinity +>>> neginf = Decimal(-1) / Decimal(0) +>>> print neginf +-Infinity +>>> print neginf + inf +NaN +>>> print neginf * inf +-Infinity +>>> print dig / 0 +Infinity +>>> getcontext().traps[DivisionByZero] = 1 +>>> print dig / 0 +Traceback (most recent call last): + ... + ... + ... +DivisionByZero: x / 0 +>>> c = Context() +>>> c.traps[InvalidOperation] = 0 +>>> print c.flags[InvalidOperation] +0 +>>> c.divide(Decimal(0), Decimal(0)) +Decimal('NaN') +>>> c.traps[InvalidOperation] = 1 +>>> print c.flags[InvalidOperation] +1 +>>> c.flags[InvalidOperation] = 0 +>>> print c.flags[InvalidOperation] +0 +>>> print c.divide(Decimal(0), Decimal(0)) +Traceback (most recent call last): + ... + ... + ... +InvalidOperation: 0 / 0 +>>> print c.flags[InvalidOperation] +1 +>>> c.flags[InvalidOperation] = 0 +>>> c.traps[InvalidOperation] = 0 +>>> print c.divide(Decimal(0), Decimal(0)) +NaN +>>> print c.flags[InvalidOperation] +1 +>>> +""" + +__all__ = [ + # Two major classes + 'Decimal', 'Context', + + # Contexts + 'DefaultContext', 'BasicContext', 'ExtendedContext', + + # Exceptions + 'DecimalException', 'Clamped', 'InvalidOperation', 'DivisionByZero', + 'Inexact', 'Rounded', 'Subnormal', 'Overflow', 'Underflow', + + # Constants for use in setting up contexts + 'ROUND_DOWN', 'ROUND_HALF_UP', 'ROUND_HALF_EVEN', 'ROUND_CEILING', + 'ROUND_FLOOR', 'ROUND_UP', 'ROUND_HALF_DOWN', 'ROUND_05UP', + + # Functions for manipulating contexts + 'setcontext', 'getcontext', 'localcontext' +] + +__version__ = '1.70' # Highest version of the spec this complies with + +import copy as _copy +import math as _math +import numbers as _numbers + +try: + from collections import namedtuple as _namedtuple + DecimalTuple = _namedtuple('DecimalTuple', 'sign digits exponent') +except ImportError: + DecimalTuple = lambda *args: args + +# Rounding +ROUND_DOWN = 'ROUND_DOWN' +ROUND_HALF_UP = 'ROUND_HALF_UP' +ROUND_HALF_EVEN = 'ROUND_HALF_EVEN' +ROUND_CEILING = 'ROUND_CEILING' +ROUND_FLOOR = 'ROUND_FLOOR' +ROUND_UP = 'ROUND_UP' +ROUND_HALF_DOWN = 'ROUND_HALF_DOWN' +ROUND_05UP = 'ROUND_05UP' + +# Errors + +class DecimalException(ArithmeticError): + """Base exception class. + + Used exceptions derive from this. + If an exception derives from another exception besides this (such as + Underflow (Inexact, Rounded, Subnormal) that indicates that it is only + called if the others are present. This isn't actually used for + anything, though. + + handle -- Called when context._raise_error is called and the + trap_enabler is not set. First argument is self, second is the + context. More arguments can be given, those being after + the explanation in _raise_error (For example, + context._raise_error(NewError, '(-x)!', self._sign) would + call NewError().handle(context, self._sign).) + + To define a new exception, it should be sufficient to have it derive + from DecimalException. + """ + def handle(self, context, *args): + pass + + +class Clamped(DecimalException): + """Exponent of a 0 changed to fit bounds. + + This occurs and signals clamped if the exponent of a result has been + altered in order to fit the constraints of a specific concrete + representation. This may occur when the exponent of a zero result would + be outside the bounds of a representation, or when a large normal + number would have an encoded exponent that cannot be represented. In + this latter case, the exponent is reduced to fit and the corresponding + number of zero digits are appended to the coefficient ("fold-down"). + """ + +class InvalidOperation(DecimalException): + """An invalid operation was performed. + + Various bad things cause this: + + Something creates a signaling NaN + -INF + INF + 0 * (+-)INF + (+-)INF / (+-)INF + x % 0 + (+-)INF % x + x._rescale( non-integer ) + sqrt(-x) , x > 0 + 0 ** 0 + x ** (non-integer) + x ** (+-)INF + An operand is invalid + + The result of the operation after these is a quiet positive NaN, + except when the cause is a signaling NaN, in which case the result is + also a quiet NaN, but with the original sign, and an optional + diagnostic information. + """ + def handle(self, context, *args): + if args: + ans = _dec_from_triple(args[0]._sign, args[0]._int, 'n', True) + return ans._fix_nan(context) + return _NaN + +class ConversionSyntax(InvalidOperation): + """Trying to convert badly formed string. + + This occurs and signals invalid-operation if an string is being + converted to a number and it does not conform to the numeric string + syntax. The result is [0,qNaN]. + """ + def handle(self, context, *args): + return _NaN + +class DivisionByZero(DecimalException, ZeroDivisionError): + """Division by 0. + + This occurs and signals division-by-zero if division of a finite number + by zero was attempted (during a divide-integer or divide operation, or a + power operation with negative right-hand operand), and the dividend was + not zero. + + The result of the operation is [sign,inf], where sign is the exclusive + or of the signs of the operands for divide, or is 1 for an odd power of + -0, for power. + """ + + def handle(self, context, sign, *args): + return _SignedInfinity[sign] + +class DivisionImpossible(InvalidOperation): + """Cannot perform the division adequately. + + This occurs and signals invalid-operation if the integer result of a + divide-integer or remainder operation had too many digits (would be + longer than precision). The result is [0,qNaN]. + """ + + def handle(self, context, *args): + return _NaN + +class DivisionUndefined(InvalidOperation, ZeroDivisionError): + """Undefined result of division. + + This occurs and signals invalid-operation if division by zero was + attempted (during a divide-integer, divide, or remainder operation), and + the dividend is also zero. The result is [0,qNaN]. + """ + + def handle(self, context, *args): + return _NaN + +class Inexact(DecimalException): + """Had to round, losing information. + + This occurs and signals inexact whenever the result of an operation is + not exact (that is, it needed to be rounded and any discarded digits + were non-zero), or if an overflow or underflow condition occurs. The + result in all cases is unchanged. + + The inexact signal may be tested (or trapped) to determine if a given + operation (or sequence of operations) was inexact. + """ + +class InvalidContext(InvalidOperation): + """Invalid context. Unknown rounding, for example. + + This occurs and signals invalid-operation if an invalid context was + detected during an operation. This can occur if contexts are not checked + on creation and either the precision exceeds the capability of the + underlying concrete representation or an unknown or unsupported rounding + was specified. These aspects of the context need only be checked when + the values are required to be used. The result is [0,qNaN]. + """ + + def handle(self, context, *args): + return _NaN + +class Rounded(DecimalException): + """Number got rounded (not necessarily changed during rounding). + + This occurs and signals rounded whenever the result of an operation is + rounded (that is, some zero or non-zero digits were discarded from the + coefficient), or if an overflow or underflow condition occurs. The + result in all cases is unchanged. + + The rounded signal may be tested (or trapped) to determine if a given + operation (or sequence of operations) caused a loss of precision. + """ + +class Subnormal(DecimalException): + """Exponent < Emin before rounding. + + This occurs and signals subnormal whenever the result of a conversion or + operation is subnormal (that is, its adjusted exponent is less than + Emin, before any rounding). The result in all cases is unchanged. + + The subnormal signal may be tested (or trapped) to determine if a given + or operation (or sequence of operations) yielded a subnormal result. + """ + +class Overflow(Inexact, Rounded): + """Numerical overflow. + + This occurs and signals overflow if the adjusted exponent of a result + (from a conversion or from an operation that is not an attempt to divide + by zero), after rounding, would be greater than the largest value that + can be handled by the implementation (the value Emax). + + The result depends on the rounding mode: + + For round-half-up and round-half-even (and for round-half-down and + round-up, if implemented), the result of the operation is [sign,inf], + where sign is the sign of the intermediate result. For round-down, the + result is the largest finite number that can be represented in the + current precision, with the sign of the intermediate result. For + round-ceiling, the result is the same as for round-down if the sign of + the intermediate result is 1, or is [0,inf] otherwise. For round-floor, + the result is the same as for round-down if the sign of the intermediate + result is 0, or is [1,inf] otherwise. In all cases, Inexact and Rounded + will also be raised. + """ + + def handle(self, context, sign, *args): + if context.rounding in (ROUND_HALF_UP, ROUND_HALF_EVEN, + ROUND_HALF_DOWN, ROUND_UP): + return _SignedInfinity[sign] + if sign == 0: + if context.rounding == ROUND_CEILING: + return _SignedInfinity[sign] + return _dec_from_triple(sign, '9'*context.prec, + context.Emax-context.prec+1) + if sign == 1: + if context.rounding == ROUND_FLOOR: + return _SignedInfinity[sign] + return _dec_from_triple(sign, '9'*context.prec, + context.Emax-context.prec+1) + + +class Underflow(Inexact, Rounded, Subnormal): + """Numerical underflow with result rounded to 0. + + This occurs and signals underflow if a result is inexact and the + adjusted exponent of the result would be smaller (more negative) than + the smallest value that can be handled by the implementation (the value + Emin). That is, the result is both inexact and subnormal. + + The result after an underflow will be a subnormal number rounded, if + necessary, so that its exponent is not less than Etiny. This may result + in 0 with the sign of the intermediate result and an exponent of Etiny. + + In all cases, Inexact, Rounded, and Subnormal will also be raised. + """ + +# List of public traps and flags +_signals = [Clamped, DivisionByZero, Inexact, Overflow, Rounded, + Underflow, InvalidOperation, Subnormal] + +# Map conditions (per the spec) to signals +_condition_map = {ConversionSyntax:InvalidOperation, + DivisionImpossible:InvalidOperation, + DivisionUndefined:InvalidOperation, + InvalidContext:InvalidOperation} + +##### Context Functions ################################################## + +# The getcontext() and setcontext() function manage access to a thread-local +# current context. Py2.4 offers direct support for thread locals. If that +# is not available, use threading.currentThread() which is slower but will +# work for older Pythons. If threads are not part of the build, create a +# mock threading object with threading.local() returning the module namespace. + +try: + import threading +except ImportError: + # Python was compiled without threads; create a mock object instead + import sys + class MockThreading(object): + def local(self, sys=sys): + return sys.modules[__name__] + threading = MockThreading() + del sys, MockThreading + +try: + threading.local + +except AttributeError: + + # To fix reloading, force it to create a new context + # Old contexts have different exceptions in their dicts, making problems. + if hasattr(threading.currentThread(), '__decimal_context__'): + del threading.currentThread().__decimal_context__ + + def setcontext(context): + """Set this thread's context to context.""" + if context in (DefaultContext, BasicContext, ExtendedContext): + context = context.copy() + context.clear_flags() + threading.currentThread().__decimal_context__ = context + + def getcontext(): + """Returns this thread's context. + + If this thread does not yet have a context, returns + a new context and sets this thread's context. + New contexts are copies of DefaultContext. + """ + try: + return threading.currentThread().__decimal_context__ + except AttributeError: + context = Context() + threading.currentThread().__decimal_context__ = context + return context + +else: + + local = threading.local() + if hasattr(local, '__decimal_context__'): + del local.__decimal_context__ + + def getcontext(_local=local): + """Returns this thread's context. + + If this thread does not yet have a context, returns + a new context and sets this thread's context. + New contexts are copies of DefaultContext. + """ + try: + return _local.__decimal_context__ + except AttributeError: + context = Context() + _local.__decimal_context__ = context + return context + + def setcontext(context, _local=local): + """Set this thread's context to context.""" + if context in (DefaultContext, BasicContext, ExtendedContext): + context = context.copy() + context.clear_flags() + _local.__decimal_context__ = context + + del threading, local # Don't contaminate the namespace + +def localcontext(ctx=None): + """Return a context manager for a copy of the supplied context + + Uses a copy of the current context if no context is specified + The returned context manager creates a local decimal context + in a with statement: + def sin(x): + with localcontext() as ctx: + ctx.prec += 2 + # Rest of sin calculation algorithm + # uses a precision 2 greater than normal + return +s # Convert result to normal precision + + def sin(x): + with localcontext(ExtendedContext): + # Rest of sin calculation algorithm + # uses the Extended Context from the + # General Decimal Arithmetic Specification + return +s # Convert result to normal context + + >>> setcontext(DefaultContext) + >>> print getcontext().prec + 28 + >>> with localcontext(): + ... ctx = getcontext() + ... ctx.prec += 2 + ... print ctx.prec + ... + 30 + >>> with localcontext(ExtendedContext): + ... print getcontext().prec + ... + 9 + >>> print getcontext().prec + 28 + """ + if ctx is None: ctx = getcontext() + return _ContextManager(ctx) + + +##### Decimal class ####################################################### + +class Decimal(object): + """Floating point class for decimal arithmetic.""" + + __slots__ = ('_exp','_int','_sign', '_is_special') + # Generally, the value of the Decimal instance is given by + # (-1)**_sign * _int * 10**_exp + # Special values are signified by _is_special == True + + # We're immutable, so use __new__ not __init__ + def __new__(cls, value="0", context=None): + """Create a decimal point instance. + + >>> Decimal('3.14') # string input + Decimal('3.14') + >>> Decimal((0, (3, 1, 4), -2)) # tuple (sign, digit_tuple, exponent) + Decimal('3.14') + >>> Decimal(314) # int or long + Decimal('314') + >>> Decimal(Decimal(314)) # another decimal instance + Decimal('314') + >>> Decimal(' 3.14 \\n') # leading and trailing whitespace okay + Decimal('3.14') + """ + + # Note that the coefficient, self._int, is actually stored as + # a string rather than as a tuple of digits. This speeds up + # the "digits to integer" and "integer to digits" conversions + # that are used in almost every arithmetic operation on + # Decimals. This is an internal detail: the as_tuple function + # and the Decimal constructor still deal with tuples of + # digits. + + self = object.__new__(cls) + + # From a string + # REs insist on real strings, so we can too. + if isinstance(value, basestring): + m = _parser(value.strip()) + if m is None: + if context is None: + context = getcontext() + return context._raise_error(ConversionSyntax, + "Invalid literal for Decimal: %r" % value) + + if m.group('sign') == "-": + self._sign = 1 + else: + self._sign = 0 + intpart = m.group('int') + if intpart is not None: + # finite number + fracpart = m.group('frac') or '' + exp = int(m.group('exp') or '0') + self._int = str(int(intpart+fracpart)) + self._exp = exp - len(fracpart) + self._is_special = False + else: + diag = m.group('diag') + if diag is not None: + # NaN + self._int = str(int(diag or '0')).lstrip('0') + if m.group('signal'): + self._exp = 'N' + else: + self._exp = 'n' + else: + # infinity + self._int = '0' + self._exp = 'F' + self._is_special = True + return self + + # From an integer + if isinstance(value, (int,long)): + if value >= 0: + self._sign = 0 + else: + self._sign = 1 + self._exp = 0 + self._int = str(abs(value)) + self._is_special = False + return self + + # From another decimal + if isinstance(value, Decimal): + self._exp = value._exp + self._sign = value._sign + self._int = value._int + self._is_special = value._is_special + return self + + # From an internal working value + if isinstance(value, _WorkRep): + self._sign = value.sign + self._int = str(value.int) + self._exp = int(value.exp) + self._is_special = False + return self + + # tuple/list conversion (possibly from as_tuple()) + if isinstance(value, (list,tuple)): + if len(value) != 3: + raise ValueError('Invalid tuple size in creation of Decimal ' + 'from list or tuple. The list or tuple ' + 'should have exactly three elements.') + # process sign. The isinstance test rejects floats + if not (isinstance(value[0], (int, long)) and value[0] in (0,1)): + raise ValueError("Invalid sign. The first value in the tuple " + "should be an integer; either 0 for a " + "positive number or 1 for a negative number.") + self._sign = value[0] + if value[2] == 'F': + # infinity: value[1] is ignored + self._int = '0' + self._exp = value[2] + self._is_special = True + else: + # process and validate the digits in value[1] + digits = [] + for digit in value[1]: + if isinstance(digit, (int, long)) and 0 <= digit <= 9: + # skip leading zeros + if digits or digit != 0: + digits.append(digit) + else: + raise ValueError("The second value in the tuple must " + "be composed of integers in the range " + "0 through 9.") + if value[2] in ('n', 'N'): + # NaN: digits form the diagnostic + self._int = ''.join(map(str, digits)) + self._exp = value[2] + self._is_special = True + elif isinstance(value[2], (int, long)): + # finite number: digits give the coefficient + self._int = ''.join(map(str, digits or [0])) + self._exp = value[2] + self._is_special = False + else: + raise ValueError("The third value in the tuple must " + "be an integer, or one of the " + "strings 'F', 'n', 'N'.") + return self + + if isinstance(value, float): + value = Decimal.from_float(value) + self._exp = value._exp + self._sign = value._sign + self._int = value._int + self._is_special = value._is_special + return self + + raise TypeError("Cannot convert %r to Decimal" % value) + + # @classmethod, but @decorator is not valid Python 2.3 syntax, so + # don't use it (see notes on Py2.3 compatibility at top of file) + def from_float(cls, f): + """Converts a float to a decimal number, exactly. + + Note that Decimal.from_float(0.1) is not the same as Decimal('0.1'). + Since 0.1 is not exactly representable in binary floating point, the + value is stored as the nearest representable value which is + 0x1.999999999999ap-4. The exact equivalent of the value in decimal + is 0.1000000000000000055511151231257827021181583404541015625. + + >>> Decimal.from_float(0.1) + Decimal('0.1000000000000000055511151231257827021181583404541015625') + >>> Decimal.from_float(float('nan')) + Decimal('NaN') + >>> Decimal.from_float(float('inf')) + Decimal('Infinity') + >>> Decimal.from_float(-float('inf')) + Decimal('-Infinity') + >>> Decimal.from_float(-0.0) + Decimal('-0') + + """ + if isinstance(f, (int, long)): # handle integer inputs + return cls(f) + if _math.isinf(f) or _math.isnan(f): # raises TypeError if not a float + return cls(repr(f)) + if _math.copysign(1.0, f) == 1.0: + sign = 0 + else: + sign = 1 + n, d = abs(f).as_integer_ratio() + k = d.bit_length() - 1 + result = _dec_from_triple(sign, str(n*5**k), -k) + if cls is Decimal: + return result + else: + return cls(result) + from_float = classmethod(from_float) + + def _isnan(self): + """Returns whether the number is not actually one. + + 0 if a number + 1 if NaN + 2 if sNaN + """ + if self._is_special: + exp = self._exp + if exp == 'n': + return 1 + elif exp == 'N': + return 2 + return 0 + + def _isinfinity(self): + """Returns whether the number is infinite + + 0 if finite or not a number + 1 if +INF + -1 if -INF + """ + if self._exp == 'F': + if self._sign: + return -1 + return 1 + return 0 + + def _check_nans(self, other=None, context=None): + """Returns whether the number is not actually one. + + if self, other are sNaN, signal + if self, other are NaN return nan + return 0 + + Done before operations. + """ + + self_is_nan = self._isnan() + if other is None: + other_is_nan = False + else: + other_is_nan = other._isnan() + + if self_is_nan or other_is_nan: + if context is None: + context = getcontext() + + if self_is_nan == 2: + return context._raise_error(InvalidOperation, 'sNaN', + self) + if other_is_nan == 2: + return context._raise_error(InvalidOperation, 'sNaN', + other) + if self_is_nan: + return self._fix_nan(context) + + return other._fix_nan(context) + return 0 + + def _compare_check_nans(self, other, context): + """Version of _check_nans used for the signaling comparisons + compare_signal, __le__, __lt__, __ge__, __gt__. + + Signal InvalidOperation if either self or other is a (quiet + or signaling) NaN. Signaling NaNs take precedence over quiet + NaNs. + + Return 0 if neither operand is a NaN. + + """ + if context is None: + context = getcontext() + + if self._is_special or other._is_special: + if self.is_snan(): + return context._raise_error(InvalidOperation, + 'comparison involving sNaN', + self) + elif other.is_snan(): + return context._raise_error(InvalidOperation, + 'comparison involving sNaN', + other) + elif self.is_qnan(): + return context._raise_error(InvalidOperation, + 'comparison involving NaN', + self) + elif other.is_qnan(): + return context._raise_error(InvalidOperation, + 'comparison involving NaN', + other) + return 0 + + def __nonzero__(self): + """Return True if self is nonzero; otherwise return False. + + NaNs and infinities are considered nonzero. + """ + return self._is_special or self._int != '0' + + def _cmp(self, other): + """Compare the two non-NaN decimal instances self and other. + + Returns -1 if self < other, 0 if self == other and 1 + if self > other. This routine is for internal use only.""" + + if self._is_special or other._is_special: + self_inf = self._isinfinity() + other_inf = other._isinfinity() + if self_inf == other_inf: + return 0 + elif self_inf < other_inf: + return -1 + else: + return 1 + + # check for zeros; Decimal('0') == Decimal('-0') + if not self: + if not other: + return 0 + else: + return -((-1)**other._sign) + if not other: + return (-1)**self._sign + + # If different signs, neg one is less + if other._sign < self._sign: + return -1 + if self._sign < other._sign: + return 1 + + self_adjusted = self.adjusted() + other_adjusted = other.adjusted() + if self_adjusted == other_adjusted: + self_padded = self._int + '0'*(self._exp - other._exp) + other_padded = other._int + '0'*(other._exp - self._exp) + if self_padded == other_padded: + return 0 + elif self_padded < other_padded: + return -(-1)**self._sign + else: + return (-1)**self._sign + elif self_adjusted > other_adjusted: + return (-1)**self._sign + else: # self_adjusted < other_adjusted + return -((-1)**self._sign) + + # Note: The Decimal standard doesn't cover rich comparisons for + # Decimals. In particular, the specification is silent on the + # subject of what should happen for a comparison involving a NaN. + # We take the following approach: + # + # == comparisons involving a quiet NaN always return False + # != comparisons involving a quiet NaN always return True + # == or != comparisons involving a signaling NaN signal + # InvalidOperation, and return False or True as above if the + # InvalidOperation is not trapped. + # <, >, <= and >= comparisons involving a (quiet or signaling) + # NaN signal InvalidOperation, and return False if the + # InvalidOperation is not trapped. + # + # This behavior is designed to conform as closely as possible to + # that specified by IEEE 754. + + def __eq__(self, other, context=None): + other = _convert_other(other, allow_float=True) + if other is NotImplemented: + return other + if self._check_nans(other, context): + return False + return self._cmp(other) == 0 + + def __ne__(self, other, context=None): + other = _convert_other(other, allow_float=True) + if other is NotImplemented: + return other + if self._check_nans(other, context): + return True + return self._cmp(other) != 0 + + def __lt__(self, other, context=None): + other = _convert_other(other, allow_float=True) + if other is NotImplemented: + return other + ans = self._compare_check_nans(other, context) + if ans: + return False + return self._cmp(other) < 0 + + def __le__(self, other, context=None): + other = _convert_other(other, allow_float=True) + if other is NotImplemented: + return other + ans = self._compare_check_nans(other, context) + if ans: + return False + return self._cmp(other) <= 0 + + def __gt__(self, other, context=None): + other = _convert_other(other, allow_float=True) + if other is NotImplemented: + return other + ans = self._compare_check_nans(other, context) + if ans: + return False + return self._cmp(other) > 0 + + def __ge__(self, other, context=None): + other = _convert_other(other, allow_float=True) + if other is NotImplemented: + return other + ans = self._compare_check_nans(other, context) + if ans: + return False + return self._cmp(other) >= 0 + + def compare(self, other, context=None): + """Compares one to another. + + -1 => a < b + 0 => a = b + 1 => a > b + NaN => one is NaN + Like __cmp__, but returns Decimal instances. + """ + other = _convert_other(other, raiseit=True) + + # Compare(NaN, NaN) = NaN + if (self._is_special or other and other._is_special): + ans = self._check_nans(other, context) + if ans: + return ans + + return Decimal(self._cmp(other)) + + def __hash__(self): + """x.__hash__() <==> hash(x)""" + # Decimal integers must hash the same as the ints + # + # The hash of a nonspecial noninteger Decimal must depend only + # on the value of that Decimal, and not on its representation. + # For example: hash(Decimal('100E-1')) == hash(Decimal('10')). + + # Equality comparisons involving signaling nans can raise an + # exception; since equality checks are implicitly and + # unpredictably used when checking set and dict membership, we + # prevent signaling nans from being used as set elements or + # dict keys by making __hash__ raise an exception. + if self._is_special: + if self.is_snan(): + raise TypeError('Cannot hash a signaling NaN value.') + elif self.is_nan(): + # 0 to match hash(float('nan')) + return 0 + else: + # values chosen to match hash(float('inf')) and + # hash(float('-inf')). + if self._sign: + return -271828 + else: + return 314159 + + # In Python 2.7, we're allowing comparisons (but not + # arithmetic operations) between floats and Decimals; so if + # a Decimal instance is exactly representable as a float then + # its hash should match that of the float. + self_as_float = float(self) + if Decimal.from_float(self_as_float) == self: + return hash(self_as_float) + + if self._isinteger(): + op = _WorkRep(self.to_integral_value()) + # to make computation feasible for Decimals with large + # exponent, we use the fact that hash(n) == hash(m) for + # any two nonzero integers n and m such that (i) n and m + # have the same sign, and (ii) n is congruent to m modulo + # 2**64-1. So we can replace hash((-1)**s*c*10**e) with + # hash((-1)**s*c*pow(10, e, 2**64-1). + return hash((-1)**op.sign*op.int*pow(10, op.exp, 2**64-1)) + # The value of a nonzero nonspecial Decimal instance is + # faithfully represented by the triple consisting of its sign, + # its adjusted exponent, and its coefficient with trailing + # zeros removed. + return hash((self._sign, + self._exp+len(self._int), + self._int.rstrip('0'))) + + def as_tuple(self): + """Represents the number as a triple tuple. + + To show the internals exactly as they are. + """ + return DecimalTuple(self._sign, tuple(map(int, self._int)), self._exp) + + def __repr__(self): + """Represents the number as an instance of Decimal.""" + # Invariant: eval(repr(d)) == d + return "Decimal('%s')" % str(self) + + def __str__(self, eng=False, context=None): + """Return string representation of the number in scientific notation. + + Captures all of the information in the underlying representation. + """ + + sign = ['', '-'][self._sign] + if self._is_special: + if self._exp == 'F': + return sign + 'Infinity' + elif self._exp == 'n': + return sign + 'NaN' + self._int + else: # self._exp == 'N' + return sign + 'sNaN' + self._int + + # number of digits of self._int to left of decimal point + leftdigits = self._exp + len(self._int) + + # dotplace is number of digits of self._int to the left of the + # decimal point in the mantissa of the output string (that is, + # after adjusting the exponent) + if self._exp <= 0 and leftdigits > -6: + # no exponent required + dotplace = leftdigits + elif not eng: + # usual scientific notation: 1 digit on left of the point + dotplace = 1 + elif self._int == '0': + # engineering notation, zero + dotplace = (leftdigits + 1) % 3 - 1 + else: + # engineering notation, nonzero + dotplace = (leftdigits - 1) % 3 + 1 + + if dotplace <= 0: + intpart = '0' + fracpart = '.' + '0'*(-dotplace) + self._int + elif dotplace >= len(self._int): + intpart = self._int+'0'*(dotplace-len(self._int)) + fracpart = '' + else: + intpart = self._int[:dotplace] + fracpart = '.' + self._int[dotplace:] + if leftdigits == dotplace: + exp = '' + else: + if context is None: + context = getcontext() + exp = ['e', 'E'][context.capitals] + "%+d" % (leftdigits-dotplace) + + return sign + intpart + fracpart + exp + + def to_eng_string(self, context=None): + """Convert to engineering-type string. + + Engineering notation has an exponent which is a multiple of 3, so there + are up to 3 digits left of the decimal place. + + Same rules for when in exponential and when as a value as in __str__. + """ + return self.__str__(eng=True, context=context) + + def __neg__(self, context=None): + """Returns a copy with the sign switched. + + Rounds, if it has reason. + """ + if self._is_special: + ans = self._check_nans(context=context) + if ans: + return ans + + if context is None: + context = getcontext() + + if not self and context.rounding != ROUND_FLOOR: + # -Decimal('0') is Decimal('0'), not Decimal('-0'), except + # in ROUND_FLOOR rounding mode. + ans = self.copy_abs() + else: + ans = self.copy_negate() + + return ans._fix(context) + + def __pos__(self, context=None): + """Returns a copy, unless it is a sNaN. + + Rounds the number (if more then precision digits) + """ + if self._is_special: + ans = self._check_nans(context=context) + if ans: + return ans + + if context is None: + context = getcontext() + + if not self and context.rounding != ROUND_FLOOR: + # + (-0) = 0, except in ROUND_FLOOR rounding mode. + ans = self.copy_abs() + else: + ans = Decimal(self) + + return ans._fix(context) + + def __abs__(self, round=True, context=None): + """Returns the absolute value of self. + + If the keyword argument 'round' is false, do not round. The + expression self.__abs__(round=False) is equivalent to + self.copy_abs(). + """ + if not round: + return self.copy_abs() + + if self._is_special: + ans = self._check_nans(context=context) + if ans: + return ans + + if self._sign: + ans = self.__neg__(context=context) + else: + ans = self.__pos__(context=context) + + return ans + + def __add__(self, other, context=None): + """Returns self + other. + + -INF + INF (or the reverse) cause InvalidOperation errors. + """ + other = _convert_other(other) + if other is NotImplemented: + return other + + if context is None: + context = getcontext() + + if self._is_special or other._is_special: + ans = self._check_nans(other, context) + if ans: + return ans + + if self._isinfinity(): + # If both INF, same sign => same as both, opposite => error. + if self._sign != other._sign and other._isinfinity(): + return context._raise_error(InvalidOperation, '-INF + INF') + return Decimal(self) + if other._isinfinity(): + return Decimal(other) # Can't both be infinity here + + exp = min(self._exp, other._exp) + negativezero = 0 + if context.rounding == ROUND_FLOOR and self._sign != other._sign: + # If the answer is 0, the sign should be negative, in this case. + negativezero = 1 + + if not self and not other: + sign = min(self._sign, other._sign) + if negativezero: + sign = 1 + ans = _dec_from_triple(sign, '0', exp) + ans = ans._fix(context) + return ans + if not self: + exp = max(exp, other._exp - context.prec-1) + ans = other._rescale(exp, context.rounding) + ans = ans._fix(context) + return ans + if not other: + exp = max(exp, self._exp - context.prec-1) + ans = self._rescale(exp, context.rounding) + ans = ans._fix(context) + return ans + + op1 = _WorkRep(self) + op2 = _WorkRep(other) + op1, op2 = _normalize(op1, op2, context.prec) + + result = _WorkRep() + if op1.sign != op2.sign: + # Equal and opposite + if op1.int == op2.int: + ans = _dec_from_triple(negativezero, '0', exp) + ans = ans._fix(context) + return ans + if op1.int < op2.int: + op1, op2 = op2, op1 + # OK, now abs(op1) > abs(op2) + if op1.sign == 1: + result.sign = 1 + op1.sign, op2.sign = op2.sign, op1.sign + else: + result.sign = 0 + # So we know the sign, and op1 > 0. + elif op1.sign == 1: + result.sign = 1 + op1.sign, op2.sign = (0, 0) + else: + result.sign = 0 + # Now, op1 > abs(op2) > 0 + + if op2.sign == 0: + result.int = op1.int + op2.int + else: + result.int = op1.int - op2.int + + result.exp = op1.exp + ans = Decimal(result) + ans = ans._fix(context) + return ans + + __radd__ = __add__ + + def __sub__(self, other, context=None): + """Return self - other""" + other = _convert_other(other) + if other is NotImplemented: + return other + + if self._is_special or other._is_special: + ans = self._check_nans(other, context=context) + if ans: + return ans + + # self - other is computed as self + other.copy_negate() + return self.__add__(other.copy_negate(), context=context) + + def __rsub__(self, other, context=None): + """Return other - self""" + other = _convert_other(other) + if other is NotImplemented: + return other + + return other.__sub__(self, context=context) + + def __mul__(self, other, context=None): + """Return self * other. + + (+-) INF * 0 (or its reverse) raise InvalidOperation. + """ + other = _convert_other(other) + if other is NotImplemented: + return other + + if context is None: + context = getcontext() + + resultsign = self._sign ^ other._sign + + if self._is_special or other._is_special: + ans = self._check_nans(other, context) + if ans: + return ans + + if self._isinfinity(): + if not other: + return context._raise_error(InvalidOperation, '(+-)INF * 0') + return _SignedInfinity[resultsign] + + if other._isinfinity(): + if not self: + return context._raise_error(InvalidOperation, '0 * (+-)INF') + return _SignedInfinity[resultsign] + + resultexp = self._exp + other._exp + + # Special case for multiplying by zero + if not self or not other: + ans = _dec_from_triple(resultsign, '0', resultexp) + # Fixing in case the exponent is out of bounds + ans = ans._fix(context) + return ans + + # Special case for multiplying by power of 10 + if self._int == '1': + ans = _dec_from_triple(resultsign, other._int, resultexp) + ans = ans._fix(context) + return ans + if other._int == '1': + ans = _dec_from_triple(resultsign, self._int, resultexp) + ans = ans._fix(context) + return ans + + op1 = _WorkRep(self) + op2 = _WorkRep(other) + + ans = _dec_from_triple(resultsign, str(op1.int * op2.int), resultexp) + ans = ans._fix(context) + + return ans + __rmul__ = __mul__ + + def __truediv__(self, other, context=None): + """Return self / other.""" + other = _convert_other(other) + if other is NotImplemented: + return NotImplemented + + if context is None: + context = getcontext() + + sign = self._sign ^ other._sign + + if self._is_special or other._is_special: + ans = self._check_nans(other, context) + if ans: + return ans + + if self._isinfinity() and other._isinfinity(): + return context._raise_error(InvalidOperation, '(+-)INF/(+-)INF') + + if self._isinfinity(): + return _SignedInfinity[sign] + + if other._isinfinity(): + context._raise_error(Clamped, 'Division by infinity') + return _dec_from_triple(sign, '0', context.Etiny()) + + # Special cases for zeroes + if not other: + if not self: + return context._raise_error(DivisionUndefined, '0 / 0') + return context._raise_error(DivisionByZero, 'x / 0', sign) + + if not self: + exp = self._exp - other._exp + coeff = 0 + else: + # OK, so neither = 0, INF or NaN + shift = len(other._int) - len(self._int) + context.prec + 1 + exp = self._exp - other._exp - shift + op1 = _WorkRep(self) + op2 = _WorkRep(other) + if shift >= 0: + coeff, remainder = divmod(op1.int * 10**shift, op2.int) + else: + coeff, remainder = divmod(op1.int, op2.int * 10**-shift) + if remainder: + # result is not exact; adjust to ensure correct rounding + if coeff % 5 == 0: + coeff += 1 + else: + # result is exact; get as close to ideal exponent as possible + ideal_exp = self._exp - other._exp + while exp < ideal_exp and coeff % 10 == 0: + coeff //= 10 + exp += 1 + + ans = _dec_from_triple(sign, str(coeff), exp) + return ans._fix(context) + + def _divide(self, other, context): + """Return (self // other, self % other), to context.prec precision. + + Assumes that neither self nor other is a NaN, that self is not + infinite and that other is nonzero. + """ + sign = self._sign ^ other._sign + if other._isinfinity(): + ideal_exp = self._exp + else: + ideal_exp = min(self._exp, other._exp) + + expdiff = self.adjusted() - other.adjusted() + if not self or other._isinfinity() or expdiff <= -2: + return (_dec_from_triple(sign, '0', 0), + self._rescale(ideal_exp, context.rounding)) + if expdiff <= context.prec: + op1 = _WorkRep(self) + op2 = _WorkRep(other) + if op1.exp >= op2.exp: + op1.int *= 10**(op1.exp - op2.exp) + else: + op2.int *= 10**(op2.exp - op1.exp) + q, r = divmod(op1.int, op2.int) + if q < 10**context.prec: + return (_dec_from_triple(sign, str(q), 0), + _dec_from_triple(self._sign, str(r), ideal_exp)) + + # Here the quotient is too large to be representable + ans = context._raise_error(DivisionImpossible, + 'quotient too large in //, % or divmod') + return ans, ans + + def __rtruediv__(self, other, context=None): + """Swaps self/other and returns __truediv__.""" + other = _convert_other(other) + if other is NotImplemented: + return other + return other.__truediv__(self, context=context) + + __div__ = __truediv__ + __rdiv__ = __rtruediv__ + + def __divmod__(self, other, context=None): + """ + Return (self // other, self % other) + """ + other = _convert_other(other) + if other is NotImplemented: + return other + + if context is None: + context = getcontext() + + ans = self._check_nans(other, context) + if ans: + return (ans, ans) + + sign = self._sign ^ other._sign + if self._isinfinity(): + if other._isinfinity(): + ans = context._raise_error(InvalidOperation, 'divmod(INF, INF)') + return ans, ans + else: + return (_SignedInfinity[sign], + context._raise_error(InvalidOperation, 'INF % x')) + + if not other: + if not self: + ans = context._raise_error(DivisionUndefined, 'divmod(0, 0)') + return ans, ans + else: + return (context._raise_error(DivisionByZero, 'x // 0', sign), + context._raise_error(InvalidOperation, 'x % 0')) + + quotient, remainder = self._divide(other, context) + remainder = remainder._fix(context) + return quotient, remainder + + def __rdivmod__(self, other, context=None): + """Swaps self/other and returns __divmod__.""" + other = _convert_other(other) + if other is NotImplemented: + return other + return other.__divmod__(self, context=context) + + def __mod__(self, other, context=None): + """ + self % other + """ + other = _convert_other(other) + if other is NotImplemented: + return other + + if context is None: + context = getcontext() + + ans = self._check_nans(other, context) + if ans: + return ans + + if self._isinfinity(): + return context._raise_error(InvalidOperation, 'INF % x') + elif not other: + if self: + return context._raise_error(InvalidOperation, 'x % 0') + else: + return context._raise_error(DivisionUndefined, '0 % 0') + + remainder = self._divide(other, context)[1] + remainder = remainder._fix(context) + return remainder + + def __rmod__(self, other, context=None): + """Swaps self/other and returns __mod__.""" + other = _convert_other(other) + if other is NotImplemented: + return other + return other.__mod__(self, context=context) + + def remainder_near(self, other, context=None): + """ + Remainder nearest to 0- abs(remainder-near) <= other/2 + """ + if context is None: + context = getcontext() + + other = _convert_other(other, raiseit=True) + + ans = self._check_nans(other, context) + if ans: + return ans + + # self == +/-infinity -> InvalidOperation + if self._isinfinity(): + return context._raise_error(InvalidOperation, + 'remainder_near(infinity, x)') + + # other == 0 -> either InvalidOperation or DivisionUndefined + if not other: + if self: + return context._raise_error(InvalidOperation, + 'remainder_near(x, 0)') + else: + return context._raise_error(DivisionUndefined, + 'remainder_near(0, 0)') + + # other = +/-infinity -> remainder = self + if other._isinfinity(): + ans = Decimal(self) + return ans._fix(context) + + # self = 0 -> remainder = self, with ideal exponent + ideal_exponent = min(self._exp, other._exp) + if not self: + ans = _dec_from_triple(self._sign, '0', ideal_exponent) + return ans._fix(context) + + # catch most cases of large or small quotient + expdiff = self.adjusted() - other.adjusted() + if expdiff >= context.prec + 1: + # expdiff >= prec+1 => abs(self/other) > 10**prec + return context._raise_error(DivisionImpossible) + if expdiff <= -2: + # expdiff <= -2 => abs(self/other) < 0.1 + ans = self._rescale(ideal_exponent, context.rounding) + return ans._fix(context) + + # adjust both arguments to have the same exponent, then divide + op1 = _WorkRep(self) + op2 = _WorkRep(other) + if op1.exp >= op2.exp: + op1.int *= 10**(op1.exp - op2.exp) + else: + op2.int *= 10**(op2.exp - op1.exp) + q, r = divmod(op1.int, op2.int) + # remainder is r*10**ideal_exponent; other is +/-op2.int * + # 10**ideal_exponent. Apply correction to ensure that + # abs(remainder) <= abs(other)/2 + if 2*r + (q&1) > op2.int: + r -= op2.int + q += 1 + + if q >= 10**context.prec: + return context._raise_error(DivisionImpossible) + + # result has same sign as self unless r is negative + sign = self._sign + if r < 0: + sign = 1-sign + r = -r + + ans = _dec_from_triple(sign, str(r), ideal_exponent) + return ans._fix(context) + + def __floordiv__(self, other, context=None): + """self // other""" + other = _convert_other(other) + if other is NotImplemented: + return other + + if context is None: + context = getcontext() + + ans = self._check_nans(other, context) + if ans: + return ans + + if self._isinfinity(): + if other._isinfinity(): + return context._raise_error(InvalidOperation, 'INF // INF') + else: + return _SignedInfinity[self._sign ^ other._sign] + + if not other: + if self: + return context._raise_error(DivisionByZero, 'x // 0', + self._sign ^ other._sign) + else: + return context._raise_error(DivisionUndefined, '0 // 0') + + return self._divide(other, context)[0] + + def __rfloordiv__(self, other, context=None): + """Swaps self/other and returns __floordiv__.""" + other = _convert_other(other) + if other is NotImplemented: + return other + return other.__floordiv__(self, context=context) + + def __float__(self): + """Float representation.""" + if self._isnan(): + if self.is_snan(): + raise ValueError("Cannot convert signaling NaN to float") + s = "-nan" if self._sign else "nan" + else: + s = str(self) + return float(s) + + def __int__(self): + """Converts self to an int, truncating if necessary.""" + if self._is_special: + if self._isnan(): + raise ValueError("Cannot convert NaN to integer") + elif self._isinfinity(): + raise OverflowError("Cannot convert infinity to integer") + s = (-1)**self._sign + if self._exp >= 0: + return s*int(self._int)*10**self._exp + else: + return s*int(self._int[:self._exp] or '0') + + __trunc__ = __int__ + + def real(self): + return self + real = property(real) + + def imag(self): + return Decimal(0) + imag = property(imag) + + def conjugate(self): + return self + + def __complex__(self): + return complex(float(self)) + + def __long__(self): + """Converts to a long. + + Equivalent to long(int(self)) + """ + return long(self.__int__()) + + def _fix_nan(self, context): + """Decapitate the payload of a NaN to fit the context""" + payload = self._int + + # maximum length of payload is precision if _clamp=0, + # precision-1 if _clamp=1. + max_payload_len = context.prec - context._clamp + if len(payload) > max_payload_len: + payload = payload[len(payload)-max_payload_len:].lstrip('0') + return _dec_from_triple(self._sign, payload, self._exp, True) + return Decimal(self) + + def _fix(self, context): + """Round if it is necessary to keep self within prec precision. + + Rounds and fixes the exponent. Does not raise on a sNaN. + + Arguments: + self - Decimal instance + context - context used. + """ + + if self._is_special: + if self._isnan(): + # decapitate payload if necessary + return self._fix_nan(context) + else: + # self is +/-Infinity; return unaltered + return Decimal(self) + + # if self is zero then exponent should be between Etiny and + # Emax if _clamp==0, and between Etiny and Etop if _clamp==1. + Etiny = context.Etiny() + Etop = context.Etop() + if not self: + exp_max = [context.Emax, Etop][context._clamp] + new_exp = min(max(self._exp, Etiny), exp_max) + if new_exp != self._exp: + context._raise_error(Clamped) + return _dec_from_triple(self._sign, '0', new_exp) + else: + return Decimal(self) + + # exp_min is the smallest allowable exponent of the result, + # equal to max(self.adjusted()-context.prec+1, Etiny) + exp_min = len(self._int) + self._exp - context.prec + if exp_min > Etop: + # overflow: exp_min > Etop iff self.adjusted() > Emax + ans = context._raise_error(Overflow, 'above Emax', self._sign) + context._raise_error(Inexact) + context._raise_error(Rounded) + return ans + + self_is_subnormal = exp_min < Etiny + if self_is_subnormal: + exp_min = Etiny + + # round if self has too many digits + if self._exp < exp_min: + digits = len(self._int) + self._exp - exp_min + if digits < 0: + self = _dec_from_triple(self._sign, '1', exp_min-1) + digits = 0 + rounding_method = self._pick_rounding_function[context.rounding] + changed = rounding_method(self, digits) + coeff = self._int[:digits] or '0' + if changed > 0: + coeff = str(int(coeff)+1) + if len(coeff) > context.prec: + coeff = coeff[:-1] + exp_min += 1 + + # check whether the rounding pushed the exponent out of range + if exp_min > Etop: + ans = context._raise_error(Overflow, 'above Emax', self._sign) + else: + ans = _dec_from_triple(self._sign, coeff, exp_min) + + # raise the appropriate signals, taking care to respect + # the precedence described in the specification + if changed and self_is_subnormal: + context._raise_error(Underflow) + if self_is_subnormal: + context._raise_error(Subnormal) + if changed: + context._raise_error(Inexact) + context._raise_error(Rounded) + if not ans: + # raise Clamped on underflow to 0 + context._raise_error(Clamped) + return ans + + if self_is_subnormal: + context._raise_error(Subnormal) + + # fold down if _clamp == 1 and self has too few digits + if context._clamp == 1 and self._exp > Etop: + context._raise_error(Clamped) + self_padded = self._int + '0'*(self._exp - Etop) + return _dec_from_triple(self._sign, self_padded, Etop) + + # here self was representable to begin with; return unchanged + return Decimal(self) + + # for each of the rounding functions below: + # self is a finite, nonzero Decimal + # prec is an integer satisfying 0 <= prec < len(self._int) + # + # each function returns either -1, 0, or 1, as follows: + # 1 indicates that self should be rounded up (away from zero) + # 0 indicates that self should be truncated, and that all the + # digits to be truncated are zeros (so the value is unchanged) + # -1 indicates that there are nonzero digits to be truncated + + def _round_down(self, prec): + """Also known as round-towards-0, truncate.""" + if _all_zeros(self._int, prec): + return 0 + else: + return -1 + + def _round_up(self, prec): + """Rounds away from 0.""" + return -self._round_down(prec) + + def _round_half_up(self, prec): + """Rounds 5 up (away from 0)""" + if self._int[prec] in '56789': + return 1 + elif _all_zeros(self._int, prec): + return 0 + else: + return -1 + + def _round_half_down(self, prec): + """Round 5 down""" + if _exact_half(self._int, prec): + return -1 + else: + return self._round_half_up(prec) + + def _round_half_even(self, prec): + """Round 5 to even, rest to nearest.""" + if _exact_half(self._int, prec) and \ + (prec == 0 or self._int[prec-1] in '02468'): + return -1 + else: + return self._round_half_up(prec) + + def _round_ceiling(self, prec): + """Rounds up (not away from 0 if negative.)""" + if self._sign: + return self._round_down(prec) + else: + return -self._round_down(prec) + + def _round_floor(self, prec): + """Rounds down (not towards 0 if negative)""" + if not self._sign: + return self._round_down(prec) + else: + return -self._round_down(prec) + + def _round_05up(self, prec): + """Round down unless digit prec-1 is 0 or 5.""" + if prec and self._int[prec-1] not in '05': + return self._round_down(prec) + else: + return -self._round_down(prec) + + _pick_rounding_function = dict( + ROUND_DOWN = _round_down, + ROUND_UP = _round_up, + ROUND_HALF_UP = _round_half_up, + ROUND_HALF_DOWN = _round_half_down, + ROUND_HALF_EVEN = _round_half_even, + ROUND_CEILING = _round_ceiling, + ROUND_FLOOR = _round_floor, + ROUND_05UP = _round_05up, + ) + + def fma(self, other, third, context=None): + """Fused multiply-add. + + Returns self*other+third with no rounding of the intermediate + product self*other. + + self and other are multiplied together, with no rounding of + the result. The third operand is then added to the result, + and a single final rounding is performed. + """ + + other = _convert_other(other, raiseit=True) + + # compute product; raise InvalidOperation if either operand is + # a signaling NaN or if the product is zero times infinity. + if self._is_special or other._is_special: + if context is None: + context = getcontext() + if self._exp == 'N': + return context._raise_error(InvalidOperation, 'sNaN', self) + if other._exp == 'N': + return context._raise_error(InvalidOperation, 'sNaN', other) + if self._exp == 'n': + product = self + elif other._exp == 'n': + product = other + elif self._exp == 'F': + if not other: + return context._raise_error(InvalidOperation, + 'INF * 0 in fma') + product = _SignedInfinity[self._sign ^ other._sign] + elif other._exp == 'F': + if not self: + return context._raise_error(InvalidOperation, + '0 * INF in fma') + product = _SignedInfinity[self._sign ^ other._sign] + else: + product = _dec_from_triple(self._sign ^ other._sign, + str(int(self._int) * int(other._int)), + self._exp + other._exp) + + third = _convert_other(third, raiseit=True) + return product.__add__(third, context) + + def _power_modulo(self, other, modulo, context=None): + """Three argument version of __pow__""" + + # if can't convert other and modulo to Decimal, raise + # TypeError; there's no point returning NotImplemented (no + # equivalent of __rpow__ for three argument pow) + other = _convert_other(other, raiseit=True) + modulo = _convert_other(modulo, raiseit=True) + + if context is None: + context = getcontext() + + # deal with NaNs: if there are any sNaNs then first one wins, + # (i.e. behaviour for NaNs is identical to that of fma) + self_is_nan = self._isnan() + other_is_nan = other._isnan() + modulo_is_nan = modulo._isnan() + if self_is_nan or other_is_nan or modulo_is_nan: + if self_is_nan == 2: + return context._raise_error(InvalidOperation, 'sNaN', + self) + if other_is_nan == 2: + return context._raise_error(InvalidOperation, 'sNaN', + other) + if modulo_is_nan == 2: + return context._raise_error(InvalidOperation, 'sNaN', + modulo) + if self_is_nan: + return self._fix_nan(context) + if other_is_nan: + return other._fix_nan(context) + return modulo._fix_nan(context) + + # check inputs: we apply same restrictions as Python's pow() + if not (self._isinteger() and + other._isinteger() and + modulo._isinteger()): + return context._raise_error(InvalidOperation, + 'pow() 3rd argument not allowed ' + 'unless all arguments are integers') + if other < 0: + return context._raise_error(InvalidOperation, + 'pow() 2nd argument cannot be ' + 'negative when 3rd argument specified') + if not modulo: + return context._raise_error(InvalidOperation, + 'pow() 3rd argument cannot be 0') + + # additional restriction for decimal: the modulus must be less + # than 10**prec in absolute value + if modulo.adjusted() >= context.prec: + return context._raise_error(InvalidOperation, + 'insufficient precision: pow() 3rd ' + 'argument must not have more than ' + 'precision digits') + + # define 0**0 == NaN, for consistency with two-argument pow + # (even though it hurts!) + if not other and not self: + return context._raise_error(InvalidOperation, + 'at least one of pow() 1st argument ' + 'and 2nd argument must be nonzero ;' + '0**0 is not defined') + + # compute sign of result + if other._iseven(): + sign = 0 + else: + sign = self._sign + + # convert modulo to a Python integer, and self and other to + # Decimal integers (i.e. force their exponents to be >= 0) + modulo = abs(int(modulo)) + base = _WorkRep(self.to_integral_value()) + exponent = _WorkRep(other.to_integral_value()) + + # compute result using integer pow() + base = (base.int % modulo * pow(10, base.exp, modulo)) % modulo + for i in xrange(exponent.exp): + base = pow(base, 10, modulo) + base = pow(base, exponent.int, modulo) + + return _dec_from_triple(sign, str(base), 0) + + def _power_exact(self, other, p): + """Attempt to compute self**other exactly. + + Given Decimals self and other and an integer p, attempt to + compute an exact result for the power self**other, with p + digits of precision. Return None if self**other is not + exactly representable in p digits. + + Assumes that elimination of special cases has already been + performed: self and other must both be nonspecial; self must + be positive and not numerically equal to 1; other must be + nonzero. For efficiency, other._exp should not be too large, + so that 10**abs(other._exp) is a feasible calculation.""" + + # In the comments below, we write x for the value of self and y for the + # value of other. Write x = xc*10**xe and abs(y) = yc*10**ye, with xc + # and yc positive integers not divisible by 10. + + # The main purpose of this method is to identify the *failure* + # of x**y to be exactly representable with as little effort as + # possible. So we look for cheap and easy tests that + # eliminate the possibility of x**y being exact. Only if all + # these tests are passed do we go on to actually compute x**y. + + # Here's the main idea. Express y as a rational number m/n, with m and + # n relatively prime and n>0. Then for x**y to be exactly + # representable (at *any* precision), xc must be the nth power of a + # positive integer and xe must be divisible by n. If y is negative + # then additionally xc must be a power of either 2 or 5, hence a power + # of 2**n or 5**n. + # + # There's a limit to how small |y| can be: if y=m/n as above + # then: + # + # (1) if xc != 1 then for the result to be representable we + # need xc**(1/n) >= 2, and hence also xc**|y| >= 2. So + # if |y| <= 1/nbits(xc) then xc < 2**nbits(xc) <= + # 2**(1/|y|), hence xc**|y| < 2 and the result is not + # representable. + # + # (2) if xe != 0, |xe|*(1/n) >= 1, so |xe|*|y| >= 1. Hence if + # |y| < 1/|xe| then the result is not representable. + # + # Note that since x is not equal to 1, at least one of (1) and + # (2) must apply. Now |y| < 1/nbits(xc) iff |yc|*nbits(xc) < + # 10**-ye iff len(str(|yc|*nbits(xc)) <= -ye. + # + # There's also a limit to how large y can be, at least if it's + # positive: the normalized result will have coefficient xc**y, + # so if it's representable then xc**y < 10**p, and y < + # p/log10(xc). Hence if y*log10(xc) >= p then the result is + # not exactly representable. + + # if len(str(abs(yc*xe)) <= -ye then abs(yc*xe) < 10**-ye, + # so |y| < 1/xe and the result is not representable. + # Similarly, len(str(abs(yc)*xc_bits)) <= -ye implies |y| + # < 1/nbits(xc). + + x = _WorkRep(self) + xc, xe = x.int, x.exp + while xc % 10 == 0: + xc //= 10 + xe += 1 + + y = _WorkRep(other) + yc, ye = y.int, y.exp + while yc % 10 == 0: + yc //= 10 + ye += 1 + + # case where xc == 1: result is 10**(xe*y), with xe*y + # required to be an integer + if xc == 1: + xe *= yc + # result is now 10**(xe * 10**ye); xe * 10**ye must be integral + while xe % 10 == 0: + xe //= 10 + ye += 1 + if ye < 0: + return None + exponent = xe * 10**ye + if y.sign == 1: + exponent = -exponent + # if other is a nonnegative integer, use ideal exponent + if other._isinteger() and other._sign == 0: + ideal_exponent = self._exp*int(other) + zeros = min(exponent-ideal_exponent, p-1) + else: + zeros = 0 + return _dec_from_triple(0, '1' + '0'*zeros, exponent-zeros) + + # case where y is negative: xc must be either a power + # of 2 or a power of 5. + if y.sign == 1: + last_digit = xc % 10 + if last_digit in (2,4,6,8): + # quick test for power of 2 + if xc & -xc != xc: + return None + # now xc is a power of 2; e is its exponent + e = _nbits(xc)-1 + + # We now have: + # + # x = 2**e * 10**xe, e > 0, and y < 0. + # + # The exact result is: + # + # x**y = 5**(-e*y) * 10**(e*y + xe*y) + # + # provided that both e*y and xe*y are integers. Note that if + # 5**(-e*y) >= 10**p, then the result can't be expressed + # exactly with p digits of precision. + # + # Using the above, we can guard against large values of ye. + # 93/65 is an upper bound for log(10)/log(5), so if + # + # ye >= len(str(93*p//65)) + # + # then + # + # -e*y >= -y >= 10**ye > 93*p/65 > p*log(10)/log(5), + # + # so 5**(-e*y) >= 10**p, and the coefficient of the result + # can't be expressed in p digits. + + # emax >= largest e such that 5**e < 10**p. + emax = p*93//65 + if ye >= len(str(emax)): + return None + + # Find -e*y and -xe*y; both must be integers + e = _decimal_lshift_exact(e * yc, ye) + xe = _decimal_lshift_exact(xe * yc, ye) + if e is None or xe is None: + return None + + if e > emax: + return None + xc = 5**e + + elif last_digit == 5: + # e >= log_5(xc) if xc is a power of 5; we have + # equality all the way up to xc=5**2658 + e = _nbits(xc)*28//65 + xc, remainder = divmod(5**e, xc) + if remainder: + return None + while xc % 5 == 0: + xc //= 5 + e -= 1 + + # Guard against large values of ye, using the same logic as in + # the 'xc is a power of 2' branch. 10/3 is an upper bound for + # log(10)/log(2). + emax = p*10//3 + if ye >= len(str(emax)): + return None + + e = _decimal_lshift_exact(e * yc, ye) + xe = _decimal_lshift_exact(xe * yc, ye) + if e is None or xe is None: + return None + + if e > emax: + return None + xc = 2**e + else: + return None + + if xc >= 10**p: + return None + xe = -e-xe + return _dec_from_triple(0, str(xc), xe) + + # now y is positive; find m and n such that y = m/n + if ye >= 0: + m, n = yc*10**ye, 1 + else: + if xe != 0 and len(str(abs(yc*xe))) <= -ye: + return None + xc_bits = _nbits(xc) + if xc != 1 and len(str(abs(yc)*xc_bits)) <= -ye: + return None + m, n = yc, 10**(-ye) + while m % 2 == n % 2 == 0: + m //= 2 + n //= 2 + while m % 5 == n % 5 == 0: + m //= 5 + n //= 5 + + # compute nth root of xc*10**xe + if n > 1: + # if 1 < xc < 2**n then xc isn't an nth power + if xc != 1 and xc_bits <= n: + return None + + xe, rem = divmod(xe, n) + if rem != 0: + return None + + # compute nth root of xc using Newton's method + a = 1L << -(-_nbits(xc)//n) # initial estimate + while True: + q, r = divmod(xc, a**(n-1)) + if a <= q: + break + else: + a = (a*(n-1) + q)//n + if not (a == q and r == 0): + return None + xc = a + + # now xc*10**xe is the nth root of the original xc*10**xe + # compute mth power of xc*10**xe + + # if m > p*100//_log10_lb(xc) then m > p/log10(xc), hence xc**m > + # 10**p and the result is not representable. + if xc > 1 and m > p*100//_log10_lb(xc): + return None + xc = xc**m + xe *= m + if xc > 10**p: + return None + + # by this point the result *is* exactly representable + # adjust the exponent to get as close as possible to the ideal + # exponent, if necessary + str_xc = str(xc) + if other._isinteger() and other._sign == 0: + ideal_exponent = self._exp*int(other) + zeros = min(xe-ideal_exponent, p-len(str_xc)) + else: + zeros = 0 + return _dec_from_triple(0, str_xc+'0'*zeros, xe-zeros) + + def __pow__(self, other, modulo=None, context=None): + """Return self ** other [ % modulo]. + + With two arguments, compute self**other. + + With three arguments, compute (self**other) % modulo. For the + three argument form, the following restrictions on the + arguments hold: + + - all three arguments must be integral + - other must be nonnegative + - either self or other (or both) must be nonzero + - modulo must be nonzero and must have at most p digits, + where p is the context precision. + + If any of these restrictions is violated the InvalidOperation + flag is raised. + + The result of pow(self, other, modulo) is identical to the + result that would be obtained by computing (self**other) % + modulo with unbounded precision, but is computed more + efficiently. It is always exact. + """ + + if modulo is not None: + return self._power_modulo(other, modulo, context) + + other = _convert_other(other) + if other is NotImplemented: + return other + + if context is None: + context = getcontext() + + # either argument is a NaN => result is NaN + ans = self._check_nans(other, context) + if ans: + return ans + + # 0**0 = NaN (!), x**0 = 1 for nonzero x (including +/-Infinity) + if not other: + if not self: + return context._raise_error(InvalidOperation, '0 ** 0') + else: + return _One + + # result has sign 1 iff self._sign is 1 and other is an odd integer + result_sign = 0 + if self._sign == 1: + if other._isinteger(): + if not other._iseven(): + result_sign = 1 + else: + # -ve**noninteger = NaN + # (-0)**noninteger = 0**noninteger + if self: + return context._raise_error(InvalidOperation, + 'x ** y with x negative and y not an integer') + # negate self, without doing any unwanted rounding + self = self.copy_negate() + + # 0**(+ve or Inf)= 0; 0**(-ve or -Inf) = Infinity + if not self: + if other._sign == 0: + return _dec_from_triple(result_sign, '0', 0) + else: + return _SignedInfinity[result_sign] + + # Inf**(+ve or Inf) = Inf; Inf**(-ve or -Inf) = 0 + if self._isinfinity(): + if other._sign == 0: + return _SignedInfinity[result_sign] + else: + return _dec_from_triple(result_sign, '0', 0) + + # 1**other = 1, but the choice of exponent and the flags + # depend on the exponent of self, and on whether other is a + # positive integer, a negative integer, or neither + if self == _One: + if other._isinteger(): + # exp = max(self._exp*max(int(other), 0), + # 1-context.prec) but evaluating int(other) directly + # is dangerous until we know other is small (other + # could be 1e999999999) + if other._sign == 1: + multiplier = 0 + elif other > context.prec: + multiplier = context.prec + else: + multiplier = int(other) + + exp = self._exp * multiplier + if exp < 1-context.prec: + exp = 1-context.prec + context._raise_error(Rounded) + else: + context._raise_error(Inexact) + context._raise_error(Rounded) + exp = 1-context.prec + + return _dec_from_triple(result_sign, '1'+'0'*-exp, exp) + + # compute adjusted exponent of self + self_adj = self.adjusted() + + # self ** infinity is infinity if self > 1, 0 if self < 1 + # self ** -infinity is infinity if self < 1, 0 if self > 1 + if other._isinfinity(): + if (other._sign == 0) == (self_adj < 0): + return _dec_from_triple(result_sign, '0', 0) + else: + return _SignedInfinity[result_sign] + + # from here on, the result always goes through the call + # to _fix at the end of this function. + ans = None + exact = False + + # crude test to catch cases of extreme overflow/underflow. If + # log10(self)*other >= 10**bound and bound >= len(str(Emax)) + # then 10**bound >= 10**len(str(Emax)) >= Emax+1 and hence + # self**other >= 10**(Emax+1), so overflow occurs. The test + # for underflow is similar. + bound = self._log10_exp_bound() + other.adjusted() + if (self_adj >= 0) == (other._sign == 0): + # self > 1 and other +ve, or self < 1 and other -ve + # possibility of overflow + if bound >= len(str(context.Emax)): + ans = _dec_from_triple(result_sign, '1', context.Emax+1) + else: + # self > 1 and other -ve, or self < 1 and other +ve + # possibility of underflow to 0 + Etiny = context.Etiny() + if bound >= len(str(-Etiny)): + ans = _dec_from_triple(result_sign, '1', Etiny-1) + + # try for an exact result with precision +1 + if ans is None: + ans = self._power_exact(other, context.prec + 1) + if ans is not None: + if result_sign == 1: + ans = _dec_from_triple(1, ans._int, ans._exp) + exact = True + + # usual case: inexact result, x**y computed directly as exp(y*log(x)) + if ans is None: + p = context.prec + x = _WorkRep(self) + xc, xe = x.int, x.exp + y = _WorkRep(other) + yc, ye = y.int, y.exp + if y.sign == 1: + yc = -yc + + # compute correctly rounded result: start with precision +3, + # then increase precision until result is unambiguously roundable + extra = 3 + while True: + coeff, exp = _dpower(xc, xe, yc, ye, p+extra) + if coeff % (5*10**(len(str(coeff))-p-1)): + break + extra += 3 + + ans = _dec_from_triple(result_sign, str(coeff), exp) + + # unlike exp, ln and log10, the power function respects the + # rounding mode; no need to switch to ROUND_HALF_EVEN here + + # There's a difficulty here when 'other' is not an integer and + # the result is exact. In this case, the specification + # requires that the Inexact flag be raised (in spite of + # exactness), but since the result is exact _fix won't do this + # for us. (Correspondingly, the Underflow signal should also + # be raised for subnormal results.) We can't directly raise + # these signals either before or after calling _fix, since + # that would violate the precedence for signals. So we wrap + # the ._fix call in a temporary context, and reraise + # afterwards. + if exact and not other._isinteger(): + # pad with zeros up to length context.prec+1 if necessary; this + # ensures that the Rounded signal will be raised. + if len(ans._int) <= context.prec: + expdiff = context.prec + 1 - len(ans._int) + ans = _dec_from_triple(ans._sign, ans._int+'0'*expdiff, + ans._exp-expdiff) + + # create a copy of the current context, with cleared flags/traps + newcontext = context.copy() + newcontext.clear_flags() + for exception in _signals: + newcontext.traps[exception] = 0 + + # round in the new context + ans = ans._fix(newcontext) + + # raise Inexact, and if necessary, Underflow + newcontext._raise_error(Inexact) + if newcontext.flags[Subnormal]: + newcontext._raise_error(Underflow) + + # propagate signals to the original context; _fix could + # have raised any of Overflow, Underflow, Subnormal, + # Inexact, Rounded, Clamped. Overflow needs the correct + # arguments. Note that the order of the exceptions is + # important here. + if newcontext.flags[Overflow]: + context._raise_error(Overflow, 'above Emax', ans._sign) + for exception in Underflow, Subnormal, Inexact, Rounded, Clamped: + if newcontext.flags[exception]: + context._raise_error(exception) + + else: + ans = ans._fix(context) + + return ans + + def __rpow__(self, other, context=None): + """Swaps self/other and returns __pow__.""" + other = _convert_other(other) + if other is NotImplemented: + return other + return other.__pow__(self, context=context) + + def normalize(self, context=None): + """Normalize- strip trailing 0s, change anything equal to 0 to 0e0""" + + if context is None: + context = getcontext() + + if self._is_special: + ans = self._check_nans(context=context) + if ans: + return ans + + dup = self._fix(context) + if dup._isinfinity(): + return dup + + if not dup: + return _dec_from_triple(dup._sign, '0', 0) + exp_max = [context.Emax, context.Etop()][context._clamp] + end = len(dup._int) + exp = dup._exp + while dup._int[end-1] == '0' and exp < exp_max: + exp += 1 + end -= 1 + return _dec_from_triple(dup._sign, dup._int[:end], exp) + + def quantize(self, exp, rounding=None, context=None, watchexp=True): + """Quantize self so its exponent is the same as that of exp. + + Similar to self._rescale(exp._exp) but with error checking. + """ + exp = _convert_other(exp, raiseit=True) + + if context is None: + context = getcontext() + if rounding is None: + rounding = context.rounding + + if self._is_special or exp._is_special: + ans = self._check_nans(exp, context) + if ans: + return ans + + if exp._isinfinity() or self._isinfinity(): + if exp._isinfinity() and self._isinfinity(): + return Decimal(self) # if both are inf, it is OK + return context._raise_error(InvalidOperation, + 'quantize with one INF') + + # if we're not watching exponents, do a simple rescale + if not watchexp: + ans = self._rescale(exp._exp, rounding) + # raise Inexact and Rounded where appropriate + if ans._exp > self._exp: + context._raise_error(Rounded) + if ans != self: + context._raise_error(Inexact) + return ans + + # exp._exp should be between Etiny and Emax + if not (context.Etiny() <= exp._exp <= context.Emax): + return context._raise_error(InvalidOperation, + 'target exponent out of bounds in quantize') + + if not self: + ans = _dec_from_triple(self._sign, '0', exp._exp) + return ans._fix(context) + + self_adjusted = self.adjusted() + if self_adjusted > context.Emax: + return context._raise_error(InvalidOperation, + 'exponent of quantize result too large for current context') + if self_adjusted - exp._exp + 1 > context.prec: + return context._raise_error(InvalidOperation, + 'quantize result has too many digits for current context') + + ans = self._rescale(exp._exp, rounding) + if ans.adjusted() > context.Emax: + return context._raise_error(InvalidOperation, + 'exponent of quantize result too large for current context') + if len(ans._int) > context.prec: + return context._raise_error(InvalidOperation, + 'quantize result has too many digits for current context') + + # raise appropriate flags + if ans and ans.adjusted() < context.Emin: + context._raise_error(Subnormal) + if ans._exp > self._exp: + if ans != self: + context._raise_error(Inexact) + context._raise_error(Rounded) + + # call to fix takes care of any necessary folddown, and + # signals Clamped if necessary + ans = ans._fix(context) + return ans + + def same_quantum(self, other): + """Return True if self and other have the same exponent; otherwise + return False. + + If either operand is a special value, the following rules are used: + * return True if both operands are infinities + * return True if both operands are NaNs + * otherwise, return False. + """ + other = _convert_other(other, raiseit=True) + if self._is_special or other._is_special: + return (self.is_nan() and other.is_nan() or + self.is_infinite() and other.is_infinite()) + return self._exp == other._exp + + def _rescale(self, exp, rounding): + """Rescale self so that the exponent is exp, either by padding with zeros + or by truncating digits, using the given rounding mode. + + Specials are returned without change. This operation is + quiet: it raises no flags, and uses no information from the + context. + + exp = exp to scale to (an integer) + rounding = rounding mode + """ + if self._is_special: + return Decimal(self) + if not self: + return _dec_from_triple(self._sign, '0', exp) + + if self._exp >= exp: + # pad answer with zeros if necessary + return _dec_from_triple(self._sign, + self._int + '0'*(self._exp - exp), exp) + + # too many digits; round and lose data. If self.adjusted() < + # exp-1, replace self by 10**(exp-1) before rounding + digits = len(self._int) + self._exp - exp + if digits < 0: + self = _dec_from_triple(self._sign, '1', exp-1) + digits = 0 + this_function = self._pick_rounding_function[rounding] + changed = this_function(self, digits) + coeff = self._int[:digits] or '0' + if changed == 1: + coeff = str(int(coeff)+1) + return _dec_from_triple(self._sign, coeff, exp) + + def _round(self, places, rounding): + """Round a nonzero, nonspecial Decimal to a fixed number of + significant figures, using the given rounding mode. + + Infinities, NaNs and zeros are returned unaltered. + + This operation is quiet: it raises no flags, and uses no + information from the context. + + """ + if places <= 0: + raise ValueError("argument should be at least 1 in _round") + if self._is_special or not self: + return Decimal(self) + ans = self._rescale(self.adjusted()+1-places, rounding) + # it can happen that the rescale alters the adjusted exponent; + # for example when rounding 99.97 to 3 significant figures. + # When this happens we end up with an extra 0 at the end of + # the number; a second rescale fixes this. + if ans.adjusted() != self.adjusted(): + ans = ans._rescale(ans.adjusted()+1-places, rounding) + return ans + + def to_integral_exact(self, rounding=None, context=None): + """Rounds to a nearby integer. + + If no rounding mode is specified, take the rounding mode from + the context. This method raises the Rounded and Inexact flags + when appropriate. + + See also: to_integral_value, which does exactly the same as + this method except that it doesn't raise Inexact or Rounded. + """ + if self._is_special: + ans = self._check_nans(context=context) + if ans: + return ans + return Decimal(self) + if self._exp >= 0: + return Decimal(self) + if not self: + return _dec_from_triple(self._sign, '0', 0) + if context is None: + context = getcontext() + if rounding is None: + rounding = context.rounding + ans = self._rescale(0, rounding) + if ans != self: + context._raise_error(Inexact) + context._raise_error(Rounded) + return ans + + def to_integral_value(self, rounding=None, context=None): + """Rounds to the nearest integer, without raising inexact, rounded.""" + if context is None: + context = getcontext() + if rounding is None: + rounding = context.rounding + if self._is_special: + ans = self._check_nans(context=context) + if ans: + return ans + return Decimal(self) + if self._exp >= 0: + return Decimal(self) + else: + return self._rescale(0, rounding) + + # the method name changed, but we provide also the old one, for compatibility + to_integral = to_integral_value + + def sqrt(self, context=None): + """Return the square root of self.""" + if context is None: + context = getcontext() + + if self._is_special: + ans = self._check_nans(context=context) + if ans: + return ans + + if self._isinfinity() and self._sign == 0: + return Decimal(self) + + if not self: + # exponent = self._exp // 2. sqrt(-0) = -0 + ans = _dec_from_triple(self._sign, '0', self._exp // 2) + return ans._fix(context) + + if self._sign == 1: + return context._raise_error(InvalidOperation, 'sqrt(-x), x > 0') + + # At this point self represents a positive number. Let p be + # the desired precision and express self in the form c*100**e + # with c a positive real number and e an integer, c and e + # being chosen so that 100**(p-1) <= c < 100**p. Then the + # (exact) square root of self is sqrt(c)*10**e, and 10**(p-1) + # <= sqrt(c) < 10**p, so the closest representable Decimal at + # precision p is n*10**e where n = round_half_even(sqrt(c)), + # the closest integer to sqrt(c) with the even integer chosen + # in the case of a tie. + # + # To ensure correct rounding in all cases, we use the + # following trick: we compute the square root to an extra + # place (precision p+1 instead of precision p), rounding down. + # Then, if the result is inexact and its last digit is 0 or 5, + # we increase the last digit to 1 or 6 respectively; if it's + # exact we leave the last digit alone. Now the final round to + # p places (or fewer in the case of underflow) will round + # correctly and raise the appropriate flags. + + # use an extra digit of precision + prec = context.prec+1 + + # write argument in the form c*100**e where e = self._exp//2 + # is the 'ideal' exponent, to be used if the square root is + # exactly representable. l is the number of 'digits' of c in + # base 100, so that 100**(l-1) <= c < 100**l. + op = _WorkRep(self) + e = op.exp >> 1 + if op.exp & 1: + c = op.int * 10 + l = (len(self._int) >> 1) + 1 + else: + c = op.int + l = len(self._int)+1 >> 1 + + # rescale so that c has exactly prec base 100 'digits' + shift = prec-l + if shift >= 0: + c *= 100**shift + exact = True + else: + c, remainder = divmod(c, 100**-shift) + exact = not remainder + e -= shift + + # find n = floor(sqrt(c)) using Newton's method + n = 10**prec + while True: + q = c//n + if n <= q: + break + else: + n = n + q >> 1 + exact = exact and n*n == c + + if exact: + # result is exact; rescale to use ideal exponent e + if shift >= 0: + # assert n % 10**shift == 0 + n //= 10**shift + else: + n *= 10**-shift + e += shift + else: + # result is not exact; fix last digit as described above + if n % 5 == 0: + n += 1 + + ans = _dec_from_triple(0, str(n), e) + + # round, and fit to current context + context = context._shallow_copy() + rounding = context._set_rounding(ROUND_HALF_EVEN) + ans = ans._fix(context) + context.rounding = rounding + + return ans + + def max(self, other, context=None): + """Returns the larger value. + + Like max(self, other) except if one is not a number, returns + NaN (and signals if one is sNaN). Also rounds. + """ + other = _convert_other(other, raiseit=True) + + if context is None: + context = getcontext() + + if self._is_special or other._is_special: + # If one operand is a quiet NaN and the other is number, then the + # number is always returned + sn = self._isnan() + on = other._isnan() + if sn or on: + if on == 1 and sn == 0: + return self._fix(context) + if sn == 1 and on == 0: + return other._fix(context) + return self._check_nans(other, context) + + c = self._cmp(other) + if c == 0: + # If both operands are finite and equal in numerical value + # then an ordering is applied: + # + # If the signs differ then max returns the operand with the + # positive sign and min returns the operand with the negative sign + # + # If the signs are the same then the exponent is used to select + # the result. This is exactly the ordering used in compare_total. + c = self.compare_total(other) + + if c == -1: + ans = other + else: + ans = self + + return ans._fix(context) + + def min(self, other, context=None): + """Returns the smaller value. + + Like min(self, other) except if one is not a number, returns + NaN (and signals if one is sNaN). Also rounds. + """ + other = _convert_other(other, raiseit=True) + + if context is None: + context = getcontext() + + if self._is_special or other._is_special: + # If one operand is a quiet NaN and the other is number, then the + # number is always returned + sn = self._isnan() + on = other._isnan() + if sn or on: + if on == 1 and sn == 0: + return self._fix(context) + if sn == 1 and on == 0: + return other._fix(context) + return self._check_nans(other, context) + + c = self._cmp(other) + if c == 0: + c = self.compare_total(other) + + if c == -1: + ans = self + else: + ans = other + + return ans._fix(context) + + def _isinteger(self): + """Returns whether self is an integer""" + if self._is_special: + return False + if self._exp >= 0: + return True + rest = self._int[self._exp:] + return rest == '0'*len(rest) + + def _iseven(self): + """Returns True if self is even. Assumes self is an integer.""" + if not self or self._exp > 0: + return True + return self._int[-1+self._exp] in '02468' + + def adjusted(self): + """Return the adjusted exponent of self""" + try: + return self._exp + len(self._int) - 1 + # If NaN or Infinity, self._exp is string + except TypeError: + return 0 + + def canonical(self, context=None): + """Returns the same Decimal object. + + As we do not have different encodings for the same number, the + received object already is in its canonical form. + """ + return self + + def compare_signal(self, other, context=None): + """Compares self to the other operand numerically. + + It's pretty much like compare(), but all NaNs signal, with signaling + NaNs taking precedence over quiet NaNs. + """ + other = _convert_other(other, raiseit = True) + ans = self._compare_check_nans(other, context) + if ans: + return ans + return self.compare(other, context=context) + + def compare_total(self, other): + """Compares self to other using the abstract representations. + + This is not like the standard compare, which use their numerical + value. Note that a total ordering is defined for all possible abstract + representations. + """ + other = _convert_other(other, raiseit=True) + + # if one is negative and the other is positive, it's easy + if self._sign and not other._sign: + return _NegativeOne + if not self._sign and other._sign: + return _One + sign = self._sign + + # let's handle both NaN types + self_nan = self._isnan() + other_nan = other._isnan() + if self_nan or other_nan: + if self_nan == other_nan: + # compare payloads as though they're integers + self_key = len(self._int), self._int + other_key = len(other._int), other._int + if self_key < other_key: + if sign: + return _One + else: + return _NegativeOne + if self_key > other_key: + if sign: + return _NegativeOne + else: + return _One + return _Zero + + if sign: + if self_nan == 1: + return _NegativeOne + if other_nan == 1: + return _One + if self_nan == 2: + return _NegativeOne + if other_nan == 2: + return _One + else: + if self_nan == 1: + return _One + if other_nan == 1: + return _NegativeOne + if self_nan == 2: + return _One + if other_nan == 2: + return _NegativeOne + + if self < other: + return _NegativeOne + if self > other: + return _One + + if self._exp < other._exp: + if sign: + return _One + else: + return _NegativeOne + if self._exp > other._exp: + if sign: + return _NegativeOne + else: + return _One + return _Zero + + + def compare_total_mag(self, other): + """Compares self to other using abstract repr., ignoring sign. + + Like compare_total, but with operand's sign ignored and assumed to be 0. + """ + other = _convert_other(other, raiseit=True) + + s = self.copy_abs() + o = other.copy_abs() + return s.compare_total(o) + + def copy_abs(self): + """Returns a copy with the sign set to 0. """ + return _dec_from_triple(0, self._int, self._exp, self._is_special) + + def copy_negate(self): + """Returns a copy with the sign inverted.""" + if self._sign: + return _dec_from_triple(0, self._int, self._exp, self._is_special) + else: + return _dec_from_triple(1, self._int, self._exp, self._is_special) + + def copy_sign(self, other): + """Returns self with the sign of other.""" + other = _convert_other(other, raiseit=True) + return _dec_from_triple(other._sign, self._int, + self._exp, self._is_special) + + def exp(self, context=None): + """Returns e ** self.""" + + if context is None: + context = getcontext() + + # exp(NaN) = NaN + ans = self._check_nans(context=context) + if ans: + return ans + + # exp(-Infinity) = 0 + if self._isinfinity() == -1: + return _Zero + + # exp(0) = 1 + if not self: + return _One + + # exp(Infinity) = Infinity + if self._isinfinity() == 1: + return Decimal(self) + + # the result is now guaranteed to be inexact (the true + # mathematical result is transcendental). There's no need to + # raise Rounded and Inexact here---they'll always be raised as + # a result of the call to _fix. + p = context.prec + adj = self.adjusted() + + # we only need to do any computation for quite a small range + # of adjusted exponents---for example, -29 <= adj <= 10 for + # the default context. For smaller exponent the result is + # indistinguishable from 1 at the given precision, while for + # larger exponent the result either overflows or underflows. + if self._sign == 0 and adj > len(str((context.Emax+1)*3)): + # overflow + ans = _dec_from_triple(0, '1', context.Emax+1) + elif self._sign == 1 and adj > len(str((-context.Etiny()+1)*3)): + # underflow to 0 + ans = _dec_from_triple(0, '1', context.Etiny()-1) + elif self._sign == 0 and adj < -p: + # p+1 digits; final round will raise correct flags + ans = _dec_from_triple(0, '1' + '0'*(p-1) + '1', -p) + elif self._sign == 1 and adj < -p-1: + # p+1 digits; final round will raise correct flags + ans = _dec_from_triple(0, '9'*(p+1), -p-1) + # general case + else: + op = _WorkRep(self) + c, e = op.int, op.exp + if op.sign == 1: + c = -c + + # compute correctly rounded result: increase precision by + # 3 digits at a time until we get an unambiguously + # roundable result + extra = 3 + while True: + coeff, exp = _dexp(c, e, p+extra) + if coeff % (5*10**(len(str(coeff))-p-1)): + break + extra += 3 + + ans = _dec_from_triple(0, str(coeff), exp) + + # at this stage, ans should round correctly with *any* + # rounding mode, not just with ROUND_HALF_EVEN + context = context._shallow_copy() + rounding = context._set_rounding(ROUND_HALF_EVEN) + ans = ans._fix(context) + context.rounding = rounding + + return ans + + def is_canonical(self): + """Return True if self is canonical; otherwise return False. + + Currently, the encoding of a Decimal instance is always + canonical, so this method returns True for any Decimal. + """ + return True + + def is_finite(self): + """Return True if self is finite; otherwise return False. + + A Decimal instance is considered finite if it is neither + infinite nor a NaN. + """ + return not self._is_special + + def is_infinite(self): + """Return True if self is infinite; otherwise return False.""" + return self._exp == 'F' + + def is_nan(self): + """Return True if self is a qNaN or sNaN; otherwise return False.""" + return self._exp in ('n', 'N') + + def is_normal(self, context=None): + """Return True if self is a normal number; otherwise return False.""" + if self._is_special or not self: + return False + if context is None: + context = getcontext() + return context.Emin <= self.adjusted() + + def is_qnan(self): + """Return True if self is a quiet NaN; otherwise return False.""" + return self._exp == 'n' + + def is_signed(self): + """Return True if self is negative; otherwise return False.""" + return self._sign == 1 + + def is_snan(self): + """Return True if self is a signaling NaN; otherwise return False.""" + return self._exp == 'N' + + def is_subnormal(self, context=None): + """Return True if self is subnormal; otherwise return False.""" + if self._is_special or not self: + return False + if context is None: + context = getcontext() + return self.adjusted() < context.Emin + + def is_zero(self): + """Return True if self is a zero; otherwise return False.""" + return not self._is_special and self._int == '0' + + def _ln_exp_bound(self): + """Compute a lower bound for the adjusted exponent of self.ln(). + In other words, compute r such that self.ln() >= 10**r. Assumes + that self is finite and positive and that self != 1. + """ + + # for 0.1 <= x <= 10 we use the inequalities 1-1/x <= ln(x) <= x-1 + adj = self._exp + len(self._int) - 1 + if adj >= 1: + # argument >= 10; we use 23/10 = 2.3 as a lower bound for ln(10) + return len(str(adj*23//10)) - 1 + if adj <= -2: + # argument <= 0.1 + return len(str((-1-adj)*23//10)) - 1 + op = _WorkRep(self) + c, e = op.int, op.exp + if adj == 0: + # 1 < self < 10 + num = str(c-10**-e) + den = str(c) + return len(num) - len(den) - (num < den) + # adj == -1, 0.1 <= self < 1 + return e + len(str(10**-e - c)) - 1 + + + def ln(self, context=None): + """Returns the natural (base e) logarithm of self.""" + + if context is None: + context = getcontext() + + # ln(NaN) = NaN + ans = self._check_nans(context=context) + if ans: + return ans + + # ln(0.0) == -Infinity + if not self: + return _NegativeInfinity + + # ln(Infinity) = Infinity + if self._isinfinity() == 1: + return _Infinity + + # ln(1.0) == 0.0 + if self == _One: + return _Zero + + # ln(negative) raises InvalidOperation + if self._sign == 1: + return context._raise_error(InvalidOperation, + 'ln of a negative value') + + # result is irrational, so necessarily inexact + op = _WorkRep(self) + c, e = op.int, op.exp + p = context.prec + + # correctly rounded result: repeatedly increase precision by 3 + # until we get an unambiguously roundable result + places = p - self._ln_exp_bound() + 2 # at least p+3 places + while True: + coeff = _dlog(c, e, places) + # assert len(str(abs(coeff)))-p >= 1 + if coeff % (5*10**(len(str(abs(coeff)))-p-1)): + break + places += 3 + ans = _dec_from_triple(int(coeff<0), str(abs(coeff)), -places) + + context = context._shallow_copy() + rounding = context._set_rounding(ROUND_HALF_EVEN) + ans = ans._fix(context) + context.rounding = rounding + return ans + + def _log10_exp_bound(self): + """Compute a lower bound for the adjusted exponent of self.log10(). + In other words, find r such that self.log10() >= 10**r. + Assumes that self is finite and positive and that self != 1. + """ + + # For x >= 10 or x < 0.1 we only need a bound on the integer + # part of log10(self), and this comes directly from the + # exponent of x. For 0.1 <= x <= 10 we use the inequalities + # 1-1/x <= log(x) <= x-1. If x > 1 we have |log10(x)| > + # (1-1/x)/2.31 > 0. If x < 1 then |log10(x)| > (1-x)/2.31 > 0 + + adj = self._exp + len(self._int) - 1 + if adj >= 1: + # self >= 10 + return len(str(adj))-1 + if adj <= -2: + # self < 0.1 + return len(str(-1-adj))-1 + op = _WorkRep(self) + c, e = op.int, op.exp + if adj == 0: + # 1 < self < 10 + num = str(c-10**-e) + den = str(231*c) + return len(num) - len(den) - (num < den) + 2 + # adj == -1, 0.1 <= self < 1 + num = str(10**-e-c) + return len(num) + e - (num < "231") - 1 + + def log10(self, context=None): + """Returns the base 10 logarithm of self.""" + + if context is None: + context = getcontext() + + # log10(NaN) = NaN + ans = self._check_nans(context=context) + if ans: + return ans + + # log10(0.0) == -Infinity + if not self: + return _NegativeInfinity + + # log10(Infinity) = Infinity + if self._isinfinity() == 1: + return _Infinity + + # log10(negative or -Infinity) raises InvalidOperation + if self._sign == 1: + return context._raise_error(InvalidOperation, + 'log10 of a negative value') + + # log10(10**n) = n + if self._int[0] == '1' and self._int[1:] == '0'*(len(self._int) - 1): + # answer may need rounding + ans = Decimal(self._exp + len(self._int) - 1) + else: + # result is irrational, so necessarily inexact + op = _WorkRep(self) + c, e = op.int, op.exp + p = context.prec + + # correctly rounded result: repeatedly increase precision + # until result is unambiguously roundable + places = p-self._log10_exp_bound()+2 + while True: + coeff = _dlog10(c, e, places) + # assert len(str(abs(coeff)))-p >= 1 + if coeff % (5*10**(len(str(abs(coeff)))-p-1)): + break + places += 3 + ans = _dec_from_triple(int(coeff<0), str(abs(coeff)), -places) + + context = context._shallow_copy() + rounding = context._set_rounding(ROUND_HALF_EVEN) + ans = ans._fix(context) + context.rounding = rounding + return ans + + def logb(self, context=None): + """ Returns the exponent of the magnitude of self's MSD. + + The result is the integer which is the exponent of the magnitude + of the most significant digit of self (as though it were truncated + to a single digit while maintaining the value of that digit and + without limiting the resulting exponent). + """ + # logb(NaN) = NaN + ans = self._check_nans(context=context) + if ans: + return ans + + if context is None: + context = getcontext() + + # logb(+/-Inf) = +Inf + if self._isinfinity(): + return _Infinity + + # logb(0) = -Inf, DivisionByZero + if not self: + return context._raise_error(DivisionByZero, 'logb(0)', 1) + + # otherwise, simply return the adjusted exponent of self, as a + # Decimal. Note that no attempt is made to fit the result + # into the current context. + ans = Decimal(self.adjusted()) + return ans._fix(context) + + def _islogical(self): + """Return True if self is a logical operand. + + For being logical, it must be a finite number with a sign of 0, + an exponent of 0, and a coefficient whose digits must all be + either 0 or 1. + """ + if self._sign != 0 or self._exp != 0: + return False + for dig in self._int: + if dig not in '01': + return False + return True + + def _fill_logical(self, context, opa, opb): + dif = context.prec - len(opa) + if dif > 0: + opa = '0'*dif + opa + elif dif < 0: + opa = opa[-context.prec:] + dif = context.prec - len(opb) + if dif > 0: + opb = '0'*dif + opb + elif dif < 0: + opb = opb[-context.prec:] + return opa, opb + + def logical_and(self, other, context=None): + """Applies an 'and' operation between self and other's digits.""" + if context is None: + context = getcontext() + + other = _convert_other(other, raiseit=True) + + if not self._islogical() or not other._islogical(): + return context._raise_error(InvalidOperation) + + # fill to context.prec + (opa, opb) = self._fill_logical(context, self._int, other._int) + + # make the operation, and clean starting zeroes + result = "".join([str(int(a)&int(b)) for a,b in zip(opa,opb)]) + return _dec_from_triple(0, result.lstrip('0') or '0', 0) + + def logical_invert(self, context=None): + """Invert all its digits.""" + if context is None: + context = getcontext() + return self.logical_xor(_dec_from_triple(0,'1'*context.prec,0), + context) + + def logical_or(self, other, context=None): + """Applies an 'or' operation between self and other's digits.""" + if context is None: + context = getcontext() + + other = _convert_other(other, raiseit=True) + + if not self._islogical() or not other._islogical(): + return context._raise_error(InvalidOperation) + + # fill to context.prec + (opa, opb) = self._fill_logical(context, self._int, other._int) + + # make the operation, and clean starting zeroes + result = "".join([str(int(a)|int(b)) for a,b in zip(opa,opb)]) + return _dec_from_triple(0, result.lstrip('0') or '0', 0) + + def logical_xor(self, other, context=None): + """Applies an 'xor' operation between self and other's digits.""" + if context is None: + context = getcontext() + + other = _convert_other(other, raiseit=True) + + if not self._islogical() or not other._islogical(): + return context._raise_error(InvalidOperation) + + # fill to context.prec + (opa, opb) = self._fill_logical(context, self._int, other._int) + + # make the operation, and clean starting zeroes + result = "".join([str(int(a)^int(b)) for a,b in zip(opa,opb)]) + return _dec_from_triple(0, result.lstrip('0') or '0', 0) + + def max_mag(self, other, context=None): + """Compares the values numerically with their sign ignored.""" + other = _convert_other(other, raiseit=True) + + if context is None: + context = getcontext() + + if self._is_special or other._is_special: + # If one operand is a quiet NaN and the other is number, then the + # number is always returned + sn = self._isnan() + on = other._isnan() + if sn or on: + if on == 1 and sn == 0: + return self._fix(context) + if sn == 1 and on == 0: + return other._fix(context) + return self._check_nans(other, context) + + c = self.copy_abs()._cmp(other.copy_abs()) + if c == 0: + c = self.compare_total(other) + + if c == -1: + ans = other + else: + ans = self + + return ans._fix(context) + + def min_mag(self, other, context=None): + """Compares the values numerically with their sign ignored.""" + other = _convert_other(other, raiseit=True) + + if context is None: + context = getcontext() + + if self._is_special or other._is_special: + # If one operand is a quiet NaN and the other is number, then the + # number is always returned + sn = self._isnan() + on = other._isnan() + if sn or on: + if on == 1 and sn == 0: + return self._fix(context) + if sn == 1 and on == 0: + return other._fix(context) + return self._check_nans(other, context) + + c = self.copy_abs()._cmp(other.copy_abs()) + if c == 0: + c = self.compare_total(other) + + if c == -1: + ans = self + else: + ans = other + + return ans._fix(context) + + def next_minus(self, context=None): + """Returns the largest representable number smaller than itself.""" + if context is None: + context = getcontext() + + ans = self._check_nans(context=context) + if ans: + return ans + + if self._isinfinity() == -1: + return _NegativeInfinity + if self._isinfinity() == 1: + return _dec_from_triple(0, '9'*context.prec, context.Etop()) + + context = context.copy() + context._set_rounding(ROUND_FLOOR) + context._ignore_all_flags() + new_self = self._fix(context) + if new_self != self: + return new_self + return self.__sub__(_dec_from_triple(0, '1', context.Etiny()-1), + context) + + def next_plus(self, context=None): + """Returns the smallest representable number larger than itself.""" + if context is None: + context = getcontext() + + ans = self._check_nans(context=context) + if ans: + return ans + + if self._isinfinity() == 1: + return _Infinity + if self._isinfinity() == -1: + return _dec_from_triple(1, '9'*context.prec, context.Etop()) + + context = context.copy() + context._set_rounding(ROUND_CEILING) + context._ignore_all_flags() + new_self = self._fix(context) + if new_self != self: + return new_self + return self.__add__(_dec_from_triple(0, '1', context.Etiny()-1), + context) + + def next_toward(self, other, context=None): + """Returns the number closest to self, in the direction towards other. + + The result is the closest representable number to self + (excluding self) that is in the direction towards other, + unless both have the same value. If the two operands are + numerically equal, then the result is a copy of self with the + sign set to be the same as the sign of other. + """ + other = _convert_other(other, raiseit=True) + + if context is None: + context = getcontext() + + ans = self._check_nans(other, context) + if ans: + return ans + + comparison = self._cmp(other) + if comparison == 0: + return self.copy_sign(other) + + if comparison == -1: + ans = self.next_plus(context) + else: # comparison == 1 + ans = self.next_minus(context) + + # decide which flags to raise using value of ans + if ans._isinfinity(): + context._raise_error(Overflow, + 'Infinite result from next_toward', + ans._sign) + context._raise_error(Inexact) + context._raise_error(Rounded) + elif ans.adjusted() < context.Emin: + context._raise_error(Underflow) + context._raise_error(Subnormal) + context._raise_error(Inexact) + context._raise_error(Rounded) + # if precision == 1 then we don't raise Clamped for a + # result 0E-Etiny. + if not ans: + context._raise_error(Clamped) + + return ans + + def number_class(self, context=None): + """Returns an indication of the class of self. + + The class is one of the following strings: + sNaN + NaN + -Infinity + -Normal + -Subnormal + -Zero + +Zero + +Subnormal + +Normal + +Infinity + """ + if self.is_snan(): + return "sNaN" + if self.is_qnan(): + return "NaN" + inf = self._isinfinity() + if inf == 1: + return "+Infinity" + if inf == -1: + return "-Infinity" + if self.is_zero(): + if self._sign: + return "-Zero" + else: + return "+Zero" + if context is None: + context = getcontext() + if self.is_subnormal(context=context): + if self._sign: + return "-Subnormal" + else: + return "+Subnormal" + # just a normal, regular, boring number, :) + if self._sign: + return "-Normal" + else: + return "+Normal" + + def radix(self): + """Just returns 10, as this is Decimal, :)""" + return Decimal(10) + + def rotate(self, other, context=None): + """Returns a rotated copy of self, value-of-other times.""" + if context is None: + context = getcontext() + + other = _convert_other(other, raiseit=True) + + ans = self._check_nans(other, context) + if ans: + return ans + + if other._exp != 0: + return context._raise_error(InvalidOperation) + if not (-context.prec <= int(other) <= context.prec): + return context._raise_error(InvalidOperation) + + if self._isinfinity(): + return Decimal(self) + + # get values, pad if necessary + torot = int(other) + rotdig = self._int + topad = context.prec - len(rotdig) + if topad > 0: + rotdig = '0'*topad + rotdig + elif topad < 0: + rotdig = rotdig[-topad:] + + # let's rotate! + rotated = rotdig[torot:] + rotdig[:torot] + return _dec_from_triple(self._sign, + rotated.lstrip('0') or '0', self._exp) + + def scaleb(self, other, context=None): + """Returns self operand after adding the second value to its exp.""" + if context is None: + context = getcontext() + + other = _convert_other(other, raiseit=True) + + ans = self._check_nans(other, context) + if ans: + return ans + + if other._exp != 0: + return context._raise_error(InvalidOperation) + liminf = -2 * (context.Emax + context.prec) + limsup = 2 * (context.Emax + context.prec) + if not (liminf <= int(other) <= limsup): + return context._raise_error(InvalidOperation) + + if self._isinfinity(): + return Decimal(self) + + d = _dec_from_triple(self._sign, self._int, self._exp + int(other)) + d = d._fix(context) + return d + + def shift(self, other, context=None): + """Returns a shifted copy of self, value-of-other times.""" + if context is None: + context = getcontext() + + other = _convert_other(other, raiseit=True) + + ans = self._check_nans(other, context) + if ans: + return ans + + if other._exp != 0: + return context._raise_error(InvalidOperation) + if not (-context.prec <= int(other) <= context.prec): + return context._raise_error(InvalidOperation) + + if self._isinfinity(): + return Decimal(self) + + # get values, pad if necessary + torot = int(other) + rotdig = self._int + topad = context.prec - len(rotdig) + if topad > 0: + rotdig = '0'*topad + rotdig + elif topad < 0: + rotdig = rotdig[-topad:] + + # let's shift! + if torot < 0: + shifted = rotdig[:torot] + else: + shifted = rotdig + '0'*torot + shifted = shifted[-context.prec:] + + return _dec_from_triple(self._sign, + shifted.lstrip('0') or '0', self._exp) + + # Support for pickling, copy, and deepcopy + def __reduce__(self): + return (self.__class__, (str(self),)) + + def __copy__(self): + if type(self) is Decimal: + return self # I'm immutable; therefore I am my own clone + return self.__class__(str(self)) + + def __deepcopy__(self, memo): + if type(self) is Decimal: + return self # My components are also immutable + return self.__class__(str(self)) + + # PEP 3101 support. the _localeconv keyword argument should be + # considered private: it's provided for ease of testing only. + def __format__(self, specifier, context=None, _localeconv=None): + """Format a Decimal instance according to the given specifier. + + The specifier should be a standard format specifier, with the + form described in PEP 3101. Formatting types 'e', 'E', 'f', + 'F', 'g', 'G', 'n' and '%' are supported. If the formatting + type is omitted it defaults to 'g' or 'G', depending on the + value of context.capitals. + """ + + # Note: PEP 3101 says that if the type is not present then + # there should be at least one digit after the decimal point. + # We take the liberty of ignoring this requirement for + # Decimal---it's presumably there to make sure that + # format(float, '') behaves similarly to str(float). + if context is None: + context = getcontext() + + spec = _parse_format_specifier(specifier, _localeconv=_localeconv) + + # special values don't care about the type or precision + if self._is_special: + sign = _format_sign(self._sign, spec) + body = str(self.copy_abs()) + return _format_align(sign, body, spec) + + # a type of None defaults to 'g' or 'G', depending on context + if spec['type'] is None: + spec['type'] = ['g', 'G'][context.capitals] + + # if type is '%', adjust exponent of self accordingly + if spec['type'] == '%': + self = _dec_from_triple(self._sign, self._int, self._exp+2) + + # round if necessary, taking rounding mode from the context + rounding = context.rounding + precision = spec['precision'] + if precision is not None: + if spec['type'] in 'eE': + self = self._round(precision+1, rounding) + elif spec['type'] in 'fF%': + self = self._rescale(-precision, rounding) + elif spec['type'] in 'gG' and len(self._int) > precision: + self = self._round(precision, rounding) + # special case: zeros with a positive exponent can't be + # represented in fixed point; rescale them to 0e0. + if not self and self._exp > 0 and spec['type'] in 'fF%': + self = self._rescale(0, rounding) + + # figure out placement of the decimal point + leftdigits = self._exp + len(self._int) + if spec['type'] in 'eE': + if not self and precision is not None: + dotplace = 1 - precision + else: + dotplace = 1 + elif spec['type'] in 'fF%': + dotplace = leftdigits + elif spec['type'] in 'gG': + if self._exp <= 0 and leftdigits > -6: + dotplace = leftdigits + else: + dotplace = 1 + + # find digits before and after decimal point, and get exponent + if dotplace < 0: + intpart = '0' + fracpart = '0'*(-dotplace) + self._int + elif dotplace > len(self._int): + intpart = self._int + '0'*(dotplace-len(self._int)) + fracpart = '' + else: + intpart = self._int[:dotplace] or '0' + fracpart = self._int[dotplace:] + exp = leftdigits-dotplace + + # done with the decimal-specific stuff; hand over the rest + # of the formatting to the _format_number function + return _format_number(self._sign, intpart, fracpart, exp, spec) + +def _dec_from_triple(sign, coefficient, exponent, special=False): + """Create a decimal instance directly, without any validation, + normalization (e.g. removal of leading zeros) or argument + conversion. + + This function is for *internal use only*. + """ + + self = object.__new__(Decimal) + self._sign = sign + self._int = coefficient + self._exp = exponent + self._is_special = special + + return self + +# Register Decimal as a kind of Number (an abstract base class). +# However, do not register it as Real (because Decimals are not +# interoperable with floats). +_numbers.Number.register(Decimal) + + +##### Context class ####################################################### + +class _ContextManager(object): + """Context manager class to support localcontext(). + + Sets a copy of the supplied context in __enter__() and restores + the previous decimal context in __exit__() + """ + def __init__(self, new_context): + self.new_context = new_context.copy() + def __enter__(self): + self.saved_context = getcontext() + setcontext(self.new_context) + return self.new_context + def __exit__(self, t, v, tb): + setcontext(self.saved_context) + +class Context(object): + """Contains the context for a Decimal instance. + + Contains: + prec - precision (for use in rounding, division, square roots..) + rounding - rounding type (how you round) + traps - If traps[exception] = 1, then the exception is + raised when it is caused. Otherwise, a value is + substituted in. + flags - When an exception is caused, flags[exception] is set. + (Whether or not the trap_enabler is set) + Should be reset by user of Decimal instance. + Emin - Minimum exponent + Emax - Maximum exponent + capitals - If 1, 1*10^1 is printed as 1E+1. + If 0, printed as 1e1 + _clamp - If 1, change exponents if too high (Default 0) + """ + + def __init__(self, prec=None, rounding=None, + traps=None, flags=None, + Emin=None, Emax=None, + capitals=None, _clamp=0, + _ignored_flags=None): + # Set defaults; for everything except flags and _ignored_flags, + # inherit from DefaultContext. + try: + dc = DefaultContext + except NameError: + pass + + self.prec = prec if prec is not None else dc.prec + self.rounding = rounding if rounding is not None else dc.rounding + self.Emin = Emin if Emin is not None else dc.Emin + self.Emax = Emax if Emax is not None else dc.Emax + self.capitals = capitals if capitals is not None else dc.capitals + self._clamp = _clamp if _clamp is not None else dc._clamp + + if _ignored_flags is None: + self._ignored_flags = [] + else: + self._ignored_flags = _ignored_flags + + if traps is None: + self.traps = dc.traps.copy() + elif not isinstance(traps, dict): + self.traps = dict((s, int(s in traps)) for s in _signals) + else: + self.traps = traps + + if flags is None: + self.flags = dict.fromkeys(_signals, 0) + elif not isinstance(flags, dict): + self.flags = dict((s, int(s in flags)) for s in _signals) + else: + self.flags = flags + + def __repr__(self): + """Show the current context.""" + s = [] + s.append('Context(prec=%(prec)d, rounding=%(rounding)s, ' + 'Emin=%(Emin)d, Emax=%(Emax)d, capitals=%(capitals)d' + % vars(self)) + names = [f.__name__ for f, v in self.flags.items() if v] + s.append('flags=[' + ', '.join(names) + ']') + names = [t.__name__ for t, v in self.traps.items() if v] + s.append('traps=[' + ', '.join(names) + ']') + return ', '.join(s) + ')' + + def clear_flags(self): + """Reset all flags to zero""" + for flag in self.flags: + self.flags[flag] = 0 + + def _shallow_copy(self): + """Returns a shallow copy from self.""" + nc = Context(self.prec, self.rounding, self.traps, + self.flags, self.Emin, self.Emax, + self.capitals, self._clamp, self._ignored_flags) + return nc + + def copy(self): + """Returns a deep copy from self.""" + nc = Context(self.prec, self.rounding, self.traps.copy(), + self.flags.copy(), self.Emin, self.Emax, + self.capitals, self._clamp, self._ignored_flags) + return nc + __copy__ = copy + + def _raise_error(self, condition, explanation = None, *args): + """Handles an error + + If the flag is in _ignored_flags, returns the default response. + Otherwise, it sets the flag, then, if the corresponding + trap_enabler is set, it reraises the exception. Otherwise, it returns + the default value after setting the flag. + """ + error = _condition_map.get(condition, condition) + if error in self._ignored_flags: + # Don't touch the flag + return error().handle(self, *args) + + self.flags[error] = 1 + if not self.traps[error]: + # The errors define how to handle themselves. + return condition().handle(self, *args) + + # Errors should only be risked on copies of the context + # self._ignored_flags = [] + raise error(explanation) + + def _ignore_all_flags(self): + """Ignore all flags, if they are raised""" + return self._ignore_flags(*_signals) + + def _ignore_flags(self, *flags): + """Ignore the flags, if they are raised""" + # Do not mutate-- This way, copies of a context leave the original + # alone. + self._ignored_flags = (self._ignored_flags + list(flags)) + return list(flags) + + def _regard_flags(self, *flags): + """Stop ignoring the flags, if they are raised""" + if flags and isinstance(flags[0], (tuple,list)): + flags = flags[0] + for flag in flags: + self._ignored_flags.remove(flag) + + # We inherit object.__hash__, so we must deny this explicitly + __hash__ = None + + def Etiny(self): + """Returns Etiny (= Emin - prec + 1)""" + return int(self.Emin - self.prec + 1) + + def Etop(self): + """Returns maximum exponent (= Emax - prec + 1)""" + return int(self.Emax - self.prec + 1) + + def _set_rounding(self, type): + """Sets the rounding type. + + Sets the rounding type, and returns the current (previous) + rounding type. Often used like: + + context = context.copy() + # so you don't change the calling context + # if an error occurs in the middle. + rounding = context._set_rounding(ROUND_UP) + val = self.__sub__(other, context=context) + context._set_rounding(rounding) + + This will make it round up for that operation. + """ + rounding = self.rounding + self.rounding= type + return rounding + + def create_decimal(self, num='0'): + """Creates a new Decimal instance but using self as context. + + This method implements the to-number operation of the + IBM Decimal specification.""" + + if isinstance(num, basestring) and num != num.strip(): + return self._raise_error(ConversionSyntax, + "no trailing or leading whitespace is " + "permitted.") + + d = Decimal(num, context=self) + if d._isnan() and len(d._int) > self.prec - self._clamp: + return self._raise_error(ConversionSyntax, + "diagnostic info too long in NaN") + return d._fix(self) + + def create_decimal_from_float(self, f): + """Creates a new Decimal instance from a float but rounding using self + as the context. + + >>> context = Context(prec=5, rounding=ROUND_DOWN) + >>> context.create_decimal_from_float(3.1415926535897932) + Decimal('3.1415') + >>> context = Context(prec=5, traps=[Inexact]) + >>> context.create_decimal_from_float(3.1415926535897932) + Traceback (most recent call last): + ... + Inexact: None + + """ + d = Decimal.from_float(f) # An exact conversion + return d._fix(self) # Apply the context rounding + + # Methods + def abs(self, a): + """Returns the absolute value of the operand. + + If the operand is negative, the result is the same as using the minus + operation on the operand. Otherwise, the result is the same as using + the plus operation on the operand. + + >>> ExtendedContext.abs(Decimal('2.1')) + Decimal('2.1') + >>> ExtendedContext.abs(Decimal('-100')) + Decimal('100') + >>> ExtendedContext.abs(Decimal('101.5')) + Decimal('101.5') + >>> ExtendedContext.abs(Decimal('-101.5')) + Decimal('101.5') + >>> ExtendedContext.abs(-1) + Decimal('1') + """ + a = _convert_other(a, raiseit=True) + return a.__abs__(context=self) + + def add(self, a, b): + """Return the sum of the two operands. + + >>> ExtendedContext.add(Decimal('12'), Decimal('7.00')) + Decimal('19.00') + >>> ExtendedContext.add(Decimal('1E+2'), Decimal('1.01E+4')) + Decimal('1.02E+4') + >>> ExtendedContext.add(1, Decimal(2)) + Decimal('3') + >>> ExtendedContext.add(Decimal(8), 5) + Decimal('13') + >>> ExtendedContext.add(5, 5) + Decimal('10') + """ + a = _convert_other(a, raiseit=True) + r = a.__add__(b, context=self) + if r is NotImplemented: + raise TypeError("Unable to convert %s to Decimal" % b) + else: + return r + + def _apply(self, a): + return str(a._fix(self)) + + def canonical(self, a): + """Returns the same Decimal object. + + As we do not have different encodings for the same number, the + received object already is in its canonical form. + + >>> ExtendedContext.canonical(Decimal('2.50')) + Decimal('2.50') + """ + return a.canonical(context=self) + + def compare(self, a, b): + """Compares values numerically. + + If the signs of the operands differ, a value representing each operand + ('-1' if the operand is less than zero, '0' if the operand is zero or + negative zero, or '1' if the operand is greater than zero) is used in + place of that operand for the comparison instead of the actual + operand. + + The comparison is then effected by subtracting the second operand from + the first and then returning a value according to the result of the + subtraction: '-1' if the result is less than zero, '0' if the result is + zero or negative zero, or '1' if the result is greater than zero. + + >>> ExtendedContext.compare(Decimal('2.1'), Decimal('3')) + Decimal('-1') + >>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.1')) + Decimal('0') + >>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.10')) + Decimal('0') + >>> ExtendedContext.compare(Decimal('3'), Decimal('2.1')) + Decimal('1') + >>> ExtendedContext.compare(Decimal('2.1'), Decimal('-3')) + Decimal('1') + >>> ExtendedContext.compare(Decimal('-3'), Decimal('2.1')) + Decimal('-1') + >>> ExtendedContext.compare(1, 2) + Decimal('-1') + >>> ExtendedContext.compare(Decimal(1), 2) + Decimal('-1') + >>> ExtendedContext.compare(1, Decimal(2)) + Decimal('-1') + """ + a = _convert_other(a, raiseit=True) + return a.compare(b, context=self) + + def compare_signal(self, a, b): + """Compares the values of the two operands numerically. + + It's pretty much like compare(), but all NaNs signal, with signaling + NaNs taking precedence over quiet NaNs. + + >>> c = ExtendedContext + >>> c.compare_signal(Decimal('2.1'), Decimal('3')) + Decimal('-1') + >>> c.compare_signal(Decimal('2.1'), Decimal('2.1')) + Decimal('0') + >>> c.flags[InvalidOperation] = 0 + >>> print c.flags[InvalidOperation] + 0 + >>> c.compare_signal(Decimal('NaN'), Decimal('2.1')) + Decimal('NaN') + >>> print c.flags[InvalidOperation] + 1 + >>> c.flags[InvalidOperation] = 0 + >>> print c.flags[InvalidOperation] + 0 + >>> c.compare_signal(Decimal('sNaN'), Decimal('2.1')) + Decimal('NaN') + >>> print c.flags[InvalidOperation] + 1 + >>> c.compare_signal(-1, 2) + Decimal('-1') + >>> c.compare_signal(Decimal(-1), 2) + Decimal('-1') + >>> c.compare_signal(-1, Decimal(2)) + Decimal('-1') + """ + a = _convert_other(a, raiseit=True) + return a.compare_signal(b, context=self) + + def compare_total(self, a, b): + """Compares two operands using their abstract representation. + + This is not like the standard compare, which use their numerical + value. Note that a total ordering is defined for all possible abstract + representations. + + >>> ExtendedContext.compare_total(Decimal('12.73'), Decimal('127.9')) + Decimal('-1') + >>> ExtendedContext.compare_total(Decimal('-127'), Decimal('12')) + Decimal('-1') + >>> ExtendedContext.compare_total(Decimal('12.30'), Decimal('12.3')) + Decimal('-1') + >>> ExtendedContext.compare_total(Decimal('12.30'), Decimal('12.30')) + Decimal('0') + >>> ExtendedContext.compare_total(Decimal('12.3'), Decimal('12.300')) + Decimal('1') + >>> ExtendedContext.compare_total(Decimal('12.3'), Decimal('NaN')) + Decimal('-1') + >>> ExtendedContext.compare_total(1, 2) + Decimal('-1') + >>> ExtendedContext.compare_total(Decimal(1), 2) + Decimal('-1') + >>> ExtendedContext.compare_total(1, Decimal(2)) + Decimal('-1') + """ + a = _convert_other(a, raiseit=True) + return a.compare_total(b) + + def compare_total_mag(self, a, b): + """Compares two operands using their abstract representation ignoring sign. + + Like compare_total, but with operand's sign ignored and assumed to be 0. + """ + a = _convert_other(a, raiseit=True) + return a.compare_total_mag(b) + + def copy_abs(self, a): + """Returns a copy of the operand with the sign set to 0. + + >>> ExtendedContext.copy_abs(Decimal('2.1')) + Decimal('2.1') + >>> ExtendedContext.copy_abs(Decimal('-100')) + Decimal('100') + >>> ExtendedContext.copy_abs(-1) + Decimal('1') + """ + a = _convert_other(a, raiseit=True) + return a.copy_abs() + + def copy_decimal(self, a): + """Returns a copy of the decimal object. + + >>> ExtendedContext.copy_decimal(Decimal('2.1')) + Decimal('2.1') + >>> ExtendedContext.copy_decimal(Decimal('-1.00')) + Decimal('-1.00') + >>> ExtendedContext.copy_decimal(1) + Decimal('1') + """ + a = _convert_other(a, raiseit=True) + return Decimal(a) + + def copy_negate(self, a): + """Returns a copy of the operand with the sign inverted. + + >>> ExtendedContext.copy_negate(Decimal('101.5')) + Decimal('-101.5') + >>> ExtendedContext.copy_negate(Decimal('-101.5')) + Decimal('101.5') + >>> ExtendedContext.copy_negate(1) + Decimal('-1') + """ + a = _convert_other(a, raiseit=True) + return a.copy_negate() + + def copy_sign(self, a, b): + """Copies the second operand's sign to the first one. + + In detail, it returns a copy of the first operand with the sign + equal to the sign of the second operand. + + >>> ExtendedContext.copy_sign(Decimal( '1.50'), Decimal('7.33')) + Decimal('1.50') + >>> ExtendedContext.copy_sign(Decimal('-1.50'), Decimal('7.33')) + Decimal('1.50') + >>> ExtendedContext.copy_sign(Decimal( '1.50'), Decimal('-7.33')) + Decimal('-1.50') + >>> ExtendedContext.copy_sign(Decimal('-1.50'), Decimal('-7.33')) + Decimal('-1.50') + >>> ExtendedContext.copy_sign(1, -2) + Decimal('-1') + >>> ExtendedContext.copy_sign(Decimal(1), -2) + Decimal('-1') + >>> ExtendedContext.copy_sign(1, Decimal(-2)) + Decimal('-1') + """ + a = _convert_other(a, raiseit=True) + return a.copy_sign(b) + + def divide(self, a, b): + """Decimal division in a specified context. + + >>> ExtendedContext.divide(Decimal('1'), Decimal('3')) + Decimal('0.333333333') + >>> ExtendedContext.divide(Decimal('2'), Decimal('3')) + Decimal('0.666666667') + >>> ExtendedContext.divide(Decimal('5'), Decimal('2')) + Decimal('2.5') + >>> ExtendedContext.divide(Decimal('1'), Decimal('10')) + Decimal('0.1') + >>> ExtendedContext.divide(Decimal('12'), Decimal('12')) + Decimal('1') + >>> ExtendedContext.divide(Decimal('8.00'), Decimal('2')) + Decimal('4.00') + >>> ExtendedContext.divide(Decimal('2.400'), Decimal('2.0')) + Decimal('1.20') + >>> ExtendedContext.divide(Decimal('1000'), Decimal('100')) + Decimal('10') + >>> ExtendedContext.divide(Decimal('1000'), Decimal('1')) + Decimal('1000') + >>> ExtendedContext.divide(Decimal('2.40E+6'), Decimal('2')) + Decimal('1.20E+6') + >>> ExtendedContext.divide(5, 5) + Decimal('1') + >>> ExtendedContext.divide(Decimal(5), 5) + Decimal('1') + >>> ExtendedContext.divide(5, Decimal(5)) + Decimal('1') + """ + a = _convert_other(a, raiseit=True) + r = a.__div__(b, context=self) + if r is NotImplemented: + raise TypeError("Unable to convert %s to Decimal" % b) + else: + return r + + def divide_int(self, a, b): + """Divides two numbers and returns the integer part of the result. + + >>> ExtendedContext.divide_int(Decimal('2'), Decimal('3')) + Decimal('0') + >>> ExtendedContext.divide_int(Decimal('10'), Decimal('3')) + Decimal('3') + >>> ExtendedContext.divide_int(Decimal('1'), Decimal('0.3')) + Decimal('3') + >>> ExtendedContext.divide_int(10, 3) + Decimal('3') + >>> ExtendedContext.divide_int(Decimal(10), 3) + Decimal('3') + >>> ExtendedContext.divide_int(10, Decimal(3)) + Decimal('3') + """ + a = _convert_other(a, raiseit=True) + r = a.__floordiv__(b, context=self) + if r is NotImplemented: + raise TypeError("Unable to convert %s to Decimal" % b) + else: + return r + + def divmod(self, a, b): + """Return (a // b, a % b). + + >>> ExtendedContext.divmod(Decimal(8), Decimal(3)) + (Decimal('2'), Decimal('2')) + >>> ExtendedContext.divmod(Decimal(8), Decimal(4)) + (Decimal('2'), Decimal('0')) + >>> ExtendedContext.divmod(8, 4) + (Decimal('2'), Decimal('0')) + >>> ExtendedContext.divmod(Decimal(8), 4) + (Decimal('2'), Decimal('0')) + >>> ExtendedContext.divmod(8, Decimal(4)) + (Decimal('2'), Decimal('0')) + """ + a = _convert_other(a, raiseit=True) + r = a.__divmod__(b, context=self) + if r is NotImplemented: + raise TypeError("Unable to convert %s to Decimal" % b) + else: + return r + + def exp(self, a): + """Returns e ** a. + + >>> c = ExtendedContext.copy() + >>> c.Emin = -999 + >>> c.Emax = 999 + >>> c.exp(Decimal('-Infinity')) + Decimal('0') + >>> c.exp(Decimal('-1')) + Decimal('0.367879441') + >>> c.exp(Decimal('0')) + Decimal('1') + >>> c.exp(Decimal('1')) + Decimal('2.71828183') + >>> c.exp(Decimal('0.693147181')) + Decimal('2.00000000') + >>> c.exp(Decimal('+Infinity')) + Decimal('Infinity') + >>> c.exp(10) + Decimal('22026.4658') + """ + a =_convert_other(a, raiseit=True) + return a.exp(context=self) + + def fma(self, a, b, c): + """Returns a multiplied by b, plus c. + + The first two operands are multiplied together, using multiply, + the third operand is then added to the result of that + multiplication, using add, all with only one final rounding. + + >>> ExtendedContext.fma(Decimal('3'), Decimal('5'), Decimal('7')) + Decimal('22') + >>> ExtendedContext.fma(Decimal('3'), Decimal('-5'), Decimal('7')) + Decimal('-8') + >>> ExtendedContext.fma(Decimal('888565290'), Decimal('1557.96930'), Decimal('-86087.7578')) + Decimal('1.38435736E+12') + >>> ExtendedContext.fma(1, 3, 4) + Decimal('7') + >>> ExtendedContext.fma(1, Decimal(3), 4) + Decimal('7') + >>> ExtendedContext.fma(1, 3, Decimal(4)) + Decimal('7') + """ + a = _convert_other(a, raiseit=True) + return a.fma(b, c, context=self) + + def is_canonical(self, a): + """Return True if the operand is canonical; otherwise return False. + + Currently, the encoding of a Decimal instance is always + canonical, so this method returns True for any Decimal. + + >>> ExtendedContext.is_canonical(Decimal('2.50')) + True + """ + return a.is_canonical() + + def is_finite(self, a): + """Return True if the operand is finite; otherwise return False. + + A Decimal instance is considered finite if it is neither + infinite nor a NaN. + + >>> ExtendedContext.is_finite(Decimal('2.50')) + True + >>> ExtendedContext.is_finite(Decimal('-0.3')) + True + >>> ExtendedContext.is_finite(Decimal('0')) + True + >>> ExtendedContext.is_finite(Decimal('Inf')) + False + >>> ExtendedContext.is_finite(Decimal('NaN')) + False + >>> ExtendedContext.is_finite(1) + True + """ + a = _convert_other(a, raiseit=True) + return a.is_finite() + + def is_infinite(self, a): + """Return True if the operand is infinite; otherwise return False. + + >>> ExtendedContext.is_infinite(Decimal('2.50')) + False + >>> ExtendedContext.is_infinite(Decimal('-Inf')) + True + >>> ExtendedContext.is_infinite(Decimal('NaN')) + False + >>> ExtendedContext.is_infinite(1) + False + """ + a = _convert_other(a, raiseit=True) + return a.is_infinite() + + def is_nan(self, a): + """Return True if the operand is a qNaN or sNaN; + otherwise return False. + + >>> ExtendedContext.is_nan(Decimal('2.50')) + False + >>> ExtendedContext.is_nan(Decimal('NaN')) + True + >>> ExtendedContext.is_nan(Decimal('-sNaN')) + True + >>> ExtendedContext.is_nan(1) + False + """ + a = _convert_other(a, raiseit=True) + return a.is_nan() + + def is_normal(self, a): + """Return True if the operand is a normal number; + otherwise return False. + + >>> c = ExtendedContext.copy() + >>> c.Emin = -999 + >>> c.Emax = 999 + >>> c.is_normal(Decimal('2.50')) + True + >>> c.is_normal(Decimal('0.1E-999')) + False + >>> c.is_normal(Decimal('0.00')) + False + >>> c.is_normal(Decimal('-Inf')) + False + >>> c.is_normal(Decimal('NaN')) + False + >>> c.is_normal(1) + True + """ + a = _convert_other(a, raiseit=True) + return a.is_normal(context=self) + + def is_qnan(self, a): + """Return True if the operand is a quiet NaN; otherwise return False. + + >>> ExtendedContext.is_qnan(Decimal('2.50')) + False + >>> ExtendedContext.is_qnan(Decimal('NaN')) + True + >>> ExtendedContext.is_qnan(Decimal('sNaN')) + False + >>> ExtendedContext.is_qnan(1) + False + """ + a = _convert_other(a, raiseit=True) + return a.is_qnan() + + def is_signed(self, a): + """Return True if the operand is negative; otherwise return False. + + >>> ExtendedContext.is_signed(Decimal('2.50')) + False + >>> ExtendedContext.is_signed(Decimal('-12')) + True + >>> ExtendedContext.is_signed(Decimal('-0')) + True + >>> ExtendedContext.is_signed(8) + False + >>> ExtendedContext.is_signed(-8) + True + """ + a = _convert_other(a, raiseit=True) + return a.is_signed() + + def is_snan(self, a): + """Return True if the operand is a signaling NaN; + otherwise return False. + + >>> ExtendedContext.is_snan(Decimal('2.50')) + False + >>> ExtendedContext.is_snan(Decimal('NaN')) + False + >>> ExtendedContext.is_snan(Decimal('sNaN')) + True + >>> ExtendedContext.is_snan(1) + False + """ + a = _convert_other(a, raiseit=True) + return a.is_snan() + + def is_subnormal(self, a): + """Return True if the operand is subnormal; otherwise return False. + + >>> c = ExtendedContext.copy() + >>> c.Emin = -999 + >>> c.Emax = 999 + >>> c.is_subnormal(Decimal('2.50')) + False + >>> c.is_subnormal(Decimal('0.1E-999')) + True + >>> c.is_subnormal(Decimal('0.00')) + False + >>> c.is_subnormal(Decimal('-Inf')) + False + >>> c.is_subnormal(Decimal('NaN')) + False + >>> c.is_subnormal(1) + False + """ + a = _convert_other(a, raiseit=True) + return a.is_subnormal(context=self) + + def is_zero(self, a): + """Return True if the operand is a zero; otherwise return False. + + >>> ExtendedContext.is_zero(Decimal('0')) + True + >>> ExtendedContext.is_zero(Decimal('2.50')) + False + >>> ExtendedContext.is_zero(Decimal('-0E+2')) + True + >>> ExtendedContext.is_zero(1) + False + >>> ExtendedContext.is_zero(0) + True + """ + a = _convert_other(a, raiseit=True) + return a.is_zero() + + def ln(self, a): + """Returns the natural (base e) logarithm of the operand. + + >>> c = ExtendedContext.copy() + >>> c.Emin = -999 + >>> c.Emax = 999 + >>> c.ln(Decimal('0')) + Decimal('-Infinity') + >>> c.ln(Decimal('1.000')) + Decimal('0') + >>> c.ln(Decimal('2.71828183')) + Decimal('1.00000000') + >>> c.ln(Decimal('10')) + Decimal('2.30258509') + >>> c.ln(Decimal('+Infinity')) + Decimal('Infinity') + >>> c.ln(1) + Decimal('0') + """ + a = _convert_other(a, raiseit=True) + return a.ln(context=self) + + def log10(self, a): + """Returns the base 10 logarithm of the operand. + + >>> c = ExtendedContext.copy() + >>> c.Emin = -999 + >>> c.Emax = 999 + >>> c.log10(Decimal('0')) + Decimal('-Infinity') + >>> c.log10(Decimal('0.001')) + Decimal('-3') + >>> c.log10(Decimal('1.000')) + Decimal('0') + >>> c.log10(Decimal('2')) + Decimal('0.301029996') + >>> c.log10(Decimal('10')) + Decimal('1') + >>> c.log10(Decimal('70')) + Decimal('1.84509804') + >>> c.log10(Decimal('+Infinity')) + Decimal('Infinity') + >>> c.log10(0) + Decimal('-Infinity') + >>> c.log10(1) + Decimal('0') + """ + a = _convert_other(a, raiseit=True) + return a.log10(context=self) + + def logb(self, a): + """ Returns the exponent of the magnitude of the operand's MSD. + + The result is the integer which is the exponent of the magnitude + of the most significant digit of the operand (as though the + operand were truncated to a single digit while maintaining the + value of that digit and without limiting the resulting exponent). + + >>> ExtendedContext.logb(Decimal('250')) + Decimal('2') + >>> ExtendedContext.logb(Decimal('2.50')) + Decimal('0') + >>> ExtendedContext.logb(Decimal('0.03')) + Decimal('-2') + >>> ExtendedContext.logb(Decimal('0')) + Decimal('-Infinity') + >>> ExtendedContext.logb(1) + Decimal('0') + >>> ExtendedContext.logb(10) + Decimal('1') + >>> ExtendedContext.logb(100) + Decimal('2') + """ + a = _convert_other(a, raiseit=True) + return a.logb(context=self) + + def logical_and(self, a, b): + """Applies the logical operation 'and' between each operand's digits. + + The operands must be both logical numbers. + + >>> ExtendedContext.logical_and(Decimal('0'), Decimal('0')) + Decimal('0') + >>> ExtendedContext.logical_and(Decimal('0'), Decimal('1')) + Decimal('0') + >>> ExtendedContext.logical_and(Decimal('1'), Decimal('0')) + Decimal('0') + >>> ExtendedContext.logical_and(Decimal('1'), Decimal('1')) + Decimal('1') + >>> ExtendedContext.logical_and(Decimal('1100'), Decimal('1010')) + Decimal('1000') + >>> ExtendedContext.logical_and(Decimal('1111'), Decimal('10')) + Decimal('10') + >>> ExtendedContext.logical_and(110, 1101) + Decimal('100') + >>> ExtendedContext.logical_and(Decimal(110), 1101) + Decimal('100') + >>> ExtendedContext.logical_and(110, Decimal(1101)) + Decimal('100') + """ + a = _convert_other(a, raiseit=True) + return a.logical_and(b, context=self) + + def logical_invert(self, a): + """Invert all the digits in the operand. + + The operand must be a logical number. + + >>> ExtendedContext.logical_invert(Decimal('0')) + Decimal('111111111') + >>> ExtendedContext.logical_invert(Decimal('1')) + Decimal('111111110') + >>> ExtendedContext.logical_invert(Decimal('111111111')) + Decimal('0') + >>> ExtendedContext.logical_invert(Decimal('101010101')) + Decimal('10101010') + >>> ExtendedContext.logical_invert(1101) + Decimal('111110010') + """ + a = _convert_other(a, raiseit=True) + return a.logical_invert(context=self) + + def logical_or(self, a, b): + """Applies the logical operation 'or' between each operand's digits. + + The operands must be both logical numbers. + + >>> ExtendedContext.logical_or(Decimal('0'), Decimal('0')) + Decimal('0') + >>> ExtendedContext.logical_or(Decimal('0'), Decimal('1')) + Decimal('1') + >>> ExtendedContext.logical_or(Decimal('1'), Decimal('0')) + Decimal('1') + >>> ExtendedContext.logical_or(Decimal('1'), Decimal('1')) + Decimal('1') + >>> ExtendedContext.logical_or(Decimal('1100'), Decimal('1010')) + Decimal('1110') + >>> ExtendedContext.logical_or(Decimal('1110'), Decimal('10')) + Decimal('1110') + >>> ExtendedContext.logical_or(110, 1101) + Decimal('1111') + >>> ExtendedContext.logical_or(Decimal(110), 1101) + Decimal('1111') + >>> ExtendedContext.logical_or(110, Decimal(1101)) + Decimal('1111') + """ + a = _convert_other(a, raiseit=True) + return a.logical_or(b, context=self) + + def logical_xor(self, a, b): + """Applies the logical operation 'xor' between each operand's digits. + + The operands must be both logical numbers. + + >>> ExtendedContext.logical_xor(Decimal('0'), Decimal('0')) + Decimal('0') + >>> ExtendedContext.logical_xor(Decimal('0'), Decimal('1')) + Decimal('1') + >>> ExtendedContext.logical_xor(Decimal('1'), Decimal('0')) + Decimal('1') + >>> ExtendedContext.logical_xor(Decimal('1'), Decimal('1')) + Decimal('0') + >>> ExtendedContext.logical_xor(Decimal('1100'), Decimal('1010')) + Decimal('110') + >>> ExtendedContext.logical_xor(Decimal('1111'), Decimal('10')) + Decimal('1101') + >>> ExtendedContext.logical_xor(110, 1101) + Decimal('1011') + >>> ExtendedContext.logical_xor(Decimal(110), 1101) + Decimal('1011') + >>> ExtendedContext.logical_xor(110, Decimal(1101)) + Decimal('1011') + """ + a = _convert_other(a, raiseit=True) + return a.logical_xor(b, context=self) + + def max(self, a, b): + """max compares two values numerically and returns the maximum. + + If either operand is a NaN then the general rules apply. + Otherwise, the operands are compared as though by the compare + operation. If they are numerically equal then the left-hand operand + is chosen as the result. Otherwise the maximum (closer to positive + infinity) of the two operands is chosen as the result. + + >>> ExtendedContext.max(Decimal('3'), Decimal('2')) + Decimal('3') + >>> ExtendedContext.max(Decimal('-10'), Decimal('3')) + Decimal('3') + >>> ExtendedContext.max(Decimal('1.0'), Decimal('1')) + Decimal('1') + >>> ExtendedContext.max(Decimal('7'), Decimal('NaN')) + Decimal('7') + >>> ExtendedContext.max(1, 2) + Decimal('2') + >>> ExtendedContext.max(Decimal(1), 2) + Decimal('2') + >>> ExtendedContext.max(1, Decimal(2)) + Decimal('2') + """ + a = _convert_other(a, raiseit=True) + return a.max(b, context=self) + + def max_mag(self, a, b): + """Compares the values numerically with their sign ignored. + + >>> ExtendedContext.max_mag(Decimal('7'), Decimal('NaN')) + Decimal('7') + >>> ExtendedContext.max_mag(Decimal('7'), Decimal('-10')) + Decimal('-10') + >>> ExtendedContext.max_mag(1, -2) + Decimal('-2') + >>> ExtendedContext.max_mag(Decimal(1), -2) + Decimal('-2') + >>> ExtendedContext.max_mag(1, Decimal(-2)) + Decimal('-2') + """ + a = _convert_other(a, raiseit=True) + return a.max_mag(b, context=self) + + def min(self, a, b): + """min compares two values numerically and returns the minimum. + + If either operand is a NaN then the general rules apply. + Otherwise, the operands are compared as though by the compare + operation. If they are numerically equal then the left-hand operand + is chosen as the result. Otherwise the minimum (closer to negative + infinity) of the two operands is chosen as the result. + + >>> ExtendedContext.min(Decimal('3'), Decimal('2')) + Decimal('2') + >>> ExtendedContext.min(Decimal('-10'), Decimal('3')) + Decimal('-10') + >>> ExtendedContext.min(Decimal('1.0'), Decimal('1')) + Decimal('1.0') + >>> ExtendedContext.min(Decimal('7'), Decimal('NaN')) + Decimal('7') + >>> ExtendedContext.min(1, 2) + Decimal('1') + >>> ExtendedContext.min(Decimal(1), 2) + Decimal('1') + >>> ExtendedContext.min(1, Decimal(29)) + Decimal('1') + """ + a = _convert_other(a, raiseit=True) + return a.min(b, context=self) + + def min_mag(self, a, b): + """Compares the values numerically with their sign ignored. + + >>> ExtendedContext.min_mag(Decimal('3'), Decimal('-2')) + Decimal('-2') + >>> ExtendedContext.min_mag(Decimal('-3'), Decimal('NaN')) + Decimal('-3') + >>> ExtendedContext.min_mag(1, -2) + Decimal('1') + >>> ExtendedContext.min_mag(Decimal(1), -2) + Decimal('1') + >>> ExtendedContext.min_mag(1, Decimal(-2)) + Decimal('1') + """ + a = _convert_other(a, raiseit=True) + return a.min_mag(b, context=self) + + def minus(self, a): + """Minus corresponds to unary prefix minus in Python. + + The operation is evaluated using the same rules as subtract; the + operation minus(a) is calculated as subtract('0', a) where the '0' + has the same exponent as the operand. + + >>> ExtendedContext.minus(Decimal('1.3')) + Decimal('-1.3') + >>> ExtendedContext.minus(Decimal('-1.3')) + Decimal('1.3') + >>> ExtendedContext.minus(1) + Decimal('-1') + """ + a = _convert_other(a, raiseit=True) + return a.__neg__(context=self) + + def multiply(self, a, b): + """multiply multiplies two operands. + + If either operand is a special value then the general rules apply. + Otherwise, the operands are multiplied together + ('long multiplication'), resulting in a number which may be as long as + the sum of the lengths of the two operands. + + >>> ExtendedContext.multiply(Decimal('1.20'), Decimal('3')) + Decimal('3.60') + >>> ExtendedContext.multiply(Decimal('7'), Decimal('3')) + Decimal('21') + >>> ExtendedContext.multiply(Decimal('0.9'), Decimal('0.8')) + Decimal('0.72') + >>> ExtendedContext.multiply(Decimal('0.9'), Decimal('-0')) + Decimal('-0.0') + >>> ExtendedContext.multiply(Decimal('654321'), Decimal('654321')) + Decimal('4.28135971E+11') + >>> ExtendedContext.multiply(7, 7) + Decimal('49') + >>> ExtendedContext.multiply(Decimal(7), 7) + Decimal('49') + >>> ExtendedContext.multiply(7, Decimal(7)) + Decimal('49') + """ + a = _convert_other(a, raiseit=True) + r = a.__mul__(b, context=self) + if r is NotImplemented: + raise TypeError("Unable to convert %s to Decimal" % b) + else: + return r + + def next_minus(self, a): + """Returns the largest representable number smaller than a. + + >>> c = ExtendedContext.copy() + >>> c.Emin = -999 + >>> c.Emax = 999 + >>> ExtendedContext.next_minus(Decimal('1')) + Decimal('0.999999999') + >>> c.next_minus(Decimal('1E-1007')) + Decimal('0E-1007') + >>> ExtendedContext.next_minus(Decimal('-1.00000003')) + Decimal('-1.00000004') + >>> c.next_minus(Decimal('Infinity')) + Decimal('9.99999999E+999') + >>> c.next_minus(1) + Decimal('0.999999999') + """ + a = _convert_other(a, raiseit=True) + return a.next_minus(context=self) + + def next_plus(self, a): + """Returns the smallest representable number larger than a. + + >>> c = ExtendedContext.copy() + >>> c.Emin = -999 + >>> c.Emax = 999 + >>> ExtendedContext.next_plus(Decimal('1')) + Decimal('1.00000001') + >>> c.next_plus(Decimal('-1E-1007')) + Decimal('-0E-1007') + >>> ExtendedContext.next_plus(Decimal('-1.00000003')) + Decimal('-1.00000002') + >>> c.next_plus(Decimal('-Infinity')) + Decimal('-9.99999999E+999') + >>> c.next_plus(1) + Decimal('1.00000001') + """ + a = _convert_other(a, raiseit=True) + return a.next_plus(context=self) + + def next_toward(self, a, b): + """Returns the number closest to a, in direction towards b. + + The result is the closest representable number from the first + operand (but not the first operand) that is in the direction + towards the second operand, unless the operands have the same + value. + + >>> c = ExtendedContext.copy() + >>> c.Emin = -999 + >>> c.Emax = 999 + >>> c.next_toward(Decimal('1'), Decimal('2')) + Decimal('1.00000001') + >>> c.next_toward(Decimal('-1E-1007'), Decimal('1')) + Decimal('-0E-1007') + >>> c.next_toward(Decimal('-1.00000003'), Decimal('0')) + Decimal('-1.00000002') + >>> c.next_toward(Decimal('1'), Decimal('0')) + Decimal('0.999999999') + >>> c.next_toward(Decimal('1E-1007'), Decimal('-100')) + Decimal('0E-1007') + >>> c.next_toward(Decimal('-1.00000003'), Decimal('-10')) + Decimal('-1.00000004') + >>> c.next_toward(Decimal('0.00'), Decimal('-0.0000')) + Decimal('-0.00') + >>> c.next_toward(0, 1) + Decimal('1E-1007') + >>> c.next_toward(Decimal(0), 1) + Decimal('1E-1007') + >>> c.next_toward(0, Decimal(1)) + Decimal('1E-1007') + """ + a = _convert_other(a, raiseit=True) + return a.next_toward(b, context=self) + + def normalize(self, a): + """normalize reduces an operand to its simplest form. + + Essentially a plus operation with all trailing zeros removed from the + result. + + >>> ExtendedContext.normalize(Decimal('2.1')) + Decimal('2.1') + >>> ExtendedContext.normalize(Decimal('-2.0')) + Decimal('-2') + >>> ExtendedContext.normalize(Decimal('1.200')) + Decimal('1.2') + >>> ExtendedContext.normalize(Decimal('-120')) + Decimal('-1.2E+2') + >>> ExtendedContext.normalize(Decimal('120.00')) + Decimal('1.2E+2') + >>> ExtendedContext.normalize(Decimal('0.00')) + Decimal('0') + >>> ExtendedContext.normalize(6) + Decimal('6') + """ + a = _convert_other(a, raiseit=True) + return a.normalize(context=self) + + def number_class(self, a): + """Returns an indication of the class of the operand. + + The class is one of the following strings: + -sNaN + -NaN + -Infinity + -Normal + -Subnormal + -Zero + +Zero + +Subnormal + +Normal + +Infinity + + >>> c = Context(ExtendedContext) + >>> c.Emin = -999 + >>> c.Emax = 999 + >>> c.number_class(Decimal('Infinity')) + '+Infinity' + >>> c.number_class(Decimal('1E-10')) + '+Normal' + >>> c.number_class(Decimal('2.50')) + '+Normal' + >>> c.number_class(Decimal('0.1E-999')) + '+Subnormal' + >>> c.number_class(Decimal('0')) + '+Zero' + >>> c.number_class(Decimal('-0')) + '-Zero' + >>> c.number_class(Decimal('-0.1E-999')) + '-Subnormal' + >>> c.number_class(Decimal('-1E-10')) + '-Normal' + >>> c.number_class(Decimal('-2.50')) + '-Normal' + >>> c.number_class(Decimal('-Infinity')) + '-Infinity' + >>> c.number_class(Decimal('NaN')) + 'NaN' + >>> c.number_class(Decimal('-NaN')) + 'NaN' + >>> c.number_class(Decimal('sNaN')) + 'sNaN' + >>> c.number_class(123) + '+Normal' + """ + a = _convert_other(a, raiseit=True) + return a.number_class(context=self) + + def plus(self, a): + """Plus corresponds to unary prefix plus in Python. + + The operation is evaluated using the same rules as add; the + operation plus(a) is calculated as add('0', a) where the '0' + has the same exponent as the operand. + + >>> ExtendedContext.plus(Decimal('1.3')) + Decimal('1.3') + >>> ExtendedContext.plus(Decimal('-1.3')) + Decimal('-1.3') + >>> ExtendedContext.plus(-1) + Decimal('-1') + """ + a = _convert_other(a, raiseit=True) + return a.__pos__(context=self) + + def power(self, a, b, modulo=None): + """Raises a to the power of b, to modulo if given. + + With two arguments, compute a**b. If a is negative then b + must be integral. The result will be inexact unless b is + integral and the result is finite and can be expressed exactly + in 'precision' digits. + + With three arguments, compute (a**b) % modulo. For the + three argument form, the following restrictions on the + arguments hold: + + - all three arguments must be integral + - b must be nonnegative + - at least one of a or b must be nonzero + - modulo must be nonzero and have at most 'precision' digits + + The result of pow(a, b, modulo) is identical to the result + that would be obtained by computing (a**b) % modulo with + unbounded precision, but is computed more efficiently. It is + always exact. + + >>> c = ExtendedContext.copy() + >>> c.Emin = -999 + >>> c.Emax = 999 + >>> c.power(Decimal('2'), Decimal('3')) + Decimal('8') + >>> c.power(Decimal('-2'), Decimal('3')) + Decimal('-8') + >>> c.power(Decimal('2'), Decimal('-3')) + Decimal('0.125') + >>> c.power(Decimal('1.7'), Decimal('8')) + Decimal('69.7575744') + >>> c.power(Decimal('10'), Decimal('0.301029996')) + Decimal('2.00000000') + >>> c.power(Decimal('Infinity'), Decimal('-1')) + Decimal('0') + >>> c.power(Decimal('Infinity'), Decimal('0')) + Decimal('1') + >>> c.power(Decimal('Infinity'), Decimal('1')) + Decimal('Infinity') + >>> c.power(Decimal('-Infinity'), Decimal('-1')) + Decimal('-0') + >>> c.power(Decimal('-Infinity'), Decimal('0')) + Decimal('1') + >>> c.power(Decimal('-Infinity'), Decimal('1')) + Decimal('-Infinity') + >>> c.power(Decimal('-Infinity'), Decimal('2')) + Decimal('Infinity') + >>> c.power(Decimal('0'), Decimal('0')) + Decimal('NaN') + + >>> c.power(Decimal('3'), Decimal('7'), Decimal('16')) + Decimal('11') + >>> c.power(Decimal('-3'), Decimal('7'), Decimal('16')) + Decimal('-11') + >>> c.power(Decimal('-3'), Decimal('8'), Decimal('16')) + Decimal('1') + >>> c.power(Decimal('3'), Decimal('7'), Decimal('-16')) + Decimal('11') + >>> c.power(Decimal('23E12345'), Decimal('67E189'), Decimal('123456789')) + Decimal('11729830') + >>> c.power(Decimal('-0'), Decimal('17'), Decimal('1729')) + Decimal('-0') + >>> c.power(Decimal('-23'), Decimal('0'), Decimal('65537')) + Decimal('1') + >>> ExtendedContext.power(7, 7) + Decimal('823543') + >>> ExtendedContext.power(Decimal(7), 7) + Decimal('823543') + >>> ExtendedContext.power(7, Decimal(7), 2) + Decimal('1') + """ + a = _convert_other(a, raiseit=True) + r = a.__pow__(b, modulo, context=self) + if r is NotImplemented: + raise TypeError("Unable to convert %s to Decimal" % b) + else: + return r + + def quantize(self, a, b): + """Returns a value equal to 'a' (rounded), having the exponent of 'b'. + + The coefficient of the result is derived from that of the left-hand + operand. It may be rounded using the current rounding setting (if the + exponent is being increased), multiplied by a positive power of ten (if + the exponent is being decreased), or is unchanged (if the exponent is + already equal to that of the right-hand operand). + + Unlike other operations, if the length of the coefficient after the + quantize operation would be greater than precision then an Invalid + operation condition is raised. This guarantees that, unless there is + an error condition, the exponent of the result of a quantize is always + equal to that of the right-hand operand. + + Also unlike other operations, quantize will never raise Underflow, even + if the result is subnormal and inexact. + + >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.001')) + Decimal('2.170') + >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.01')) + Decimal('2.17') + >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.1')) + Decimal('2.2') + >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+0')) + Decimal('2') + >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+1')) + Decimal('0E+1') + >>> ExtendedContext.quantize(Decimal('-Inf'), Decimal('Infinity')) + Decimal('-Infinity') + >>> ExtendedContext.quantize(Decimal('2'), Decimal('Infinity')) + Decimal('NaN') + >>> ExtendedContext.quantize(Decimal('-0.1'), Decimal('1')) + Decimal('-0') + >>> ExtendedContext.quantize(Decimal('-0'), Decimal('1e+5')) + Decimal('-0E+5') + >>> ExtendedContext.quantize(Decimal('+35236450.6'), Decimal('1e-2')) + Decimal('NaN') + >>> ExtendedContext.quantize(Decimal('-35236450.6'), Decimal('1e-2')) + Decimal('NaN') + >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-1')) + Decimal('217.0') + >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-0')) + Decimal('217') + >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+1')) + Decimal('2.2E+2') + >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+2')) + Decimal('2E+2') + >>> ExtendedContext.quantize(1, 2) + Decimal('1') + >>> ExtendedContext.quantize(Decimal(1), 2) + Decimal('1') + >>> ExtendedContext.quantize(1, Decimal(2)) + Decimal('1') + """ + a = _convert_other(a, raiseit=True) + return a.quantize(b, context=self) + + def radix(self): + """Just returns 10, as this is Decimal, :) + + >>> ExtendedContext.radix() + Decimal('10') + """ + return Decimal(10) + + def remainder(self, a, b): + """Returns the remainder from integer division. + + The result is the residue of the dividend after the operation of + calculating integer division as described for divide-integer, rounded + to precision digits if necessary. The sign of the result, if + non-zero, is the same as that of the original dividend. + + This operation will fail under the same conditions as integer division + (that is, if integer division on the same two operands would fail, the + remainder cannot be calculated). + + >>> ExtendedContext.remainder(Decimal('2.1'), Decimal('3')) + Decimal('2.1') + >>> ExtendedContext.remainder(Decimal('10'), Decimal('3')) + Decimal('1') + >>> ExtendedContext.remainder(Decimal('-10'), Decimal('3')) + Decimal('-1') + >>> ExtendedContext.remainder(Decimal('10.2'), Decimal('1')) + Decimal('0.2') + >>> ExtendedContext.remainder(Decimal('10'), Decimal('0.3')) + Decimal('0.1') + >>> ExtendedContext.remainder(Decimal('3.6'), Decimal('1.3')) + Decimal('1.0') + >>> ExtendedContext.remainder(22, 6) + Decimal('4') + >>> ExtendedContext.remainder(Decimal(22), 6) + Decimal('4') + >>> ExtendedContext.remainder(22, Decimal(6)) + Decimal('4') + """ + a = _convert_other(a, raiseit=True) + r = a.__mod__(b, context=self) + if r is NotImplemented: + raise TypeError("Unable to convert %s to Decimal" % b) + else: + return r + + def remainder_near(self, a, b): + """Returns to be "a - b * n", where n is the integer nearest the exact + value of "x / b" (if two integers are equally near then the even one + is chosen). If the result is equal to 0 then its sign will be the + sign of a. + + This operation will fail under the same conditions as integer division + (that is, if integer division on the same two operands would fail, the + remainder cannot be calculated). + + >>> ExtendedContext.remainder_near(Decimal('2.1'), Decimal('3')) + Decimal('-0.9') + >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('6')) + Decimal('-2') + >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('3')) + Decimal('1') + >>> ExtendedContext.remainder_near(Decimal('-10'), Decimal('3')) + Decimal('-1') + >>> ExtendedContext.remainder_near(Decimal('10.2'), Decimal('1')) + Decimal('0.2') + >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('0.3')) + Decimal('0.1') + >>> ExtendedContext.remainder_near(Decimal('3.6'), Decimal('1.3')) + Decimal('-0.3') + >>> ExtendedContext.remainder_near(3, 11) + Decimal('3') + >>> ExtendedContext.remainder_near(Decimal(3), 11) + Decimal('3') + >>> ExtendedContext.remainder_near(3, Decimal(11)) + Decimal('3') + """ + a = _convert_other(a, raiseit=True) + return a.remainder_near(b, context=self) + + def rotate(self, a, b): + """Returns a rotated copy of a, b times. + + The coefficient of the result is a rotated copy of the digits in + the coefficient of the first operand. The number of places of + rotation is taken from the absolute value of the second operand, + with the rotation being to the left if the second operand is + positive or to the right otherwise. + + >>> ExtendedContext.rotate(Decimal('34'), Decimal('8')) + Decimal('400000003') + >>> ExtendedContext.rotate(Decimal('12'), Decimal('9')) + Decimal('12') + >>> ExtendedContext.rotate(Decimal('123456789'), Decimal('-2')) + Decimal('891234567') + >>> ExtendedContext.rotate(Decimal('123456789'), Decimal('0')) + Decimal('123456789') + >>> ExtendedContext.rotate(Decimal('123456789'), Decimal('+2')) + Decimal('345678912') + >>> ExtendedContext.rotate(1333333, 1) + Decimal('13333330') + >>> ExtendedContext.rotate(Decimal(1333333), 1) + Decimal('13333330') + >>> ExtendedContext.rotate(1333333, Decimal(1)) + Decimal('13333330') + """ + a = _convert_other(a, raiseit=True) + return a.rotate(b, context=self) + + def same_quantum(self, a, b): + """Returns True if the two operands have the same exponent. + + The result is never affected by either the sign or the coefficient of + either operand. + + >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('0.001')) + False + >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('0.01')) + True + >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('1')) + False + >>> ExtendedContext.same_quantum(Decimal('Inf'), Decimal('-Inf')) + True + >>> ExtendedContext.same_quantum(10000, -1) + True + >>> ExtendedContext.same_quantum(Decimal(10000), -1) + True + >>> ExtendedContext.same_quantum(10000, Decimal(-1)) + True + """ + a = _convert_other(a, raiseit=True) + return a.same_quantum(b) + + def scaleb (self, a, b): + """Returns the first operand after adding the second value its exp. + + >>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('-2')) + Decimal('0.0750') + >>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('0')) + Decimal('7.50') + >>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('3')) + Decimal('7.50E+3') + >>> ExtendedContext.scaleb(1, 4) + Decimal('1E+4') + >>> ExtendedContext.scaleb(Decimal(1), 4) + Decimal('1E+4') + >>> ExtendedContext.scaleb(1, Decimal(4)) + Decimal('1E+4') + """ + a = _convert_other(a, raiseit=True) + return a.scaleb(b, context=self) + + def shift(self, a, b): + """Returns a shifted copy of a, b times. + + The coefficient of the result is a shifted copy of the digits + in the coefficient of the first operand. The number of places + to shift is taken from the absolute value of the second operand, + with the shift being to the left if the second operand is + positive or to the right otherwise. Digits shifted into the + coefficient are zeros. + + >>> ExtendedContext.shift(Decimal('34'), Decimal('8')) + Decimal('400000000') + >>> ExtendedContext.shift(Decimal('12'), Decimal('9')) + Decimal('0') + >>> ExtendedContext.shift(Decimal('123456789'), Decimal('-2')) + Decimal('1234567') + >>> ExtendedContext.shift(Decimal('123456789'), Decimal('0')) + Decimal('123456789') + >>> ExtendedContext.shift(Decimal('123456789'), Decimal('+2')) + Decimal('345678900') + >>> ExtendedContext.shift(88888888, 2) + Decimal('888888800') + >>> ExtendedContext.shift(Decimal(88888888), 2) + Decimal('888888800') + >>> ExtendedContext.shift(88888888, Decimal(2)) + Decimal('888888800') + """ + a = _convert_other(a, raiseit=True) + return a.shift(b, context=self) + + def sqrt(self, a): + """Square root of a non-negative number to context precision. + + If the result must be inexact, it is rounded using the round-half-even + algorithm. + + >>> ExtendedContext.sqrt(Decimal('0')) + Decimal('0') + >>> ExtendedContext.sqrt(Decimal('-0')) + Decimal('-0') + >>> ExtendedContext.sqrt(Decimal('0.39')) + Decimal('0.624499800') + >>> ExtendedContext.sqrt(Decimal('100')) + Decimal('10') + >>> ExtendedContext.sqrt(Decimal('1')) + Decimal('1') + >>> ExtendedContext.sqrt(Decimal('1.0')) + Decimal('1.0') + >>> ExtendedContext.sqrt(Decimal('1.00')) + Decimal('1.0') + >>> ExtendedContext.sqrt(Decimal('7')) + Decimal('2.64575131') + >>> ExtendedContext.sqrt(Decimal('10')) + Decimal('3.16227766') + >>> ExtendedContext.sqrt(2) + Decimal('1.41421356') + >>> ExtendedContext.prec + 9 + """ + a = _convert_other(a, raiseit=True) + return a.sqrt(context=self) + + def subtract(self, a, b): + """Return the difference between the two operands. + + >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.07')) + Decimal('0.23') + >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.30')) + Decimal('0.00') + >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('2.07')) + Decimal('-0.77') + >>> ExtendedContext.subtract(8, 5) + Decimal('3') + >>> ExtendedContext.subtract(Decimal(8), 5) + Decimal('3') + >>> ExtendedContext.subtract(8, Decimal(5)) + Decimal('3') + """ + a = _convert_other(a, raiseit=True) + r = a.__sub__(b, context=self) + if r is NotImplemented: + raise TypeError("Unable to convert %s to Decimal" % b) + else: + return r + + def to_eng_string(self, a): + """Converts a number to a string, using scientific notation. + + The operation is not affected by the context. + """ + a = _convert_other(a, raiseit=True) + return a.to_eng_string(context=self) + + def to_sci_string(self, a): + """Converts a number to a string, using scientific notation. + + The operation is not affected by the context. + """ + a = _convert_other(a, raiseit=True) + return a.__str__(context=self) + + def to_integral_exact(self, a): + """Rounds to an integer. + + When the operand has a negative exponent, the result is the same + as using the quantize() operation using the given operand as the + left-hand-operand, 1E+0 as the right-hand-operand, and the precision + of the operand as the precision setting; Inexact and Rounded flags + are allowed in this operation. The rounding mode is taken from the + context. + + >>> ExtendedContext.to_integral_exact(Decimal('2.1')) + Decimal('2') + >>> ExtendedContext.to_integral_exact(Decimal('100')) + Decimal('100') + >>> ExtendedContext.to_integral_exact(Decimal('100.0')) + Decimal('100') + >>> ExtendedContext.to_integral_exact(Decimal('101.5')) + Decimal('102') + >>> ExtendedContext.to_integral_exact(Decimal('-101.5')) + Decimal('-102') + >>> ExtendedContext.to_integral_exact(Decimal('10E+5')) + Decimal('1.0E+6') + >>> ExtendedContext.to_integral_exact(Decimal('7.89E+77')) + Decimal('7.89E+77') + >>> ExtendedContext.to_integral_exact(Decimal('-Inf')) + Decimal('-Infinity') + """ + a = _convert_other(a, raiseit=True) + return a.to_integral_exact(context=self) + + def to_integral_value(self, a): + """Rounds to an integer. + + When the operand has a negative exponent, the result is the same + as using the quantize() operation using the given operand as the + left-hand-operand, 1E+0 as the right-hand-operand, and the precision + of the operand as the precision setting, except that no flags will + be set. The rounding mode is taken from the context. + + >>> ExtendedContext.to_integral_value(Decimal('2.1')) + Decimal('2') + >>> ExtendedContext.to_integral_value(Decimal('100')) + Decimal('100') + >>> ExtendedContext.to_integral_value(Decimal('100.0')) + Decimal('100') + >>> ExtendedContext.to_integral_value(Decimal('101.5')) + Decimal('102') + >>> ExtendedContext.to_integral_value(Decimal('-101.5')) + Decimal('-102') + >>> ExtendedContext.to_integral_value(Decimal('10E+5')) + Decimal('1.0E+6') + >>> ExtendedContext.to_integral_value(Decimal('7.89E+77')) + Decimal('7.89E+77') + >>> ExtendedContext.to_integral_value(Decimal('-Inf')) + Decimal('-Infinity') + """ + a = _convert_other(a, raiseit=True) + return a.to_integral_value(context=self) + + # the method name changed, but we provide also the old one, for compatibility + to_integral = to_integral_value + +class _WorkRep(object): + __slots__ = ('sign','int','exp') + # sign: 0 or 1 + # int: int or long + # exp: None, int, or string + + def __init__(self, value=None): + if value is None: + self.sign = None + self.int = 0 + self.exp = None + elif isinstance(value, Decimal): + self.sign = value._sign + self.int = int(value._int) + self.exp = value._exp + else: + # assert isinstance(value, tuple) + self.sign = value[0] + self.int = value[1] + self.exp = value[2] + + def __repr__(self): + return "(%r, %r, %r)" % (self.sign, self.int, self.exp) + + __str__ = __repr__ + + + +def _normalize(op1, op2, prec = 0): + """Normalizes op1, op2 to have the same exp and length of coefficient. + + Done during addition. + """ + if op1.exp < op2.exp: + tmp = op2 + other = op1 + else: + tmp = op1 + other = op2 + + # Let exp = min(tmp.exp - 1, tmp.adjusted() - precision - 1). + # Then adding 10**exp to tmp has the same effect (after rounding) + # as adding any positive quantity smaller than 10**exp; similarly + # for subtraction. So if other is smaller than 10**exp we replace + # it with 10**exp. This avoids tmp.exp - other.exp getting too large. + tmp_len = len(str(tmp.int)) + other_len = len(str(other.int)) + exp = tmp.exp + min(-1, tmp_len - prec - 2) + if other_len + other.exp - 1 < exp: + other.int = 1 + other.exp = exp + + tmp.int *= 10 ** (tmp.exp - other.exp) + tmp.exp = other.exp + return op1, op2 + +##### Integer arithmetic functions used by ln, log10, exp and __pow__ ##### + +# This function from Tim Peters was taken from here: +# http://mail.python.org/pipermail/python-list/1999-July/007758.html +# The correction being in the function definition is for speed, and +# the whole function is not resolved with math.log because of avoiding +# the use of floats. +def _nbits(n, correction = { + '0': 4, '1': 3, '2': 2, '3': 2, + '4': 1, '5': 1, '6': 1, '7': 1, + '8': 0, '9': 0, 'a': 0, 'b': 0, + 'c': 0, 'd': 0, 'e': 0, 'f': 0}): + """Number of bits in binary representation of the positive integer n, + or 0 if n == 0. + """ + if n < 0: + raise ValueError("The argument to _nbits should be nonnegative.") + hex_n = "%x" % n + return 4*len(hex_n) - correction[hex_n[0]] + +def _decimal_lshift_exact(n, e): + """ Given integers n and e, return n * 10**e if it's an integer, else None. + + The computation is designed to avoid computing large powers of 10 + unnecessarily. + + >>> _decimal_lshift_exact(3, 4) + 30000 + >>> _decimal_lshift_exact(300, -999999999) # returns None + + """ + if n == 0: + return 0 + elif e >= 0: + return n * 10**e + else: + # val_n = largest power of 10 dividing n. + str_n = str(abs(n)) + val_n = len(str_n) - len(str_n.rstrip('0')) + return None if val_n < -e else n // 10**-e + +def _sqrt_nearest(n, a): + """Closest integer to the square root of the positive integer n. a is + an initial approximation to the square root. Any positive integer + will do for a, but the closer a is to the square root of n the + faster convergence will be. + + """ + if n <= 0 or a <= 0: + raise ValueError("Both arguments to _sqrt_nearest should be positive.") + + b=0 + while a != b: + b, a = a, a--n//a>>1 + return a + +def _rshift_nearest(x, shift): + """Given an integer x and a nonnegative integer shift, return closest + integer to x / 2**shift; use round-to-even in case of a tie. + + """ + b, q = 1L << shift, x >> shift + return q + (2*(x & (b-1)) + (q&1) > b) + +def _div_nearest(a, b): + """Closest integer to a/b, a and b positive integers; rounds to even + in the case of a tie. + + """ + q, r = divmod(a, b) + return q + (2*r + (q&1) > b) + +def _ilog(x, M, L = 8): + """Integer approximation to M*log(x/M), with absolute error boundable + in terms only of x/M. + + Given positive integers x and M, return an integer approximation to + M * log(x/M). For L = 8 and 0.1 <= x/M <= 10 the difference + between the approximation and the exact result is at most 22. For + L = 8 and 1.0 <= x/M <= 10.0 the difference is at most 15. In + both cases these are upper bounds on the error; it will usually be + much smaller.""" + + # The basic algorithm is the following: let log1p be the function + # log1p(x) = log(1+x). Then log(x/M) = log1p((x-M)/M). We use + # the reduction + # + # log1p(y) = 2*log1p(y/(1+sqrt(1+y))) + # + # repeatedly until the argument to log1p is small (< 2**-L in + # absolute value). For small y we can use the Taylor series + # expansion + # + # log1p(y) ~ y - y**2/2 + y**3/3 - ... - (-y)**T/T + # + # truncating at T such that y**T is small enough. The whole + # computation is carried out in a form of fixed-point arithmetic, + # with a real number z being represented by an integer + # approximation to z*M. To avoid loss of precision, the y below + # is actually an integer approximation to 2**R*y*M, where R is the + # number of reductions performed so far. + + y = x-M + # argument reduction; R = number of reductions performed + R = 0 + while (R <= L and long(abs(y)) << L-R >= M or + R > L and abs(y) >> R-L >= M): + y = _div_nearest(long(M*y) << 1, + M + _sqrt_nearest(M*(M+_rshift_nearest(y, R)), M)) + R += 1 + + # Taylor series with T terms + T = -int(-10*len(str(M))//(3*L)) + yshift = _rshift_nearest(y, R) + w = _div_nearest(M, T) + for k in xrange(T-1, 0, -1): + w = _div_nearest(M, k) - _div_nearest(yshift*w, M) + + return _div_nearest(w*y, M) + +def _dlog10(c, e, p): + """Given integers c, e and p with c > 0, p >= 0, compute an integer + approximation to 10**p * log10(c*10**e), with an absolute error of + at most 1. Assumes that c*10**e is not exactly 1.""" + + # increase precision by 2; compensate for this by dividing + # final result by 100 + p += 2 + + # write c*10**e as d*10**f with either: + # f >= 0 and 1 <= d <= 10, or + # f <= 0 and 0.1 <= d <= 1. + # Thus for c*10**e close to 1, f = 0 + l = len(str(c)) + f = e+l - (e+l >= 1) + + if p > 0: + M = 10**p + k = e+p-f + if k >= 0: + c *= 10**k + else: + c = _div_nearest(c, 10**-k) + + log_d = _ilog(c, M) # error < 5 + 22 = 27 + log_10 = _log10_digits(p) # error < 1 + log_d = _div_nearest(log_d*M, log_10) + log_tenpower = f*M # exact + else: + log_d = 0 # error < 2.31 + log_tenpower = _div_nearest(f, 10**-p) # error < 0.5 + + return _div_nearest(log_tenpower+log_d, 100) + +def _dlog(c, e, p): + """Given integers c, e and p with c > 0, compute an integer + approximation to 10**p * log(c*10**e), with an absolute error of + at most 1. Assumes that c*10**e is not exactly 1.""" + + # Increase precision by 2. The precision increase is compensated + # for at the end with a division by 100. + p += 2 + + # rewrite c*10**e as d*10**f with either f >= 0 and 1 <= d <= 10, + # or f <= 0 and 0.1 <= d <= 1. Then we can compute 10**p * log(c*10**e) + # as 10**p * log(d) + 10**p*f * log(10). + l = len(str(c)) + f = e+l - (e+l >= 1) + + # compute approximation to 10**p*log(d), with error < 27 + if p > 0: + k = e+p-f + if k >= 0: + c *= 10**k + else: + c = _div_nearest(c, 10**-k) # error of <= 0.5 in c + + # _ilog magnifies existing error in c by a factor of at most 10 + log_d = _ilog(c, 10**p) # error < 5 + 22 = 27 + else: + # p <= 0: just approximate the whole thing by 0; error < 2.31 + log_d = 0 + + # compute approximation to f*10**p*log(10), with error < 11. + if f: + extra = len(str(abs(f)))-1 + if p + extra >= 0: + # error in f * _log10_digits(p+extra) < |f| * 1 = |f| + # after division, error < |f|/10**extra + 0.5 < 10 + 0.5 < 11 + f_log_ten = _div_nearest(f*_log10_digits(p+extra), 10**extra) + else: + f_log_ten = 0 + else: + f_log_ten = 0 + + # error in sum < 11+27 = 38; error after division < 0.38 + 0.5 < 1 + return _div_nearest(f_log_ten + log_d, 100) + +class _Log10Memoize(object): + """Class to compute, store, and allow retrieval of, digits of the + constant log(10) = 2.302585.... This constant is needed by + Decimal.ln, Decimal.log10, Decimal.exp and Decimal.__pow__.""" + def __init__(self): + self.digits = "23025850929940456840179914546843642076011014886" + + def getdigits(self, p): + """Given an integer p >= 0, return floor(10**p)*log(10). + + For example, self.getdigits(3) returns 2302. + """ + # digits are stored as a string, for quick conversion to + # integer in the case that we've already computed enough + # digits; the stored digits should always be correct + # (truncated, not rounded to nearest). + if p < 0: + raise ValueError("p should be nonnegative") + + if p >= len(self.digits): + # compute p+3, p+6, p+9, ... digits; continue until at + # least one of the extra digits is nonzero + extra = 3 + while True: + # compute p+extra digits, correct to within 1ulp + M = 10**(p+extra+2) + digits = str(_div_nearest(_ilog(10*M, M), 100)) + if digits[-extra:] != '0'*extra: + break + extra += 3 + # keep all reliable digits so far; remove trailing zeros + # and next nonzero digit + self.digits = digits.rstrip('0')[:-1] + return int(self.digits[:p+1]) + +_log10_digits = _Log10Memoize().getdigits + +def _iexp(x, M, L=8): + """Given integers x and M, M > 0, such that x/M is small in absolute + value, compute an integer approximation to M*exp(x/M). For 0 <= + x/M <= 2.4, the absolute error in the result is bounded by 60 (and + is usually much smaller).""" + + # Algorithm: to compute exp(z) for a real number z, first divide z + # by a suitable power R of 2 so that |z/2**R| < 2**-L. Then + # compute expm1(z/2**R) = exp(z/2**R) - 1 using the usual Taylor + # series + # + # expm1(x) = x + x**2/2! + x**3/3! + ... + # + # Now use the identity + # + # expm1(2x) = expm1(x)*(expm1(x)+2) + # + # R times to compute the sequence expm1(z/2**R), + # expm1(z/2**(R-1)), ... , exp(z/2), exp(z). + + # Find R such that x/2**R/M <= 2**-L + R = _nbits((long(x)< M + T = -int(-10*len(str(M))//(3*L)) + y = _div_nearest(x, T) + Mshift = long(M)<= 0: + cshift = c*10**shift + else: + cshift = c//10**-shift + quot, rem = divmod(cshift, _log10_digits(q)) + + # reduce remainder back to original precision + rem = _div_nearest(rem, 10**extra) + + # error in result of _iexp < 120; error after division < 0.62 + return _div_nearest(_iexp(rem, 10**p), 1000), quot - p + 3 + +def _dpower(xc, xe, yc, ye, p): + """Given integers xc, xe, yc and ye representing Decimals x = xc*10**xe and + y = yc*10**ye, compute x**y. Returns a pair of integers (c, e) such that: + + 10**(p-1) <= c <= 10**p, and + (c-1)*10**e < x**y < (c+1)*10**e + + in other words, c*10**e is an approximation to x**y with p digits + of precision, and with an error in c of at most 1. (This is + almost, but not quite, the same as the error being < 1ulp: when c + == 10**(p-1) we can only guarantee error < 10ulp.) + + We assume that: x is positive and not equal to 1, and y is nonzero. + """ + + # Find b such that 10**(b-1) <= |y| <= 10**b + b = len(str(abs(yc))) + ye + + # log(x) = lxc*10**(-p-b-1), to p+b+1 places after the decimal point + lxc = _dlog(xc, xe, p+b+1) + + # compute product y*log(x) = yc*lxc*10**(-p-b-1+ye) = pc*10**(-p-1) + shift = ye-b + if shift >= 0: + pc = lxc*yc*10**shift + else: + pc = _div_nearest(lxc*yc, 10**-shift) + + if pc == 0: + # we prefer a result that isn't exactly 1; this makes it + # easier to compute a correctly rounded result in __pow__ + if ((len(str(xc)) + xe >= 1) == (yc > 0)): # if x**y > 1: + coeff, exp = 10**(p-1)+1, 1-p + else: + coeff, exp = 10**p-1, -p + else: + coeff, exp = _dexp(pc, -(p+1), p+1) + coeff = _div_nearest(coeff, 10) + exp += 1 + + return coeff, exp + +def _log10_lb(c, correction = { + '1': 100, '2': 70, '3': 53, '4': 40, '5': 31, + '6': 23, '7': 16, '8': 10, '9': 5}): + """Compute a lower bound for 100*log10(c) for a positive integer c.""" + if c <= 0: + raise ValueError("The argument to _log10_lb should be nonnegative.") + str_c = str(c) + return 100*len(str_c) - correction[str_c[0]] + +##### Helper Functions #################################################### + +def _convert_other(other, raiseit=False, allow_float=False): + """Convert other to Decimal. + + Verifies that it's ok to use in an implicit construction. + If allow_float is true, allow conversion from float; this + is used in the comparison methods (__eq__ and friends). + + """ + if isinstance(other, Decimal): + return other + if isinstance(other, (int, long)): + return Decimal(other) + if allow_float and isinstance(other, float): + return Decimal.from_float(other) + + if raiseit: + raise TypeError("Unable to convert %s to Decimal" % other) + return NotImplemented + +##### Setup Specific Contexts ############################################ + +# The default context prototype used by Context() +# Is mutable, so that new contexts can have different default values + +DefaultContext = Context( + prec=28, rounding=ROUND_HALF_EVEN, + traps=[DivisionByZero, Overflow, InvalidOperation], + flags=[], + Emax=999999999, + Emin=-999999999, + capitals=1 +) + +# Pre-made alternate contexts offered by the specification +# Don't change these; the user should be able to select these +# contexts and be able to reproduce results from other implementations +# of the spec. + +BasicContext = Context( + prec=9, rounding=ROUND_HALF_UP, + traps=[DivisionByZero, Overflow, InvalidOperation, Clamped, Underflow], + flags=[], +) + +ExtendedContext = Context( + prec=9, rounding=ROUND_HALF_EVEN, + traps=[], + flags=[], +) + + +##### crud for parsing strings ############################################# +# +# Regular expression used for parsing numeric strings. Additional +# comments: +# +# 1. Uncomment the two '\s*' lines to allow leading and/or trailing +# whitespace. But note that the specification disallows whitespace in +# a numeric string. +# +# 2. For finite numbers (not infinities and NaNs) the body of the +# number between the optional sign and the optional exponent must have +# at least one decimal digit, possibly after the decimal point. The +# lookahead expression '(?=\d|\.\d)' checks this. + +import re +_parser = re.compile(r""" # A numeric string consists of: +# \s* + (?P[-+])? # an optional sign, followed by either... + ( + (?=\d|\.\d) # ...a number (with at least one digit) + (?P\d*) # having a (possibly empty) integer part + (\.(?P\d*))? # followed by an optional fractional part + (E(?P[-+]?\d+))? # followed by an optional exponent, or... + | + Inf(inity)? # ...an infinity, or... + | + (?Ps)? # ...an (optionally signaling) + NaN # NaN + (?P\d*) # with (possibly empty) diagnostic info. + ) +# \s* + \Z +""", re.VERBOSE | re.IGNORECASE | re.UNICODE).match + +_all_zeros = re.compile('0*$').match +_exact_half = re.compile('50*$').match + +##### PEP3101 support functions ############################################## +# The functions in this section have little to do with the Decimal +# class, and could potentially be reused or adapted for other pure +# Python numeric classes that want to implement __format__ +# +# A format specifier for Decimal looks like: +# +# [[fill]align][sign][0][minimumwidth][,][.precision][type] + +_parse_format_specifier_regex = re.compile(r"""\A +(?: + (?P.)? + (?P[<>=^]) +)? +(?P[-+ ])? +(?P0)? +(?P(?!0)\d+)? +(?P,)? +(?:\.(?P0|(?!0)\d+))? +(?P[eEfFgGn%])? +\Z +""", re.VERBOSE) + +del re + +# The locale module is only needed for the 'n' format specifier. The +# rest of the PEP 3101 code functions quite happily without it, so we +# don't care too much if locale isn't present. +try: + import locale as _locale +except ImportError: + pass + +def _parse_format_specifier(format_spec, _localeconv=None): + """Parse and validate a format specifier. + + Turns a standard numeric format specifier into a dict, with the + following entries: + + fill: fill character to pad field to minimum width + align: alignment type, either '<', '>', '=' or '^' + sign: either '+', '-' or ' ' + minimumwidth: nonnegative integer giving minimum width + zeropad: boolean, indicating whether to pad with zeros + thousands_sep: string to use as thousands separator, or '' + grouping: grouping for thousands separators, in format + used by localeconv + decimal_point: string to use for decimal point + precision: nonnegative integer giving precision, or None + type: one of the characters 'eEfFgG%', or None + unicode: boolean (always True for Python 3.x) + + """ + m = _parse_format_specifier_regex.match(format_spec) + if m is None: + raise ValueError("Invalid format specifier: " + format_spec) + + # get the dictionary + format_dict = m.groupdict() + + # zeropad; defaults for fill and alignment. If zero padding + # is requested, the fill and align fields should be absent. + fill = format_dict['fill'] + align = format_dict['align'] + format_dict['zeropad'] = (format_dict['zeropad'] is not None) + if format_dict['zeropad']: + if fill is not None: + raise ValueError("Fill character conflicts with '0'" + " in format specifier: " + format_spec) + if align is not None: + raise ValueError("Alignment conflicts with '0' in " + "format specifier: " + format_spec) + format_dict['fill'] = fill or ' ' + # PEP 3101 originally specified that the default alignment should + # be left; it was later agreed that right-aligned makes more sense + # for numeric types. See http://bugs.python.org/issue6857. + format_dict['align'] = align or '>' + + # default sign handling: '-' for negative, '' for positive + if format_dict['sign'] is None: + format_dict['sign'] = '-' + + # minimumwidth defaults to 0; precision remains None if not given + format_dict['minimumwidth'] = int(format_dict['minimumwidth'] or '0') + if format_dict['precision'] is not None: + format_dict['precision'] = int(format_dict['precision']) + + # if format type is 'g' or 'G' then a precision of 0 makes little + # sense; convert it to 1. Same if format type is unspecified. + if format_dict['precision'] == 0: + if format_dict['type'] is None or format_dict['type'] in 'gG': + format_dict['precision'] = 1 + + # determine thousands separator, grouping, and decimal separator, and + # add appropriate entries to format_dict + if format_dict['type'] == 'n': + # apart from separators, 'n' behaves just like 'g' + format_dict['type'] = 'g' + if _localeconv is None: + _localeconv = _locale.localeconv() + if format_dict['thousands_sep'] is not None: + raise ValueError("Explicit thousands separator conflicts with " + "'n' type in format specifier: " + format_spec) + format_dict['thousands_sep'] = _localeconv['thousands_sep'] + format_dict['grouping'] = _localeconv['grouping'] + format_dict['decimal_point'] = _localeconv['decimal_point'] + else: + if format_dict['thousands_sep'] is None: + format_dict['thousands_sep'] = '' + format_dict['grouping'] = [3, 0] + format_dict['decimal_point'] = '.' + + # record whether return type should be str or unicode + format_dict['unicode'] = isinstance(format_spec, unicode) + + return format_dict + +def _format_align(sign, body, spec): + """Given an unpadded, non-aligned numeric string 'body' and sign + string 'sign', add padding and alignment conforming to the given + format specifier dictionary 'spec' (as produced by + parse_format_specifier). + + Also converts result to unicode if necessary. + + """ + # how much extra space do we have to play with? + minimumwidth = spec['minimumwidth'] + fill = spec['fill'] + padding = fill*(minimumwidth - len(sign) - len(body)) + + align = spec['align'] + if align == '<': + result = sign + body + padding + elif align == '>': + result = padding + sign + body + elif align == '=': + result = sign + padding + body + elif align == '^': + half = len(padding)//2 + result = padding[:half] + sign + body + padding[half:] + else: + raise ValueError('Unrecognised alignment field') + + # make sure that result is unicode if necessary + if spec['unicode']: + result = unicode(result) + + return result + +def _group_lengths(grouping): + """Convert a localeconv-style grouping into a (possibly infinite) + iterable of integers representing group lengths. + + """ + # The result from localeconv()['grouping'], and the input to this + # function, should be a list of integers in one of the + # following three forms: + # + # (1) an empty list, or + # (2) nonempty list of positive integers + [0] + # (3) list of positive integers + [locale.CHAR_MAX], or + + from itertools import chain, repeat + if not grouping: + return [] + elif grouping[-1] == 0 and len(grouping) >= 2: + return chain(grouping[:-1], repeat(grouping[-2])) + elif grouping[-1] == _locale.CHAR_MAX: + return grouping[:-1] + else: + raise ValueError('unrecognised format for grouping') + +def _insert_thousands_sep(digits, spec, min_width=1): + """Insert thousands separators into a digit string. + + spec is a dictionary whose keys should include 'thousands_sep' and + 'grouping'; typically it's the result of parsing the format + specifier using _parse_format_specifier. + + The min_width keyword argument gives the minimum length of the + result, which will be padded on the left with zeros if necessary. + + If necessary, the zero padding adds an extra '0' on the left to + avoid a leading thousands separator. For example, inserting + commas every three digits in '123456', with min_width=8, gives + '0,123,456', even though that has length 9. + + """ + + sep = spec['thousands_sep'] + grouping = spec['grouping'] + + groups = [] + for l in _group_lengths(grouping): + if l <= 0: + raise ValueError("group length should be positive") + # max(..., 1) forces at least 1 digit to the left of a separator + l = min(max(len(digits), min_width, 1), l) + groups.append('0'*(l - len(digits)) + digits[-l:]) + digits = digits[:-l] + min_width -= l + if not digits and min_width <= 0: + break + min_width -= len(sep) + else: + l = max(len(digits), min_width, 1) + groups.append('0'*(l - len(digits)) + digits[-l:]) + return sep.join(reversed(groups)) + +def _format_sign(is_negative, spec): + """Determine sign character.""" + + if is_negative: + return '-' + elif spec['sign'] in ' +': + return spec['sign'] + else: + return '' + +def _format_number(is_negative, intpart, fracpart, exp, spec): + """Format a number, given the following data: + + is_negative: true if the number is negative, else false + intpart: string of digits that must appear before the decimal point + fracpart: string of digits that must come after the point + exp: exponent, as an integer + spec: dictionary resulting from parsing the format specifier + + This function uses the information in spec to: + insert separators (decimal separator and thousands separators) + format the sign + format the exponent + add trailing '%' for the '%' type + zero-pad if necessary + fill and align if necessary + """ + + sign = _format_sign(is_negative, spec) + + if fracpart: + fracpart = spec['decimal_point'] + fracpart + + if exp != 0 or spec['type'] in 'eE': + echar = {'E': 'E', 'e': 'e', 'G': 'E', 'g': 'e'}[spec['type']] + fracpart += "{0}{1:+}".format(echar, exp) + if spec['type'] == '%': + fracpart += '%' + + if spec['zeropad']: + min_width = spec['minimumwidth'] - len(fracpart) - len(sign) + else: + min_width = 0 + intpart = _insert_thousands_sep(intpart, spec, min_width) + + return _format_align(sign, intpart+fracpart, spec) + + +##### Useful Constants (internal use only) ################################ + +# Reusable defaults +_Infinity = Decimal('Inf') +_NegativeInfinity = Decimal('-Inf') +_NaN = Decimal('NaN') +_Zero = Decimal(0) +_One = Decimal(1) +_NegativeOne = Decimal(-1) + +# _SignedInfinity[sign] is infinity w/ that sign +_SignedInfinity = (_Infinity, _NegativeInfinity) + + + +if __name__ == '__main__': + import doctest, sys + doctest.testmod(sys.modules[__name__]) diff --git a/PythonHome/Lib/decimal.pyc b/PythonHome/Lib/decimal.pyc deleted file mode 100644 index 837ea3e90796d653eacd83211480205aa35d28f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 167489 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 diff --git a/PythonHome/Lib/difflib.py b/PythonHome/Lib/difflib.py new file mode 100644 index 0000000000..3880d8472e --- /dev/null +++ b/PythonHome/Lib/difflib.py @@ -0,0 +1,2057 @@ +""" +Module difflib -- helpers for computing deltas between objects. + +Function get_close_matches(word, possibilities, n=3, cutoff=0.6): + Use SequenceMatcher to return list of the best "good enough" matches. + +Function context_diff(a, b): + For two lists of strings, return a delta in context diff format. + +Function ndiff(a, b): + Return a delta: the difference between `a` and `b` (lists of strings). + +Function restore(delta, which): + Return one of the two sequences that generated an ndiff delta. + +Function unified_diff(a, b): + For two lists of strings, return a delta in unified diff format. + +Class SequenceMatcher: + A flexible class for comparing pairs of sequences of any type. + +Class Differ: + For producing human-readable deltas from sequences of lines of text. + +Class HtmlDiff: + For producing HTML side by side comparison with change highlights. +""" + +__all__ = ['get_close_matches', 'ndiff', 'restore', 'SequenceMatcher', + 'Differ','IS_CHARACTER_JUNK', 'IS_LINE_JUNK', 'context_diff', + 'unified_diff', 'HtmlDiff', 'Match'] + +import heapq +from collections import namedtuple as _namedtuple +from functools import reduce + +Match = _namedtuple('Match', 'a b size') + +def _calculate_ratio(matches, length): + if length: + return 2.0 * matches / length + return 1.0 + +class SequenceMatcher: + + """ + SequenceMatcher is a flexible class for comparing pairs of sequences of + any type, so long as the sequence elements are hashable. The basic + algorithm predates, and is a little fancier than, an algorithm + published in the late 1980's by Ratcliff and Obershelp under the + hyperbolic name "gestalt pattern matching". The basic idea is to find + the longest contiguous matching subsequence that contains no "junk" + elements (R-O doesn't address junk). The same idea is then applied + recursively to the pieces of the sequences to the left and to the right + of the matching subsequence. This does not yield minimal edit + sequences, but does tend to yield matches that "look right" to people. + + SequenceMatcher tries to compute a "human-friendly diff" between two + sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the + longest *contiguous* & junk-free matching subsequence. That's what + catches peoples' eyes. The Windows(tm) windiff has another interesting + notion, pairing up elements that appear uniquely in each sequence. + That, and the method here, appear to yield more intuitive difference + reports than does diff. This method appears to be the least vulnerable + to synching up on blocks of "junk lines", though (like blank lines in + ordinary text files, or maybe "

" lines in HTML files). That may be + because this is the only method of the 3 that has a *concept* of + "junk" . + + Example, comparing two strings, and considering blanks to be "junk": + + >>> s = SequenceMatcher(lambda x: x == " ", + ... "private Thread currentThread;", + ... "private volatile Thread currentThread;") + >>> + + .ratio() returns a float in [0, 1], measuring the "similarity" of the + sequences. As a rule of thumb, a .ratio() value over 0.6 means the + sequences are close matches: + + >>> print round(s.ratio(), 3) + 0.866 + >>> + + If you're only interested in where the sequences match, + .get_matching_blocks() is handy: + + >>> for block in s.get_matching_blocks(): + ... print "a[%d] and b[%d] match for %d elements" % block + a[0] and b[0] match for 8 elements + a[8] and b[17] match for 21 elements + a[29] and b[38] match for 0 elements + + Note that the last tuple returned by .get_matching_blocks() is always a + dummy, (len(a), len(b), 0), and this is the only case in which the last + tuple element (number of elements matched) is 0. + + If you want to know how to change the first sequence into the second, + use .get_opcodes(): + + >>> for opcode in s.get_opcodes(): + ... print "%6s a[%d:%d] b[%d:%d]" % opcode + equal a[0:8] b[0:8] + insert a[8:8] b[8:17] + equal a[8:29] b[17:38] + + See the Differ class for a fancy human-friendly file differencer, which + uses SequenceMatcher both to compare sequences of lines, and to compare + sequences of characters within similar (near-matching) lines. + + See also function get_close_matches() in this module, which shows how + simple code building on SequenceMatcher can be used to do useful work. + + Timing: Basic R-O is cubic time worst case and quadratic time expected + case. SequenceMatcher is quadratic time for the worst case and has + expected-case behavior dependent in a complicated way on how many + elements the sequences have in common; best case time is linear. + + Methods: + + __init__(isjunk=None, a='', b='') + Construct a SequenceMatcher. + + set_seqs(a, b) + Set the two sequences to be compared. + + set_seq1(a) + Set the first sequence to be compared. + + set_seq2(b) + Set the second sequence to be compared. + + find_longest_match(alo, ahi, blo, bhi) + Find longest matching block in a[alo:ahi] and b[blo:bhi]. + + get_matching_blocks() + Return list of triples describing matching subsequences. + + get_opcodes() + Return list of 5-tuples describing how to turn a into b. + + ratio() + Return a measure of the sequences' similarity (float in [0,1]). + + quick_ratio() + Return an upper bound on .ratio() relatively quickly. + + real_quick_ratio() + Return an upper bound on ratio() very quickly. + """ + + def __init__(self, isjunk=None, a='', b='', autojunk=True): + """Construct a SequenceMatcher. + + Optional arg isjunk is None (the default), or a one-argument + function that takes a sequence element and returns true iff the + element is junk. None is equivalent to passing "lambda x: 0", i.e. + no elements are considered to be junk. For example, pass + lambda x: x in " \\t" + if you're comparing lines as sequences of characters, and don't + want to synch up on blanks or hard tabs. + + Optional arg a is the first of two sequences to be compared. By + default, an empty string. The elements of a must be hashable. See + also .set_seqs() and .set_seq1(). + + Optional arg b is the second of two sequences to be compared. By + default, an empty string. The elements of b must be hashable. See + also .set_seqs() and .set_seq2(). + + Optional arg autojunk should be set to False to disable the + "automatic junk heuristic" that treats popular elements as junk + (see module documentation for more information). + """ + + # Members: + # a + # first sequence + # b + # second sequence; differences are computed as "what do + # we need to do to 'a' to change it into 'b'?" + # b2j + # for x in b, b2j[x] is a list of the indices (into b) + # at which x appears; junk elements do not appear + # fullbcount + # for x in b, fullbcount[x] == the number of times x + # appears in b; only materialized if really needed (used + # only for computing quick_ratio()) + # matching_blocks + # a list of (i, j, k) triples, where a[i:i+k] == b[j:j+k]; + # ascending & non-overlapping in i and in j; terminated by + # a dummy (len(a), len(b), 0) sentinel + # opcodes + # a list of (tag, i1, i2, j1, j2) tuples, where tag is + # one of + # 'replace' a[i1:i2] should be replaced by b[j1:j2] + # 'delete' a[i1:i2] should be deleted + # 'insert' b[j1:j2] should be inserted + # 'equal' a[i1:i2] == b[j1:j2] + # isjunk + # a user-supplied function taking a sequence element and + # returning true iff the element is "junk" -- this has + # subtle but helpful effects on the algorithm, which I'll + # get around to writing up someday <0.9 wink>. + # DON'T USE! Only __chain_b uses this. Use isbjunk. + # isbjunk + # for x in b, isbjunk(x) == isjunk(x) but much faster; + # it's really the __contains__ method of a hidden dict. + # DOES NOT WORK for x in a! + # isbpopular + # for x in b, isbpopular(x) is true iff b is reasonably long + # (at least 200 elements) and x accounts for more than 1 + 1% of + # its elements (when autojunk is enabled). + # DOES NOT WORK for x in a! + + self.isjunk = isjunk + self.a = self.b = None + self.autojunk = autojunk + self.set_seqs(a, b) + + def set_seqs(self, a, b): + """Set the two sequences to be compared. + + >>> s = SequenceMatcher() + >>> s.set_seqs("abcd", "bcde") + >>> s.ratio() + 0.75 + """ + + self.set_seq1(a) + self.set_seq2(b) + + def set_seq1(self, a): + """Set the first sequence to be compared. + + The second sequence to be compared is not changed. + + >>> s = SequenceMatcher(None, "abcd", "bcde") + >>> s.ratio() + 0.75 + >>> s.set_seq1("bcde") + >>> s.ratio() + 1.0 + >>> + + SequenceMatcher computes and caches detailed information about the + second sequence, so if you want to compare one sequence S against + many sequences, use .set_seq2(S) once and call .set_seq1(x) + repeatedly for each of the other sequences. + + See also set_seqs() and set_seq2(). + """ + + if a is self.a: + return + self.a = a + self.matching_blocks = self.opcodes = None + + def set_seq2(self, b): + """Set the second sequence to be compared. + + The first sequence to be compared is not changed. + + >>> s = SequenceMatcher(None, "abcd", "bcde") + >>> s.ratio() + 0.75 + >>> s.set_seq2("abcd") + >>> s.ratio() + 1.0 + >>> + + SequenceMatcher computes and caches detailed information about the + second sequence, so if you want to compare one sequence S against + many sequences, use .set_seq2(S) once and call .set_seq1(x) + repeatedly for each of the other sequences. + + See also set_seqs() and set_seq1(). + """ + + if b is self.b: + return + self.b = b + self.matching_blocks = self.opcodes = None + self.fullbcount = None + self.__chain_b() + + # For each element x in b, set b2j[x] to a list of the indices in + # b where x appears; the indices are in increasing order; note that + # the number of times x appears in b is len(b2j[x]) ... + # when self.isjunk is defined, junk elements don't show up in this + # map at all, which stops the central find_longest_match method + # from starting any matching block at a junk element ... + # also creates the fast isbjunk function ... + # b2j also does not contain entries for "popular" elements, meaning + # elements that account for more than 1 + 1% of the total elements, and + # when the sequence is reasonably large (>= 200 elements); this can + # be viewed as an adaptive notion of semi-junk, and yields an enormous + # speedup when, e.g., comparing program files with hundreds of + # instances of "return NULL;" ... + # note that this is only called when b changes; so for cross-product + # kinds of matches, it's best to call set_seq2 once, then set_seq1 + # repeatedly + + def __chain_b(self): + # Because isjunk is a user-defined (not C) function, and we test + # for junk a LOT, it's important to minimize the number of calls. + # Before the tricks described here, __chain_b was by far the most + # time-consuming routine in the whole module! If anyone sees + # Jim Roskind, thank him again for profile.py -- I never would + # have guessed that. + # The first trick is to build b2j ignoring the possibility + # of junk. I.e., we don't call isjunk at all yet. Throwing + # out the junk later is much cheaper than building b2j "right" + # from the start. + b = self.b + self.b2j = b2j = {} + + for i, elt in enumerate(b): + indices = b2j.setdefault(elt, []) + indices.append(i) + + # Purge junk elements + junk = set() + isjunk = self.isjunk + if isjunk: + for elt in list(b2j.keys()): # using list() since b2j is modified + if isjunk(elt): + junk.add(elt) + del b2j[elt] + + # Purge popular elements that are not junk + popular = set() + n = len(b) + if self.autojunk and n >= 200: + ntest = n // 100 + 1 + for elt, idxs in list(b2j.items()): + if len(idxs) > ntest: + popular.add(elt) + del b2j[elt] + + # Now for x in b, isjunk(x) == x in junk, but the latter is much faster. + # Sicne the number of *unique* junk elements is probably small, the + # memory burden of keeping this set alive is likely trivial compared to + # the size of b2j. + self.isbjunk = junk.__contains__ + self.isbpopular = popular.__contains__ + + def find_longest_match(self, alo, ahi, blo, bhi): + """Find longest matching block in a[alo:ahi] and b[blo:bhi]. + + If isjunk is not defined: + + Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where + alo <= i <= i+k <= ahi + blo <= j <= j+k <= bhi + and for all (i',j',k') meeting those conditions, + k >= k' + i <= i' + and if i == i', j <= j' + + In other words, of all maximal matching blocks, return one that + starts earliest in a, and of all those maximal matching blocks that + start earliest in a, return the one that starts earliest in b. + + >>> s = SequenceMatcher(None, " abcd", "abcd abcd") + >>> s.find_longest_match(0, 5, 0, 9) + Match(a=0, b=4, size=5) + + If isjunk is defined, first the longest matching block is + determined as above, but with the additional restriction that no + junk element appears in the block. Then that block is extended as + far as possible by matching (only) junk elements on both sides. So + the resulting block never matches on junk except as identical junk + happens to be adjacent to an "interesting" match. + + Here's the same example as before, but considering blanks to be + junk. That prevents " abcd" from matching the " abcd" at the tail + end of the second sequence directly. Instead only the "abcd" can + match, and matches the leftmost "abcd" in the second sequence: + + >>> s = SequenceMatcher(lambda x: x==" ", " abcd", "abcd abcd") + >>> s.find_longest_match(0, 5, 0, 9) + Match(a=1, b=0, size=4) + + If no blocks match, return (alo, blo, 0). + + >>> s = SequenceMatcher(None, "ab", "c") + >>> s.find_longest_match(0, 2, 0, 1) + Match(a=0, b=0, size=0) + """ + + # CAUTION: stripping common prefix or suffix would be incorrect. + # E.g., + # ab + # acab + # Longest matching block is "ab", but if common prefix is + # stripped, it's "a" (tied with "b"). UNIX(tm) diff does so + # strip, so ends up claiming that ab is changed to acab by + # inserting "ca" in the middle. That's minimal but unintuitive: + # "it's obvious" that someone inserted "ac" at the front. + # Windiff ends up at the same place as diff, but by pairing up + # the unique 'b's and then matching the first two 'a's. + + a, b, b2j, isbjunk = self.a, self.b, self.b2j, self.isbjunk + besti, bestj, bestsize = alo, blo, 0 + # find longest junk-free match + # during an iteration of the loop, j2len[j] = length of longest + # junk-free match ending with a[i-1] and b[j] + j2len = {} + nothing = [] + for i in xrange(alo, ahi): + # look at all instances of a[i] in b; note that because + # b2j has no junk keys, the loop is skipped if a[i] is junk + j2lenget = j2len.get + newj2len = {} + for j in b2j.get(a[i], nothing): + # a[i] matches b[j] + if j < blo: + continue + if j >= bhi: + break + k = newj2len[j] = j2lenget(j-1, 0) + 1 + if k > bestsize: + besti, bestj, bestsize = i-k+1, j-k+1, k + j2len = newj2len + + # Extend the best by non-junk elements on each end. In particular, + # "popular" non-junk elements aren't in b2j, which greatly speeds + # the inner loop above, but also means "the best" match so far + # doesn't contain any junk *or* popular non-junk elements. + while besti > alo and bestj > blo and \ + not isbjunk(b[bestj-1]) and \ + a[besti-1] == b[bestj-1]: + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + while besti+bestsize < ahi and bestj+bestsize < bhi and \ + not isbjunk(b[bestj+bestsize]) and \ + a[besti+bestsize] == b[bestj+bestsize]: + bestsize += 1 + + # Now that we have a wholly interesting match (albeit possibly + # empty!), we may as well suck up the matching junk on each + # side of it too. Can't think of a good reason not to, and it + # saves post-processing the (possibly considerable) expense of + # figuring out what to do with it. In the case of an empty + # interesting match, this is clearly the right thing to do, + # because no other kind of match is possible in the regions. + while besti > alo and bestj > blo and \ + isbjunk(b[bestj-1]) and \ + a[besti-1] == b[bestj-1]: + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + while besti+bestsize < ahi and bestj+bestsize < bhi and \ + isbjunk(b[bestj+bestsize]) and \ + a[besti+bestsize] == b[bestj+bestsize]: + bestsize = bestsize + 1 + + return Match(besti, bestj, bestsize) + + def get_matching_blocks(self): + """Return list of triples describing matching subsequences. + + Each triple is of the form (i, j, n), and means that + a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in + i and in j. New in Python 2.5, it's also guaranteed that if + (i, j, n) and (i', j', n') are adjacent triples in the list, and + the second is not the last triple in the list, then i+n != i' or + j+n != j'. IOW, adjacent triples never describe adjacent equal + blocks. + + The last triple is a dummy, (len(a), len(b), 0), and is the only + triple with n==0. + + >>> s = SequenceMatcher(None, "abxcd", "abcd") + >>> s.get_matching_blocks() + [Match(a=0, b=0, size=2), Match(a=3, b=2, size=2), Match(a=5, b=4, size=0)] + """ + + if self.matching_blocks is not None: + return self.matching_blocks + la, lb = len(self.a), len(self.b) + + # This is most naturally expressed as a recursive algorithm, but + # at least one user bumped into extreme use cases that exceeded + # the recursion limit on their box. So, now we maintain a list + # ('queue`) of blocks we still need to look at, and append partial + # results to `matching_blocks` in a loop; the matches are sorted + # at the end. + queue = [(0, la, 0, lb)] + matching_blocks = [] + while queue: + alo, ahi, blo, bhi = queue.pop() + i, j, k = x = self.find_longest_match(alo, ahi, blo, bhi) + # a[alo:i] vs b[blo:j] unknown + # a[i:i+k] same as b[j:j+k] + # a[i+k:ahi] vs b[j+k:bhi] unknown + if k: # if k is 0, there was no matching block + matching_blocks.append(x) + if alo < i and blo < j: + queue.append((alo, i, blo, j)) + if i+k < ahi and j+k < bhi: + queue.append((i+k, ahi, j+k, bhi)) + matching_blocks.sort() + + # It's possible that we have adjacent equal blocks in the + # matching_blocks list now. Starting with 2.5, this code was added + # to collapse them. + i1 = j1 = k1 = 0 + non_adjacent = [] + for i2, j2, k2 in matching_blocks: + # Is this block adjacent to i1, j1, k1? + if i1 + k1 == i2 and j1 + k1 == j2: + # Yes, so collapse them -- this just increases the length of + # the first block by the length of the second, and the first + # block so lengthened remains the block to compare against. + k1 += k2 + else: + # Not adjacent. Remember the first block (k1==0 means it's + # the dummy we started with), and make the second block the + # new block to compare against. + if k1: + non_adjacent.append((i1, j1, k1)) + i1, j1, k1 = i2, j2, k2 + if k1: + non_adjacent.append((i1, j1, k1)) + + non_adjacent.append( (la, lb, 0) ) + self.matching_blocks = map(Match._make, non_adjacent) + return self.matching_blocks + + def get_opcodes(self): + """Return list of 5-tuples describing how to turn a into b. + + Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple + has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the + tuple preceding it, and likewise for j1 == the previous j2. + + The tags are strings, with these meanings: + + 'replace': a[i1:i2] should be replaced by b[j1:j2] + 'delete': a[i1:i2] should be deleted. + Note that j1==j2 in this case. + 'insert': b[j1:j2] should be inserted at a[i1:i1]. + Note that i1==i2 in this case. + 'equal': a[i1:i2] == b[j1:j2] + + >>> a = "qabxcd" + >>> b = "abycdf" + >>> s = SequenceMatcher(None, a, b) + >>> for tag, i1, i2, j1, j2 in s.get_opcodes(): + ... print ("%7s a[%d:%d] (%s) b[%d:%d] (%s)" % + ... (tag, i1, i2, a[i1:i2], j1, j2, b[j1:j2])) + delete a[0:1] (q) b[0:0] () + equal a[1:3] (ab) b[0:2] (ab) + replace a[3:4] (x) b[2:3] (y) + equal a[4:6] (cd) b[3:5] (cd) + insert a[6:6] () b[5:6] (f) + """ + + if self.opcodes is not None: + return self.opcodes + i = j = 0 + self.opcodes = answer = [] + for ai, bj, size in self.get_matching_blocks(): + # invariant: we've pumped out correct diffs to change + # a[:i] into b[:j], and the next matching block is + # a[ai:ai+size] == b[bj:bj+size]. So we need to pump + # out a diff to change a[i:ai] into b[j:bj], pump out + # the matching block, and move (i,j) beyond the match + tag = '' + if i < ai and j < bj: + tag = 'replace' + elif i < ai: + tag = 'delete' + elif j < bj: + tag = 'insert' + if tag: + answer.append( (tag, i, ai, j, bj) ) + i, j = ai+size, bj+size + # the list of matching blocks is terminated by a + # sentinel with size 0 + if size: + answer.append( ('equal', ai, i, bj, j) ) + return answer + + def get_grouped_opcodes(self, n=3): + """ Isolate change clusters by eliminating ranges with no changes. + + Return a generator of groups with up to n lines of context. + Each group is in the same format as returned by get_opcodes(). + + >>> from pprint import pprint + >>> a = map(str, range(1,40)) + >>> b = a[:] + >>> b[8:8] = ['i'] # Make an insertion + >>> b[20] += 'x' # Make a replacement + >>> b[23:28] = [] # Make a deletion + >>> b[30] += 'y' # Make another replacement + >>> pprint(list(SequenceMatcher(None,a,b).get_grouped_opcodes())) + [[('equal', 5, 8, 5, 8), ('insert', 8, 8, 8, 9), ('equal', 8, 11, 9, 12)], + [('equal', 16, 19, 17, 20), + ('replace', 19, 20, 20, 21), + ('equal', 20, 22, 21, 23), + ('delete', 22, 27, 23, 23), + ('equal', 27, 30, 23, 26)], + [('equal', 31, 34, 27, 30), + ('replace', 34, 35, 30, 31), + ('equal', 35, 38, 31, 34)]] + """ + + codes = self.get_opcodes() + if not codes: + codes = [("equal", 0, 1, 0, 1)] + # Fixup leading and trailing groups if they show no changes. + if codes[0][0] == 'equal': + tag, i1, i2, j1, j2 = codes[0] + codes[0] = tag, max(i1, i2-n), i2, max(j1, j2-n), j2 + if codes[-1][0] == 'equal': + tag, i1, i2, j1, j2 = codes[-1] + codes[-1] = tag, i1, min(i2, i1+n), j1, min(j2, j1+n) + + nn = n + n + group = [] + for tag, i1, i2, j1, j2 in codes: + # End the current group and start a new one whenever + # there is a large range with no changes. + if tag == 'equal' and i2-i1 > nn: + group.append((tag, i1, min(i2, i1+n), j1, min(j2, j1+n))) + yield group + group = [] + i1, j1 = max(i1, i2-n), max(j1, j2-n) + group.append((tag, i1, i2, j1 ,j2)) + if group and not (len(group)==1 and group[0][0] == 'equal'): + yield group + + def ratio(self): + """Return a measure of the sequences' similarity (float in [0,1]). + + Where T is the total number of elements in both sequences, and + M is the number of matches, this is 2.0*M / T. + Note that this is 1 if the sequences are identical, and 0 if + they have nothing in common. + + .ratio() is expensive to compute if you haven't already computed + .get_matching_blocks() or .get_opcodes(), in which case you may + want to try .quick_ratio() or .real_quick_ratio() first to get an + upper bound. + + >>> s = SequenceMatcher(None, "abcd", "bcde") + >>> s.ratio() + 0.75 + >>> s.quick_ratio() + 0.75 + >>> s.real_quick_ratio() + 1.0 + """ + + matches = reduce(lambda sum, triple: sum + triple[-1], + self.get_matching_blocks(), 0) + return _calculate_ratio(matches, len(self.a) + len(self.b)) + + def quick_ratio(self): + """Return an upper bound on ratio() relatively quickly. + + This isn't defined beyond that it is an upper bound on .ratio(), and + is faster to compute. + """ + + # viewing a and b as multisets, set matches to the cardinality + # of their intersection; this counts the number of matches + # without regard to order, so is clearly an upper bound + if self.fullbcount is None: + self.fullbcount = fullbcount = {} + for elt in self.b: + fullbcount[elt] = fullbcount.get(elt, 0) + 1 + fullbcount = self.fullbcount + # avail[x] is the number of times x appears in 'b' less the + # number of times we've seen it in 'a' so far ... kinda + avail = {} + availhas, matches = avail.__contains__, 0 + for elt in self.a: + if availhas(elt): + numb = avail[elt] + else: + numb = fullbcount.get(elt, 0) + avail[elt] = numb - 1 + if numb > 0: + matches = matches + 1 + return _calculate_ratio(matches, len(self.a) + len(self.b)) + + def real_quick_ratio(self): + """Return an upper bound on ratio() very quickly. + + This isn't defined beyond that it is an upper bound on .ratio(), and + is faster to compute than either .ratio() or .quick_ratio(). + """ + + la, lb = len(self.a), len(self.b) + # can't have more matches than the number of elements in the + # shorter sequence + return _calculate_ratio(min(la, lb), la + lb) + +def get_close_matches(word, possibilities, n=3, cutoff=0.6): + """Use SequenceMatcher to return list of the best "good enough" matches. + + word is a sequence for which close matches are desired (typically a + string). + + possibilities is a list of sequences against which to match word + (typically a list of strings). + + Optional arg n (default 3) is the maximum number of close matches to + return. n must be > 0. + + Optional arg cutoff (default 0.6) is a float in [0, 1]. Possibilities + that don't score at least that similar to word are ignored. + + The best (no more than n) matches among the possibilities are returned + in a list, sorted by similarity score, most similar first. + + >>> get_close_matches("appel", ["ape", "apple", "peach", "puppy"]) + ['apple', 'ape'] + >>> import keyword as _keyword + >>> get_close_matches("wheel", _keyword.kwlist) + ['while'] + >>> get_close_matches("apple", _keyword.kwlist) + [] + >>> get_close_matches("accept", _keyword.kwlist) + ['except'] + """ + + if not n > 0: + raise ValueError("n must be > 0: %r" % (n,)) + if not 0.0 <= cutoff <= 1.0: + raise ValueError("cutoff must be in [0.0, 1.0]: %r" % (cutoff,)) + result = [] + s = SequenceMatcher() + s.set_seq2(word) + for x in possibilities: + s.set_seq1(x) + if s.real_quick_ratio() >= cutoff and \ + s.quick_ratio() >= cutoff and \ + s.ratio() >= cutoff: + result.append((s.ratio(), x)) + + # Move the best scorers to head of list + result = heapq.nlargest(n, result) + # Strip scores for the best n matches + return [x for score, x in result] + +def _count_leading(line, ch): + """ + Return number of `ch` characters at the start of `line`. + + Example: + + >>> _count_leading(' abc', ' ') + 3 + """ + + i, n = 0, len(line) + while i < n and line[i] == ch: + i += 1 + return i + +class Differ: + r""" + Differ is a class for comparing sequences of lines of text, and + producing human-readable differences or deltas. Differ uses + SequenceMatcher both to compare sequences of lines, and to compare + sequences of characters within similar (near-matching) lines. + + Each line of a Differ delta begins with a two-letter code: + + '- ' line unique to sequence 1 + '+ ' line unique to sequence 2 + ' ' line common to both sequences + '? ' line not present in either input sequence + + Lines beginning with '? ' attempt to guide the eye to intraline + differences, and were not present in either input sequence. These lines + can be confusing if the sequences contain tab characters. + + Note that Differ makes no claim to produce a *minimal* diff. To the + contrary, minimal diffs are often counter-intuitive, because they synch + up anywhere possible, sometimes accidental matches 100 pages apart. + Restricting synch points to contiguous matches preserves some notion of + locality, at the occasional cost of producing a longer diff. + + Example: Comparing two texts. + + First we set up the texts, sequences of individual single-line strings + ending with newlines (such sequences can also be obtained from the + `readlines()` method of file-like objects): + + >>> text1 = ''' 1. Beautiful is better than ugly. + ... 2. Explicit is better than implicit. + ... 3. Simple is better than complex. + ... 4. Complex is better than complicated. + ... '''.splitlines(1) + >>> len(text1) + 4 + >>> text1[0][-1] + '\n' + >>> text2 = ''' 1. Beautiful is better than ugly. + ... 3. Simple is better than complex. + ... 4. Complicated is better than complex. + ... 5. Flat is better than nested. + ... '''.splitlines(1) + + Next we instantiate a Differ object: + + >>> d = Differ() + + Note that when instantiating a Differ object we may pass functions to + filter out line and character 'junk'. See Differ.__init__ for details. + + Finally, we compare the two: + + >>> result = list(d.compare(text1, text2)) + + 'result' is a list of strings, so let's pretty-print it: + + >>> from pprint import pprint as _pprint + >>> _pprint(result) + [' 1. Beautiful is better than ugly.\n', + '- 2. Explicit is better than implicit.\n', + '- 3. Simple is better than complex.\n', + '+ 3. Simple is better than complex.\n', + '? ++\n', + '- 4. Complex is better than complicated.\n', + '? ^ ---- ^\n', + '+ 4. Complicated is better than complex.\n', + '? ++++ ^ ^\n', + '+ 5. Flat is better than nested.\n'] + + As a single multi-line string it looks like this: + + >>> print ''.join(result), + 1. Beautiful is better than ugly. + - 2. Explicit is better than implicit. + - 3. Simple is better than complex. + + 3. Simple is better than complex. + ? ++ + - 4. Complex is better than complicated. + ? ^ ---- ^ + + 4. Complicated is better than complex. + ? ++++ ^ ^ + + 5. Flat is better than nested. + + Methods: + + __init__(linejunk=None, charjunk=None) + Construct a text differencer, with optional filters. + + compare(a, b) + Compare two sequences of lines; generate the resulting delta. + """ + + def __init__(self, linejunk=None, charjunk=None): + """ + Construct a text differencer, with optional filters. + + The two optional keyword parameters are for filter functions: + + - `linejunk`: A function that should accept a single string argument, + and return true iff the string is junk. The module-level function + `IS_LINE_JUNK` may be used to filter out lines without visible + characters, except for at most one splat ('#'). It is recommended + to leave linejunk None; as of Python 2.3, the underlying + SequenceMatcher class has grown an adaptive notion of "noise" lines + that's better than any static definition the author has ever been + able to craft. + + - `charjunk`: A function that should accept a string of length 1. The + module-level function `IS_CHARACTER_JUNK` may be used to filter out + whitespace characters (a blank or tab; **note**: bad idea to include + newline in this!). Use of IS_CHARACTER_JUNK is recommended. + """ + + self.linejunk = linejunk + self.charjunk = charjunk + + def compare(self, a, b): + r""" + Compare two sequences of lines; generate the resulting delta. + + Each sequence must contain individual single-line strings ending with + newlines. Such sequences can be obtained from the `readlines()` method + of file-like objects. The delta generated also consists of newline- + terminated strings, ready to be printed as-is via the writeline() + method of a file-like object. + + Example: + + >>> print ''.join(Differ().compare('one\ntwo\nthree\n'.splitlines(1), + ... 'ore\ntree\nemu\n'.splitlines(1))), + - one + ? ^ + + ore + ? ^ + - two + - three + ? - + + tree + + emu + """ + + cruncher = SequenceMatcher(self.linejunk, a, b) + for tag, alo, ahi, blo, bhi in cruncher.get_opcodes(): + if tag == 'replace': + g = self._fancy_replace(a, alo, ahi, b, blo, bhi) + elif tag == 'delete': + g = self._dump('-', a, alo, ahi) + elif tag == 'insert': + g = self._dump('+', b, blo, bhi) + elif tag == 'equal': + g = self._dump(' ', a, alo, ahi) + else: + raise ValueError, 'unknown tag %r' % (tag,) + + for line in g: + yield line + + def _dump(self, tag, x, lo, hi): + """Generate comparison results for a same-tagged range.""" + for i in xrange(lo, hi): + yield '%s %s' % (tag, x[i]) + + def _plain_replace(self, a, alo, ahi, b, blo, bhi): + assert alo < ahi and blo < bhi + # dump the shorter block first -- reduces the burden on short-term + # memory if the blocks are of very different sizes + if bhi - blo < ahi - alo: + first = self._dump('+', b, blo, bhi) + second = self._dump('-', a, alo, ahi) + else: + first = self._dump('-', a, alo, ahi) + second = self._dump('+', b, blo, bhi) + + for g in first, second: + for line in g: + yield line + + def _fancy_replace(self, a, alo, ahi, b, blo, bhi): + r""" + When replacing one block of lines with another, search the blocks + for *similar* lines; the best-matching pair (if any) is used as a + synch point, and intraline difference marking is done on the + similar pair. Lots of work, but often worth it. + + Example: + + >>> d = Differ() + >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1, + ... ['abcdefGhijkl\n'], 0, 1) + >>> print ''.join(results), + - abcDefghiJkl + ? ^ ^ ^ + + abcdefGhijkl + ? ^ ^ ^ + """ + + # don't synch up unless the lines have a similarity score of at + # least cutoff; best_ratio tracks the best score seen so far + best_ratio, cutoff = 0.74, 0.75 + cruncher = SequenceMatcher(self.charjunk) + eqi, eqj = None, None # 1st indices of equal lines (if any) + + # search for the pair that matches best without being identical + # (identical lines must be junk lines, & we don't want to synch up + # on junk -- unless we have to) + for j in xrange(blo, bhi): + bj = b[j] + cruncher.set_seq2(bj) + for i in xrange(alo, ahi): + ai = a[i] + if ai == bj: + if eqi is None: + eqi, eqj = i, j + continue + cruncher.set_seq1(ai) + # computing similarity is expensive, so use the quick + # upper bounds first -- have seen this speed up messy + # compares by a factor of 3. + # note that ratio() is only expensive to compute the first + # time it's called on a sequence pair; the expensive part + # of the computation is cached by cruncher + if cruncher.real_quick_ratio() > best_ratio and \ + cruncher.quick_ratio() > best_ratio and \ + cruncher.ratio() > best_ratio: + best_ratio, best_i, best_j = cruncher.ratio(), i, j + if best_ratio < cutoff: + # no non-identical "pretty close" pair + if eqi is None: + # no identical pair either -- treat it as a straight replace + for line in self._plain_replace(a, alo, ahi, b, blo, bhi): + yield line + return + # no close pair, but an identical pair -- synch up on that + best_i, best_j, best_ratio = eqi, eqj, 1.0 + else: + # there's a close pair, so forget the identical pair (if any) + eqi = None + + # a[best_i] very similar to b[best_j]; eqi is None iff they're not + # identical + + # pump out diffs from before the synch point + for line in self._fancy_helper(a, alo, best_i, b, blo, best_j): + yield line + + # do intraline marking on the synch pair + aelt, belt = a[best_i], b[best_j] + if eqi is None: + # pump out a '-', '?', '+', '?' quad for the synched lines + atags = btags = "" + cruncher.set_seqs(aelt, belt) + for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes(): + la, lb = ai2 - ai1, bj2 - bj1 + if tag == 'replace': + atags += '^' * la + btags += '^' * lb + elif tag == 'delete': + atags += '-' * la + elif tag == 'insert': + btags += '+' * lb + elif tag == 'equal': + atags += ' ' * la + btags += ' ' * lb + else: + raise ValueError, 'unknown tag %r' % (tag,) + for line in self._qformat(aelt, belt, atags, btags): + yield line + else: + # the synch pair is identical + yield ' ' + aelt + + # pump out diffs from after the synch point + for line in self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi): + yield line + + def _fancy_helper(self, a, alo, ahi, b, blo, bhi): + g = [] + if alo < ahi: + if blo < bhi: + g = self._fancy_replace(a, alo, ahi, b, blo, bhi) + else: + g = self._dump('-', a, alo, ahi) + elif blo < bhi: + g = self._dump('+', b, blo, bhi) + + for line in g: + yield line + + def _qformat(self, aline, bline, atags, btags): + r""" + Format "?" output and deal with leading tabs. + + Example: + + >>> d = Differ() + >>> results = d._qformat('\tabcDefghiJkl\n', '\tabcdefGhijkl\n', + ... ' ^ ^ ^ ', ' ^ ^ ^ ') + >>> for line in results: print repr(line) + ... + '- \tabcDefghiJkl\n' + '? \t ^ ^ ^\n' + '+ \tabcdefGhijkl\n' + '? \t ^ ^ ^\n' + """ + + # Can hurt, but will probably help most of the time. + common = min(_count_leading(aline, "\t"), + _count_leading(bline, "\t")) + common = min(common, _count_leading(atags[:common], " ")) + common = min(common, _count_leading(btags[:common], " ")) + atags = atags[common:].rstrip() + btags = btags[common:].rstrip() + + yield "- " + aline + if atags: + yield "? %s%s\n" % ("\t" * common, atags) + + yield "+ " + bline + if btags: + yield "? %s%s\n" % ("\t" * common, btags) + +# With respect to junk, an earlier version of ndiff simply refused to +# *start* a match with a junk element. The result was cases like this: +# before: private Thread currentThread; +# after: private volatile Thread currentThread; +# If you consider whitespace to be junk, the longest contiguous match +# not starting with junk is "e Thread currentThread". So ndiff reported +# that "e volatil" was inserted between the 't' and the 'e' in "private". +# While an accurate view, to people that's absurd. The current version +# looks for matching blocks that are entirely junk-free, then extends the +# longest one of those as far as possible but only with matching junk. +# So now "currentThread" is matched, then extended to suck up the +# preceding blank; then "private" is matched, and extended to suck up the +# following blank; then "Thread" is matched; and finally ndiff reports +# that "volatile " was inserted before "Thread". The only quibble +# remaining is that perhaps it was really the case that " volatile" +# was inserted after "private". I can live with that . + +import re + +def IS_LINE_JUNK(line, pat=re.compile(r"\s*#?\s*$").match): + r""" + Return 1 for ignorable line: iff `line` is blank or contains a single '#'. + + Examples: + + >>> IS_LINE_JUNK('\n') + True + >>> IS_LINE_JUNK(' # \n') + True + >>> IS_LINE_JUNK('hello\n') + False + """ + + return pat(line) is not None + +def IS_CHARACTER_JUNK(ch, ws=" \t"): + r""" + Return 1 for ignorable character: iff `ch` is a space or tab. + + Examples: + + >>> IS_CHARACTER_JUNK(' ') + True + >>> IS_CHARACTER_JUNK('\t') + True + >>> IS_CHARACTER_JUNK('\n') + False + >>> IS_CHARACTER_JUNK('x') + False + """ + + return ch in ws + + +######################################################################## +### Unified Diff +######################################################################## + +def _format_range_unified(start, stop): + 'Convert range to the "ed" format' + # Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning = start + 1 # lines start numbering with one + length = stop - start + if length == 1: + return '{}'.format(beginning) + if not length: + beginning -= 1 # empty ranges begin at line just before the range + return '{},{}'.format(beginning, length) + +def unified_diff(a, b, fromfile='', tofile='', fromfiledate='', + tofiledate='', n=3, lineterm='\n'): + r""" + Compare two sequences of lines; generate the delta as a unified diff. + + Unified diffs are a compact way of showing line changes and a few + lines of context. The number of context lines is set by 'n' which + defaults to three. + + By default, the diff control lines (those with ---, +++, or @@) are + created with a trailing newline. This is helpful so that inputs + created from file.readlines() result in diffs that are suitable for + file.writelines() since both the inputs and outputs have trailing + newlines. + + For inputs that do not have trailing newlines, set the lineterm + argument to "" so that the output will be uniformly newline free. + + The unidiff format normally has a header for filenames and modification + times. Any or all of these may be specified using strings for + 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. + The modification times are normally expressed in the ISO 8601 format. + + Example: + + >>> for line in unified_diff('one two three four'.split(), + ... 'zero one tree four'.split(), 'Original', 'Current', + ... '2005-01-26 23:30:50', '2010-04-02 10:20:52', + ... lineterm=''): + ... print line # doctest: +NORMALIZE_WHITESPACE + --- Original 2005-01-26 23:30:50 + +++ Current 2010-04-02 10:20:52 + @@ -1,4 +1,4 @@ + +zero + one + -two + -three + +tree + four + """ + + started = False + for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n): + if not started: + started = True + fromdate = '\t{}'.format(fromfiledate) if fromfiledate else '' + todate = '\t{}'.format(tofiledate) if tofiledate else '' + yield '--- {}{}{}'.format(fromfile, fromdate, lineterm) + yield '+++ {}{}{}'.format(tofile, todate, lineterm) + + first, last = group[0], group[-1] + file1_range = _format_range_unified(first[1], last[2]) + file2_range = _format_range_unified(first[3], last[4]) + yield '@@ -{} +{} @@{}'.format(file1_range, file2_range, lineterm) + + for tag, i1, i2, j1, j2 in group: + if tag == 'equal': + for line in a[i1:i2]: + yield ' ' + line + continue + if tag in ('replace', 'delete'): + for line in a[i1:i2]: + yield '-' + line + if tag in ('replace', 'insert'): + for line in b[j1:j2]: + yield '+' + line + + +######################################################################## +### Context Diff +######################################################################## + +def _format_range_context(start, stop): + 'Convert range to the "ed" format' + # Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning = start + 1 # lines start numbering with one + length = stop - start + if not length: + beginning -= 1 # empty ranges begin at line just before the range + if length <= 1: + return '{}'.format(beginning) + return '{},{}'.format(beginning, beginning + length - 1) + +# See http://www.unix.org/single_unix_specification/ +def context_diff(a, b, fromfile='', tofile='', + fromfiledate='', tofiledate='', n=3, lineterm='\n'): + r""" + Compare two sequences of lines; generate the delta as a context diff. + + Context diffs are a compact way of showing line changes and a few + lines of context. The number of context lines is set by 'n' which + defaults to three. + + By default, the diff control lines (those with *** or ---) are + created with a trailing newline. This is helpful so that inputs + created from file.readlines() result in diffs that are suitable for + file.writelines() since both the inputs and outputs have trailing + newlines. + + For inputs that do not have trailing newlines, set the lineterm + argument to "" so that the output will be uniformly newline free. + + The context diff format normally has a header for filenames and + modification times. Any or all of these may be specified using + strings for 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. + The modification times are normally expressed in the ISO 8601 format. + If not specified, the strings default to blanks. + + Example: + + >>> print ''.join(context_diff('one\ntwo\nthree\nfour\n'.splitlines(1), + ... 'zero\none\ntree\nfour\n'.splitlines(1), 'Original', 'Current')), + *** Original + --- Current + *************** + *** 1,4 **** + one + ! two + ! three + four + --- 1,4 ---- + + zero + one + ! tree + four + """ + + prefix = dict(insert='+ ', delete='- ', replace='! ', equal=' ') + started = False + for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n): + if not started: + started = True + fromdate = '\t{}'.format(fromfiledate) if fromfiledate else '' + todate = '\t{}'.format(tofiledate) if tofiledate else '' + yield '*** {}{}{}'.format(fromfile, fromdate, lineterm) + yield '--- {}{}{}'.format(tofile, todate, lineterm) + + first, last = group[0], group[-1] + yield '***************' + lineterm + + file1_range = _format_range_context(first[1], last[2]) + yield '*** {} ****{}'.format(file1_range, lineterm) + + if any(tag in ('replace', 'delete') for tag, _, _, _, _ in group): + for tag, i1, i2, _, _ in group: + if tag != 'insert': + for line in a[i1:i2]: + yield prefix[tag] + line + + file2_range = _format_range_context(first[3], last[4]) + yield '--- {} ----{}'.format(file2_range, lineterm) + + if any(tag in ('replace', 'insert') for tag, _, _, _, _ in group): + for tag, _, _, j1, j2 in group: + if tag != 'delete': + for line in b[j1:j2]: + yield prefix[tag] + line + +def ndiff(a, b, linejunk=None, charjunk=IS_CHARACTER_JUNK): + r""" + Compare `a` and `b` (lists of strings); return a `Differ`-style delta. + + Optional keyword parameters `linejunk` and `charjunk` are for filter + functions (or None): + + - linejunk: A function that should accept a single string argument, and + return true iff the string is junk. The default is None, and is + recommended; as of Python 2.3, an adaptive notion of "noise" lines is + used that does a good job on its own. + + - charjunk: A function that should accept a string of length 1. The + default is module-level function IS_CHARACTER_JUNK, which filters out + whitespace characters (a blank or tab; note: bad idea to include newline + in this!). + + Tools/scripts/ndiff.py is a command-line front-end to this function. + + Example: + + >>> diff = ndiff('one\ntwo\nthree\n'.splitlines(1), + ... 'ore\ntree\nemu\n'.splitlines(1)) + >>> print ''.join(diff), + - one + ? ^ + + ore + ? ^ + - two + - three + ? - + + tree + + emu + """ + return Differ(linejunk, charjunk).compare(a, b) + +def _mdiff(fromlines, tolines, context=None, linejunk=None, + charjunk=IS_CHARACTER_JUNK): + r"""Returns generator yielding marked up from/to side by side differences. + + Arguments: + fromlines -- list of text lines to compared to tolines + tolines -- list of text lines to be compared to fromlines + context -- number of context lines to display on each side of difference, + if None, all from/to text lines will be generated. + linejunk -- passed on to ndiff (see ndiff documentation) + charjunk -- passed on to ndiff (see ndiff documentation) + + This function returns an iterator which returns a tuple: + (from line tuple, to line tuple, boolean flag) + + from/to line tuple -- (line num, line text) + line num -- integer or None (to indicate a context separation) + line text -- original line text with following markers inserted: + '\0+' -- marks start of added text + '\0-' -- marks start of deleted text + '\0^' -- marks start of changed text + '\1' -- marks end of added/deleted/changed text + + boolean flag -- None indicates context separation, True indicates + either "from" or "to" line contains a change, otherwise False. + + This function/iterator was originally developed to generate side by side + file difference for making HTML pages (see HtmlDiff class for example + usage). + + Note, this function utilizes the ndiff function to generate the side by + side difference markup. Optional ndiff arguments may be passed to this + function and they in turn will be passed to ndiff. + """ + import re + + # regular expression for finding intraline change indices + change_re = re.compile('(\++|\-+|\^+)') + + # create the difference iterator to generate the differences + diff_lines_iterator = ndiff(fromlines,tolines,linejunk,charjunk) + + def _make_line(lines, format_key, side, num_lines=[0,0]): + """Returns line of text with user's change markup and line formatting. + + lines -- list of lines from the ndiff generator to produce a line of + text from. When producing the line of text to return, the + lines used are removed from this list. + format_key -- '+' return first line in list with "add" markup around + the entire line. + '-' return first line in list with "delete" markup around + the entire line. + '?' return first line in list with add/delete/change + intraline markup (indices obtained from second line) + None return first line in list with no markup + side -- indice into the num_lines list (0=from,1=to) + num_lines -- from/to current line number. This is NOT intended to be a + passed parameter. It is present as a keyword argument to + maintain memory of the current line numbers between calls + of this function. + + Note, this function is purposefully not defined at the module scope so + that data it needs from its parent function (within whose context it + is defined) does not need to be of module scope. + """ + num_lines[side] += 1 + # Handle case where no user markup is to be added, just return line of + # text with user's line format to allow for usage of the line number. + if format_key is None: + return (num_lines[side],lines.pop(0)[2:]) + # Handle case of intraline changes + if format_key == '?': + text, markers = lines.pop(0), lines.pop(0) + # find intraline changes (store change type and indices in tuples) + sub_info = [] + def record_sub_info(match_object,sub_info=sub_info): + sub_info.append([match_object.group(1)[0],match_object.span()]) + return match_object.group(1) + change_re.sub(record_sub_info,markers) + # process each tuple inserting our special marks that won't be + # noticed by an xml/html escaper. + for key,(begin,end) in sub_info[::-1]: + text = text[0:begin]+'\0'+key+text[begin:end]+'\1'+text[end:] + text = text[2:] + # Handle case of add/delete entire line + else: + text = lines.pop(0)[2:] + # if line of text is just a newline, insert a space so there is + # something for the user to highlight and see. + if not text: + text = ' ' + # insert marks that won't be noticed by an xml/html escaper. + text = '\0' + format_key + text + '\1' + # Return line of text, first allow user's line formatter to do its + # thing (such as adding the line number) then replace the special + # marks with what the user's change markup. + return (num_lines[side],text) + + def _line_iterator(): + """Yields from/to lines of text with a change indication. + + This function is an iterator. It itself pulls lines from a + differencing iterator, processes them and yields them. When it can + it yields both a "from" and a "to" line, otherwise it will yield one + or the other. In addition to yielding the lines of from/to text, a + boolean flag is yielded to indicate if the text line(s) have + differences in them. + + Note, this function is purposefully not defined at the module scope so + that data it needs from its parent function (within whose context it + is defined) does not need to be of module scope. + """ + lines = [] + num_blanks_pending, num_blanks_to_yield = 0, 0 + while True: + # Load up next 4 lines so we can look ahead, create strings which + # are a concatenation of the first character of each of the 4 lines + # so we can do some very readable comparisons. + while len(lines) < 4: + try: + lines.append(diff_lines_iterator.next()) + except StopIteration: + lines.append('X') + s = ''.join([line[0] for line in lines]) + if s.startswith('X'): + # When no more lines, pump out any remaining blank lines so the + # corresponding add/delete lines get a matching blank line so + # all line pairs get yielded at the next level. + num_blanks_to_yield = num_blanks_pending + elif s.startswith('-?+?'): + # simple intraline change + yield _make_line(lines,'?',0), _make_line(lines,'?',1), True + continue + elif s.startswith('--++'): + # in delete block, add block coming: we do NOT want to get + # caught up on blank lines yet, just process the delete line + num_blanks_pending -= 1 + yield _make_line(lines,'-',0), None, True + continue + elif s.startswith(('--?+', '--+', '- ')): + # in delete block and see a intraline change or unchanged line + # coming: yield the delete line and then blanks + from_line,to_line = _make_line(lines,'-',0), None + num_blanks_to_yield,num_blanks_pending = num_blanks_pending-1,0 + elif s.startswith('-+?'): + # intraline change + yield _make_line(lines,None,0), _make_line(lines,'?',1), True + continue + elif s.startswith('-?+'): + # intraline change + yield _make_line(lines,'?',0), _make_line(lines,None,1), True + continue + elif s.startswith('-'): + # delete FROM line + num_blanks_pending -= 1 + yield _make_line(lines,'-',0), None, True + continue + elif s.startswith('+--'): + # in add block, delete block coming: we do NOT want to get + # caught up on blank lines yet, just process the add line + num_blanks_pending += 1 + yield None, _make_line(lines,'+',1), True + continue + elif s.startswith(('+ ', '+-')): + # will be leaving an add block: yield blanks then add line + from_line, to_line = None, _make_line(lines,'+',1) + num_blanks_to_yield,num_blanks_pending = num_blanks_pending+1,0 + elif s.startswith('+'): + # inside an add block, yield the add line + num_blanks_pending += 1 + yield None, _make_line(lines,'+',1), True + continue + elif s.startswith(' '): + # unchanged text, yield it to both sides + yield _make_line(lines[:],None,0),_make_line(lines,None,1),False + continue + # Catch up on the blank lines so when we yield the next from/to + # pair, they are lined up. + while(num_blanks_to_yield < 0): + num_blanks_to_yield += 1 + yield None,('','\n'),True + while(num_blanks_to_yield > 0): + num_blanks_to_yield -= 1 + yield ('','\n'),None,True + if s.startswith('X'): + raise StopIteration + else: + yield from_line,to_line,True + + def _line_pair_iterator(): + """Yields from/to lines of text with a change indication. + + This function is an iterator. It itself pulls lines from the line + iterator. Its difference from that iterator is that this function + always yields a pair of from/to text lines (with the change + indication). If necessary it will collect single from/to lines + until it has a matching pair from/to pair to yield. + + Note, this function is purposefully not defined at the module scope so + that data it needs from its parent function (within whose context it + is defined) does not need to be of module scope. + """ + line_iterator = _line_iterator() + fromlines,tolines=[],[] + while True: + # Collecting lines of text until we have a from/to pair + while (len(fromlines)==0 or len(tolines)==0): + from_line, to_line, found_diff =line_iterator.next() + if from_line is not None: + fromlines.append((from_line,found_diff)) + if to_line is not None: + tolines.append((to_line,found_diff)) + # Once we have a pair, remove them from the collection and yield it + from_line, fromDiff = fromlines.pop(0) + to_line, to_diff = tolines.pop(0) + yield (from_line,to_line,fromDiff or to_diff) + + # Handle case where user does not want context differencing, just yield + # them up without doing anything else with them. + line_pair_iterator = _line_pair_iterator() + if context is None: + while True: + yield line_pair_iterator.next() + # Handle case where user wants context differencing. We must do some + # storage of lines until we know for sure that they are to be yielded. + else: + context += 1 + lines_to_write = 0 + while True: + # Store lines up until we find a difference, note use of a + # circular queue because we only need to keep around what + # we need for context. + index, contextLines = 0, [None]*(context) + found_diff = False + while(found_diff is False): + from_line, to_line, found_diff = line_pair_iterator.next() + i = index % context + contextLines[i] = (from_line, to_line, found_diff) + index += 1 + # Yield lines that we have collected so far, but first yield + # the user's separator. + if index > context: + yield None, None, None + lines_to_write = context + else: + lines_to_write = index + index = 0 + while(lines_to_write): + i = index % context + index += 1 + yield contextLines[i] + lines_to_write -= 1 + # Now yield the context lines after the change + lines_to_write = context-1 + while(lines_to_write): + from_line, to_line, found_diff = line_pair_iterator.next() + # If another change within the context, extend the context + if found_diff: + lines_to_write = context-1 + else: + lines_to_write -= 1 + yield from_line, to_line, found_diff + + +_file_template = """ + + + + + + + + + + + + %(table)s%(legend)s + + +""" + +_styles = """ + table.diff {font-family:Courier; border:medium;} + .diff_header {background-color:#e0e0e0} + td.diff_header {text-align:right} + .diff_next {background-color:#c0c0c0} + .diff_add {background-color:#aaffaa} + .diff_chg {background-color:#ffff77} + .diff_sub {background-color:#ffaaaa}""" + +_table_template = """ + + + + %(header_row)s + +%(data_rows)s +
""" + +_legend = """ + + + + +
Legends
+ + + + +
Colors
 Added 
Changed
Deleted
+ + + + +
Links
(f)irst change
(n)ext change
(t)op
""" + +class HtmlDiff(object): + """For producing HTML side by side comparison with change highlights. + + This class can be used to create an HTML table (or a complete HTML file + containing the table) showing a side by side, line by line comparison + of text with inter-line and intra-line change highlights. The table can + be generated in either full or contextual difference mode. + + The following methods are provided for HTML generation: + + make_table -- generates HTML for a single side by side table + make_file -- generates complete HTML file with a single side by side table + + See tools/scripts/diff.py for an example usage of this class. + """ + + _file_template = _file_template + _styles = _styles + _table_template = _table_template + _legend = _legend + _default_prefix = 0 + + def __init__(self,tabsize=8,wrapcolumn=None,linejunk=None, + charjunk=IS_CHARACTER_JUNK): + """HtmlDiff instance initializer + + Arguments: + tabsize -- tab stop spacing, defaults to 8. + wrapcolumn -- column number where lines are broken and wrapped, + defaults to None where lines are not wrapped. + linejunk,charjunk -- keyword arguments passed into ndiff() (used to by + HtmlDiff() to generate the side by side HTML differences). See + ndiff() documentation for argument default values and descriptions. + """ + self._tabsize = tabsize + self._wrapcolumn = wrapcolumn + self._linejunk = linejunk + self._charjunk = charjunk + + def make_file(self,fromlines,tolines,fromdesc='',todesc='',context=False, + numlines=5): + """Returns HTML file of side by side comparison with change highlights + + Arguments: + fromlines -- list of "from" lines + tolines -- list of "to" lines + fromdesc -- "from" file column header string + todesc -- "to" file column header string + context -- set to True for contextual differences (defaults to False + which shows full differences). + numlines -- number of context lines. When context is set True, + controls number of lines displayed before and after the change. + When context is False, controls the number of lines to place + the "next" link anchors before the next change (so click of + "next" link jumps to just before the change). + """ + + return self._file_template % dict( + styles = self._styles, + legend = self._legend, + table = self.make_table(fromlines,tolines,fromdesc,todesc, + context=context,numlines=numlines)) + + def _tab_newline_replace(self,fromlines,tolines): + """Returns from/to line lists with tabs expanded and newlines removed. + + Instead of tab characters being replaced by the number of spaces + needed to fill in to the next tab stop, this function will fill + the space with tab characters. This is done so that the difference + algorithms can identify changes in a file when tabs are replaced by + spaces and vice versa. At the end of the HTML generation, the tab + characters will be replaced with a nonbreakable space. + """ + def expand_tabs(line): + # hide real spaces + line = line.replace(' ','\0') + # expand tabs into spaces + line = line.expandtabs(self._tabsize) + # replace spaces from expanded tabs back into tab characters + # (we'll replace them with markup after we do differencing) + line = line.replace(' ','\t') + return line.replace('\0',' ').rstrip('\n') + fromlines = [expand_tabs(line) for line in fromlines] + tolines = [expand_tabs(line) for line in tolines] + return fromlines,tolines + + def _split_line(self,data_list,line_num,text): + """Builds list of text lines by splitting text lines at wrap point + + This function will determine if the input text line needs to be + wrapped (split) into separate lines. If so, the first wrap point + will be determined and the first line appended to the output + text line list. This function is used recursively to handle + the second part of the split line to further split it. + """ + # if blank line or context separator, just add it to the output list + if not line_num: + data_list.append((line_num,text)) + return + + # if line text doesn't need wrapping, just add it to the output list + size = len(text) + max = self._wrapcolumn + if (size <= max) or ((size -(text.count('\0')*3)) <= max): + data_list.append((line_num,text)) + return + + # scan text looking for the wrap point, keeping track if the wrap + # point is inside markers + i = 0 + n = 0 + mark = '' + while n < max and i < size: + if text[i] == '\0': + i += 1 + mark = text[i] + i += 1 + elif text[i] == '\1': + i += 1 + mark = '' + else: + i += 1 + n += 1 + + # wrap point is inside text, break it up into separate lines + line1 = text[:i] + line2 = text[i:] + + # if wrap point is inside markers, place end marker at end of first + # line and start marker at beginning of second line because each + # line will have its own table tag markup around it. + if mark: + line1 = line1 + '\1' + line2 = '\0' + mark + line2 + + # tack on first line onto the output list + data_list.append((line_num,line1)) + + # use this routine again to wrap the remaining text + self._split_line(data_list,'>',line2) + + def _line_wrapper(self,diffs): + """Returns iterator that splits (wraps) mdiff text lines""" + + # pull from/to data and flags from mdiff iterator + for fromdata,todata,flag in diffs: + # check for context separators and pass them through + if flag is None: + yield fromdata,todata,flag + continue + (fromline,fromtext),(toline,totext) = fromdata,todata + # for each from/to line split it at the wrap column to form + # list of text lines. + fromlist,tolist = [],[] + self._split_line(fromlist,fromline,fromtext) + self._split_line(tolist,toline,totext) + # yield from/to line in pairs inserting blank lines as + # necessary when one side has more wrapped lines + while fromlist or tolist: + if fromlist: + fromdata = fromlist.pop(0) + else: + fromdata = ('',' ') + if tolist: + todata = tolist.pop(0) + else: + todata = ('',' ') + yield fromdata,todata,flag + + def _collect_lines(self,diffs): + """Collects mdiff output into separate lists + + Before storing the mdiff from/to data into a list, it is converted + into a single line of text with HTML markup. + """ + + fromlist,tolist,flaglist = [],[],[] + # pull from/to data and flags from mdiff style iterator + for fromdata,todata,flag in diffs: + try: + # store HTML markup of the lines into the lists + fromlist.append(self._format_line(0,flag,*fromdata)) + tolist.append(self._format_line(1,flag,*todata)) + except TypeError: + # exceptions occur for lines where context separators go + fromlist.append(None) + tolist.append(None) + flaglist.append(flag) + return fromlist,tolist,flaglist + + def _format_line(self,side,flag,linenum,text): + """Returns HTML markup of "from" / "to" text lines + + side -- 0 or 1 indicating "from" or "to" text + flag -- indicates if difference on line + linenum -- line number (used for line number column) + text -- line text to be marked up + """ + try: + linenum = '%d' % linenum + id = ' id="%s%s"' % (self._prefix[side],linenum) + except TypeError: + # handle blank lines where linenum is '>' or '' + id = '' + # replace those things that would get confused with HTML symbols + text=text.replace("&","&").replace(">",">").replace("<","<") + + # make space non-breakable so they don't get compressed or line wrapped + text = text.replace(' ',' ').rstrip() + + return '%s%s' \ + % (id,linenum,text) + + def _make_prefix(self): + """Create unique anchor prefixes""" + + # Generate a unique anchor prefix so multiple tables + # can exist on the same HTML page without conflicts. + fromprefix = "from%d_" % HtmlDiff._default_prefix + toprefix = "to%d_" % HtmlDiff._default_prefix + HtmlDiff._default_prefix += 1 + # store prefixes so line format method has access + self._prefix = [fromprefix,toprefix] + + def _convert_flags(self,fromlist,tolist,flaglist,context,numlines): + """Makes list of "next" links""" + + # all anchor names will be generated using the unique "to" prefix + toprefix = self._prefix[1] + + # process change flags, generating middle column of next anchors/links + next_id = ['']*len(flaglist) + next_href = ['']*len(flaglist) + num_chg, in_change = 0, False + last = 0 + for i,flag in enumerate(flaglist): + if flag: + if not in_change: + in_change = True + last = i + # at the beginning of a change, drop an anchor a few lines + # (the context lines) before the change for the previous + # link + i = max([0,i-numlines]) + next_id[i] = ' id="difflib_chg_%s_%d"' % (toprefix,num_chg) + # at the beginning of a change, drop a link to the next + # change + num_chg += 1 + next_href[last] = '
n' % ( + toprefix,num_chg) + else: + in_change = False + # check for cases where there is no content to avoid exceptions + if not flaglist: + flaglist = [False] + next_id = [''] + next_href = [''] + last = 0 + if context: + fromlist = [' No Differences Found '] + tolist = fromlist + else: + fromlist = tolist = [' Empty File '] + # if not a change on first line, drop a link + if not flaglist[0]: + next_href[0] = 'f' % toprefix + # redo the last link to link to the top + next_href[last] = 't' % (toprefix) + + return fromlist,tolist,flaglist,next_href,next_id + + def make_table(self,fromlines,tolines,fromdesc='',todesc='',context=False, + numlines=5): + """Returns HTML table of side by side comparison with change highlights + + Arguments: + fromlines -- list of "from" lines + tolines -- list of "to" lines + fromdesc -- "from" file column header string + todesc -- "to" file column header string + context -- set to True for contextual differences (defaults to False + which shows full differences). + numlines -- number of context lines. When context is set True, + controls number of lines displayed before and after the change. + When context is False, controls the number of lines to place + the "next" link anchors before the next change (so click of + "next" link jumps to just before the change). + """ + + # make unique anchor prefixes so that multiple tables may exist + # on the same page without conflict. + self._make_prefix() + + # change tabs to spaces before it gets more difficult after we insert + # markup + fromlines,tolines = self._tab_newline_replace(fromlines,tolines) + + # create diffs iterator which generates side by side from/to data + if context: + context_lines = numlines + else: + context_lines = None + diffs = _mdiff(fromlines,tolines,context_lines,linejunk=self._linejunk, + charjunk=self._charjunk) + + # set up iterator to wrap lines that exceed desired width + if self._wrapcolumn: + diffs = self._line_wrapper(diffs) + + # collect up from/to lines and flags into lists (also format the lines) + fromlist,tolist,flaglist = self._collect_lines(diffs) + + # process change flags, generating middle column of next anchors/links + fromlist,tolist,flaglist,next_href,next_id = self._convert_flags( + fromlist,tolist,flaglist,context,numlines) + + s = [] + fmt = ' %s%s' + \ + '%s%s\n' + for i in range(len(flaglist)): + if flaglist[i] is None: + # mdiff yields None on separator lines skip the bogus ones + # generated for the first line + if i > 0: + s.append(' \n \n') + else: + s.append( fmt % (next_id[i],next_href[i],fromlist[i], + next_href[i],tolist[i])) + if fromdesc or todesc: + header_row = '%s%s%s%s' % ( + '
', + '%s' % fromdesc, + '
', + '%s' % todesc) + else: + header_row = '' + + table = self._table_template % dict( + data_rows=''.join(s), + header_row=header_row, + prefix=self._prefix[1]) + + return table.replace('\0+',''). \ + replace('\0-',''). \ + replace('\0^',''). \ + replace('\1',''). \ + replace('\t',' ') + +del re + +def restore(delta, which): + r""" + Generate one of the two sequences that generated a delta. + + Given a `delta` produced by `Differ.compare()` or `ndiff()`, extract + lines originating from file 1 or 2 (parameter `which`), stripping off line + prefixes. + + Examples: + + >>> diff = ndiff('one\ntwo\nthree\n'.splitlines(1), + ... 'ore\ntree\nemu\n'.splitlines(1)) + >>> diff = list(diff) + >>> print ''.join(restore(diff, 1)), + one + two + three + >>> print ''.join(restore(diff, 2)), + ore + tree + emu + """ + try: + tag = {1: "- ", 2: "+ "}[int(which)] + except KeyError: + raise ValueError, ('unknown delta choice (must be 1 or 2): %r' + % which) + prefixes = (" ", tag) + for line in delta: + if line[:2] in prefixes: + yield line[2:] + +def _test(): + import doctest, difflib + return doctest.testmod(difflib) + +if __name__ == "__main__": + _test() diff --git a/PythonHome/Lib/difflib.pyc b/PythonHome/Lib/difflib.pyc deleted file mode 100644 index 25ef4fc5de288f8b8624f9556b34ba13b7fc91eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61139 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�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 Ov%haB9vawL`hNiZ(ih?Y diff --git a/PythonHome/Lib/dircache.py b/PythonHome/Lib/dircache.py new file mode 100644 index 0000000000..7e4f0b508a --- /dev/null +++ b/PythonHome/Lib/dircache.py @@ -0,0 +1,41 @@ +"""Read and cache directory listings. + +The listdir() routine returns a sorted list of the files in a directory, +using a cache to avoid reading the directory more often than necessary. +The annotate() routine appends slashes to directories.""" +from warnings import warnpy3k +warnpy3k("the dircache module has been removed in Python 3.0", stacklevel=2) +del warnpy3k + +import os + +__all__ = ["listdir", "opendir", "annotate", "reset"] + +cache = {} + +def reset(): + """Reset the cache completely.""" + global cache + cache = {} + +def listdir(path): + """List directory contents, using cache.""" + try: + cached_mtime, list = cache[path] + del cache[path] + except KeyError: + cached_mtime, list = -1, [] + mtime = os.stat(path).st_mtime + if mtime != cached_mtime: + list = os.listdir(path) + list.sort() + cache[path] = mtime, list + return list + +opendir = listdir # XXX backward compatibility + +def annotate(head, list): + """Add '/' suffixes to directories.""" + for i in range(len(list)): + if os.path.isdir(os.path.join(head, list[i])): + list[i] = list[i] + '/' diff --git a/PythonHome/Lib/dircache.pyc b/PythonHome/Lib/dircache.pyc deleted file mode 100644 index 81bfcd3ba840a58ae20c2d43f95ee12ce7cdc877..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1516 zcmah}QEwAR5T4z$9byt1LTMEtRr`WCBxEY`*c4H24p~WMq@ZO$lM^aNoGi=JsS6@BGP>_H|bBr8<5#b z$_CjD8UwkVOyCD}l;7gqe?t^j8>O95r7mYynabNTHojGL6=LO1!)Q2s0SB9K<`0!` zmT*|*ZCrX6lvbhf(V7HN%~VCer&Vo(svNxQkdKDTfQWe2<%*5c7fodlNgHhip{7q+e> z%)__=xuPoR4Odk8l<>OZ*ayhlVB>lmxTqho0te+jrg1pRIcT^CQ7}9a)RkB^^F?i= zt=rLIcO(v)d^r^QB*JZ&qm$>=s}mHG5Tiv~Fnk9qa0<#wu7HP<-=|96Luv0(Bzi}* zcOvOh(4}12-ygegs22sD56OQ=m`;r5DUs|zPS9^r(pkoPuLPa-=n^^}?8wMp5PSP8 zFQUGKIiM>d;gAnFNz?0G2QXGl+(%8%F^KE7wyJC#CM1SOsvEBEfL*J(8N~o1(f^BW zfA$`u$|r6@ z_zHq#CU(S4u`OJy`{r)UWpR&W1%g^-@;@nN1w z3K2vzsR4ye+)(qFZ;15uWR(+N-j=-G{oR#FBxG!?P zC+UJsCZ;JTll6_}PgcRWRLlyZ>v}RtlaS^ 0: + print + print "%3d" % linestarts[i], + else: + print ' ', + + if i == lasti: print '-->', + else: print ' ', + if i in labels: print '>>', + else: print ' ', + print repr(i).rjust(4), + print opname[op].ljust(20), + i = i+1 + if op >= HAVE_ARGUMENT: + oparg = ord(code[i]) + ord(code[i+1])*256 + extended_arg + extended_arg = 0 + i = i+2 + if op == EXTENDED_ARG: + extended_arg = oparg*65536L + print repr(oparg).rjust(5), + if op in hasconst: + print '(' + repr(co.co_consts[oparg]) + ')', + elif op in hasname: + print '(' + co.co_names[oparg] + ')', + elif op in hasjrel: + print '(to ' + repr(i + oparg) + ')', + elif op in haslocal: + print '(' + co.co_varnames[oparg] + ')', + elif op in hascompare: + print '(' + cmp_op[oparg] + ')', + elif op in hasfree: + if free is None: + free = co.co_cellvars + co.co_freevars + print '(' + free[oparg] + ')', + print + +def disassemble_string(code, lasti=-1, varnames=None, names=None, + constants=None): + labels = findlabels(code) + n = len(code) + i = 0 + while i < n: + c = code[i] + op = ord(c) + if i == lasti: print '-->', + else: print ' ', + if i in labels: print '>>', + else: print ' ', + print repr(i).rjust(4), + print opname[op].ljust(15), + i = i+1 + if op >= HAVE_ARGUMENT: + oparg = ord(code[i]) + ord(code[i+1])*256 + i = i+2 + print repr(oparg).rjust(5), + if op in hasconst: + if constants: + print '(' + repr(constants[oparg]) + ')', + else: + print '(%d)'%oparg, + elif op in hasname: + if names is not None: + print '(' + names[oparg] + ')', + else: + print '(%d)'%oparg, + elif op in hasjrel: + print '(to ' + repr(i + oparg) + ')', + elif op in haslocal: + if varnames: + print '(' + varnames[oparg] + ')', + else: + print '(%d)' % oparg, + elif op in hascompare: + print '(' + cmp_op[oparg] + ')', + print + +disco = disassemble # XXX For backwards compatibility + +def findlabels(code): + """Detect all offsets in a byte code which are jump targets. + + Return the list of offsets. + + """ + labels = [] + n = len(code) + i = 0 + while i < n: + c = code[i] + op = ord(c) + i = i+1 + if op >= HAVE_ARGUMENT: + oparg = ord(code[i]) + ord(code[i+1])*256 + i = i+2 + label = -1 + if op in hasjrel: + label = i+oparg + elif op in hasjabs: + label = oparg + if label >= 0: + if label not in labels: + labels.append(label) + return labels + +def findlinestarts(code): + """Find the offsets in a byte code which are start of lines in the source. + + Generate pairs (offset, lineno) as described in Python/compile.c. + + """ + byte_increments = [ord(c) for c in code.co_lnotab[0::2]] + line_increments = [ord(c) for c in code.co_lnotab[1::2]] + + lastlineno = None + lineno = code.co_firstlineno + addr = 0 + for byte_incr, line_incr in zip(byte_increments, line_increments): + if byte_incr: + if lineno != lastlineno: + yield (addr, lineno) + lastlineno = lineno + addr += byte_incr + lineno += line_incr + if lineno != lastlineno: + yield (addr, lineno) + +def _test(): + """Simple test program to disassemble a file.""" + if sys.argv[1:]: + if sys.argv[2:]: + sys.stderr.write("usage: python dis.py [-|file]\n") + sys.exit(2) + fn = sys.argv[1] + if not fn or fn == "-": + fn = None + else: + fn = None + if fn is None: + f = sys.stdin + else: + f = open(fn) + source = f.read() + if fn is not None: + f.close() + else: + fn = "" + code = compile(source, fn, "exec") + dis(code) + +if __name__ == "__main__": + _test() diff --git a/PythonHome/Lib/dis.pyc b/PythonHome/Lib/dis.pyc index c71f03d328967dfb3038813a51f4e608749b0e46..7703b4e0eaefd4d6c2d392681c02fe042fa850a7 100644 GIT binary patch delta 468 zcmcbkzsG2UD66pr0|P^On82Uo>#EHUr>N^jDKlKL1{^hOKMVSdQ3oN zNk)F2M}BTrE~-2t8qqsagO delta 116 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 QnX2H9tZAP?Jj9RvKU%^f(EtDd diff --git a/PythonHome/Lib/distutils/ccompiler.py b/PythonHome/Lib/distutils/ccompiler.py new file mode 100644 index 0000000000..4907a0aa5a --- /dev/null +++ b/PythonHome/Lib/distutils/ccompiler.py @@ -0,0 +1,1095 @@ +"""distutils.ccompiler + +Contains CCompiler, an abstract base class that defines the interface +for the Distutils compiler abstraction model.""" + +__revision__ = "$Id$" + +import sys +import os +import re + +from distutils.errors import (CompileError, LinkError, UnknownFileError, + DistutilsPlatformError, DistutilsModuleError) +from distutils.spawn import spawn +from distutils.file_util import move_file +from distutils.dir_util import mkpath +from distutils.dep_util import newer_group +from distutils.util import split_quoted, execute +from distutils import log +# following import is for backward compatibility +from distutils.sysconfig import customize_compiler + +class CCompiler: + """Abstract base class to define the interface that must be implemented + by real compiler classes. Also has some utility methods used by + several compiler classes. + + The basic idea behind a compiler abstraction class is that each + instance can be used for all the compile/link steps in building a + single project. Thus, attributes common to all of those compile and + link steps -- include directories, macros to define, libraries to link + against, etc. -- are attributes of the compiler instance. To allow for + variability in how individual files are treated, most of those + attributes may be varied on a per-compilation or per-link basis. + """ + + # 'compiler_type' is a class attribute that identifies this class. It + # keeps code that wants to know what kind of compiler it's dealing with + # from having to import all possible compiler classes just to do an + # 'isinstance'. In concrete CCompiler subclasses, 'compiler_type' + # should really, really be one of the keys of the 'compiler_class' + # dictionary (see below -- used by the 'new_compiler()' factory + # function) -- authors of new compiler interface classes are + # responsible for updating 'compiler_class'! + compiler_type = None + + # XXX things not handled by this compiler abstraction model: + # * client can't provide additional options for a compiler, + # e.g. warning, optimization, debugging flags. Perhaps this + # should be the domain of concrete compiler abstraction classes + # (UnixCCompiler, MSVCCompiler, etc.) -- or perhaps the base + # class should have methods for the common ones. + # * can't completely override the include or library searchg + # path, ie. no "cc -I -Idir1 -Idir2" or "cc -L -Ldir1 -Ldir2". + # I'm not sure how widely supported this is even by Unix + # compilers, much less on other platforms. And I'm even less + # sure how useful it is; maybe for cross-compiling, but + # support for that is a ways off. (And anyways, cross + # compilers probably have a dedicated binary with the + # right paths compiled in. I hope.) + # * can't do really freaky things with the library list/library + # dirs, e.g. "-Ldir1 -lfoo -Ldir2 -lfoo" to link against + # different versions of libfoo.a in different locations. I + # think this is useless without the ability to null out the + # library search path anyways. + + + # Subclasses that rely on the standard filename generation methods + # implemented below should override these; see the comment near + # those methods ('object_filenames()' et. al.) for details: + src_extensions = None # list of strings + obj_extension = None # string + static_lib_extension = None + shared_lib_extension = None # string + static_lib_format = None # format string + shared_lib_format = None # prob. same as static_lib_format + exe_extension = None # string + + # Default language settings. language_map is used to detect a source + # file or Extension target language, checking source filenames. + # language_order is used to detect the language precedence, when deciding + # what language to use when mixing source types. For example, if some + # extension has two files with ".c" extension, and one with ".cpp", it + # is still linked as c++. + language_map = {".c" : "c", + ".cc" : "c++", + ".cpp" : "c++", + ".cxx" : "c++", + ".m" : "objc", + } + language_order = ["c++", "objc", "c"] + + def __init__ (self, verbose=0, dry_run=0, force=0): + self.dry_run = dry_run + self.force = force + self.verbose = verbose + + # 'output_dir': a common output directory for object, library, + # shared object, and shared library files + self.output_dir = None + + # 'macros': a list of macro definitions (or undefinitions). A + # macro definition is a 2-tuple (name, value), where the value is + # either a string or None (no explicit value). A macro + # undefinition is a 1-tuple (name,). + self.macros = [] + + # 'include_dirs': a list of directories to search for include files + self.include_dirs = [] + + # 'libraries': a list of libraries to include in any link + # (library names, not filenames: eg. "foo" not "libfoo.a") + self.libraries = [] + + # 'library_dirs': a list of directories to search for libraries + self.library_dirs = [] + + # 'runtime_library_dirs': a list of directories to search for + # shared libraries/objects at runtime + self.runtime_library_dirs = [] + + # 'objects': a list of object files (or similar, such as explicitly + # named library files) to include on any link + self.objects = [] + + for key in self.executables.keys(): + self.set_executable(key, self.executables[key]) + + def set_executables(self, **args): + """Define the executables (and options for them) that will be run + to perform the various stages of compilation. The exact set of + executables that may be specified here depends on the compiler + class (via the 'executables' class attribute), but most will have: + compiler the C/C++ compiler + linker_so linker used to create shared objects and libraries + linker_exe linker used to create binary executables + archiver static library creator + + On platforms with a command-line (Unix, DOS/Windows), each of these + is a string that will be split into executable name and (optional) + list of arguments. (Splitting the string is done similarly to how + Unix shells operate: words are delimited by spaces, but quotes and + backslashes can override this. See + 'distutils.util.split_quoted()'.) + """ + + # Note that some CCompiler implementation classes will define class + # attributes 'cpp', 'cc', etc. with hard-coded executable names; + # this is appropriate when a compiler class is for exactly one + # compiler/OS combination (eg. MSVCCompiler). Other compiler + # classes (UnixCCompiler, in particular) are driven by information + # discovered at run-time, since there are many different ways to do + # basically the same things with Unix C compilers. + + for key in args.keys(): + if key not in self.executables: + raise ValueError, \ + "unknown executable '%s' for class %s" % \ + (key, self.__class__.__name__) + self.set_executable(key, args[key]) + + def set_executable(self, key, value): + if isinstance(value, str): + setattr(self, key, split_quoted(value)) + else: + setattr(self, key, value) + + def _find_macro(self, name): + i = 0 + for defn in self.macros: + if defn[0] == name: + return i + i = i + 1 + return None + + def _check_macro_definitions(self, definitions): + """Ensures that every element of 'definitions' is a valid macro + definition, ie. either (name,value) 2-tuple or a (name,) tuple. Do + nothing if all definitions are OK, raise TypeError otherwise. + """ + for defn in definitions: + if not (isinstance(defn, tuple) and + (len (defn) == 1 or + (len (defn) == 2 and + (isinstance(defn[1], str) or defn[1] is None))) and + isinstance(defn[0], str)): + raise TypeError, \ + ("invalid macro definition '%s': " % defn) + \ + "must be tuple (string,), (string, string), or " + \ + "(string, None)" + + + # -- Bookkeeping methods ------------------------------------------- + + def define_macro(self, name, value=None): + """Define a preprocessor macro for all compilations driven by this + compiler object. The optional parameter 'value' should be a + string; if it is not supplied, then the macro will be defined + without an explicit value and the exact outcome depends on the + compiler used (XXX true? does ANSI say anything about this?) + """ + # Delete from the list of macro definitions/undefinitions if + # already there (so that this one will take precedence). + i = self._find_macro (name) + if i is not None: + del self.macros[i] + + defn = (name, value) + self.macros.append (defn) + + def undefine_macro(self, name): + """Undefine a preprocessor macro for all compilations driven by + this compiler object. If the same macro is defined by + 'define_macro()' and undefined by 'undefine_macro()' the last call + takes precedence (including multiple redefinitions or + undefinitions). If the macro is redefined/undefined on a + per-compilation basis (ie. in the call to 'compile()'), then that + takes precedence. + """ + # Delete from the list of macro definitions/undefinitions if + # already there (so that this one will take precedence). + i = self._find_macro (name) + if i is not None: + del self.macros[i] + + undefn = (name,) + self.macros.append (undefn) + + def add_include_dir(self, dir): + """Add 'dir' to the list of directories that will be searched for + header files. The compiler is instructed to search directories in + the order in which they are supplied by successive calls to + 'add_include_dir()'. + """ + self.include_dirs.append (dir) + + def set_include_dirs(self, dirs): + """Set the list of directories that will be searched to 'dirs' (a + list of strings). Overrides any preceding calls to + 'add_include_dir()'; subsequence calls to 'add_include_dir()' add + to the list passed to 'set_include_dirs()'. This does not affect + any list of standard include directories that the compiler may + search by default. + """ + self.include_dirs = dirs[:] + + def add_library(self, libname): + """Add 'libname' to the list of libraries that will be included in + all links driven by this compiler object. Note that 'libname' + should *not* be the name of a file containing a library, but the + name of the library itself: the actual filename will be inferred by + the linker, the compiler, or the compiler class (depending on the + platform). + + The linker will be instructed to link against libraries in the + order they were supplied to 'add_library()' and/or + 'set_libraries()'. It is perfectly valid to duplicate library + names; the linker will be instructed to link against libraries as + many times as they are mentioned. + """ + self.libraries.append (libname) + + def set_libraries(self, libnames): + """Set the list of libraries to be included in all links driven by + this compiler object to 'libnames' (a list of strings). This does + not affect any standard system libraries that the linker may + include by default. + """ + self.libraries = libnames[:] + + + def add_library_dir(self, dir): + """Add 'dir' to the list of directories that will be searched for + libraries specified to 'add_library()' and 'set_libraries()'. The + linker will be instructed to search for libraries in the order they + are supplied to 'add_library_dir()' and/or 'set_library_dirs()'. + """ + self.library_dirs.append(dir) + + def set_library_dirs(self, dirs): + """Set the list of library search directories to 'dirs' (a list of + strings). This does not affect any standard library search path + that the linker may search by default. + """ + self.library_dirs = dirs[:] + + def add_runtime_library_dir(self, dir): + """Add 'dir' to the list of directories that will be searched for + shared libraries at runtime. + """ + self.runtime_library_dirs.append(dir) + + def set_runtime_library_dirs(self, dirs): + """Set the list of directories to search for shared libraries at + runtime to 'dirs' (a list of strings). This does not affect any + standard search path that the runtime linker may search by + default. + """ + self.runtime_library_dirs = dirs[:] + + def add_link_object(self, object): + """Add 'object' to the list of object files (or analogues, such as + explicitly named library files or the output of "resource + compilers") to be included in every link driven by this compiler + object. + """ + self.objects.append(object) + + def set_link_objects(self, objects): + """Set the list of object files (or analogues) to be included in + every link to 'objects'. This does not affect any standard object + files that the linker may include by default (such as system + libraries). + """ + self.objects = objects[:] + + + # -- Private utility methods -------------------------------------- + # (here for the convenience of subclasses) + + # Helper method to prep compiler in subclass compile() methods + + def _setup_compile(self, outdir, macros, incdirs, sources, depends, + extra): + """Process arguments and decide which source files to compile.""" + if outdir is None: + outdir = self.output_dir + elif not isinstance(outdir, str): + raise TypeError, "'output_dir' must be a string or None" + + if macros is None: + macros = self.macros + elif isinstance(macros, list): + macros = macros + (self.macros or []) + else: + raise TypeError, "'macros' (if supplied) must be a list of tuples" + + if incdirs is None: + incdirs = self.include_dirs + elif isinstance(incdirs, (list, tuple)): + incdirs = list(incdirs) + (self.include_dirs or []) + else: + raise TypeError, \ + "'include_dirs' (if supplied) must be a list of strings" + + if extra is None: + extra = [] + + # Get the list of expected output (object) files + objects = self.object_filenames(sources, + strip_dir=0, + output_dir=outdir) + assert len(objects) == len(sources) + + pp_opts = gen_preprocess_options(macros, incdirs) + + build = {} + for i in range(len(sources)): + src = sources[i] + obj = objects[i] + ext = os.path.splitext(src)[1] + self.mkpath(os.path.dirname(obj)) + build[obj] = (src, ext) + + return macros, objects, extra, pp_opts, build + + def _get_cc_args(self, pp_opts, debug, before): + # works for unixccompiler, emxccompiler, cygwinccompiler + cc_args = pp_opts + ['-c'] + if debug: + cc_args[:0] = ['-g'] + if before: + cc_args[:0] = before + return cc_args + + def _fix_compile_args(self, output_dir, macros, include_dirs): + """Typecheck and fix-up some of the arguments to the 'compile()' + method, and return fixed-up values. Specifically: if 'output_dir' + is None, replaces it with 'self.output_dir'; ensures that 'macros' + is a list, and augments it with 'self.macros'; ensures that + 'include_dirs' is a list, and augments it with 'self.include_dirs'. + Guarantees that the returned values are of the correct type, + i.e. for 'output_dir' either string or None, and for 'macros' and + 'include_dirs' either list or None. + """ + if output_dir is None: + output_dir = self.output_dir + elif not isinstance(output_dir, str): + raise TypeError, "'output_dir' must be a string or None" + + if macros is None: + macros = self.macros + elif isinstance(macros, list): + macros = macros + (self.macros or []) + else: + raise TypeError, "'macros' (if supplied) must be a list of tuples" + + if include_dirs is None: + include_dirs = self.include_dirs + elif isinstance(include_dirs, (list, tuple)): + include_dirs = list (include_dirs) + (self.include_dirs or []) + else: + raise TypeError, \ + "'include_dirs' (if supplied) must be a list of strings" + + return output_dir, macros, include_dirs + + def _fix_object_args(self, objects, output_dir): + """Typecheck and fix up some arguments supplied to various methods. + Specifically: ensure that 'objects' is a list; if output_dir is + None, replace with self.output_dir. Return fixed versions of + 'objects' and 'output_dir'. + """ + if not isinstance(objects, (list, tuple)): + raise TypeError, \ + "'objects' must be a list or tuple of strings" + objects = list (objects) + + if output_dir is None: + output_dir = self.output_dir + elif not isinstance(output_dir, str): + raise TypeError, "'output_dir' must be a string or None" + + return (objects, output_dir) + + def _fix_lib_args(self, libraries, library_dirs, runtime_library_dirs): + """Typecheck and fix up some of the arguments supplied to the + 'link_*' methods. Specifically: ensure that all arguments are + lists, and augment them with their permanent versions + (eg. 'self.libraries' augments 'libraries'). Return a tuple with + fixed versions of all arguments. + """ + if libraries is None: + libraries = self.libraries + elif isinstance(libraries, (list, tuple)): + libraries = list (libraries) + (self.libraries or []) + else: + raise TypeError, \ + "'libraries' (if supplied) must be a list of strings" + + if library_dirs is None: + library_dirs = self.library_dirs + elif isinstance(library_dirs, (list, tuple)): + library_dirs = list (library_dirs) + (self.library_dirs or []) + else: + raise TypeError, \ + "'library_dirs' (if supplied) must be a list of strings" + + if runtime_library_dirs is None: + runtime_library_dirs = self.runtime_library_dirs + elif isinstance(runtime_library_dirs, (list, tuple)): + runtime_library_dirs = (list (runtime_library_dirs) + + (self.runtime_library_dirs or [])) + else: + raise TypeError, \ + "'runtime_library_dirs' (if supplied) " + \ + "must be a list of strings" + + return (libraries, library_dirs, runtime_library_dirs) + + def _need_link(self, objects, output_file): + """Return true if we need to relink the files listed in 'objects' + to recreate 'output_file'. + """ + if self.force: + return 1 + else: + if self.dry_run: + newer = newer_group (objects, output_file, missing='newer') + else: + newer = newer_group (objects, output_file) + return newer + + def detect_language(self, sources): + """Detect the language of a given file, or list of files. Uses + language_map, and language_order to do the job. + """ + if not isinstance(sources, list): + sources = [sources] + lang = None + index = len(self.language_order) + for source in sources: + base, ext = os.path.splitext(source) + extlang = self.language_map.get(ext) + try: + extindex = self.language_order.index(extlang) + if extindex < index: + lang = extlang + index = extindex + except ValueError: + pass + return lang + + # -- Worker methods ------------------------------------------------ + # (must be implemented by subclasses) + + def preprocess(self, source, output_file=None, macros=None, + include_dirs=None, extra_preargs=None, extra_postargs=None): + """Preprocess a single C/C++ source file, named in 'source'. + Output will be written to file named 'output_file', or stdout if + 'output_file' not supplied. 'macros' is a list of macro + definitions as for 'compile()', which will augment the macros set + with 'define_macro()' and 'undefine_macro()'. 'include_dirs' is a + list of directory names that will be added to the default list. + + Raises PreprocessError on failure. + """ + pass + + def compile(self, sources, output_dir=None, macros=None, + include_dirs=None, debug=0, extra_preargs=None, + extra_postargs=None, depends=None): + """Compile one or more source files. + + 'sources' must be a list of filenames, most likely C/C++ + files, but in reality anything that can be handled by a + particular compiler and compiler class (eg. MSVCCompiler can + handle resource files in 'sources'). Return a list of object + filenames, one per source filename in 'sources'. Depending on + the implementation, not all source files will necessarily be + compiled, but all corresponding object filenames will be + returned. + + If 'output_dir' is given, object files will be put under it, while + retaining their original path component. That is, "foo/bar.c" + normally compiles to "foo/bar.o" (for a Unix implementation); if + 'output_dir' is "build", then it would compile to + "build/foo/bar.o". + + 'macros', if given, must be a list of macro definitions. A macro + definition is either a (name, value) 2-tuple or a (name,) 1-tuple. + The former defines a macro; if the value is None, the macro is + defined without an explicit value. The 1-tuple case undefines a + macro. Later definitions/redefinitions/ undefinitions take + precedence. + + 'include_dirs', if given, must be a list of strings, the + directories to add to the default include file search path for this + compilation only. + + 'debug' is a boolean; if true, the compiler will be instructed to + output debug symbols in (or alongside) the object file(s). + + 'extra_preargs' and 'extra_postargs' are implementation- dependent. + On platforms that have the notion of a command-line (e.g. Unix, + DOS/Windows), they are most likely lists of strings: extra + command-line arguments to prepand/append to the compiler command + line. On other platforms, consult the implementation class + documentation. In any event, they are intended as an escape hatch + for those occasions when the abstract compiler framework doesn't + cut the mustard. + + 'depends', if given, is a list of filenames that all targets + depend on. If a source file is older than any file in + depends, then the source file will be recompiled. This + supports dependency tracking, but only at a coarse + granularity. + + Raises CompileError on failure. + """ + # A concrete compiler class can either override this method + # entirely or implement _compile(). + + macros, objects, extra_postargs, pp_opts, build = \ + self._setup_compile(output_dir, macros, include_dirs, sources, + depends, extra_postargs) + cc_args = self._get_cc_args(pp_opts, debug, extra_preargs) + + for obj in objects: + try: + src, ext = build[obj] + except KeyError: + continue + self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts) + + # Return *all* object filenames, not just the ones we just built. + return objects + + def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): + """Compile 'src' to product 'obj'.""" + + # A concrete compiler class that does not override compile() + # should implement _compile(). + pass + + def create_static_lib(self, objects, output_libname, output_dir=None, + debug=0, target_lang=None): + """Link a bunch of stuff together to create a static library file. + The "bunch of stuff" consists of the list of object files supplied + as 'objects', the extra object files supplied to + 'add_link_object()' and/or 'set_link_objects()', the libraries + supplied to 'add_library()' and/or 'set_libraries()', and the + libraries supplied as 'libraries' (if any). + + 'output_libname' should be a library name, not a filename; the + filename will be inferred from the library name. 'output_dir' is + the directory where the library file will be put. + + 'debug' is a boolean; if true, debugging information will be + included in the library (note that on most platforms, it is the + compile step where this matters: the 'debug' flag is included here + just for consistency). + + 'target_lang' is the target language for which the given objects + are being compiled. This allows specific linkage time treatment of + certain languages. + + Raises LibError on failure. + """ + pass + + # values for target_desc parameter in link() + SHARED_OBJECT = "shared_object" + SHARED_LIBRARY = "shared_library" + EXECUTABLE = "executable" + + def link(self, target_desc, objects, output_filename, output_dir=None, + libraries=None, library_dirs=None, runtime_library_dirs=None, + export_symbols=None, debug=0, extra_preargs=None, + extra_postargs=None, build_temp=None, target_lang=None): + """Link a bunch of stuff together to create an executable or + shared library file. + + The "bunch of stuff" consists of the list of object files supplied + as 'objects'. 'output_filename' should be a filename. If + 'output_dir' is supplied, 'output_filename' is relative to it + (i.e. 'output_filename' can provide directory components if + needed). + + 'libraries' is a list of libraries to link against. These are + library names, not filenames, since they're translated into + filenames in a platform-specific way (eg. "foo" becomes "libfoo.a" + on Unix and "foo.lib" on DOS/Windows). However, they can include a + directory component, which means the linker will look in that + specific directory rather than searching all the normal locations. + + 'library_dirs', if supplied, should be a list of directories to + search for libraries that were specified as bare library names + (ie. no directory component). These are on top of the system + default and those supplied to 'add_library_dir()' and/or + 'set_library_dirs()'. 'runtime_library_dirs' is a list of + directories that will be embedded into the shared library and used + to search for other shared libraries that *it* depends on at + run-time. (This may only be relevant on Unix.) + + 'export_symbols' is a list of symbols that the shared library will + export. (This appears to be relevant only on Windows.) + + 'debug' is as for 'compile()' and 'create_static_lib()', with the + slight distinction that it actually matters on most platforms (as + opposed to 'create_static_lib()', which includes a 'debug' flag + mostly for form's sake). + + 'extra_preargs' and 'extra_postargs' are as for 'compile()' (except + of course that they supply command-line arguments for the + particular linker being used). + + 'target_lang' is the target language for which the given objects + are being compiled. This allows specific linkage time treatment of + certain languages. + + Raises LinkError on failure. + """ + raise NotImplementedError + + + # Old 'link_*()' methods, rewritten to use the new 'link()' method. + + def link_shared_lib(self, objects, output_libname, output_dir=None, + libraries=None, library_dirs=None, + runtime_library_dirs=None, export_symbols=None, + debug=0, extra_preargs=None, extra_postargs=None, + build_temp=None, target_lang=None): + self.link(CCompiler.SHARED_LIBRARY, objects, + self.library_filename(output_libname, lib_type='shared'), + output_dir, + libraries, library_dirs, runtime_library_dirs, + export_symbols, debug, + extra_preargs, extra_postargs, build_temp, target_lang) + + + def link_shared_object(self, objects, output_filename, output_dir=None, + libraries=None, library_dirs=None, + runtime_library_dirs=None, export_symbols=None, + debug=0, extra_preargs=None, extra_postargs=None, + build_temp=None, target_lang=None): + self.link(CCompiler.SHARED_OBJECT, objects, + output_filename, output_dir, + libraries, library_dirs, runtime_library_dirs, + export_symbols, debug, + extra_preargs, extra_postargs, build_temp, target_lang) + + def link_executable(self, objects, output_progname, output_dir=None, + libraries=None, library_dirs=None, + runtime_library_dirs=None, debug=0, extra_preargs=None, + extra_postargs=None, target_lang=None): + self.link(CCompiler.EXECUTABLE, objects, + self.executable_filename(output_progname), output_dir, + libraries, library_dirs, runtime_library_dirs, None, + debug, extra_preargs, extra_postargs, None, target_lang) + + + # -- Miscellaneous methods ----------------------------------------- + # These are all used by the 'gen_lib_options() function; there is + # no appropriate default implementation so subclasses should + # implement all of these. + + def library_dir_option(self, dir): + """Return the compiler option to add 'dir' to the list of + directories searched for libraries. + """ + raise NotImplementedError + + def runtime_library_dir_option(self, dir): + """Return the compiler option to add 'dir' to the list of + directories searched for runtime libraries. + """ + raise NotImplementedError + + def library_option(self, lib): + """Return the compiler option to add 'dir' to the list of libraries + linked into the shared library or executable. + """ + raise NotImplementedError + + def has_function(self, funcname, includes=None, include_dirs=None, + libraries=None, library_dirs=None): + """Return a boolean indicating whether funcname is supported on + the current platform. The optional arguments can be used to + augment the compilation environment. + """ + + # this can't be included at module scope because it tries to + # import math which might not be available at that point - maybe + # the necessary logic should just be inlined? + import tempfile + if includes is None: + includes = [] + if include_dirs is None: + include_dirs = [] + if libraries is None: + libraries = [] + if library_dirs is None: + library_dirs = [] + fd, fname = tempfile.mkstemp(".c", funcname, text=True) + f = os.fdopen(fd, "w") + try: + for incl in includes: + f.write("""#include "%s"\n""" % incl) + f.write("""\ +main (int argc, char **argv) { + %s(); +} +""" % funcname) + finally: + f.close() + try: + objects = self.compile([fname], include_dirs=include_dirs) + except CompileError: + return False + + try: + self.link_executable(objects, "a.out", + libraries=libraries, + library_dirs=library_dirs) + except (LinkError, TypeError): + return False + return True + + def find_library_file (self, dirs, lib, debug=0): + """Search the specified list of directories for a static or shared + library file 'lib' and return the full path to that file. If + 'debug' true, look for a debugging version (if that makes sense on + the current platform). Return None if 'lib' wasn't found in any of + the specified directories. + """ + raise NotImplementedError + + # -- Filename generation methods ----------------------------------- + + # The default implementation of the filename generating methods are + # prejudiced towards the Unix/DOS/Windows view of the world: + # * object files are named by replacing the source file extension + # (eg. .c/.cpp -> .o/.obj) + # * library files (shared or static) are named by plugging the + # library name and extension into a format string, eg. + # "lib%s.%s" % (lib_name, ".a") for Unix static libraries + # * executables are named by appending an extension (possibly + # empty) to the program name: eg. progname + ".exe" for + # Windows + # + # To reduce redundant code, these methods expect to find + # several attributes in the current object (presumably defined + # as class attributes): + # * src_extensions - + # list of C/C++ source file extensions, eg. ['.c', '.cpp'] + # * obj_extension - + # object file extension, eg. '.o' or '.obj' + # * static_lib_extension - + # extension for static library files, eg. '.a' or '.lib' + # * shared_lib_extension - + # extension for shared library/object files, eg. '.so', '.dll' + # * static_lib_format - + # format string for generating static library filenames, + # eg. 'lib%s.%s' or '%s.%s' + # * shared_lib_format + # format string for generating shared library filenames + # (probably same as static_lib_format, since the extension + # is one of the intended parameters to the format string) + # * exe_extension - + # extension for executable files, eg. '' or '.exe' + + def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): + if output_dir is None: + output_dir = '' + obj_names = [] + for src_name in source_filenames: + base, ext = os.path.splitext(src_name) + base = os.path.splitdrive(base)[1] # Chop off the drive + base = base[os.path.isabs(base):] # If abs, chop off leading / + if ext not in self.src_extensions: + raise UnknownFileError, \ + "unknown file type '%s' (from '%s')" % (ext, src_name) + if strip_dir: + base = os.path.basename(base) + obj_names.append(os.path.join(output_dir, + base + self.obj_extension)) + return obj_names + + def shared_object_filename(self, basename, strip_dir=0, output_dir=''): + assert output_dir is not None + if strip_dir: + basename = os.path.basename (basename) + return os.path.join(output_dir, basename + self.shared_lib_extension) + + def executable_filename(self, basename, strip_dir=0, output_dir=''): + assert output_dir is not None + if strip_dir: + basename = os.path.basename (basename) + return os.path.join(output_dir, basename + (self.exe_extension or '')) + + def library_filename(self, libname, lib_type='static', # or 'shared' + strip_dir=0, output_dir=''): + assert output_dir is not None + if lib_type not in ("static", "shared", "dylib"): + raise ValueError, "'lib_type' must be \"static\", \"shared\" or \"dylib\"" + fmt = getattr(self, lib_type + "_lib_format") + ext = getattr(self, lib_type + "_lib_extension") + + dir, base = os.path.split (libname) + filename = fmt % (base, ext) + if strip_dir: + dir = '' + + return os.path.join(output_dir, dir, filename) + + + # -- Utility methods ----------------------------------------------- + + def announce(self, msg, level=1): + log.debug(msg) + + def debug_print(self, msg): + from distutils.debug import DEBUG + if DEBUG: + print msg + + def warn(self, msg): + sys.stderr.write("warning: %s\n" % msg) + + def execute(self, func, args, msg=None, level=1): + execute(func, args, msg, self.dry_run) + + def spawn(self, cmd): + spawn(cmd, dry_run=self.dry_run) + + def move_file(self, src, dst): + return move_file(src, dst, dry_run=self.dry_run) + + def mkpath(self, name, mode=0777): + mkpath(name, mode, dry_run=self.dry_run) + + +# class CCompiler + + +# Map a sys.platform/os.name ('posix', 'nt') to the default compiler +# type for that platform. Keys are interpreted as re match +# patterns. Order is important; platform mappings are preferred over +# OS names. +_default_compilers = ( + + # Platform string mappings + + # on a cygwin built python we can use gcc like an ordinary UNIXish + # compiler + ('cygwin.*', 'unix'), + ('os2emx', 'emx'), + + # OS name mappings + ('posix', 'unix'), + ('nt', 'msvc'), + + ) + +def get_default_compiler(osname=None, platform=None): + """ Determine the default compiler to use for the given platform. + + osname should be one of the standard Python OS names (i.e. the + ones returned by os.name) and platform the common value + returned by sys.platform for the platform in question. + + The default values are os.name and sys.platform in case the + parameters are not given. + + """ + if osname is None: + osname = os.name + if platform is None: + platform = sys.platform + for pattern, compiler in _default_compilers: + if re.match(pattern, platform) is not None or \ + re.match(pattern, osname) is not None: + return compiler + # Default to Unix compiler + return 'unix' + +# Map compiler types to (module_name, class_name) pairs -- ie. where to +# find the code that implements an interface to this compiler. (The module +# is assumed to be in the 'distutils' package.) +compiler_class = { 'unix': ('unixccompiler', 'UnixCCompiler', + "standard UNIX-style compiler"), + 'msvc': ('msvccompiler', 'MSVCCompiler', + "Microsoft Visual C++"), + 'cygwin': ('cygwinccompiler', 'CygwinCCompiler', + "Cygwin port of GNU C Compiler for Win32"), + 'mingw32': ('cygwinccompiler', 'Mingw32CCompiler', + "Mingw32 port of GNU C Compiler for Win32"), + 'bcpp': ('bcppcompiler', 'BCPPCompiler', + "Borland C++ Compiler"), + 'emx': ('emxccompiler', 'EMXCCompiler', + "EMX port of GNU C Compiler for OS/2"), + } + +def show_compilers(): + """Print list of available compilers (used by the "--help-compiler" + options to "build", "build_ext", "build_clib"). + """ + # XXX this "knows" that the compiler option it's describing is + # "--compiler", which just happens to be the case for the three + # commands that use it. + from distutils.fancy_getopt import FancyGetopt + compilers = [] + for compiler in compiler_class.keys(): + compilers.append(("compiler="+compiler, None, + compiler_class[compiler][2])) + compilers.sort() + pretty_printer = FancyGetopt(compilers) + pretty_printer.print_help("List of available compilers:") + + +def new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0): + """Generate an instance of some CCompiler subclass for the supplied + platform/compiler combination. 'plat' defaults to 'os.name' + (eg. 'posix', 'nt'), and 'compiler' defaults to the default compiler + for that platform. Currently only 'posix' and 'nt' are supported, and + the default compilers are "traditional Unix interface" (UnixCCompiler + class) and Visual C++ (MSVCCompiler class). Note that it's perfectly + possible to ask for a Unix compiler object under Windows, and a + Microsoft compiler object under Unix -- if you supply a value for + 'compiler', 'plat' is ignored. + """ + if plat is None: + plat = os.name + + try: + if compiler is None: + compiler = get_default_compiler(plat) + + (module_name, class_name, long_description) = compiler_class[compiler] + except KeyError: + msg = "don't know how to compile C/C++ code on platform '%s'" % plat + if compiler is not None: + msg = msg + " with '%s' compiler" % compiler + raise DistutilsPlatformError, msg + + try: + module_name = "distutils." + module_name + __import__ (module_name) + module = sys.modules[module_name] + klass = vars(module)[class_name] + except ImportError: + raise DistutilsModuleError, \ + "can't compile C/C++ code: unable to load module '%s'" % \ + module_name + except KeyError: + raise DistutilsModuleError, \ + ("can't compile C/C++ code: unable to find class '%s' " + + "in module '%s'") % (class_name, module_name) + + # XXX The None is necessary to preserve backwards compatibility + # with classes that expect verbose to be the first positional + # argument. + return klass(None, dry_run, force) + + +def gen_preprocess_options(macros, include_dirs): + """Generate C pre-processor options (-D, -U, -I) as used by at least + two types of compilers: the typical Unix compiler and Visual C++. + 'macros' is the usual thing, a list of 1- or 2-tuples, where (name,) + means undefine (-U) macro 'name', and (name,value) means define (-D) + macro 'name' to 'value'. 'include_dirs' is just a list of directory + names to be added to the header file search path (-I). Returns a list + of command-line options suitable for either Unix compilers or Visual + C++. + """ + # XXX it would be nice (mainly aesthetic, and so we don't generate + # stupid-looking command lines) to go over 'macros' and eliminate + # redundant definitions/undefinitions (ie. ensure that only the + # latest mention of a particular macro winds up on the command + # line). I don't think it's essential, though, since most (all?) + # Unix C compilers only pay attention to the latest -D or -U + # mention of a macro on their command line. Similar situation for + # 'include_dirs'. I'm punting on both for now. Anyways, weeding out + # redundancies like this should probably be the province of + # CCompiler, since the data structures used are inherited from it + # and therefore common to all CCompiler classes. + + pp_opts = [] + for macro in macros: + + if not (isinstance(macro, tuple) and + 1 <= len (macro) <= 2): + raise TypeError, \ + ("bad macro definition '%s': " + + "each element of 'macros' list must be a 1- or 2-tuple") % \ + macro + + if len (macro) == 1: # undefine this macro + pp_opts.append ("-U%s" % macro[0]) + elif len (macro) == 2: + if macro[1] is None: # define with no explicit value + pp_opts.append ("-D%s" % macro[0]) + else: + # XXX *don't* need to be clever about quoting the + # macro value here, because we're going to avoid the + # shell at all costs when we spawn the command! + pp_opts.append ("-D%s=%s" % macro) + + for dir in include_dirs: + pp_opts.append ("-I%s" % dir) + + return pp_opts + + +def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries): + """Generate linker options for searching library directories and + linking with specific libraries. + + 'libraries' and 'library_dirs' are, respectively, lists of library names + (not filenames!) and search directories. Returns a list of command-line + options suitable for use with some compiler (depending on the two format + strings passed in). + """ + lib_opts = [] + + for dir in library_dirs: + lib_opts.append(compiler.library_dir_option(dir)) + + for dir in runtime_library_dirs: + opt = compiler.runtime_library_dir_option(dir) + if isinstance(opt, list): + lib_opts.extend(opt) + else: + lib_opts.append(opt) + + # XXX it's important that we *not* remove redundant library mentions! + # sometimes you really do have to say "-lfoo -lbar -lfoo" in order to + # resolve all symbols. I just hope we never have to say "-lfoo obj.o + # -lbar" to get things to work -- that's certainly a possibility, but a + # pretty nasty way to arrange your C code. + + for lib in libraries: + lib_dir, lib_name = os.path.split(lib) + if lib_dir != '': + lib_file = compiler.find_library_file([lib_dir], lib_name) + if lib_file is not None: + lib_opts.append(lib_file) + else: + compiler.warn("no library file corresponding to " + "'%s' found (skipping)" % lib) + else: + lib_opts.append(compiler.library_option(lib)) + + return lib_opts diff --git a/PythonHome/Lib/distutils/ccompiler.pyc b/PythonHome/Lib/distutils/ccompiler.pyc deleted file mode 100644 index 74c07b1a93e97253ef498a3f1b6dccc9d8bffe69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36549 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 diff --git a/PythonHome/Lib/distutils/command/__init__.py b/PythonHome/Lib/distutils/command/__init__.py new file mode 100644 index 0000000000..20b159f74e --- /dev/null +++ b/PythonHome/Lib/distutils/command/__init__.py @@ -0,0 +1,33 @@ +"""distutils.command + +Package containing implementation of all the standard Distutils +commands.""" + +__revision__ = "$Id$" + +__all__ = ['build', + 'build_py', + 'build_ext', + 'build_clib', + 'build_scripts', + 'clean', + 'install', + 'install_lib', + 'install_headers', + 'install_scripts', + 'install_data', + 'sdist', + 'register', + 'bdist', + 'bdist_dumb', + 'bdist_rpm', + 'bdist_wininst', + 'upload', + 'check', + # These two are reserved for future use: + #'bdist_sdux', + #'bdist_pkgtool', + # Note: + # bdist_packager is not included because it only provides + # an abstract base class + ] diff --git a/PythonHome/Lib/distutils/command/__init__.pyc b/PythonHome/Lib/distutils/command/__init__.pyc deleted file mode 100644 index 29005876628c8f91d003023b83f99725e56ddbcc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 660 zcmah`%TB{U40Ky4B~S_!IOo8j7kc1=gb+f43m2%w0jY{)w(F%`v3V%#@c1wOj32<8 zK7bR6;>dHlTu0vJndz_-BBy1lckvoH09iTovsZAgjA)Ix%--yMLM@zv$wD_QE7`_Rk&Qy-1*Gtm%Bkr zvbBFi$~7VfABd%SwO)2Bi7*_ZjD|Q62tUD}2)#Z}Mjt%Ov(vLg=1oG+`UI23;uA!1 dz=%UxaoG1onp5S>WjGEW)Y{EQJ diff --git a/PythonHome/Lib/distutils/command/bdist.py b/PythonHome/Lib/distutils/command/bdist.py new file mode 100644 index 0000000000..d7910b14d6 --- /dev/null +++ b/PythonHome/Lib/distutils/command/bdist.py @@ -0,0 +1,146 @@ +"""distutils.command.bdist + +Implements the Distutils 'bdist' command (create a built [binary] +distribution).""" + +__revision__ = "$Id$" + +import os + +from distutils.util import get_platform +from distutils.core import Command +from distutils.errors import DistutilsPlatformError, DistutilsOptionError + + +def show_formats(): + """Print list of available formats (arguments to "--format" option). + """ + from distutils.fancy_getopt import FancyGetopt + formats = [] + for format in bdist.format_commands: + formats.append(("formats=" + format, None, + bdist.format_command[format][1])) + pretty_printer = FancyGetopt(formats) + pretty_printer.print_help("List of available distribution formats:") + + +class bdist(Command): + + description = "create a built (binary) distribution" + + user_options = [('bdist-base=', 'b', + "temporary directory for creating built distributions"), + ('plat-name=', 'p', + "platform name to embed in generated filenames " + "(default: %s)" % get_platform()), + ('formats=', None, + "formats for distribution (comma-separated list)"), + ('dist-dir=', 'd', + "directory to put final built distributions in " + "[default: dist]"), + ('skip-build', None, + "skip rebuilding everything (for testing/debugging)"), + ('owner=', 'u', + "Owner name used when creating a tar file" + " [default: current user]"), + ('group=', 'g', + "Group name used when creating a tar file" + " [default: current group]"), + ] + + boolean_options = ['skip-build'] + + help_options = [ + ('help-formats', None, + "lists available distribution formats", show_formats), + ] + + # The following commands do not take a format option from bdist + no_format_option = ('bdist_rpm',) + + # This won't do in reality: will need to distinguish RPM-ish Linux, + # Debian-ish Linux, Solaris, FreeBSD, ..., Windows, Mac OS. + default_format = {'posix': 'gztar', + 'nt': 'zip', + 'os2': 'zip'} + + # Establish the preferred order (for the --help-formats option). + format_commands = ['rpm', 'gztar', 'bztar', 'ztar', 'tar', + 'wininst', 'zip', 'msi'] + + # And the real information. + format_command = {'rpm': ('bdist_rpm', "RPM distribution"), + 'gztar': ('bdist_dumb', "gzip'ed tar file"), + 'bztar': ('bdist_dumb', "bzip2'ed tar file"), + 'ztar': ('bdist_dumb', "compressed tar file"), + 'tar': ('bdist_dumb', "tar file"), + 'wininst': ('bdist_wininst', + "Windows executable installer"), + 'zip': ('bdist_dumb', "ZIP file"), + 'msi': ('bdist_msi', "Microsoft Installer") + } + + + def initialize_options(self): + self.bdist_base = None + self.plat_name = None + self.formats = None + self.dist_dir = None + self.skip_build = 0 + self.group = None + self.owner = None + + def finalize_options(self): + # have to finalize 'plat_name' before 'bdist_base' + if self.plat_name is None: + if self.skip_build: + self.plat_name = get_platform() + else: + self.plat_name = self.get_finalized_command('build').plat_name + + # 'bdist_base' -- parent of per-built-distribution-format + # temporary directories (eg. we'll probably have + # "build/bdist./dumb", "build/bdist./rpm", etc.) + if self.bdist_base is None: + build_base = self.get_finalized_command('build').build_base + self.bdist_base = os.path.join(build_base, + 'bdist.' + self.plat_name) + + self.ensure_string_list('formats') + if self.formats is None: + try: + self.formats = [self.default_format[os.name]] + except KeyError: + raise DistutilsPlatformError, \ + "don't know how to create built distributions " + \ + "on platform %s" % os.name + + if self.dist_dir is None: + self.dist_dir = "dist" + + def run(self): + # Figure out which sub-commands we need to run. + commands = [] + for format in self.formats: + try: + commands.append(self.format_command[format][0]) + except KeyError: + raise DistutilsOptionError, "invalid format '%s'" % format + + # Reinitialize and run each command. + for i in range(len(self.formats)): + cmd_name = commands[i] + sub_cmd = self.reinitialize_command(cmd_name) + if cmd_name not in self.no_format_option: + sub_cmd.format = self.formats[i] + + # passing the owner and group names for tar archiving + if cmd_name == 'bdist_dumb': + sub_cmd.owner = self.owner + sub_cmd.group = self.group + + # If we're going to need to run this command again, tell it to + # keep its temporary files around so subsequent runs go faster. + if cmd_name in commands[i+1:]: + sub_cmd.keep_temp = 1 + self.run_command(cmd_name) diff --git a/PythonHome/Lib/distutils/command/bdist.pyc b/PythonHome/Lib/distutils/command/bdist.pyc deleted file mode 100644 index 0b14c75de2b59cf7635548717b0469e7fdd568e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5129 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 diff --git a/PythonHome/Lib/distutils/command/bdist_msi.py b/PythonHome/Lib/distutils/command/bdist_msi.py new file mode 100644 index 0000000000..703f873b16 --- /dev/null +++ b/PythonHome/Lib/distutils/command/bdist_msi.py @@ -0,0 +1,742 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2005, 2006 Martin von Lwis +# Licensed to PSF under a Contributor Agreement. +# The bdist_wininst command proper +# based on bdist_wininst +""" +Implements the bdist_msi command. +""" +import sys, os +from sysconfig import get_python_version + +from distutils.core import Command +from distutils.dir_util import remove_tree +from distutils.version import StrictVersion +from distutils.errors import DistutilsOptionError +from distutils import log +from distutils.util import get_platform + +import msilib +from msilib import schema, sequence, text +from msilib import Directory, Feature, Dialog, add_data + +class PyDialog(Dialog): + """Dialog class with a fixed layout: controls at the top, then a ruler, + then a list of buttons: back, next, cancel. Optionally a bitmap at the + left.""" + def __init__(self, *args, **kw): + """Dialog(database, name, x, y, w, h, attributes, title, first, + default, cancel, bitmap=true)""" + Dialog.__init__(self, *args) + ruler = self.h - 36 + #if kw.get("bitmap", True): + # self.bitmap("Bitmap", 0, 0, bmwidth, ruler, "PythonWin") + self.line("BottomLine", 0, ruler, self.w, 0) + + def title(self, title): + "Set the title text of the dialog at the top." + # name, x, y, w, h, flags=Visible|Enabled|Transparent|NoPrefix, + # text, in VerdanaBold10 + self.text("Title", 15, 10, 320, 60, 0x30003, + r"{\VerdanaBold10}%s" % title) + + def back(self, title, next, name = "Back", active = 1): + """Add a back button with a given title, the tab-next button, + its name in the Control table, possibly initially disabled. + + Return the button, so that events can be associated""" + if active: + flags = 3 # Visible|Enabled + else: + flags = 1 # Visible + return self.pushbutton(name, 180, self.h-27 , 56, 17, flags, title, next) + + def cancel(self, title, next, name = "Cancel", active = 1): + """Add a cancel button with a given title, the tab-next button, + its name in the Control table, possibly initially disabled. + + Return the button, so that events can be associated""" + if active: + flags = 3 # Visible|Enabled + else: + flags = 1 # Visible + return self.pushbutton(name, 304, self.h-27, 56, 17, flags, title, next) + + def next(self, title, next, name = "Next", active = 1): + """Add a Next button with a given title, the tab-next button, + its name in the Control table, possibly initially disabled. + + Return the button, so that events can be associated""" + if active: + flags = 3 # Visible|Enabled + else: + flags = 1 # Visible + return self.pushbutton(name, 236, self.h-27, 56, 17, flags, title, next) + + def xbutton(self, name, title, next, xpos): + """Add a button with a given title, the tab-next button, + its name in the Control table, giving its x position; the + y-position is aligned with the other buttons. + + Return the button, so that events can be associated""" + return self.pushbutton(name, int(self.w*xpos - 28), self.h-27, 56, 17, 3, title, next) + +class bdist_msi (Command): + + description = "create a Microsoft Installer (.msi) binary distribution" + + user_options = [('bdist-dir=', None, + "temporary directory for creating the distribution"), + ('plat-name=', 'p', + "platform name to embed in generated filenames " + "(default: %s)" % get_platform()), + ('keep-temp', 'k', + "keep the pseudo-installation tree around after " + + "creating the distribution archive"), + ('target-version=', None, + "require a specific python version" + + " on the target system"), + ('no-target-compile', 'c', + "do not compile .py to .pyc on the target system"), + ('no-target-optimize', 'o', + "do not compile .py to .pyo (optimized)" + "on the target system"), + ('dist-dir=', 'd', + "directory to put final built distributions in"), + ('skip-build', None, + "skip rebuilding everything (for testing/debugging)"), + ('install-script=', None, + "basename of installation script to be run after" + "installation or before deinstallation"), + ('pre-install-script=', None, + "Fully qualified filename of a script to be run before " + "any files are installed. This script need not be in the " + "distribution"), + ] + + boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize', + 'skip-build'] + + all_versions = ['2.0', '2.1', '2.2', '2.3', '2.4', + '2.5', '2.6', '2.7', '2.8', '2.9', + '3.0', '3.1', '3.2', '3.3', '3.4', + '3.5', '3.6', '3.7', '3.8', '3.9'] + other_version = 'X' + + def initialize_options (self): + self.bdist_dir = None + self.plat_name = None + self.keep_temp = 0 + self.no_target_compile = 0 + self.no_target_optimize = 0 + self.target_version = None + self.dist_dir = None + self.skip_build = None + self.install_script = None + self.pre_install_script = None + self.versions = None + + def finalize_options (self): + self.set_undefined_options('bdist', ('skip_build', 'skip_build')) + + if self.bdist_dir is None: + bdist_base = self.get_finalized_command('bdist').bdist_base + self.bdist_dir = os.path.join(bdist_base, 'msi') + + short_version = get_python_version() + if (not self.target_version) and self.distribution.has_ext_modules(): + self.target_version = short_version + + if self.target_version: + self.versions = [self.target_version] + if not self.skip_build and self.distribution.has_ext_modules()\ + and self.target_version != short_version: + raise DistutilsOptionError, \ + "target version can only be %s, or the '--skip-build'" \ + " option must be specified" % (short_version,) + else: + self.versions = list(self.all_versions) + + self.set_undefined_options('bdist', + ('dist_dir', 'dist_dir'), + ('plat_name', 'plat_name'), + ) + + if self.pre_install_script: + raise DistutilsOptionError, "the pre-install-script feature is not yet implemented" + + if self.install_script: + for script in self.distribution.scripts: + if self.install_script == os.path.basename(script): + break + else: + raise DistutilsOptionError, \ + "install_script '%s' not found in scripts" % \ + self.install_script + self.install_script_key = None + # finalize_options() + + + def run (self): + if not self.skip_build: + self.run_command('build') + + install = self.reinitialize_command('install', reinit_subcommands=1) + install.prefix = self.bdist_dir + install.skip_build = self.skip_build + install.warn_dir = 0 + + install_lib = self.reinitialize_command('install_lib') + # we do not want to include pyc or pyo files + install_lib.compile = 0 + install_lib.optimize = 0 + + if self.distribution.has_ext_modules(): + # If we are building an installer for a Python version other + # than the one we are currently running, then we need to ensure + # our build_lib reflects the other Python version rather than ours. + # Note that for target_version!=sys.version, we must have skipped the + # build step, so there is no issue with enforcing the build of this + # version. + target_version = self.target_version + if not target_version: + assert self.skip_build, "Should have already checked this" + target_version = sys.version[0:3] + plat_specifier = ".%s-%s" % (self.plat_name, target_version) + build = self.get_finalized_command('build') + build.build_lib = os.path.join(build.build_base, + 'lib' + plat_specifier) + + log.info("installing to %s", self.bdist_dir) + install.ensure_finalized() + + # avoid warning of 'install_lib' about installing + # into a directory not in sys.path + sys.path.insert(0, os.path.join(self.bdist_dir, 'PURELIB')) + + install.run() + + del sys.path[0] + + self.mkpath(self.dist_dir) + fullname = self.distribution.get_fullname() + installer_name = self.get_installer_filename(fullname) + installer_name = os.path.abspath(installer_name) + if os.path.exists(installer_name): os.unlink(installer_name) + + metadata = self.distribution.metadata + author = metadata.author + if not author: + author = metadata.maintainer + if not author: + author = "UNKNOWN" + version = metadata.get_version() + # ProductVersion must be strictly numeric + # XXX need to deal with prerelease versions + sversion = "%d.%d.%d" % StrictVersion(version).version + # Prefix ProductName with Python x.y, so that + # it sorts together with the other Python packages + # in Add-Remove-Programs (APR) + fullname = self.distribution.get_fullname() + if self.target_version: + product_name = "Python %s %s" % (self.target_version, fullname) + else: + product_name = "Python %s" % (fullname) + self.db = msilib.init_database(installer_name, schema, + product_name, msilib.gen_uuid(), + sversion, author) + msilib.add_tables(self.db, sequence) + props = [('DistVersion', version)] + email = metadata.author_email or metadata.maintainer_email + if email: + props.append(("ARPCONTACT", email)) + if metadata.url: + props.append(("ARPURLINFOABOUT", metadata.url)) + if props: + add_data(self.db, 'Property', props) + + self.add_find_python() + self.add_files() + self.add_scripts() + self.add_ui() + self.db.Commit() + + if hasattr(self.distribution, 'dist_files'): + tup = 'bdist_msi', self.target_version or 'any', fullname + self.distribution.dist_files.append(tup) + + if not self.keep_temp: + remove_tree(self.bdist_dir, dry_run=self.dry_run) + + def add_files(self): + db = self.db + cab = msilib.CAB("distfiles") + rootdir = os.path.abspath(self.bdist_dir) + + root = Directory(db, cab, None, rootdir, "TARGETDIR", "SourceDir") + f = Feature(db, "Python", "Python", "Everything", + 0, 1, directory="TARGETDIR") + + items = [(f, root, '')] + for version in self.versions + [self.other_version]: + target = "TARGETDIR" + version + name = default = "Python" + version + desc = "Everything" + if version is self.other_version: + title = "Python from another location" + level = 2 + else: + title = "Python %s from registry" % version + level = 1 + f = Feature(db, name, title, desc, 1, level, directory=target) + dir = Directory(db, cab, root, rootdir, target, default) + items.append((f, dir, version)) + db.Commit() + + seen = {} + for feature, dir, version in items: + todo = [dir] + while todo: + dir = todo.pop() + for file in os.listdir(dir.absolute): + afile = os.path.join(dir.absolute, file) + if os.path.isdir(afile): + short = "%s|%s" % (dir.make_short(file), file) + default = file + version + newdir = Directory(db, cab, dir, file, default, short) + todo.append(newdir) + else: + if not dir.component: + dir.start_component(dir.logical, feature, 0) + if afile not in seen: + key = seen[afile] = dir.add_file(file) + if file==self.install_script: + if self.install_script_key: + raise DistutilsOptionError( + "Multiple files with name %s" % file) + self.install_script_key = '[#%s]' % key + else: + key = seen[afile] + add_data(self.db, "DuplicateFile", + [(key + version, dir.component, key, None, dir.logical)]) + db.Commit() + cab.commit(db) + + def add_find_python(self): + """Adds code to the installer to compute the location of Python. + + Properties PYTHON.MACHINE.X.Y and PYTHON.USER.X.Y will be set from the + registry for each version of Python. + + Properties TARGETDIRX.Y will be set from PYTHON.USER.X.Y if defined, + else from PYTHON.MACHINE.X.Y. + + Properties PYTHONX.Y will be set to TARGETDIRX.Y\\python.exe""" + + start = 402 + for ver in self.versions: + install_path = r"SOFTWARE\Python\PythonCore\%s\InstallPath" % ver + machine_reg = "python.machine." + ver + user_reg = "python.user." + ver + machine_prop = "PYTHON.MACHINE." + ver + user_prop = "PYTHON.USER." + ver + machine_action = "PythonFromMachine" + ver + user_action = "PythonFromUser" + ver + exe_action = "PythonExe" + ver + target_dir_prop = "TARGETDIR" + ver + exe_prop = "PYTHON" + ver + if msilib.Win64: + # type: msidbLocatorTypeRawValue + msidbLocatorType64bit + Type = 2+16 + else: + Type = 2 + add_data(self.db, "RegLocator", + [(machine_reg, 2, install_path, None, Type), + (user_reg, 1, install_path, None, Type)]) + add_data(self.db, "AppSearch", + [(machine_prop, machine_reg), + (user_prop, user_reg)]) + add_data(self.db, "CustomAction", + [(machine_action, 51+256, target_dir_prop, "[" + machine_prop + "]"), + (user_action, 51+256, target_dir_prop, "[" + user_prop + "]"), + (exe_action, 51+256, exe_prop, "[" + target_dir_prop + "]\\python.exe"), + ]) + add_data(self.db, "InstallExecuteSequence", + [(machine_action, machine_prop, start), + (user_action, user_prop, start + 1), + (exe_action, None, start + 2), + ]) + add_data(self.db, "InstallUISequence", + [(machine_action, machine_prop, start), + (user_action, user_prop, start + 1), + (exe_action, None, start + 2), + ]) + add_data(self.db, "Condition", + [("Python" + ver, 0, "NOT TARGETDIR" + ver)]) + start += 4 + assert start < 500 + + def add_scripts(self): + if self.install_script: + start = 6800 + for ver in self.versions + [self.other_version]: + install_action = "install_script." + ver + exe_prop = "PYTHON" + ver + add_data(self.db, "CustomAction", + [(install_action, 50, exe_prop, self.install_script_key)]) + add_data(self.db, "InstallExecuteSequence", + [(install_action, "&Python%s=3" % ver, start)]) + start += 1 + # XXX pre-install scripts are currently refused in finalize_options() + # but if this feature is completed, it will also need to add + # entries for each version as the above code does + if self.pre_install_script: + scriptfn = os.path.join(self.bdist_dir, "preinstall.bat") + f = open(scriptfn, "w") + # The batch file will be executed with [PYTHON], so that %1 + # is the path to the Python interpreter; %0 will be the path + # of the batch file. + # rem =""" + # %1 %0 + # exit + # """ + # + f.write('rem ="""\n%1 %0\nexit\n"""\n') + f.write(open(self.pre_install_script).read()) + f.close() + add_data(self.db, "Binary", + [("PreInstall", msilib.Binary(scriptfn)) + ]) + add_data(self.db, "CustomAction", + [("PreInstall", 2, "PreInstall", None) + ]) + add_data(self.db, "InstallExecuteSequence", + [("PreInstall", "NOT Installed", 450)]) + + + def add_ui(self): + db = self.db + x = y = 50 + w = 370 + h = 300 + title = "[ProductName] Setup" + + # see "Dialog Style Bits" + modal = 3 # visible | modal + modeless = 1 # visible + + # UI customization properties + add_data(db, "Property", + # See "DefaultUIFont Property" + [("DefaultUIFont", "DlgFont8"), + # See "ErrorDialog Style Bit" + ("ErrorDialog", "ErrorDlg"), + ("Progress1", "Install"), # modified in maintenance type dlg + ("Progress2", "installs"), + ("MaintenanceForm_Action", "Repair"), + # possible values: ALL, JUSTME + ("WhichUsers", "ALL") + ]) + + # Fonts, see "TextStyle Table" + add_data(db, "TextStyle", + [("DlgFont8", "Tahoma", 9, None, 0), + ("DlgFontBold8", "Tahoma", 8, None, 1), #bold + ("VerdanaBold10", "Verdana", 10, None, 1), + ("VerdanaRed9", "Verdana", 9, 255, 0), + ]) + + # UI Sequences, see "InstallUISequence Table", "Using a Sequence Table" + # Numbers indicate sequence; see sequence.py for how these action integrate + add_data(db, "InstallUISequence", + [("PrepareDlg", "Not Privileged or Windows9x or Installed", 140), + ("WhichUsersDlg", "Privileged and not Windows9x and not Installed", 141), + # In the user interface, assume all-users installation if privileged. + ("SelectFeaturesDlg", "Not Installed", 1230), + # XXX no support for resume installations yet + #("ResumeDlg", "Installed AND (RESUME OR Preselected)", 1240), + ("MaintenanceTypeDlg", "Installed AND NOT RESUME AND NOT Preselected", 1250), + ("ProgressDlg", None, 1280)]) + + add_data(db, 'ActionText', text.ActionText) + add_data(db, 'UIText', text.UIText) + ##################################################################### + # Standard dialogs: FatalError, UserExit, ExitDialog + fatal=PyDialog(db, "FatalError", x, y, w, h, modal, title, + "Finish", "Finish", "Finish") + fatal.title("[ProductName] Installer ended prematurely") + fatal.back("< Back", "Finish", active = 0) + fatal.cancel("Cancel", "Back", active = 0) + fatal.text("Description1", 15, 70, 320, 80, 0x30003, + "[ProductName] setup ended prematurely because of an error. Your system has not been modified. To install this program at a later time, please run the installation again.") + fatal.text("Description2", 15, 155, 320, 20, 0x30003, + "Click the Finish button to exit the Installer.") + c=fatal.next("Finish", "Cancel", name="Finish") + c.event("EndDialog", "Exit") + + user_exit=PyDialog(db, "UserExit", x, y, w, h, modal, title, + "Finish", "Finish", "Finish") + user_exit.title("[ProductName] Installer was interrupted") + user_exit.back("< Back", "Finish", active = 0) + user_exit.cancel("Cancel", "Back", active = 0) + user_exit.text("Description1", 15, 70, 320, 80, 0x30003, + "[ProductName] setup was interrupted. Your system has not been modified. " + "To install this program at a later time, please run the installation again.") + user_exit.text("Description2", 15, 155, 320, 20, 0x30003, + "Click the Finish button to exit the Installer.") + c = user_exit.next("Finish", "Cancel", name="Finish") + c.event("EndDialog", "Exit") + + exit_dialog = PyDialog(db, "ExitDialog", x, y, w, h, modal, title, + "Finish", "Finish", "Finish") + exit_dialog.title("Completing the [ProductName] Installer") + exit_dialog.back("< Back", "Finish", active = 0) + exit_dialog.cancel("Cancel", "Back", active = 0) + exit_dialog.text("Description", 15, 235, 320, 20, 0x30003, + "Click the Finish button to exit the Installer.") + c = exit_dialog.next("Finish", "Cancel", name="Finish") + c.event("EndDialog", "Return") + + ##################################################################### + # Required dialog: FilesInUse, ErrorDlg + inuse = PyDialog(db, "FilesInUse", + x, y, w, h, + 19, # KeepModeless|Modal|Visible + title, + "Retry", "Retry", "Retry", bitmap=False) + inuse.text("Title", 15, 6, 200, 15, 0x30003, + r"{\DlgFontBold8}Files in Use") + inuse.text("Description", 20, 23, 280, 20, 0x30003, + "Some files that need to be updated are currently in use.") + inuse.text("Text", 20, 55, 330, 50, 3, + "The following applications are using files that need to be updated by this setup. Close these applications and then click Retry to continue the installation or Cancel to exit it.") + inuse.control("List", "ListBox", 20, 107, 330, 130, 7, "FileInUseProcess", + None, None, None) + c=inuse.back("Exit", "Ignore", name="Exit") + c.event("EndDialog", "Exit") + c=inuse.next("Ignore", "Retry", name="Ignore") + c.event("EndDialog", "Ignore") + c=inuse.cancel("Retry", "Exit", name="Retry") + c.event("EndDialog","Retry") + + # See "Error Dialog". See "ICE20" for the required names of the controls. + error = Dialog(db, "ErrorDlg", + 50, 10, 330, 101, + 65543, # Error|Minimize|Modal|Visible + title, + "ErrorText", None, None) + error.text("ErrorText", 50,9,280,48,3, "") + #error.control("ErrorIcon", "Icon", 15, 9, 24, 24, 5242881, None, "py.ico", None, None) + error.pushbutton("N",120,72,81,21,3,"No",None).event("EndDialog","ErrorNo") + error.pushbutton("Y",240,72,81,21,3,"Yes",None).event("EndDialog","ErrorYes") + error.pushbutton("A",0,72,81,21,3,"Abort",None).event("EndDialog","ErrorAbort") + error.pushbutton("C",42,72,81,21,3,"Cancel",None).event("EndDialog","ErrorCancel") + error.pushbutton("I",81,72,81,21,3,"Ignore",None).event("EndDialog","ErrorIgnore") + error.pushbutton("O",159,72,81,21,3,"Ok",None).event("EndDialog","ErrorOk") + error.pushbutton("R",198,72,81,21,3,"Retry",None).event("EndDialog","ErrorRetry") + + ##################################################################### + # Global "Query Cancel" dialog + cancel = Dialog(db, "CancelDlg", 50, 10, 260, 85, 3, title, + "No", "No", "No") + cancel.text("Text", 48, 15, 194, 30, 3, + "Are you sure you want to cancel [ProductName] installation?") + #cancel.control("Icon", "Icon", 15, 15, 24, 24, 5242881, None, + # "py.ico", None, None) + c=cancel.pushbutton("Yes", 72, 57, 56, 17, 3, "Yes", "No") + c.event("EndDialog", "Exit") + + c=cancel.pushbutton("No", 132, 57, 56, 17, 3, "No", "Yes") + c.event("EndDialog", "Return") + + ##################################################################### + # Global "Wait for costing" dialog + costing = Dialog(db, "WaitForCostingDlg", 50, 10, 260, 85, modal, title, + "Return", "Return", "Return") + costing.text("Text", 48, 15, 194, 30, 3, + "Please wait while the installer finishes determining your disk space requirements.") + c = costing.pushbutton("Return", 102, 57, 56, 17, 3, "Return", None) + c.event("EndDialog", "Exit") + + ##################################################################### + # Preparation dialog: no user input except cancellation + prep = PyDialog(db, "PrepareDlg", x, y, w, h, modeless, title, + "Cancel", "Cancel", "Cancel") + prep.text("Description", 15, 70, 320, 40, 0x30003, + "Please wait while the Installer prepares to guide you through the installation.") + prep.title("Welcome to the [ProductName] Installer") + c=prep.text("ActionText", 15, 110, 320, 20, 0x30003, "Pondering...") + c.mapping("ActionText", "Text") + c=prep.text("ActionData", 15, 135, 320, 30, 0x30003, None) + c.mapping("ActionData", "Text") + prep.back("Back", None, active=0) + prep.next("Next", None, active=0) + c=prep.cancel("Cancel", None) + c.event("SpawnDialog", "CancelDlg") + + ##################################################################### + # Feature (Python directory) selection + seldlg = PyDialog(db, "SelectFeaturesDlg", x, y, w, h, modal, title, + "Next", "Next", "Cancel") + seldlg.title("Select Python Installations") + + seldlg.text("Hint", 15, 30, 300, 20, 3, + "Select the Python locations where %s should be installed." + % self.distribution.get_fullname()) + + seldlg.back("< Back", None, active=0) + c = seldlg.next("Next >", "Cancel") + order = 1 + c.event("[TARGETDIR]", "[SourceDir]", ordering=order) + for version in self.versions + [self.other_version]: + order += 1 + c.event("[TARGETDIR]", "[TARGETDIR%s]" % version, + "FEATURE_SELECTED AND &Python%s=3" % version, + ordering=order) + c.event("SpawnWaitDialog", "WaitForCostingDlg", ordering=order + 1) + c.event("EndDialog", "Return", ordering=order + 2) + c = seldlg.cancel("Cancel", "Features") + c.event("SpawnDialog", "CancelDlg") + + c = seldlg.control("Features", "SelectionTree", 15, 60, 300, 120, 3, + "FEATURE", None, "PathEdit", None) + c.event("[FEATURE_SELECTED]", "1") + ver = self.other_version + install_other_cond = "FEATURE_SELECTED AND &Python%s=3" % ver + dont_install_other_cond = "FEATURE_SELECTED AND &Python%s<>3" % ver + + c = seldlg.text("Other", 15, 200, 300, 15, 3, + "Provide an alternate Python location") + c.condition("Enable", install_other_cond) + c.condition("Show", install_other_cond) + c.condition("Disable", dont_install_other_cond) + c.condition("Hide", dont_install_other_cond) + + c = seldlg.control("PathEdit", "PathEdit", 15, 215, 300, 16, 1, + "TARGETDIR" + ver, None, "Next", None) + c.condition("Enable", install_other_cond) + c.condition("Show", install_other_cond) + c.condition("Disable", dont_install_other_cond) + c.condition("Hide", dont_install_other_cond) + + ##################################################################### + # Disk cost + cost = PyDialog(db, "DiskCostDlg", x, y, w, h, modal, title, + "OK", "OK", "OK", bitmap=False) + cost.text("Title", 15, 6, 200, 15, 0x30003, + "{\DlgFontBold8}Disk Space Requirements") + cost.text("Description", 20, 20, 280, 20, 0x30003, + "The disk space required for the installation of the selected features.") + cost.text("Text", 20, 53, 330, 60, 3, + "The highlighted volumes (if any) do not have enough disk space " + "available for the currently selected features. You can either " + "remove some files from the highlighted volumes, or choose to " + "install less features onto local drive(s), or select different " + "destination drive(s).") + cost.control("VolumeList", "VolumeCostList", 20, 100, 330, 150, 393223, + None, "{120}{70}{70}{70}{70}", None, None) + cost.xbutton("OK", "Ok", None, 0.5).event("EndDialog", "Return") + + ##################################################################### + # WhichUsers Dialog. Only available on NT, and for privileged users. + # This must be run before FindRelatedProducts, because that will + # take into account whether the previous installation was per-user + # or per-machine. We currently don't support going back to this + # dialog after "Next" was selected; to support this, we would need to + # find how to reset the ALLUSERS property, and how to re-run + # FindRelatedProducts. + # On Windows9x, the ALLUSERS property is ignored on the command line + # and in the Property table, but installer fails according to the documentation + # if a dialog attempts to set ALLUSERS. + whichusers = PyDialog(db, "WhichUsersDlg", x, y, w, h, modal, title, + "AdminInstall", "Next", "Cancel") + whichusers.title("Select whether to install [ProductName] for all users of this computer.") + # A radio group with two options: allusers, justme + g = whichusers.radiogroup("AdminInstall", 15, 60, 260, 50, 3, + "WhichUsers", "", "Next") + g.add("ALL", 0, 5, 150, 20, "Install for all users") + g.add("JUSTME", 0, 25, 150, 20, "Install just for me") + + whichusers.back("Back", None, active=0) + + c = whichusers.next("Next >", "Cancel") + c.event("[ALLUSERS]", "1", 'WhichUsers="ALL"', 1) + c.event("EndDialog", "Return", ordering = 2) + + c = whichusers.cancel("Cancel", "AdminInstall") + c.event("SpawnDialog", "CancelDlg") + + ##################################################################### + # Installation Progress dialog (modeless) + progress = PyDialog(db, "ProgressDlg", x, y, w, h, modeless, title, + "Cancel", "Cancel", "Cancel", bitmap=False) + progress.text("Title", 20, 15, 200, 15, 0x30003, + "{\DlgFontBold8}[Progress1] [ProductName]") + progress.text("Text", 35, 65, 300, 30, 3, + "Please wait while the Installer [Progress2] [ProductName]. " + "This may take several minutes.") + progress.text("StatusLabel", 35, 100, 35, 20, 3, "Status:") + + c=progress.text("ActionText", 70, 100, w-70, 20, 3, "Pondering...") + c.mapping("ActionText", "Text") + + #c=progress.text("ActionData", 35, 140, 300, 20, 3, None) + #c.mapping("ActionData", "Text") + + c=progress.control("ProgressBar", "ProgressBar", 35, 120, 300, 10, 65537, + None, "Progress done", None, None) + c.mapping("SetProgress", "Progress") + + progress.back("< Back", "Next", active=False) + progress.next("Next >", "Cancel", active=False) + progress.cancel("Cancel", "Back").event("SpawnDialog", "CancelDlg") + + ################################################################### + # Maintenance type: repair/uninstall + maint = PyDialog(db, "MaintenanceTypeDlg", x, y, w, h, modal, title, + "Next", "Next", "Cancel") + maint.title("Welcome to the [ProductName] Setup Wizard") + maint.text("BodyText", 15, 63, 330, 42, 3, + "Select whether you want to repair or remove [ProductName].") + g=maint.radiogroup("RepairRadioGroup", 15, 108, 330, 60, 3, + "MaintenanceForm_Action", "", "Next") + #g.add("Change", 0, 0, 200, 17, "&Change [ProductName]") + g.add("Repair", 0, 18, 200, 17, "&Repair [ProductName]") + g.add("Remove", 0, 36, 200, 17, "Re&move [ProductName]") + + maint.back("< Back", None, active=False) + c=maint.next("Finish", "Cancel") + # Change installation: Change progress dialog to "Change", then ask + # for feature selection + #c.event("[Progress1]", "Change", 'MaintenanceForm_Action="Change"', 1) + #c.event("[Progress2]", "changes", 'MaintenanceForm_Action="Change"', 2) + + # Reinstall: Change progress dialog to "Repair", then invoke reinstall + # Also set list of reinstalled features to "ALL" + c.event("[REINSTALL]", "ALL", 'MaintenanceForm_Action="Repair"', 5) + c.event("[Progress1]", "Repairing", 'MaintenanceForm_Action="Repair"', 6) + c.event("[Progress2]", "repairs", 'MaintenanceForm_Action="Repair"', 7) + c.event("Reinstall", "ALL", 'MaintenanceForm_Action="Repair"', 8) + + # Uninstall: Change progress to "Remove", then invoke uninstall + # Also set list of removed features to "ALL" + c.event("[REMOVE]", "ALL", 'MaintenanceForm_Action="Remove"', 11) + c.event("[Progress1]", "Removing", 'MaintenanceForm_Action="Remove"', 12) + c.event("[Progress2]", "removes", 'MaintenanceForm_Action="Remove"', 13) + c.event("Remove", "ALL", 'MaintenanceForm_Action="Remove"', 14) + + # Close dialog when maintenance action scheduled + c.event("EndDialog", "Return", 'MaintenanceForm_Action<>"Change"', 20) + #c.event("NewDialog", "SelectFeaturesDlg", 'MaintenanceForm_Action="Change"', 21) + + maint.cancel("Cancel", "RepairRadioGroup").event("SpawnDialog", "CancelDlg") + + def get_installer_filename(self, fullname): + # Factored out to allow overriding in subclasses + if self.target_version: + base_name = "%s.%s-py%s.msi" % (fullname, self.plat_name, + self.target_version) + else: + base_name = "%s.%s.msi" % (fullname, self.plat_name) + installer_name = os.path.join(self.dist_dir, base_name) + return installer_name diff --git a/PythonHome/Lib/distutils/command/bdist_msi.pyc b/PythonHome/Lib/distutils/command/bdist_msi.pyc deleted file mode 100644 index 53016ee53776bb8aebe3422e77d14d37077be1f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23758 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" % (self.distribution.get_contact(), + self.distribution.get_contact_email())) + self.ensure_string('packager') + self.ensure_string_list('doc_files') + if isinstance(self.doc_files, list): + for readme in ('README', 'README.txt'): + if os.path.exists(readme) and readme not in self.doc_files: + self.doc_files.append(readme) + + self.ensure_string('release', "1") + self.ensure_string('serial') # should it be an int? + + self.ensure_string('distribution_name') + + self.ensure_string('changelog') + # Format changelog correctly + self.changelog = self._format_changelog(self.changelog) + + self.ensure_filename('icon') + + self.ensure_filename('prep_script') + self.ensure_filename('build_script') + self.ensure_filename('install_script') + self.ensure_filename('clean_script') + self.ensure_filename('verify_script') + self.ensure_filename('pre_install') + self.ensure_filename('post_install') + self.ensure_filename('pre_uninstall') + self.ensure_filename('post_uninstall') + + # XXX don't forget we punted on summaries and descriptions -- they + # should be handled here eventually! + + # Now *this* is some meta-data that belongs in the setup script... + self.ensure_string_list('provides') + self.ensure_string_list('requires') + self.ensure_string_list('conflicts') + self.ensure_string_list('build_requires') + self.ensure_string_list('obsoletes') + + self.ensure_string('force_arch') + # finalize_package_data () + + + def run (self): + + if DEBUG: + print "before _get_package_data():" + print "vendor =", self.vendor + print "packager =", self.packager + print "doc_files =", self.doc_files + print "changelog =", self.changelog + + # make directories + if self.spec_only: + spec_dir = self.dist_dir + self.mkpath(spec_dir) + else: + rpm_dir = {} + for d in ('SOURCES', 'SPECS', 'BUILD', 'RPMS', 'SRPMS'): + rpm_dir[d] = os.path.join(self.rpm_base, d) + self.mkpath(rpm_dir[d]) + spec_dir = rpm_dir['SPECS'] + + # Spec file goes into 'dist_dir' if '--spec-only specified', + # build/rpm. otherwise. + spec_path = os.path.join(spec_dir, + "%s.spec" % self.distribution.get_name()) + self.execute(write_file, + (spec_path, + self._make_spec_file()), + "writing '%s'" % spec_path) + + if self.spec_only: # stop if requested + return + + # Make a source distribution and copy to SOURCES directory with + # optional icon. + saved_dist_files = self.distribution.dist_files[:] + sdist = self.reinitialize_command('sdist') + if self.use_bzip2: + sdist.formats = ['bztar'] + else: + sdist.formats = ['gztar'] + self.run_command('sdist') + self.distribution.dist_files = saved_dist_files + + source = sdist.get_archive_files()[0] + source_dir = rpm_dir['SOURCES'] + self.copy_file(source, source_dir) + + if self.icon: + if os.path.exists(self.icon): + self.copy_file(self.icon, source_dir) + else: + raise DistutilsFileError, \ + "icon file '%s' does not exist" % self.icon + + + # build package + log.info("building RPMs") + rpm_cmd = ['rpm'] + if os.path.exists('/usr/bin/rpmbuild') or \ + os.path.exists('/bin/rpmbuild'): + rpm_cmd = ['rpmbuild'] + + if self.source_only: # what kind of RPMs? + rpm_cmd.append('-bs') + elif self.binary_only: + rpm_cmd.append('-bb') + else: + rpm_cmd.append('-ba') + if self.rpm3_mode: + rpm_cmd.extend(['--define', + '_topdir %s' % os.path.abspath(self.rpm_base)]) + if not self.keep_temp: + rpm_cmd.append('--clean') + + if self.quiet: + rpm_cmd.append('--quiet') + + rpm_cmd.append(spec_path) + # Determine the binary rpm names that should be built out of this spec + # file + # Note that some of these may not be really built (if the file + # list is empty) + nvr_string = "%{name}-%{version}-%{release}" + src_rpm = nvr_string + ".src.rpm" + non_src_rpm = "%{arch}/" + nvr_string + ".%{arch}.rpm" + q_cmd = r"rpm -q --qf '%s %s\n' --specfile '%s'" % ( + src_rpm, non_src_rpm, spec_path) + + out = os.popen(q_cmd) + try: + binary_rpms = [] + source_rpm = None + while 1: + line = out.readline() + if not line: + break + l = string.split(string.strip(line)) + assert(len(l) == 2) + binary_rpms.append(l[1]) + # The source rpm is named after the first entry in the spec file + if source_rpm is None: + source_rpm = l[0] + + status = out.close() + if status: + raise DistutilsExecError("Failed to execute: %s" % repr(q_cmd)) + + finally: + out.close() + + self.spawn(rpm_cmd) + + if not self.dry_run: + if self.distribution.has_ext_modules(): + pyversion = get_python_version() + else: + pyversion = 'any' + + if not self.binary_only: + srpm = os.path.join(rpm_dir['SRPMS'], source_rpm) + assert(os.path.exists(srpm)) + self.move_file(srpm, self.dist_dir) + filename = os.path.join(self.dist_dir, source_rpm) + self.distribution.dist_files.append( + ('bdist_rpm', pyversion, filename)) + + if not self.source_only: + for rpm in binary_rpms: + rpm = os.path.join(rpm_dir['RPMS'], rpm) + if os.path.exists(rpm): + self.move_file(rpm, self.dist_dir) + filename = os.path.join(self.dist_dir, + os.path.basename(rpm)) + self.distribution.dist_files.append( + ('bdist_rpm', pyversion, filename)) + # run() + + def _dist_path(self, path): + return os.path.join(self.dist_dir, os.path.basename(path)) + + def _make_spec_file(self): + """Generate the text of an RPM spec file and return it as a + list of strings (one per line). + """ + # definitions and headers + spec_file = [ + '%define name ' + self.distribution.get_name(), + '%define version ' + self.distribution.get_version().replace('-','_'), + '%define unmangled_version ' + self.distribution.get_version(), + '%define release ' + self.release.replace('-','_'), + '', + 'Summary: ' + self.distribution.get_description(), + ] + + # put locale summaries into spec file + # XXX not supported for now (hard to put a dictionary + # in a config file -- arg!) + #for locale in self.summaries.keys(): + # spec_file.append('Summary(%s): %s' % (locale, + # self.summaries[locale])) + + spec_file.extend([ + 'Name: %{name}', + 'Version: %{version}', + 'Release: %{release}',]) + + # XXX yuck! this filename is available from the "sdist" command, + # but only after it has run: and we create the spec file before + # running "sdist", in case of --spec-only. + if self.use_bzip2: + spec_file.append('Source0: %{name}-%{unmangled_version}.tar.bz2') + else: + spec_file.append('Source0: %{name}-%{unmangled_version}.tar.gz') + + spec_file.extend([ + 'License: ' + self.distribution.get_license(), + 'Group: ' + self.group, + 'BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot', + 'Prefix: %{_prefix}', ]) + + if not self.force_arch: + # noarch if no extension modules + if not self.distribution.has_ext_modules(): + spec_file.append('BuildArch: noarch') + else: + spec_file.append( 'BuildArch: %s' % self.force_arch ) + + for field in ('Vendor', + 'Packager', + 'Provides', + 'Requires', + 'Conflicts', + 'Obsoletes', + ): + val = getattr(self, string.lower(field)) + if isinstance(val, list): + spec_file.append('%s: %s' % (field, string.join(val))) + elif val is not None: + spec_file.append('%s: %s' % (field, val)) + + + if self.distribution.get_url() != 'UNKNOWN': + spec_file.append('Url: ' + self.distribution.get_url()) + + if self.distribution_name: + spec_file.append('Distribution: ' + self.distribution_name) + + if self.build_requires: + spec_file.append('BuildRequires: ' + + string.join(self.build_requires)) + + if self.icon: + spec_file.append('Icon: ' + os.path.basename(self.icon)) + + if self.no_autoreq: + spec_file.append('AutoReq: 0') + + spec_file.extend([ + '', + '%description', + self.distribution.get_long_description() + ]) + + # put locale descriptions into spec file + # XXX again, suppressed because config file syntax doesn't + # easily support this ;-( + #for locale in self.descriptions.keys(): + # spec_file.extend([ + # '', + # '%description -l ' + locale, + # self.descriptions[locale], + # ]) + + # rpm scripts + # figure out default build script + def_setup_call = "%s %s" % (self.python,os.path.basename(sys.argv[0])) + def_build = "%s build" % def_setup_call + if self.use_rpm_opt_flags: + def_build = 'env CFLAGS="$RPM_OPT_FLAGS" ' + def_build + + # insert contents of files + + # XXX this is kind of misleading: user-supplied options are files + # that we open and interpolate into the spec file, but the defaults + # are just text that we drop in as-is. Hmmm. + + install_cmd = ('%s install -O1 --root=$RPM_BUILD_ROOT ' + '--record=INSTALLED_FILES') % def_setup_call + + script_options = [ + ('prep', 'prep_script', "%setup -n %{name}-%{unmangled_version}"), + ('build', 'build_script', def_build), + ('install', 'install_script', install_cmd), + ('clean', 'clean_script', "rm -rf $RPM_BUILD_ROOT"), + ('verifyscript', 'verify_script', None), + ('pre', 'pre_install', None), + ('post', 'post_install', None), + ('preun', 'pre_uninstall', None), + ('postun', 'post_uninstall', None), + ] + + for (rpm_opt, attr, default) in script_options: + # Insert contents of file referred to, if no file is referred to + # use 'default' as contents of script + val = getattr(self, attr) + if val or default: + spec_file.extend([ + '', + '%' + rpm_opt,]) + if val: + spec_file.extend(string.split(open(val, 'r').read(), '\n')) + else: + spec_file.append(default) + + + # files section + spec_file.extend([ + '', + '%files -f INSTALLED_FILES', + '%defattr(-,root,root)', + ]) + + if self.doc_files: + spec_file.append('%doc ' + string.join(self.doc_files)) + + if self.changelog: + spec_file.extend([ + '', + '%changelog',]) + spec_file.extend(self.changelog) + + return spec_file + + # _make_spec_file () + + def _format_changelog(self, changelog): + """Format the changelog correctly and convert it to a list of strings + """ + if not changelog: + return changelog + new_changelog = [] + for line in string.split(string.strip(changelog), '\n'): + line = string.strip(line) + if line[0] == '*': + new_changelog.extend(['', line]) + elif line[0] == '-': + new_changelog.append(line) + else: + new_changelog.append(' ' + line) + + # strip trailing newline inserted by first changelog entry + if not new_changelog[0]: + del new_changelog[0] + + return new_changelog + + # _format_changelog() + +# class bdist_rpm diff --git a/PythonHome/Lib/distutils/command/bdist_rpm.pyc b/PythonHome/Lib/distutils/command/bdist_rpm.pyc deleted file mode 100644 index 80da0eb98c0a0bae6ab8635e44e7a7cde062eaea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17601 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 cur_version: + bv = get_build_version() + else: + if self.target_version < "2.4": + bv = 6.0 + else: + bv = 7.1 + else: + # for current version - use authoritative check. + bv = get_build_version() + + # wininst-x.y.exe is in the same directory as this file + directory = os.path.dirname(__file__) + # we must use a wininst-x.y.exe built with the same C compiler + # used for python. XXX What about mingw, borland, and so on? + + # if plat_name starts with "win" but is not "win32" + # we want to strip "win" and leave the rest (e.g. -amd64) + # for all other cases, we don't want any suffix + if self.plat_name != 'win32' and self.plat_name[:3] == 'win': + sfix = self.plat_name[3:] + else: + sfix = '' + + filename = os.path.join(directory, "wininst-%.1f%s.exe" % (bv, sfix)) + f = open(filename, "rb") + try: + return f.read() + finally: + f.close() +# class bdist_wininst diff --git a/PythonHome/Lib/distutils/command/bdist_wininst.pyc b/PythonHome/Lib/distutils/command/bdist_wininst.pyc deleted file mode 100644 index 2b1d9e8c085e0bbc9633ee5bde561c39f19cedbf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10650 zcmd5?OLH98bv`|V*9-yTB?6R4i7lBBhLQ#}DLPJM!lp>uRZJvAX-J|BQEB&dUjPHl zbPxOXkOT#mE21ikxV%b!h!@^C+bpt3XbGrvaMp}q=D#38>+~>Kk zbH4MqtpCSc^H+C%x*bdTSI6%SeC;ohBqBRVJ=yUjsYz0oUQKq8arwIJ)T{i2>`Z8W zLVAG-h%WOWoHrPrkEMo#gb0Rmm*I@ezLQ~#cj7{x$;L`dDj-hqT90@an|ogX|mB_ zRrsKrc2iq4o45Oep6Q#kuzs;`{2x~R{q?6huKVTqcl2 zlQ)#ix^i2R4M{Fb@@+}3NODz@wd+h)kAuJ7B#mRU!kNbUTgu zX0sqC4D9!qmdEe2!7no3^gAZOYWzKunjCDF_`BVnVYBsHiP?>Yz2Y5z&0ew%j6XDH z(B^uS=Ape@*69)k)(n%ZU24pv|2m_9{rS=;uZ&$mRw&3>ag!MgA|0El{|epv&GKa+j2A${E`>&bxzR z(|*VuM^<^7TPoWff4WXwcgOhoFm+7&R2R(DF__Qzi5YLO%OE_+O~vq|2|q{ukB7b9 zk$-O(^}wQILd6Aub#-ZDvz8M?DI^=LXCVeB7m{rF{)hWrTMbJM2$E5;WJoUW?x~9> zV&h`-b`;0P+IF0!MV|FG?cbrnNzIY}F<2#9xBf@(-tzaMrg}Wqw!fZcsaeO7s^D*? z*{Ja?e?1x&+4?4VhNHT>m3V!i%B4D3?iObT1x5DCEe4_-oAu48_aHj5%5)$Q6PEa; znz_ZL9U%eKAB%*F`OEer#C91Vw#xvqT?TONGJtEB z0r(44IG3^2MIx=!NQw!TaT*0h(Wxp3pOy%tAu&=*1jSH6(E&{804A&e#=%5YTgiQ) zlPJPfYPp!fOuWjF6H&~Z>=u*As>Bsk50r~gr9x?xJQ+HsQjHI;4421KH&I$Xb=z`rJnUGtA7PAI0E;6fP(-JG~`K5JeHLq4re6)nKsuY4>U7TWhUhSeBj9w zPaZ3O98AcuC*g#ojv|;tTMuUBaZPY@2TeIRCC6$~Vj9PGW#?J3|3FiNm9rIvy3FSP zuCrpYIT|1+;tr5`T-W+p$$wL3j_Y!WRsKebc^WJz!f;&qqNc>O_X%OQS+M9Sc~W=# zUBJG)hd-`nTa+JuwkD5tK?e)f>X+mgc918BHOW`J5ALma_;-gB&gj5}YC>gj+F)DC zOL~F9izpY=5T$KeAS?EL)+$?88r6@Z6mSka1K_Mdo{7Bxo%MG61hLnBck6zCXcd`C z^=y)WhGIa`P^NmCFa7m3yRKlit2P4g%<-{Rc^s()$M4S+U6*m8vEv2TOz9oTs~Rz* zQj0=S&|a`Gkzt}3C{vSE{2MHwC7>aqN2OaRc!=X@i^F!7Z7CdK);Um;w02cDLn0Dl z0YyjU*NG2RQbEkgtU}EoD)u#Vkag35i&E12kqynmBJ5|$5Q-r{y##e8lq|iz^1u{5 zDn-|#Km{)|xxnOgcBaj3_hGt^0EZakhO5+T^36n_XH;!-ba1444T*RQwRvx;zU0l< zmb`PdhBsS#5m0c}tK&0=QUkx!^@g|Xo%3dDtW`+hN=K0J&p0LUCLsW<4w<^H%w3a% zIz$lyH?a z9{#x`uK-1E%Ht_1&dR}ya?Cx;W2_b1n^zQh;2qWcT`?WqFN}3Z-^~OIUzMIO{a58N zy!K<9E1(s(fx$S%*R<%asjKMUy49vad_qrYUfn8(2 zH-g#H$bhj9+qLo{{kO0BL^;@9eFyk7sue6s_*Ipi!=CLHp&fQgc(PsEV`>8x3?JS>?;F^62umbKe!OquL)d&U%x$-hPU;_Qtl9ROEm+22op~_K%_xt> zRr!68fteV*iM|SeNmN8?TwlJO#=T);E?-omNDVFme6=h~@F@#4Utz^#PHMCdJ_>&H z-tC(j32`P4k*UV$tg`W`K<Rb<^Jf)H8bQ;%J@{zVyCaTjyr_uVZh3R+_ z`r&}m-451}57wDbdjyw|I4wt(3suXh0j)*ex#}FmD$+e=&Ea4G(t1Ruh>9W)2>iO- zZn~QR84(3aEtuy-ohl7nJO=6!;u>_}yk1^XaGfNonA0wNG36ar^rJ%)mO%zxrwh+O z$C_Xj?W$n4L3vKSF`X{LI-$U6%uuzLYzKpyU6ef6t-h%CcY(Bk#(zLHAKXCFqGEGu z`6_eQn5eGjDXU>p*-d$H1y#DeLvy4@bwBD2%f0bb%3bIgk7Q%CS)M3*XoK27N9B$2 znx4bR4?e^&MmX&*33&7Rse7}~-V3!e-Yh=U@AJ^ zPkGbcsoJvFoLH+hYt4xTj3TYs+KQ%A-jcUmTkz&UCng+`%_$$Z@U{PmnmyS(knH{f$vPNa2szkmi`TJfu#HsA&$pmOW zC3(MUhXtWEqXnQeD}ygo!6C114^0Ml>btA(B|-5 zn5xHw-q7H%bkv}Mwsr)e&dbH|ps_)iAJ}&d4mu6qEp-7th36d+ML!E(C0CG5nlV#; ziICg)st%zsqRayBaQC_0BGzxYL6)L*ItQwCV#lFV3GzI~q!V*I@`~eWw z1*#vXYE!j9#T>y7SI7hFW$9ixeyH3XP+ZlG-a6wdxTP-MRp76wZxzrx45(BUp@Z|x zon`Vd5>-$L__`1fb%m}^aXQv|9)DPQT4AV~vBgTof9;5%8(g}Kb$`VK$R8j+vqf#2Re?O0+5D0ul(e zD5?VoXmz*-moFCx4FOoO0FcR{a4!(&Q1AiV(3qbf?yx8FK%Yw`(vXFxidL6b2cVAE;p5iWUBolGow z8g7%@&b;K8DCXRYMq@CnTr`jleVVe$_bQInifXJ|t11@{3Iu@Z6cjh=R1SP1>=F)+ z>xva|Lt5a364^y+u-d;ePO4l;pVzld@lM4q2ULfaeE& zrgi35jQXI%M6JG`u^Z{fyL%Li@yIG{JOx)y;sUbTL#$jQ_vDr`EuwTYB#RM zxj4@$vB4*x@Oymq?M7fIE!1FUd5bj~So5_hjz7!Qn;rv)taSeI5@&D?p4EaTE$X}i*i`I&K%E6QS&5%sH)ptpx)gt(B*lL zm0bB9z?9{>q(;=Md*^X@E6(nmLG1|7PM3IABcAmk^bjma4)6qL!Se&6^vevk%qZ1( z5mD;*cslG~mwWfio(W>aIQT??OY4DJ4EX?-s?Ojnz#&XduqV+5NQvoST}|mM|5z2L z#YY^9k>Iha3j`QoVWYHbNeQ%ZwLl$Q^Q2l|yeZH}6}l?K0a_oyh@GZwh&6BD0f?|P z%aZrWGmzr!Btik@)v4xE_uD#ZuWnqUX2ajv8+*I@cm783ZIm@&pt6r}h_mHrR+Ith z_S(jkUB@W_JrDJs)B_vo+l{`xAD6ys9{fEz1^7P8MJm~FcU6peuc3NvP|94i2bh;vE=f1uHfw+5_S0J#v-G>TzBj1olUc zx5%j%kwHwg0nwhI$21S2Za`lzO}_>oY^rtv9#q{sUE5MQQBzri&H9MEWv^f~UF2`{ zp9vf(p3})wcX{9e5%GCm&K*tO^a;(%h772m{=nCBN1p&qM$z2|G*7h;s5Y$-K~y30iBs=AK174pS`fVcWj4uguXCTZ!#<&lK_8E`{fIlaw26!y)^fh zXEgxX$+Dh_($VA2D;&eHOaasckT!*HQ`6}( zWi7tiTIN}<>hMm{n550qSZcHy+l?!;-))?B?|qyg43jLzad5+7n49}B9`WDf!r)z0 zxM(J)S7=9k7D4&l?w)EEH4IPGPmKQ;5)j-qpng&heGt+i)X<;$peJpH|9#H7N4yEn vNAJ!>JqZFQ9hHC@MO^bAa;mC~uDdtH?{iLd$a%VS;%HGWcndImkk' under the base build directory. We only use one of + # them for a given distribution, though -- + if self.build_purelib is None: + self.build_purelib = os.path.join(self.build_base, 'lib') + if self.build_platlib is None: + self.build_platlib = os.path.join(self.build_base, + 'lib' + plat_specifier) + + # 'build_lib' is the actual directory that we will use for this + # particular module distribution -- if user didn't supply it, pick + # one of 'build_purelib' or 'build_platlib'. + if self.build_lib is None: + if self.distribution.ext_modules: + self.build_lib = self.build_platlib + else: + self.build_lib = self.build_purelib + + # 'build_temp' -- temporary directory for compiler turds, + # "build/temp." + if self.build_temp is None: + self.build_temp = os.path.join(self.build_base, + 'temp' + plat_specifier) + if self.build_scripts is None: + self.build_scripts = os.path.join(self.build_base, + 'scripts-' + sys.version[0:3]) + + if self.executable is None: + self.executable = os.path.normpath(sys.executable) + + def run(self): + # Run all relevant sub-commands. This will be some subset of: + # - build_py - pure Python modules + # - build_clib - standalone C libraries + # - build_ext - Python extensions + # - build_scripts - (Python) scripts + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + # -- Predicates for the sub-command list --------------------------- + + def has_pure_modules (self): + return self.distribution.has_pure_modules() + + def has_c_libraries (self): + return self.distribution.has_c_libraries() + + def has_ext_modules (self): + return self.distribution.has_ext_modules() + + def has_scripts (self): + return self.distribution.has_scripts() + + sub_commands = [('build_py', has_pure_modules), + ('build_clib', has_c_libraries), + ('build_ext', has_ext_modules), + ('build_scripts', has_scripts), + ] diff --git a/PythonHome/Lib/distutils/command/build.pyc b/PythonHome/Lib/distutils/command/build.pyc deleted file mode 100644 index a3fd3248108a2d4abd787245b302d25cbc613943..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5097 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 GOaB7&o1`ZI diff --git a/PythonHome/Lib/distutils/command/build_ext.py b/PythonHome/Lib/distutils/command/build_ext.py new file mode 100644 index 0000000000..f0a7d4cafd --- /dev/null +++ b/PythonHome/Lib/distutils/command/build_ext.py @@ -0,0 +1,766 @@ +"""distutils.command.build_ext + +Implements the Distutils 'build_ext' command, for building extension +modules (currently limited to C extensions, should accommodate C++ +extensions ASAP).""" + +# This module should be kept compatible with Python 2.1. + +__revision__ = "$Id$" + +import sys, os, string, re +from types import * +from site import USER_BASE, USER_SITE +from distutils.core import Command +from distutils.errors import * +from distutils.sysconfig import customize_compiler, get_python_version +from distutils.dep_util import newer_group +from distutils.extension import Extension +from distutils.util import get_platform +from distutils import log + +if os.name == 'nt': + from distutils.msvccompiler import get_build_version + MSVC_VERSION = int(get_build_version()) + +# An extension name is just a dot-separated list of Python NAMEs (ie. +# the same as a fully-qualified module name). +extension_name_re = re.compile \ + (r'^[a-zA-Z_][a-zA-Z_0-9]*(\.[a-zA-Z_][a-zA-Z_0-9]*)*$') + + +def show_compilers (): + from distutils.ccompiler import show_compilers + show_compilers() + + +class build_ext (Command): + + description = "build C/C++ extensions (compile/link to build directory)" + + # XXX thoughts on how to deal with complex command-line options like + # these, i.e. how to make it so fancy_getopt can suck them off the + # command line and make it look like setup.py defined the appropriate + # lists of tuples of what-have-you. + # - each command needs a callback to process its command-line options + # - Command.__init__() needs access to its share of the whole + # command line (must ultimately come from + # Distribution.parse_command_line()) + # - it then calls the current command class' option-parsing + # callback to deal with weird options like -D, which have to + # parse the option text and churn out some custom data + # structure + # - that data structure (in this case, a list of 2-tuples) + # will then be present in the command object by the time + # we get to finalize_options() (i.e. the constructor + # takes care of both command-line and client options + # in between initialize_options() and finalize_options()) + + sep_by = " (separated by '%s')" % os.pathsep + user_options = [ + ('build-lib=', 'b', + "directory for compiled extension modules"), + ('build-temp=', 't', + "directory for temporary files (build by-products)"), + ('plat-name=', 'p', + "platform name to cross-compile for, if supported " + "(default: %s)" % get_platform()), + ('inplace', 'i', + "ignore build-lib and put compiled extensions into the source " + + "directory alongside your pure Python modules"), + ('include-dirs=', 'I', + "list of directories to search for header files" + sep_by), + ('define=', 'D', + "C preprocessor macros to define"), + ('undef=', 'U', + "C preprocessor macros to undefine"), + ('libraries=', 'l', + "external C libraries to link with"), + ('library-dirs=', 'L', + "directories to search for external C libraries" + sep_by), + ('rpath=', 'R', + "directories to search for shared C libraries at runtime"), + ('link-objects=', 'O', + "extra explicit link objects to include in the link"), + ('debug', 'g', + "compile/link with debugging information"), + ('force', 'f', + "forcibly build everything (ignore file timestamps)"), + ('compiler=', 'c', + "specify the compiler type"), + ('swig-cpp', None, + "make SWIG create C++ files (default is C)"), + ('swig-opts=', None, + "list of SWIG command line options"), + ('swig=', None, + "path to the SWIG executable"), + ('user', None, + "add user include, library and rpath"), + ] + + boolean_options = ['inplace', 'debug', 'force', 'swig-cpp', 'user'] + + help_options = [ + ('help-compiler', None, + "list available compilers", show_compilers), + ] + + def initialize_options (self): + self.extensions = None + self.build_lib = None + self.plat_name = None + self.build_temp = None + self.inplace = 0 + self.package = None + + self.include_dirs = None + self.define = None + self.undef = None + self.libraries = None + self.library_dirs = None + self.rpath = None + self.link_objects = None + self.debug = None + self.force = None + self.compiler = None + self.swig = None + self.swig_cpp = None + self.swig_opts = None + self.user = None + + def finalize_options(self): + from distutils import sysconfig + + self.set_undefined_options('build', + ('build_lib', 'build_lib'), + ('build_temp', 'build_temp'), + ('compiler', 'compiler'), + ('debug', 'debug'), + ('force', 'force'), + ('plat_name', 'plat_name'), + ) + + if self.package is None: + self.package = self.distribution.ext_package + + self.extensions = self.distribution.ext_modules + + # Make sure Python's include directories (for Python.h, pyconfig.h, + # etc.) are in the include search path. + py_include = sysconfig.get_python_inc() + plat_py_include = sysconfig.get_python_inc(plat_specific=1) + if self.include_dirs is None: + self.include_dirs = self.distribution.include_dirs or [] + if isinstance(self.include_dirs, str): + self.include_dirs = self.include_dirs.split(os.pathsep) + + # Put the Python "system" include dir at the end, so that + # any local include dirs take precedence. + self.include_dirs.append(py_include) + if plat_py_include != py_include: + self.include_dirs.append(plat_py_include) + + self.ensure_string_list('libraries') + + # Life is easier if we're not forever checking for None, so + # simplify these options to empty lists if unset + if self.libraries is None: + self.libraries = [] + if self.library_dirs is None: + self.library_dirs = [] + elif type(self.library_dirs) is StringType: + self.library_dirs = string.split(self.library_dirs, os.pathsep) + + if self.rpath is None: + self.rpath = [] + elif type(self.rpath) is StringType: + self.rpath = string.split(self.rpath, os.pathsep) + + # for extensions under windows use different directories + # for Release and Debug builds. + # also Python's library directory must be appended to library_dirs + if os.name == 'nt': + # the 'libs' directory is for binary installs - we assume that + # must be the *native* platform. But we don't really support + # cross-compiling via a binary install anyway, so we let it go. + self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs')) + if self.debug: + self.build_temp = os.path.join(self.build_temp, "Debug") + else: + self.build_temp = os.path.join(self.build_temp, "Release") + + # Append the source distribution include and library directories, + # this allows distutils on windows to work in the source tree + self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC')) + if MSVC_VERSION == 9: + # Use the .lib files for the correct architecture + if self.plat_name == 'win32': + suffix = '' + else: + # win-amd64 or win-ia64 + suffix = self.plat_name[4:] + new_lib = os.path.join(sys.exec_prefix, 'PCbuild') + if suffix: + new_lib = os.path.join(new_lib, suffix) + self.library_dirs.append(new_lib) + + elif MSVC_VERSION == 8: + self.library_dirs.append(os.path.join(sys.exec_prefix, + 'PC', 'VS8.0')) + elif MSVC_VERSION == 7: + self.library_dirs.append(os.path.join(sys.exec_prefix, + 'PC', 'VS7.1')) + else: + self.library_dirs.append(os.path.join(sys.exec_prefix, + 'PC', 'VC6')) + + # OS/2 (EMX) doesn't support Debug vs Release builds, but has the + # import libraries in its "Config" subdirectory + if os.name == 'os2': + self.library_dirs.append(os.path.join(sys.exec_prefix, 'Config')) + + # for extensions under Cygwin and AtheOS Python's library directory must be + # appended to library_dirs + if sys.platform[:6] == 'cygwin' or sys.platform[:6] == 'atheos': + if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")): + # building third party extensions + self.library_dirs.append(os.path.join(sys.prefix, "lib", + "python" + get_python_version(), + "config")) + else: + # building python standard extensions + self.library_dirs.append('.') + + # 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 sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")): + # building third party extensions + self.library_dirs.append(sysconfig.get_config_var('LIBDIR')) + else: + # building python standard extensions + self.library_dirs.append('.') + + # The argument parsing will result in self.define being a string, but + # it has to be a list of 2-tuples. All the preprocessor symbols + # specified by the 'define' option will be set to '1'. Multiple + # symbols can be separated with commas. + + if self.define: + defines = self.define.split(',') + self.define = map(lambda symbol: (symbol, '1'), defines) + + # The option for macros to undefine is also a string from the + # option parsing, but has to be a list. Multiple symbols can also + # be separated with commas here. + if self.undef: + self.undef = self.undef.split(',') + + if self.swig_opts is None: + self.swig_opts = [] + else: + self.swig_opts = self.swig_opts.split(' ') + + # Finally add the user include and library directories if requested + if self.user: + user_include = os.path.join(USER_BASE, "include") + user_lib = os.path.join(USER_BASE, "lib") + if os.path.isdir(user_include): + self.include_dirs.append(user_include) + if os.path.isdir(user_lib): + self.library_dirs.append(user_lib) + self.rpath.append(user_lib) + + def run(self): + from distutils.ccompiler import new_compiler + + # 'self.extensions', as supplied by setup.py, is a list of + # Extension instances. See the documentation for Extension (in + # distutils.extension) for details. + # + # For backwards compatibility with Distutils 0.8.2 and earlier, we + # also allow the 'extensions' list to be a list of tuples: + # (ext_name, build_info) + # where build_info is a dictionary containing everything that + # Extension instances do except the name, with a few things being + # differently named. We convert these 2-tuples to Extension + # instances as needed. + + if not self.extensions: + return + + # If we were asked to build any C/C++ libraries, make sure that the + # directory where we put them is in the library search path for + # linking extensions. + if self.distribution.has_c_libraries(): + build_clib = self.get_finalized_command('build_clib') + self.libraries.extend(build_clib.get_library_names() or []) + self.library_dirs.append(build_clib.build_clib) + + # Setup the CCompiler object that we'll use to do all the + # compiling and linking + self.compiler = new_compiler(compiler=self.compiler, + verbose=self.verbose, + dry_run=self.dry_run, + force=self.force) + customize_compiler(self.compiler) + # If we are cross-compiling, init the compiler now (if we are not + # cross-compiling, init would not hurt, but people may rely on + # late initialization of compiler even if they shouldn't...) + if os.name == 'nt' and self.plat_name != get_platform(): + self.compiler.initialize(self.plat_name) + + # And make sure that any compile/link-related options (which might + # come from the command-line or from the setup script) are set in + # that CCompiler object -- that way, they automatically apply to + # all compiling and linking done here. + if self.include_dirs is not None: + self.compiler.set_include_dirs(self.include_dirs) + if self.define is not None: + # 'define' option is a list of (name,value) tuples + for (name, value) in self.define: + self.compiler.define_macro(name, value) + if self.undef is not None: + for macro in self.undef: + self.compiler.undefine_macro(macro) + if self.libraries is not None: + self.compiler.set_libraries(self.libraries) + if self.library_dirs is not None: + self.compiler.set_library_dirs(self.library_dirs) + if self.rpath is not None: + self.compiler.set_runtime_library_dirs(self.rpath) + if self.link_objects is not None: + self.compiler.set_link_objects(self.link_objects) + + # Now actually compile and link everything. + self.build_extensions() + + def check_extensions_list(self, extensions): + """Ensure that the list of extensions (presumably provided as a + command option 'extensions') is valid, i.e. it is a list of + Extension objects. We also support the old-style list of 2-tuples, + where the tuples are (ext_name, build_info), which are converted to + Extension instances here. + + Raise DistutilsSetupError if the structure is invalid anywhere; + just returns otherwise. + """ + if not isinstance(extensions, list): + raise DistutilsSetupError, \ + "'ext_modules' option must be a list of Extension instances" + + for i, ext in enumerate(extensions): + if isinstance(ext, Extension): + continue # OK! (assume type-checking done + # by Extension constructor) + + if not isinstance(ext, tuple) or len(ext) != 2: + raise DistutilsSetupError, \ + ("each element of 'ext_modules' option must be an " + "Extension instance or 2-tuple") + + ext_name, build_info = ext + + log.warn(("old-style (ext_name, build_info) tuple found in " + "ext_modules for extension '%s'" + "-- please convert to Extension instance" % ext_name)) + + if not (isinstance(ext_name, str) and + extension_name_re.match(ext_name)): + raise DistutilsSetupError, \ + ("first element of each tuple in 'ext_modules' " + "must be the extension name (a string)") + + if not isinstance(build_info, dict): + raise DistutilsSetupError, \ + ("second element of each tuple in 'ext_modules' " + "must be a dictionary (build info)") + + # OK, the (ext_name, build_info) dict is type-safe: convert it + # to an Extension instance. + ext = Extension(ext_name, build_info['sources']) + + # Easy stuff: one-to-one mapping from dict elements to + # instance attributes. + for key in ('include_dirs', 'library_dirs', 'libraries', + 'extra_objects', 'extra_compile_args', + 'extra_link_args'): + val = build_info.get(key) + if val is not None: + setattr(ext, key, val) + + # Medium-easy stuff: same syntax/semantics, different names. + ext.runtime_library_dirs = build_info.get('rpath') + if 'def_file' in build_info: + log.warn("'def_file' element of build info dict " + "no longer supported") + + # Non-trivial stuff: 'macros' split into 'define_macros' + # and 'undef_macros'. + macros = build_info.get('macros') + if macros: + ext.define_macros = [] + ext.undef_macros = [] + for macro in macros: + if not (isinstance(macro, tuple) and len(macro) in (1, 2)): + raise DistutilsSetupError, \ + ("'macros' element of build info dict " + "must be 1- or 2-tuple") + if len(macro) == 1: + ext.undef_macros.append(macro[0]) + elif len(macro) == 2: + ext.define_macros.append(macro) + + extensions[i] = ext + + def get_source_files(self): + self.check_extensions_list(self.extensions) + filenames = [] + + # Wouldn't it be neat if we knew the names of header files too... + for ext in self.extensions: + filenames.extend(ext.sources) + + return filenames + + def get_outputs(self): + # Sanity check the 'extensions' list -- can't assume this is being + # done in the same run as a 'build_extensions()' call (in fact, we + # can probably assume that it *isn't*!). + self.check_extensions_list(self.extensions) + + # And build the list of output (built) filenames. Note that this + # ignores the 'inplace' flag, and assumes everything goes in the + # "build" tree. + outputs = [] + for ext in self.extensions: + outputs.append(self.get_ext_fullpath(ext.name)) + return outputs + + def build_extensions(self): + # First, sanity-check the 'extensions' list + self.check_extensions_list(self.extensions) + + for ext in self.extensions: + self.build_extension(ext) + + def build_extension(self, ext): + sources = ext.sources + if sources is None or type(sources) not in (ListType, TupleType): + raise DistutilsSetupError, \ + ("in 'ext_modules' option (extension '%s'), " + + "'sources' must be present and must be " + + "a list of source filenames") % ext.name + sources = list(sources) + + ext_path = self.get_ext_fullpath(ext.name) + depends = sources + ext.depends + if not (self.force or newer_group(depends, ext_path, 'newer')): + log.debug("skipping '%s' extension (up-to-date)", ext.name) + return + else: + log.info("building '%s' extension", ext.name) + + # First, scan the sources for SWIG definition files (.i), run + # SWIG on 'em to create .c files, and modify the sources list + # accordingly. + sources = self.swig_sources(sources, ext) + + # Next, compile the source code to object files. + + # XXX not honouring 'define_macros' or 'undef_macros' -- the + # CCompiler API needs to change to accommodate this, and I + # want to do one thing at a time! + + # Two possible sources for extra compiler arguments: + # - 'extra_compile_args' in Extension object + # - CFLAGS environment variable (not particularly + # elegant, but people seem to expect it and I + # guess it's useful) + # The environment variable should take precedence, and + # any sensible compiler will give precedence to later + # command line args. Hence we combine them in order: + extra_args = ext.extra_compile_args or [] + + macros = ext.define_macros[:] + for undef in ext.undef_macros: + macros.append((undef,)) + + objects = self.compiler.compile(sources, + output_dir=self.build_temp, + macros=macros, + include_dirs=ext.include_dirs, + debug=self.debug, + extra_postargs=extra_args, + depends=ext.depends) + + # XXX -- this is a Vile HACK! + # + # The setup.py script for Python on Unix needs to be able to + # get this list so it can perform all the clean up needed to + # avoid keeping object files around when cleaning out a failed + # build of an extension module. Since Distutils does not + # track dependencies, we have to get rid of intermediates to + # ensure all the intermediates will be properly re-built. + # + self._built_objects = objects[:] + + # Now link the object files together into a "shared object" -- + # of course, first we have to figure out all the other things + # that go into the mix. + if ext.extra_objects: + objects.extend(ext.extra_objects) + extra_args = ext.extra_link_args or [] + + # Detect target language, if not provided + language = ext.language or self.compiler.detect_language(sources) + + self.compiler.link_shared_object( + objects, ext_path, + libraries=self.get_libraries(ext), + library_dirs=ext.library_dirs, + runtime_library_dirs=ext.runtime_library_dirs, + extra_postargs=extra_args, + export_symbols=self.get_export_symbols(ext), + debug=self.debug, + build_temp=self.build_temp, + target_lang=language) + + + def swig_sources (self, sources, extension): + + """Walk the list of source files in 'sources', looking for SWIG + interface (.i) files. Run SWIG on all that are found, and + return a modified 'sources' list with SWIG source files replaced + by the generated C (or C++) files. + """ + + new_sources = [] + swig_sources = [] + swig_targets = {} + + # XXX this drops generated C/C++ files into the source tree, which + # is fine for developers who want to distribute the generated + # source -- but there should be an option to put SWIG output in + # the temp dir. + + if self.swig_cpp: + log.warn("--swig-cpp is deprecated - use --swig-opts=-c++") + + if self.swig_cpp or ('-c++' in self.swig_opts) or \ + ('-c++' in extension.swig_opts): + target_ext = '.cpp' + else: + target_ext = '.c' + + for source in sources: + (base, ext) = os.path.splitext(source) + if ext == ".i": # SWIG interface file + new_sources.append(base + '_wrap' + target_ext) + swig_sources.append(source) + swig_targets[source] = new_sources[-1] + else: + new_sources.append(source) + + if not swig_sources: + return new_sources + + swig = self.swig or self.find_swig() + swig_cmd = [swig, "-python"] + swig_cmd.extend(self.swig_opts) + if self.swig_cpp: + swig_cmd.append("-c++") + + # Do not override commandline arguments + if not self.swig_opts: + for o in extension.swig_opts: + swig_cmd.append(o) + + for source in swig_sources: + target = swig_targets[source] + log.info("swigging %s to %s", source, target) + self.spawn(swig_cmd + ["-o", target, source]) + + return new_sources + + # swig_sources () + + def find_swig (self): + """Return the name of the SWIG executable. On Unix, this is + just "swig" -- it should be in the PATH. Tries a bit harder on + Windows. + """ + + if os.name == "posix": + return "swig" + elif os.name == "nt": + + # Look for SWIG in its standard installation directory on + # Windows (or so I presume!). If we find it there, great; + # if not, act like Unix and assume it's in the PATH. + for vers in ("1.3", "1.2", "1.1"): + fn = os.path.join("c:\\swig%s" % vers, "swig.exe") + if os.path.isfile(fn): + return fn + else: + return "swig.exe" + + elif os.name == "os2": + # assume swig available in the PATH. + return "swig.exe" + + else: + raise DistutilsPlatformError, \ + ("I don't know how to find (much less run) SWIG " + "on platform '%s'") % os.name + + # find_swig () + + # -- Name generators ----------------------------------------------- + # (extension names, filenames, whatever) + def get_ext_fullpath(self, ext_name): + """Returns the path of the filename for a given extension. + + The file is located in `build_lib` or directly in the package + (inplace option). + """ + # makes sure the extension name is only using dots + all_dots = string.maketrans('/'+os.sep, '..') + ext_name = ext_name.translate(all_dots) + + fullname = self.get_ext_fullname(ext_name) + modpath = fullname.split('.') + filename = self.get_ext_filename(ext_name) + filename = os.path.split(filename)[-1] + + if not self.inplace: + # no further work needed + # returning : + # build_dir/package/path/filename + filename = os.path.join(*modpath[:-1]+[filename]) + return os.path.join(self.build_lib, filename) + + # the inplace option requires to find the package directory + # using the build_py command for that + package = '.'.join(modpath[0:-1]) + build_py = self.get_finalized_command('build_py') + package_dir = os.path.abspath(build_py.get_package_dir(package)) + + # returning + # package_dir/filename + return os.path.join(package_dir, filename) + + def get_ext_fullname(self, ext_name): + """Returns the fullname of a given extension name. + + Adds the `package.` prefix""" + if self.package is None: + return ext_name + else: + return self.package + '.' + ext_name + + def get_ext_filename(self, ext_name): + r"""Convert the name of an extension (eg. "foo.bar") into the name + of the file from which it will be loaded (eg. "foo/bar.so", or + "foo\bar.pyd"). + """ + from distutils.sysconfig import get_config_var + ext_path = string.split(ext_name, '.') + # OS/2 has an 8 character module (extension) limit :-( + if os.name == "os2": + ext_path[len(ext_path) - 1] = ext_path[len(ext_path) - 1][:8] + # extensions in debug_mode are named 'module_d.pyd' under windows + so_ext = get_config_var('SO') + if os.name == 'nt' and self.debug: + return os.path.join(*ext_path) + '_d' + so_ext + return os.path.join(*ext_path) + so_ext + + def get_export_symbols (self, ext): + """Return the list of symbols that a shared extension has to + export. This either uses 'ext.export_symbols' or, if it's not + provided, "init" + module_name. Only relevant on Windows, where + the .pyd file (DLL) must export the module "init" function. + """ + initfunc_name = "init" + ext.name.split('.')[-1] + if initfunc_name not in ext.export_symbols: + ext.export_symbols.append(initfunc_name) + return ext.export_symbols + + def get_libraries (self, ext): + """Return the list of libraries to link against when building a + shared extension. On most platforms, this is just 'ext.libraries'; + on Windows and OS/2, we add the Python library (eg. python20.dll). + """ + # The python library is always needed on Windows. For MSVC, this + # is redundant, since the library is mentioned in a pragma in + # pyconfig.h that MSVC groks. The other Windows compilers all seem + # to need it mentioned explicitly, though, so that's what we do. + # Append '_d' to the python import library on debug builds. + if sys.platform == "win32": + from distutils.msvccompiler import MSVCCompiler + if not isinstance(self.compiler, MSVCCompiler): + template = "python%d%d" + if self.debug: + template = template + '_d' + pythonlib = (template % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + # don't extend ext.libraries, it may be shared with other + # extensions, it is a reference to the original list + return ext.libraries + [pythonlib] + else: + return ext.libraries + elif sys.platform == "os2emx": + # EMX/GCC requires the python library explicitly, and I + # believe VACPP does as well (though not confirmed) - AIM Apr01 + template = "python%d%d" + # debug versions of the main DLL aren't supported, at least + # not at this time - AIM Apr01 + #if self.debug: + # template = template + '_d' + pythonlib = (template % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + # don't extend ext.libraries, it may be shared with other + # extensions, it is a reference to the original list + return ext.libraries + [pythonlib] + elif sys.platform[:6] == "cygwin": + template = "python%d.%d" + pythonlib = (template % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + # don't extend ext.libraries, it may be shared with other + # extensions, it is a reference to the original list + return ext.libraries + [pythonlib] + elif sys.platform[:6] == "atheos": + from distutils import sysconfig + + template = "python%d.%d" + pythonlib = (template % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + # Get SHLIBS from Makefile + extra = [] + for lib in sysconfig.get_config_var('SHLIBS').split(): + if lib.startswith('-l'): + extra.append(lib[2:]) + else: + extra.append(lib) + # don't extend ext.libraries, it may be shared with other + # extensions, it is a reference to the original list + return ext.libraries + [pythonlib, "m"] + extra + + elif sys.platform == 'darwin': + # Don't use the default code below + return ext.libraries + elif sys.platform[:3] == 'aix': + # Don't use the default code below + return ext.libraries + else: + from distutils import sysconfig + if sysconfig.get_config_var('Py_ENABLE_SHARED'): + template = "python%d.%d" + pythonlib = (template % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + return ext.libraries + [pythonlib] + else: + return ext.libraries + +# class build_ext diff --git a/PythonHome/Lib/distutils/command/build_ext.pyc b/PythonHome/Lib/distutils/command/build_ext.pyc deleted file mode 100644 index 0f280ab0f85a4a187cf63fff710327881564ea16..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19280 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 Zv7(bOefk_jY7A~8OkoN4mx`5v{{_OVO8@`> diff --git a/PythonHome/Lib/distutils/command/build_py.py b/PythonHome/Lib/distutils/command/build_py.py new file mode 100644 index 0000000000..c123c622c4 --- /dev/null +++ b/PythonHome/Lib/distutils/command/build_py.py @@ -0,0 +1,394 @@ +"""distutils.command.build_py + +Implements the Distutils 'build_py' command.""" + +__revision__ = "$Id$" + +import os +import sys +from glob import glob + +from distutils.core import Command +from distutils.errors import DistutilsOptionError, DistutilsFileError +from distutils.util import convert_path +from distutils import log + +class build_py(Command): + + description = "\"build\" pure Python modules (copy to build directory)" + + user_options = [ + ('build-lib=', 'd', "directory to \"build\" (copy) to"), + ('compile', 'c', "compile .py to .pyc"), + ('no-compile', None, "don't compile .py files [default]"), + ('optimize=', 'O', + "also compile with optimization: -O1 for \"python -O\", " + "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), + ('force', 'f', "forcibly build everything (ignore file timestamps)"), + ] + + boolean_options = ['compile', 'force'] + negative_opt = {'no-compile' : 'compile'} + + def initialize_options(self): + self.build_lib = None + self.py_modules = None + self.package = None + self.package_data = None + self.package_dir = None + self.compile = 0 + self.optimize = 0 + self.force = None + + def finalize_options(self): + self.set_undefined_options('build', + ('build_lib', 'build_lib'), + ('force', 'force')) + + # Get the distribution options that are aliases for build_py + # options -- list of packages and list of modules. + self.packages = self.distribution.packages + self.py_modules = self.distribution.py_modules + self.package_data = self.distribution.package_data + self.package_dir = {} + if self.distribution.package_dir: + for name, path in self.distribution.package_dir.items(): + self.package_dir[name] = convert_path(path) + self.data_files = self.get_data_files() + + # Ick, copied straight from install_lib.py (fancy_getopt needs a + # type system! Hell, *everything* needs a type system!!!) + if not isinstance(self.optimize, int): + try: + self.optimize = int(self.optimize) + assert 0 <= self.optimize <= 2 + except (ValueError, AssertionError): + raise DistutilsOptionError("optimize must be 0, 1, or 2") + + def run(self): + # XXX copy_file by default preserves atime and mtime. IMHO this is + # the right thing to do, but perhaps it should be an option -- in + # particular, a site administrator might want installed files to + # reflect the time of installation rather than the last + # modification time before the installed release. + + # XXX copy_file by default preserves mode, which appears to be the + # wrong thing to do: if a file is read-only in the working + # directory, we want it to be installed read/write so that the next + # installation of the same module distribution can overwrite it + # without problems. (This might be a Unix-specific issue.) Thus + # we turn off 'preserve_mode' when copying to the build directory, + # since the build directory is supposed to be exactly what the + # installation will look like (ie. we preserve mode when + # installing). + + # Two options control which modules will be installed: 'packages' + # and 'py_modules'. The former lets us work with whole packages, not + # specifying individual modules at all; the latter is for + # specifying modules one-at-a-time. + + if self.py_modules: + self.build_modules() + if self.packages: + self.build_packages() + self.build_package_data() + + self.byte_compile(self.get_outputs(include_bytecode=0)) + + def get_data_files(self): + """Generate list of '(package,src_dir,build_dir,filenames)' tuples""" + data = [] + if not self.packages: + return data + for package in self.packages: + # Locate package source directory + src_dir = self.get_package_dir(package) + + # Compute package build directory + build_dir = os.path.join(*([self.build_lib] + package.split('.'))) + + # Length of path to strip from found files + plen = 0 + if src_dir: + plen = len(src_dir)+1 + + # Strip directory from globbed filenames + filenames = [ + file[plen:] for file in self.find_data_files(package, src_dir) + ] + data.append((package, src_dir, build_dir, filenames)) + return data + + def find_data_files(self, package, src_dir): + """Return filenames for package's data files in 'src_dir'""" + globs = (self.package_data.get('', []) + + self.package_data.get(package, [])) + files = [] + for pattern in globs: + # Each pattern has to be converted to a platform-specific path + filelist = glob(os.path.join(src_dir, convert_path(pattern))) + # Files that match more than one pattern are only added once + files.extend([fn for fn in filelist if fn not in files + and os.path.isfile(fn)]) + return files + + def build_package_data(self): + """Copy data files into build directory""" + for package, src_dir, build_dir, filenames in self.data_files: + for filename in filenames: + target = os.path.join(build_dir, filename) + self.mkpath(os.path.dirname(target)) + self.copy_file(os.path.join(src_dir, filename), target, + preserve_mode=False) + + def get_package_dir(self, package): + """Return the directory, relative to the top of the source + distribution, where package 'package' should be found + (at least according to the 'package_dir' option, if any).""" + + path = package.split('.') + + if not self.package_dir: + if path: + return os.path.join(*path) + else: + return '' + else: + tail = [] + while path: + try: + pdir = self.package_dir['.'.join(path)] + except KeyError: + tail.insert(0, path[-1]) + del path[-1] + else: + tail.insert(0, pdir) + return os.path.join(*tail) + else: + # Oops, got all the way through 'path' without finding a + # match in package_dir. If package_dir defines a directory + # for the root (nameless) package, then fallback on it; + # otherwise, we might as well have not consulted + # package_dir at all, as we just use the directory implied + # by 'tail' (which should be the same as the original value + # of 'path' at this point). + pdir = self.package_dir.get('') + if pdir is not None: + tail.insert(0, pdir) + + if tail: + return os.path.join(*tail) + else: + return '' + + def check_package(self, package, package_dir): + # Empty dir name means current directory, which we can probably + # assume exists. Also, os.path.exists and isdir don't know about + # my "empty string means current dir" convention, so we have to + # circumvent them. + if package_dir != "": + if not os.path.exists(package_dir): + raise DistutilsFileError( + "package directory '%s' does not exist" % package_dir) + if not os.path.isdir(package_dir): + raise DistutilsFileError( + "supposed package directory '%s' exists, " + "but is not a directory" % package_dir) + + # Require __init__.py for all but the "root package" + if package: + init_py = os.path.join(package_dir, "__init__.py") + if os.path.isfile(init_py): + return init_py + else: + log.warn(("package init file '%s' not found " + + "(or not a regular file)"), init_py) + + # Either not in a package at all (__init__.py not expected), or + # __init__.py doesn't exist -- so don't return the filename. + return None + + def check_module(self, module, module_file): + if not os.path.isfile(module_file): + log.warn("file %s (for module %s) not found", module_file, module) + return False + else: + return True + + def find_package_modules(self, package, package_dir): + self.check_package(package, package_dir) + module_files = glob(os.path.join(package_dir, "*.py")) + modules = [] + setup_script = os.path.abspath(self.distribution.script_name) + + for f in module_files: + abs_f = os.path.abspath(f) + if abs_f != setup_script: + module = os.path.splitext(os.path.basename(f))[0] + modules.append((package, module, f)) + else: + self.debug_print("excluding %s" % setup_script) + return modules + + def find_modules(self): + """Finds individually-specified Python modules, ie. those listed by + module name in 'self.py_modules'. Returns a list of tuples (package, + module_base, filename): 'package' is a tuple of the path through + package-space to the module; 'module_base' is the bare (no + packages, no dots) module name, and 'filename' is the path to the + ".py" file (relative to the distribution root) that implements the + module. + """ + # Map package names to tuples of useful info about the package: + # (package_dir, checked) + # package_dir - the directory where we'll find source files for + # this package + # checked - true if we have checked that the package directory + # is valid (exists, contains __init__.py, ... ?) + packages = {} + + # List of (package, module, filename) tuples to return + modules = [] + + # We treat modules-in-packages almost the same as toplevel modules, + # just the "package" for a toplevel is empty (either an empty + # string or empty list, depending on context). Differences: + # - don't check for __init__.py in directory for empty package + for module in self.py_modules: + path = module.split('.') + package = '.'.join(path[0:-1]) + module_base = path[-1] + + try: + (package_dir, checked) = packages[package] + except KeyError: + package_dir = self.get_package_dir(package) + checked = 0 + + if not checked: + init_py = self.check_package(package, package_dir) + packages[package] = (package_dir, 1) + if init_py: + modules.append((package, "__init__", init_py)) + + # XXX perhaps we should also check for just .pyc files + # (so greedy closed-source bastards can distribute Python + # modules too) + module_file = os.path.join(package_dir, module_base + ".py") + if not self.check_module(module, module_file): + continue + + modules.append((package, module_base, module_file)) + + return modules + + def find_all_modules(self): + """Compute the list of all modules that will be built, whether + they are specified one-module-at-a-time ('self.py_modules') or + by whole packages ('self.packages'). Return a list of tuples + (package, module, module_file), just like 'find_modules()' and + 'find_package_modules()' do.""" + modules = [] + if self.py_modules: + modules.extend(self.find_modules()) + if self.packages: + for package in self.packages: + package_dir = self.get_package_dir(package) + m = self.find_package_modules(package, package_dir) + modules.extend(m) + return modules + + def get_source_files(self): + return [module[-1] for module in self.find_all_modules()] + + def get_module_outfile(self, build_dir, package, module): + outfile_path = [build_dir] + list(package) + [module + ".py"] + return os.path.join(*outfile_path) + + def get_outputs(self, include_bytecode=1): + modules = self.find_all_modules() + outputs = [] + for (package, module, module_file) in modules: + package = package.split('.') + filename = self.get_module_outfile(self.build_lib, package, module) + outputs.append(filename) + if include_bytecode: + if self.compile: + outputs.append(filename + "c") + if self.optimize > 0: + outputs.append(filename + "o") + + outputs += [ + os.path.join(build_dir, filename) + for package, src_dir, build_dir, filenames in self.data_files + for filename in filenames + ] + + return outputs + + def build_module(self, module, module_file, package): + if isinstance(package, str): + package = package.split('.') + elif not isinstance(package, (list, tuple)): + raise TypeError( + "'package' must be a string (dot-separated), list, or tuple") + + # Now put the module source file into the "build" area -- this is + # easy, we just copy it somewhere under self.build_lib (the build + # directory for Python source). + outfile = self.get_module_outfile(self.build_lib, package, module) + dir = os.path.dirname(outfile) + self.mkpath(dir) + return self.copy_file(module_file, outfile, preserve_mode=0) + + def build_modules(self): + modules = self.find_modules() + for (package, module, module_file) in modules: + + # Now "build" the module -- ie. copy the source file to + # self.build_lib (the build directory for Python source). + # (Actually, it gets copied to the directory for this package + # under self.build_lib.) + self.build_module(module, module_file, package) + + def build_packages(self): + for package in self.packages: + + # Get list of (package, module, module_file) tuples based on + # scanning the package directory. 'package' is only included + # in the tuple so that 'find_modules()' and + # 'find_package_tuples()' have a consistent interface; it's + # ignored here (apart from a sanity check). Also, 'module' is + # the *unqualified* module name (ie. no dots, no package -- we + # already know its package!), and 'module_file' is the path to + # the .py file, relative to the current directory + # (ie. including 'package_dir'). + package_dir = self.get_package_dir(package) + modules = self.find_package_modules(package, package_dir) + + # Now loop over the modules we found, "building" each one (just + # copy it to self.build_lib). + for (package_, module, module_file) in modules: + assert package == package_ + self.build_module(module, module_file, package) + + def byte_compile(self, files): + if sys.dont_write_bytecode: + self.warn('byte-compiling is disabled, skipping.') + return + + from distutils.util import byte_compile + prefix = self.build_lib + if prefix[-1] != os.sep: + prefix = prefix + os.sep + + # XXX this code is essentially the same as the 'byte_compile() + # method of the "install_lib" command, except for the determination + # of the 'prefix' string. Hmmm. + + if self.compile: + byte_compile(files, optimize=0, + force=self.force, prefix=prefix, dry_run=self.dry_run) + if self.optimize > 0: + byte_compile(files, optimize=self.optimize, + force=self.force, prefix=prefix, dry_run=self.dry_run) diff --git a/PythonHome/Lib/distutils/command/build_py.pyc b/PythonHome/Lib/distutils/command/build_py.pyc deleted file mode 100644 index 8382e73389256f5f55567f2128a752ac48d691d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11218 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 V@!}9iX$l^17Dl^(-PCO9e*sZ^LhJwl diff --git a/PythonHome/Lib/distutils/command/build_scripts.py b/PythonHome/Lib/distutils/command/build_scripts.py new file mode 100644 index 0000000000..567df6587e --- /dev/null +++ b/PythonHome/Lib/distutils/command/build_scripts.py @@ -0,0 +1,131 @@ +"""distutils.command.build_scripts + +Implements the Distutils 'build_scripts' command.""" + +__revision__ = "$Id$" + +import os, re +from stat import ST_MODE +from distutils.core import Command +from distutils.dep_util import newer +from distutils.util import convert_path +from distutils import log + +# check if Python is called on the first line with this expression +first_line_re = re.compile('^#!.*python[0-9.]*([ \t].*)?$') + +class build_scripts (Command): + + description = "\"build\" scripts (copy and fixup #! line)" + + user_options = [ + ('build-dir=', 'd', "directory to \"build\" (copy) to"), + ('force', 'f', "forcibly build everything (ignore file timestamps"), + ('executable=', 'e', "specify final destination interpreter path"), + ] + + boolean_options = ['force'] + + + def initialize_options (self): + self.build_dir = None + self.scripts = None + self.force = None + self.executable = None + self.outfiles = None + + def finalize_options (self): + self.set_undefined_options('build', + ('build_scripts', 'build_dir'), + ('force', 'force'), + ('executable', 'executable')) + self.scripts = self.distribution.scripts + + def get_source_files(self): + return self.scripts + + def run (self): + if not self.scripts: + return + self.copy_scripts() + + + def copy_scripts (self): + """Copy each script listed in 'self.scripts'; if it's marked as a + Python script in the Unix way (first line matches 'first_line_re', + ie. starts with "\#!" and contains "python"), then adjust the first + line to refer to the current Python interpreter as we copy. + """ + _sysconfig = __import__('sysconfig') + self.mkpath(self.build_dir) + outfiles = [] + for script in self.scripts: + adjust = 0 + script = convert_path(script) + outfile = os.path.join(self.build_dir, os.path.basename(script)) + outfiles.append(outfile) + + if not self.force and not newer(script, outfile): + log.debug("not copying %s (up-to-date)", script) + continue + + # Always open the file, but ignore failures in dry-run mode -- + # that way, we'll get accurate feedback if we can read the + # script. + try: + f = open(script, "r") + except IOError: + if not self.dry_run: + raise + f = None + else: + first_line = f.readline() + if not first_line: + self.warn("%s is an empty file (skipping)" % script) + continue + + match = first_line_re.match(first_line) + if match: + adjust = 1 + post_interp = match.group(1) or '' + + if adjust: + log.info("copying and adjusting %s -> %s", script, + self.build_dir) + if not self.dry_run: + outf = open(outfile, "w") + if not _sysconfig.is_python_build(): + outf.write("#!%s%s\n" % + (self.executable, + post_interp)) + else: + outf.write("#!%s%s\n" % + (os.path.join( + _sysconfig.get_config_var("BINDIR"), + "python%s%s" % (_sysconfig.get_config_var("VERSION"), + _sysconfig.get_config_var("EXE"))), + post_interp)) + outf.writelines(f.readlines()) + outf.close() + if f: + f.close() + else: + if f: + f.close() + self.copy_file(script, outfile) + + if os.name == 'posix': + for file in outfiles: + if self.dry_run: + log.info("changing mode of %s", file) + else: + oldmode = os.stat(file)[ST_MODE] & 07777 + newmode = (oldmode | 0555) & 07777 + if newmode != oldmode: + log.info("changing mode of %s from %o to %o", + file, oldmode, newmode) + os.chmod(file, newmode) + + # copy_scripts () + +# class build_scripts diff --git a/PythonHome/Lib/distutils/command/build_scripts.pyc b/PythonHome/Lib/distutils/command/build_scripts.pyc deleted file mode 100644 index ec07c2fcd3b171eea58c065f4ce76deec8657ce2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4429 zcmb_fUvnEt5$|2evL(xZ66ccK7Pw=&WMw5!{qYY#~kTjIEB7;!&(eeF?>{qm3l|fa8bFx1t0q5pqP?O=j z?9cmgO$G}xtjm7gkLP93kl~{2FZ%I<44N`rlKmwKOhx+3lGf!FmR*swA!c5BSbtIe zAo5D&H~Xu!WUtkvnK8}GtQ)&*VB6hdIPBzU`(T_6(!_SlY~*aCu`?VE%+Tb{M()T& zk1qJ5%{Le~qYHUkh1xqi>7DE={Oz^^4Bb4My0T_0v0U2@G%8 zH**r#d5EvwLu241z=IaZ12CX-MGn1hs&WVvt3(mt!953T4#l7NfHW5J$c2bUcb~uSbI{H(Ry=X64;Zv+`p{z*74m+pIKQ zSCnUwE20Z^s%8rm$F1~=vTIbNXMZpqX9t6`NEJo~00N>cKa5)0VP2F5iw{iXvZ1lA zGaOmF2q|-Fx?|Tl7#P32vG+i=Bh$@#XOPG{gD8anIxZ{nD9fEGN2Ng<(K}t*%x{SA zrxc|vz;z;$D8TFhV^2Zk`wr0c9iWQe3-YQe0jYuXLj_22*=up5yXsW6A*Op{ zdPg@JGo)L@*Zx;<+cz-sOtavyv!0)L6ENMwC4McQF!v5uF)kVBse$uNda-NAV@b@) z>;Sh$k;fz`&hZL+_`VIss}R#Ddkx{cpv@4j1eIVum?6wiQ-m1;9^s4N;ne@pszbnF zi!lyaqA_)!R?!RcHP+k$*;@l2F`&JhUxE3x@TRm{sA%$1xVUYW1t~uca9*)l^!wL&b}=>jQGgSCUgs*4s+6}vc(8wi zXPP^~&H!G;A8r^l7t(UvY{xM;QvN+W{Ud$-=*2|N;al*pO8MmlMyoP`_4MnrkaFuf z4#aK9yGXj9oMTr_Nw3O79WBWO|4lirNC^Rt^BQG9#1t=4s=2KsjJ;+kf9hjkucf!x z2JVATnRiX6do)eONW0dV6j?0VWM*hjZ~M(3M_Dh*+@_6&o$?qQ9UFBT(e&>ZT5DYB zfH3Q!U**|pbkaGCTD`2aPBS{BUH8b?Xj5qkvwTvT&HFP|nQ2Ezza@&Qlgu4O8_#dA zZ)jR1Q)Jx!HwKfn^I^~Ca8zrB9f-n9+KYwY39 z?xUSpvw??&Q(6oB`fx32-EG|go0b_#k_|@%3erT48XmLs@fn(FFs2QTw|il=eBrcq z`UM=o%H*J9P2L$AmG6v3CQp5G*POsgMK_R|gYltC7GTkR?mT&1mROs}q~%$HOFm{M zSGA?-qznTUIq8(S*1vBApX$}P)ZSrPj7Q3z<-G#8DKN2#$2QUOL)lKs%o(jbaFvNL z8Tt@OULtt8zH)GFt1)z8iB<9LpgUrd};^m6}kn>3bE2o0C`)8O$%si+;bjo=o8l)<7Z@g8CS zEvuUNI@J9TUt6M)S~FM;YWi&kcY>wxJ@)4+!CJ6{EL{s4VH53@pcby+w-($CYe6$; zU~UD!!l`oOgmT!Rd?tc5p%W#wK9w3gE|qYl-_Ma>#@E;|U&J@q&~cYe*WNdJGid341xhRx*TPzb^=rL?&pbYrdacD-jj<$2 zi!O}k4U!;Byv!_YPm*|p9K07w6Muvse@=J^W{(!U*)gg2D_<#>^wf+JzUpJj>(RZO zQ@UPNbi#}t>+Qo6fS1q+CpF$iUw86tpwRp2C*DO5xT>Y4fF!($@SlDvE8)KZ@H^); diff --git a/PythonHome/Lib/distutils/command/check.py b/PythonHome/Lib/distutils/command/check.py new file mode 100644 index 0000000000..152bf0de98 --- /dev/null +++ b/PythonHome/Lib/distutils/command/check.py @@ -0,0 +1,149 @@ +"""distutils.command.check + +Implements the Distutils 'check' command. +""" +__revision__ = "$Id$" + +from distutils.core import Command +from distutils.dist import PKG_INFO_ENCODING +from distutils.errors import DistutilsSetupError + +try: + # docutils is installed + from docutils.utils import Reporter + from docutils.parsers.rst import Parser + from docutils import frontend + from docutils import nodes + from StringIO import StringIO + + class SilentReporter(Reporter): + + def __init__(self, source, report_level, halt_level, stream=None, + debug=0, encoding='ascii', error_handler='replace'): + self.messages = [] + Reporter.__init__(self, source, report_level, halt_level, stream, + debug, encoding, error_handler) + + def system_message(self, level, message, *children, **kwargs): + self.messages.append((level, message, children, kwargs)) + return nodes.system_message(message, level=level, + type=self.levels[level], + *children, **kwargs) + + HAS_DOCUTILS = True +except ImportError: + # docutils is not installed + HAS_DOCUTILS = False + +class check(Command): + """This command checks the meta-data of the package. + """ + description = ("perform some checks on the package") + user_options = [('metadata', 'm', 'Verify meta-data'), + ('restructuredtext', 'r', + ('Checks if long string meta-data syntax ' + 'are reStructuredText-compliant')), + ('strict', 's', + 'Will exit with an error if a check fails')] + + boolean_options = ['metadata', 'restructuredtext', 'strict'] + + def initialize_options(self): + """Sets default values for options.""" + self.restructuredtext = 0 + self.metadata = 1 + self.strict = 0 + self._warnings = 0 + + def finalize_options(self): + pass + + def warn(self, msg): + """Counts the number of warnings that occurs.""" + self._warnings += 1 + return Command.warn(self, msg) + + def run(self): + """Runs the command.""" + # perform the various tests + if self.metadata: + self.check_metadata() + if self.restructuredtext: + if HAS_DOCUTILS: + self.check_restructuredtext() + elif self.strict: + raise DistutilsSetupError('The docutils package is needed.') + + # let's raise an error in strict mode, if we have at least + # one warning + if self.strict and self._warnings > 0: + raise DistutilsSetupError('Please correct your package.') + + def check_metadata(self): + """Ensures that all required elements of meta-data are supplied. + + name, version, URL, (author and author_email) or + (maintainer and maintainer_email)). + + Warns if any are missing. + """ + metadata = self.distribution.metadata + + missing = [] + for attr in ('name', 'version', 'url'): + if not (hasattr(metadata, attr) and getattr(metadata, attr)): + missing.append(attr) + + if missing: + self.warn("missing required meta-data: %s" % ', '.join(missing)) + if metadata.author: + if not metadata.author_email: + self.warn("missing meta-data: if 'author' supplied, " + + "'author_email' must be supplied too") + elif metadata.maintainer: + if not metadata.maintainer_email: + self.warn("missing meta-data: if 'maintainer' supplied, " + + "'maintainer_email' must be supplied too") + else: + self.warn("missing meta-data: either (author and author_email) " + + "or (maintainer and maintainer_email) " + + "must be supplied") + + def check_restructuredtext(self): + """Checks if the long string fields are reST-compliant.""" + data = self.distribution.get_long_description() + if not isinstance(data, unicode): + data = data.decode(PKG_INFO_ENCODING) + for warning in self._check_rst_data(data): + line = warning[-1].get('line') + if line is None: + warning = warning[1] + else: + warning = '%s (line %s)' % (warning[1], line) + self.warn(warning) + + def _check_rst_data(self, data): + """Returns warnings when the provided data doesn't compile.""" + source_path = StringIO() + parser = Parser() + settings = frontend.OptionParser().get_default_values() + settings.tab_width = 4 + settings.pep_references = None + settings.rfc_references = None + reporter = SilentReporter(source_path, + settings.report_level, + settings.halt_level, + stream=settings.warning_stream, + debug=settings.debug, + encoding=settings.error_encoding, + error_handler=settings.error_encoding_error_handler) + + document = nodes.document(settings, reporter, source=source_path) + document.note_source(source_path, -1) + try: + parser.parse(data, document) + except AttributeError: + reporter.messages.append((-1, 'Could not finish the parsing.', + '', {})) + + return reporter.messages diff --git a/PythonHome/Lib/distutils/command/check.pyc b/PythonHome/Lib/distutils/command/check.pyc deleted file mode 100644 index fd49bfb45739abd9a9d6fee4099ab9717b025569..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6045 zcmb_gTXP&o6+Sb&y6oy|S(fc02}5pLQ?^2d6i}&~MIxm}4g!@^!)T{h8hLhR zJ>6?tl>CD8%paim7yJcy6>kl2Onp6$!&)7|Itozva;*HZh> zd%xZ7%II$fzwe>gf8dje?Bg5Aejr&WSwo6Y`VHA{NWgYeil+2uWPirDXQY^w{+#U3 zNpLdIDYH_{OTQ)iEl)BhMO*p{vcKTl^HMBIe@XV2e7mLXW!Yc$?Y0yv(qEDN6|@(` zw4{fz^t>o4CL3@l9+~0Tb@k2AlZuS zc2;@P>pW?0-O%NQ-Rf5Tep+T*-6PYz+iu_L4+_&arL&PcGSQ7OU9_nLo6(rQZJXfp z>aFb6{NMQN1ZcTAe6D+jzT+G^KKvxbxS$S0Eu@Cf0=ewP_lF?dRatH8 zN&IOk5_d8%9WE9xu*F@Zg8_^tW>pQto>*u4$wv9OFY^u}1 zf#$V|%7XgM>n$OFnwM!1t>rzz==I=$yT+pAlW&sEYjQ5e13wZZy)7$3_y`? z(W6w~xb#|xQ+-oO$S!zP2|pbe%wIqr4XtRe2bJ4t_M99@&%9r4OUD zHc@Q=P$Mq4!Q~pfXHev6>AVwTYS**2YFK-DQAFlp?xF{|JBrdWQrF~KsXtWIO9AR# z?w%#&eo%BaeMj-fyH5gm^F7|JFa%XL06erUH6Ng|jWW|qhlPvor^V3N2vUryfy=AX zZYc!jTxeS-#jl_m|A3#@@NtB{1a4760v?rPI@8orzmt)=HOwK>hh%VGb(K*+slEIOEJ>Y}RK9o7&!kEc)cJkO;?cU^&`QAEBq)7vDD@|T)$2EP3;>R?d!J}y zM#lgJm=VbD13~|28it(G03SlR+hh}70E6_DAj_JN7_rDQt%!%E_x^E4Vkz+3NLsS0 ztGP`yf`JIAQ5ut(%v-E|0fe6xCbfWqs;*7fMJEWDWBRRaji_qK8Xy#E5Fb1?sFiDI z{l)vc$&H=spWVLo@vhqdQ&0FbIH)tk6rXDB`Av{2t%v0Y__1^fX|#eRSpKYj*P55S zvS{`!s;s}G;+2Ka`Y2!)@+g#t?+|=%eEya^Y6zk$V=g2eO7%8%H)-0-jJk}ps)yj- zWx@YF^o_IydtN^BC<%9eY?8_9Yy6 zG-Z0u$=TkHUb6~KS0j7n4CNUDgpEyql+9=?1yH{N>QTSn^=8x`S{EId3035(%3k|s zuG4cr!I^lqIUW0-+~4|o?goJm!u@7#SVkV`>04D1X>@=3WIo|m@T1`E9Jq}HAHRuu zN3%#Kwaj_z`~XN(l^!Zcdz9MLxmp!=2*5x+zKDLsRn_Nl1ryOUR1Hdj*kFLRGpB4D8a+fIfReWTAF(j(I6s+U-MUAhmV0rwDzPYc# znm=OV1Zx2MfE$l3uvuV>{gL{3leZ@LKSlxS4>O$t_|TYemMqx`kc+Ex~_Q2n+YaR(vf$o^IwA;r z5GoL8nvx)Fw6y{S`^r4iMd%Tu$J%p@OMq`KQn~D3QeC66OjBUbiac&KAI%8702_W)m;tqxNQBL=CxNkws5AvM z9&I#ca;y|186?0)yeh;zm-hQNgvql4Gq5MSk|$mn{NT$}Y*83m0IbK$@;a^Tn9q(Y~ zvw9Gdv_~kK-Sgd}1rPEUm02WgzSasB!%M+x&JW(+Ec7iYff5!n9^1^nL4V6^Zn4+~q97+$?k> zK?69^3Rl9`T&vNVX|1+iYAtPdnDNJZ_^78P@QnMw^{T{~=q!^*F}$(XhN0EF!nB_? z5A;;xv|nAp>W#s38eM3%^jhN|0ErXhi_Vs}V7pa=AN^m=cRU)?Q`Dhib%uEokm`0l zG%>R{RRLap@lL4jqfbB|riC?egyH9rr0(Dy|6KJh7t?eV@(fpD@2g?M|7v|>xs9mO G4*vrR`(H5t diff --git a/PythonHome/Lib/distutils/command/clean.py b/PythonHome/Lib/distutils/command/clean.py new file mode 100644 index 0000000000..90ef35f1ca --- /dev/null +++ b/PythonHome/Lib/distutils/command/clean.py @@ -0,0 +1,80 @@ +"""distutils.command.clean + +Implements the Distutils 'clean' command.""" + +# contributed by Bastian Kleineidam , added 2000-03-18 + +__revision__ = "$Id$" + +import os +from distutils.core import Command +from distutils.dir_util import remove_tree +from distutils import log + +class clean(Command): + + description = "clean up temporary files from 'build' command" + user_options = [ + ('build-base=', 'b', + "base build directory (default: 'build.build-base')"), + ('build-lib=', None, + "build directory for all modules (default: 'build.build-lib')"), + ('build-temp=', 't', + "temporary build directory (default: 'build.build-temp')"), + ('build-scripts=', None, + "build directory for scripts (default: 'build.build-scripts')"), + ('bdist-base=', None, + "temporary directory for built distributions"), + ('all', 'a', + "remove all build output, not just temporary by-products") + ] + + boolean_options = ['all'] + + def initialize_options(self): + self.build_base = None + self.build_lib = None + self.build_temp = None + self.build_scripts = None + self.bdist_base = None + self.all = None + + def finalize_options(self): + self.set_undefined_options('build', + ('build_base', 'build_base'), + ('build_lib', 'build_lib'), + ('build_scripts', 'build_scripts'), + ('build_temp', 'build_temp')) + self.set_undefined_options('bdist', + ('bdist_base', 'bdist_base')) + + def run(self): + # remove the build/temp. directory (unless it's already + # gone) + if os.path.exists(self.build_temp): + remove_tree(self.build_temp, dry_run=self.dry_run) + else: + log.debug("'%s' does not exist -- can't clean it", + self.build_temp) + + if self.all: + # remove build directories + for directory in (self.build_lib, + self.bdist_base, + self.build_scripts): + if os.path.exists(directory): + remove_tree(directory, dry_run=self.dry_run) + else: + log.warn("'%s' does not exist -- can't clean it", + directory) + + # just for the heck of it, try to remove the base build directory: + # we might have emptied it right now, but if not we don't care + if not self.dry_run: + try: + os.rmdir(self.build_base) + log.info("removing '%s'", self.build_base) + except OSError: + pass + +# class clean diff --git a/PythonHome/Lib/distutils/command/clean.pyc b/PythonHome/Lib/distutils/command/clean.pyc deleted file mode 100644 index 8d7e7a75ee7d63f1313fcb233f3feb0630ac19b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3101 zcmbtWTW=dx5T5ldwsUEkke2d*R#hsSi~Rr(NL5oIS{{l}kTwqi6SS;-j?)c$arYdT z2EkMK1N;kq0RM`IKJ*8`H*@T@lPXfu#M$vVvvcOm<(nB-->kR)IsExxM6&euq-(=h^8C$-7GA{^?rELKQu$)ZWYLH7gJ z*#nX5{OQEEI-TT2RGj+bIMK!*7kTP;hSNAvrH_WK7glc=8NFxO$D#R*DfYg+@>N{u zkQGao^^O0$n%941vXCBSBOA5w$;YUg0r@5N4QI{yhdFWdh$G$k@ ztoZ_J7rtH5LOuYE8*`I-W>mxzYc98PCUBXBv)6Mg8Er0v=96>wEn>&6v$YoCFt&(? zKxdvA%UD53B=nJZ=inr9a_;3*JDJ)~{Vccs$<)}T+zwBBlLEmUSu^6~@l(O`1dn+L z0(AXO6bj6E0i-!jb-n<`90wS43t)^;ORQ_Z%ZRr%Ugnv$WsXAzh~;t<8$+aQ=_SY8 zu9q)o(Q*RpzMKvk5O4*<`i)M;U3`-e<73r7`ZgXO@c}92qgiPl3CR1CQ@aJBIE!r@ zCGl@M%qJ4l`{0^25b|2(rwosjFiUW`AS5T!lF&*NdPtkpDxKBIo4r6N*66H)p2HDg zkM^ai#p!_E4>%+N-xe@n-CH&}VCgO=V^JC6_l2z!ITuNDZs!Evil%vsbMZ3H!qR2D zT@oqt;6%!;%g7Gft!+5XQ1fx7)jYWJI^asWZn8FU2CB}b>SMl!m2s-7@>#)3lEtCp z4k}oFgM~%1JUXdJ)~a;oQPF2?a;^YpPZo9XJullP+n^IP$x<3gWWgpCf77cUMYbih zEp(N}ReJiK4x`wgoJlI(+e(YIc);X;bkp!FcSyhZ=#LRGy3-Rh)*!G&2tniOvJl@l}ov$~{59 z0^Iyw&mTou$NFvr#8v#_Ix!TP7m$ zIljy;2vv8ydzF^guCzcK-ln(Z-N9<3#+cgl?t1H9mk%wC6q$DcNB14a-M-UUHpCte zz5N?cy^D5o(e4FY1~-{}PAk`$G_G>|U2gAH=iidO+(FzB+`sM=bXqt?7=;0M=$lMJ z`4woJ&=Q7Ol\n" % header) + file.write("\n") + file.write(body) + if body[-1] != "\n": + file.write("\n") + file.close() + return filename + + def _preprocess(self, body, headers, include_dirs, lang): + src = self._gen_temp_sourcefile(body, headers, lang) + out = "_configtest.i" + self.temp_files.extend([src, out]) + self.compiler.preprocess(src, out, include_dirs=include_dirs) + return (src, out) + + def _compile(self, body, headers, include_dirs, lang): + src = self._gen_temp_sourcefile(body, headers, lang) + if self.dump_source: + dump_file(src, "compiling '%s':" % src) + (obj,) = self.compiler.object_filenames([src]) + self.temp_files.extend([src, obj]) + self.compiler.compile([src], include_dirs=include_dirs) + return (src, obj) + + def _link(self, body, headers, include_dirs, libraries, library_dirs, + lang): + (src, obj) = self._compile(body, headers, include_dirs, lang) + prog = os.path.splitext(os.path.basename(src))[0] + self.compiler.link_executable([obj], prog, + libraries=libraries, + library_dirs=library_dirs, + target_lang=lang) + + if self.compiler.exe_extension is not None: + prog = prog + self.compiler.exe_extension + self.temp_files.append(prog) + + return (src, obj, prog) + + def _clean(self, *filenames): + if not filenames: + filenames = self.temp_files + self.temp_files = [] + log.info("removing: %s", ' '.join(filenames)) + for filename in filenames: + try: + os.remove(filename) + except OSError: + pass + + + # XXX these ignore the dry-run flag: what to do, what to do? even if + # you want a dry-run build, you still need some sort of configuration + # info. My inclination is to make it up to the real config command to + # consult 'dry_run', and assume a default (minimal) configuration if + # true. The problem with trying to do it here is that you'd have to + # return either true or false from all the 'try' methods, neither of + # which is correct. + + # XXX need access to the header search path and maybe default macros. + + def try_cpp(self, body=None, headers=None, include_dirs=None, lang="c"): + """Construct a source file from 'body' (a string containing lines + of C/C++ code) and 'headers' (a list of header files to include) + and run it through the preprocessor. Return true if the + preprocessor succeeded, false if there were any errors. + ('body' probably isn't of much use, but what the heck.) + """ + from distutils.ccompiler import CompileError + self._check_compiler() + ok = 1 + try: + self._preprocess(body, headers, include_dirs, lang) + except CompileError: + ok = 0 + + self._clean() + return ok + + def search_cpp(self, pattern, body=None, headers=None, include_dirs=None, + lang="c"): + """Construct a source file (just like 'try_cpp()'), run it through + the preprocessor, and return true if any line of the output matches + 'pattern'. 'pattern' should either be a compiled regex object or a + string containing a regex. If both 'body' and 'headers' are None, + preprocesses an empty file -- which can be useful to determine the + symbols the preprocessor and compiler set by default. + """ + self._check_compiler() + src, out = self._preprocess(body, headers, include_dirs, lang) + + if isinstance(pattern, str): + pattern = re.compile(pattern) + + file = open(out) + match = 0 + while 1: + line = file.readline() + if line == '': + break + if pattern.search(line): + match = 1 + break + + file.close() + self._clean() + return match + + def try_compile(self, body, headers=None, include_dirs=None, lang="c"): + """Try to compile a source file built from 'body' and 'headers'. + Return true on success, false otherwise. + """ + from distutils.ccompiler import CompileError + self._check_compiler() + try: + self._compile(body, headers, include_dirs, lang) + ok = 1 + except CompileError: + ok = 0 + + log.info(ok and "success!" or "failure.") + self._clean() + return ok + + def try_link(self, body, headers=None, include_dirs=None, libraries=None, + library_dirs=None, lang="c"): + """Try to compile and link a source file, built from 'body' and + 'headers', to executable form. Return true on success, false + otherwise. + """ + from distutils.ccompiler import CompileError, LinkError + self._check_compiler() + try: + self._link(body, headers, include_dirs, + libraries, library_dirs, lang) + ok = 1 + except (CompileError, LinkError): + ok = 0 + + log.info(ok and "success!" or "failure.") + self._clean() + return ok + + def try_run(self, body, headers=None, include_dirs=None, libraries=None, + library_dirs=None, lang="c"): + """Try to compile, link to an executable, and run a program + built from 'body' and 'headers'. Return true on success, false + otherwise. + """ + from distutils.ccompiler import CompileError, LinkError + self._check_compiler() + try: + src, obj, exe = self._link(body, headers, include_dirs, + libraries, library_dirs, lang) + self.spawn([exe]) + ok = 1 + except (CompileError, LinkError, DistutilsExecError): + ok = 0 + + log.info(ok and "success!" or "failure.") + self._clean() + return ok + + + # -- High-level methods -------------------------------------------- + # (these are the ones that are actually likely to be useful + # when implementing a real-world config command!) + + def check_func(self, func, headers=None, include_dirs=None, + libraries=None, library_dirs=None, decl=0, call=0): + + """Determine if function 'func' is available by constructing a + source file that refers to 'func', and compiles and links it. + If everything succeeds, returns true; otherwise returns false. + + The constructed source file starts out by including the header + files listed in 'headers'. If 'decl' is true, it then declares + 'func' (as "int func()"); you probably shouldn't supply 'headers' + and set 'decl' true in the same call, or you might get errors about + a conflicting declarations for 'func'. Finally, the constructed + 'main()' function either references 'func' or (if 'call' is true) + calls it. 'libraries' and 'library_dirs' are used when + linking. + """ + + self._check_compiler() + body = [] + if decl: + body.append("int %s ();" % func) + body.append("int main () {") + if call: + body.append(" %s();" % func) + else: + body.append(" %s;" % func) + body.append("}") + body = "\n".join(body) + "\n" + + return self.try_link(body, headers, include_dirs, + libraries, library_dirs) + + # check_func () + + def check_lib(self, library, library_dirs=None, headers=None, + include_dirs=None, other_libraries=[]): + """Determine if 'library' is available to be linked against, + without actually checking that any particular symbols are provided + by it. 'headers' will be used in constructing the source file to + be compiled, but the only effect of this is to check if all the + header files listed are available. Any libraries listed in + 'other_libraries' will be included in the link, in case 'library' + has symbols that depend on other libraries. + """ + self._check_compiler() + return self.try_link("int main (void) { }", + headers, include_dirs, + [library]+other_libraries, library_dirs) + + def check_header(self, header, include_dirs=None, library_dirs=None, + lang="c"): + """Determine if the system header file named by 'header_file' + exists and can be found by the preprocessor; return true if so, + false otherwise. + """ + return self.try_cpp(body="/* No body */", headers=[header], + include_dirs=include_dirs) + + +def dump_file(filename, head=None): + """Dumps a file content into log.info. + + If head is not None, will be dumped before the file content. + """ + if head is None: + log.info('%s' % filename) + else: + log.info(head) + file = open(filename) + try: + log.info(file.read()) + finally: + file.close() diff --git a/PythonHome/Lib/distutils/command/config.pyc b/PythonHome/Lib/distutils/command/config.pyc deleted file mode 100644 index b94a34555be5e0a3f583c29ac93205d491f34216..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12389 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 PDhK}8UaOt`y}J2-;`uHL diff --git a/PythonHome/Lib/distutils/command/install.py b/PythonHome/Lib/distutils/command/install.py new file mode 100644 index 0000000000..b9f1c6c566 --- /dev/null +++ b/PythonHome/Lib/distutils/command/install.py @@ -0,0 +1,672 @@ +"""distutils.command.install + +Implements the Distutils 'install' command.""" + +from distutils import log + +# This module should be kept compatible with Python 2.1. + +__revision__ = "$Id$" + +import sys, os, string +from types import * +from distutils.core import Command +from distutils.debug import DEBUG +from distutils.sysconfig import get_config_vars +from distutils.errors import DistutilsPlatformError +from distutils.file_util import write_file +from distutils.util import convert_path, subst_vars, change_root +from distutils.util import get_platform +from distutils.errors import DistutilsOptionError +from site import USER_BASE +from site import USER_SITE + + +if sys.version < "2.2": + WINDOWS_SCHEME = { + 'purelib': '$base', + 'platlib': '$base', + 'headers': '$base/Include/$dist_name', + 'scripts': '$base/Scripts', + 'data' : '$base', + } +else: + WINDOWS_SCHEME = { + 'purelib': '$base/Lib/site-packages', + 'platlib': '$base/Lib/site-packages', + 'headers': '$base/Include/$dist_name', + 'scripts': '$base/Scripts', + 'data' : '$base', + } + +INSTALL_SCHEMES = { + 'unix_prefix': { + 'purelib': '$base/lib/python$py_version_short/site-packages', + 'platlib': '$platbase/lib/python$py_version_short/site-packages', + 'headers': '$base/include/python$py_version_short/$dist_name', + 'scripts': '$base/bin', + 'data' : '$base', + }, + 'unix_home': { + 'purelib': '$base/lib/python', + 'platlib': '$base/lib/python', + 'headers': '$base/include/python/$dist_name', + 'scripts': '$base/bin', + 'data' : '$base', + }, + 'unix_user': { + 'purelib': '$usersite', + 'platlib': '$usersite', + 'headers': '$userbase/include/python$py_version_short/$dist_name', + 'scripts': '$userbase/bin', + 'data' : '$userbase', + }, + 'nt': WINDOWS_SCHEME, + 'nt_user': { + 'purelib': '$usersite', + 'platlib': '$usersite', + 'headers': '$userbase/Python$py_version_nodot/Include/$dist_name', + 'scripts': '$userbase/Scripts', + 'data' : '$userbase', + }, + 'os2': { + 'purelib': '$base/Lib/site-packages', + 'platlib': '$base/Lib/site-packages', + 'headers': '$base/Include/$dist_name', + 'scripts': '$base/Scripts', + 'data' : '$base', + }, + 'os2_home': { + 'purelib': '$usersite', + 'platlib': '$usersite', + 'headers': '$userbase/include/python$py_version_short/$dist_name', + 'scripts': '$userbase/bin', + 'data' : '$userbase', + }, + } + +# The keys to an installation scheme; if any new types of files are to be +# installed, be sure to add an entry to every installation scheme above, +# and to SCHEME_KEYS here. +SCHEME_KEYS = ('purelib', 'platlib', 'headers', 'scripts', 'data') + + +class install (Command): + + description = "install everything from build directory" + + user_options = [ + # Select installation scheme and set base director(y|ies) + ('prefix=', None, + "installation prefix"), + ('exec-prefix=', None, + "(Unix only) prefix for platform-specific files"), + ('home=', None, + "(Unix only) home directory to install under"), + ('user', None, + "install in user site-package '%s'" % USER_SITE), + + # Or, just set the base director(y|ies) + ('install-base=', None, + "base installation directory (instead of --prefix or --home)"), + ('install-platbase=', None, + "base installation directory for platform-specific files " + + "(instead of --exec-prefix or --home)"), + ('root=', None, + "install everything relative to this alternate root directory"), + + # Or, explicitly set the installation scheme + ('install-purelib=', None, + "installation directory for pure Python module distributions"), + ('install-platlib=', None, + "installation directory for non-pure module distributions"), + ('install-lib=', None, + "installation directory for all module distributions " + + "(overrides --install-purelib and --install-platlib)"), + + ('install-headers=', None, + "installation directory for C/C++ headers"), + ('install-scripts=', None, + "installation directory for Python scripts"), + ('install-data=', None, + "installation directory for data files"), + + # Byte-compilation options -- see install_lib.py for details, as + # these are duplicated from there (but only install_lib does + # anything with them). + ('compile', 'c', "compile .py to .pyc [default]"), + ('no-compile', None, "don't compile .py files"), + ('optimize=', 'O', + "also compile with optimization: -O1 for \"python -O\", " + "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), + + # Miscellaneous control options + ('force', 'f', + "force installation (overwrite any existing files)"), + ('skip-build', None, + "skip rebuilding everything (for testing/debugging)"), + + # Where to install documentation (eventually!) + #('doc-format=', None, "format of documentation to generate"), + #('install-man=', None, "directory for Unix man pages"), + #('install-html=', None, "directory for HTML documentation"), + #('install-info=', None, "directory for GNU info files"), + + ('record=', None, + "filename in which to record list of installed files"), + ] + + boolean_options = ['compile', 'force', 'skip-build', 'user'] + negative_opt = {'no-compile' : 'compile'} + + + def initialize_options (self): + + # High-level options: these select both an installation base + # and scheme. + self.prefix = None + self.exec_prefix = None + self.home = None + self.user = 0 + + # These select only the installation base; it's up to the user to + # specify the installation scheme (currently, that means supplying + # the --install-{platlib,purelib,scripts,data} options). + self.install_base = None + self.install_platbase = None + self.root = None + + # These options are the actual installation directories; if not + # supplied by the user, they are filled in using the installation + # scheme implied by prefix/exec-prefix/home and the contents of + # that installation scheme. + self.install_purelib = None # for pure module distributions + self.install_platlib = None # non-pure (dists w/ extensions) + self.install_headers = None # for C/C++ headers + self.install_lib = None # set to either purelib or platlib + self.install_scripts = None + self.install_data = None + self.install_userbase = USER_BASE + self.install_usersite = USER_SITE + + self.compile = None + self.optimize = None + + # These two are for putting non-packagized distributions into their + # own directory and creating a .pth file if it makes sense. + # 'extra_path' comes from the setup file; 'install_path_file' can + # be turned off if it makes no sense to install a .pth file. (But + # better to install it uselessly than to guess wrong and not + # install it when it's necessary and would be used!) Currently, + # 'install_path_file' is always true unless some outsider meddles + # with it. + self.extra_path = None + self.install_path_file = 1 + + # 'force' forces installation, even if target files are not + # out-of-date. 'skip_build' skips running the "build" command, + # handy if you know it's not necessary. 'warn_dir' (which is *not* + # a user option, it's just there so the bdist_* commands can turn + # it off) determines whether we warn about installing to a + # directory not in sys.path. + self.force = 0 + self.skip_build = 0 + self.warn_dir = 1 + + # These are only here as a conduit from the 'build' command to the + # 'install_*' commands that do the real work. ('build_base' isn't + # actually used anywhere, but it might be useful in future.) They + # are not user options, because if the user told the install + # command where the build directory is, that wouldn't affect the + # build command. + self.build_base = None + self.build_lib = None + + # Not defined yet because we don't know anything about + # documentation yet. + #self.install_man = None + #self.install_html = None + #self.install_info = None + + self.record = None + + + # -- Option finalizing methods ------------------------------------- + # (This is rather more involved than for most commands, + # because this is where the policy for installing third- + # party Python modules on various platforms given a wide + # array of user input is decided. Yes, it's quite complex!) + + def finalize_options (self): + + # This method (and its pliant slaves, like 'finalize_unix()', + # 'finalize_other()', and 'select_scheme()') is where the default + # installation directories for modules, extension modules, and + # anything else we care to install from a Python module + # distribution. Thus, this code makes a pretty important policy + # statement about how third-party stuff is added to a Python + # installation! Note that the actual work of installation is done + # by the relatively simple 'install_*' commands; they just take + # their orders from the installation directory options determined + # here. + + # Check for errors/inconsistencies in the options; first, stuff + # that's wrong on any platform. + + if ((self.prefix or self.exec_prefix or self.home) and + (self.install_base or self.install_platbase)): + raise DistutilsOptionError, \ + ("must supply either prefix/exec-prefix/home or " + + "install-base/install-platbase -- not both") + + if self.home and (self.prefix or self.exec_prefix): + raise DistutilsOptionError, \ + "must supply either home or prefix/exec-prefix -- not both" + + if self.user and (self.prefix or self.exec_prefix or self.home or + self.install_base or self.install_platbase): + raise DistutilsOptionError("can't combine user with prefix, " + "exec_prefix/home, or install_(plat)base") + + # Next, stuff that's wrong (or dubious) only on certain platforms. + if os.name != "posix": + if self.exec_prefix: + self.warn("exec-prefix option ignored on this platform") + self.exec_prefix = None + + # Now the interesting logic -- so interesting that we farm it out + # to other methods. The goal of these methods is to set the final + # values for the install_{lib,scripts,data,...} options, using as + # input a heady brew of prefix, exec_prefix, home, install_base, + # install_platbase, user-supplied versions of + # install_{purelib,platlib,lib,scripts,data,...}, and the + # INSTALL_SCHEME dictionary above. Phew! + + self.dump_dirs("pre-finalize_{unix,other}") + + if os.name == 'posix': + self.finalize_unix() + else: + self.finalize_other() + + self.dump_dirs("post-finalize_{unix,other}()") + + # Expand configuration variables, tilde, etc. in self.install_base + # and self.install_platbase -- that way, we can use $base or + # $platbase in the other installation directories and not worry + # about needing recursive variable expansion (shudder). + + py_version = (string.split(sys.version))[0] + (prefix, exec_prefix) = get_config_vars('prefix', 'exec_prefix') + self.config_vars = {'dist_name': self.distribution.get_name(), + 'dist_version': self.distribution.get_version(), + 'dist_fullname': self.distribution.get_fullname(), + 'py_version': py_version, + 'py_version_short': py_version[0:3], + 'py_version_nodot': py_version[0] + py_version[2], + 'sys_prefix': prefix, + 'prefix': prefix, + 'sys_exec_prefix': exec_prefix, + 'exec_prefix': exec_prefix, + 'userbase': self.install_userbase, + 'usersite': self.install_usersite, + } + self.expand_basedirs() + + self.dump_dirs("post-expand_basedirs()") + + # Now define config vars for the base directories so we can expand + # everything else. + self.config_vars['base'] = self.install_base + self.config_vars['platbase'] = self.install_platbase + + if DEBUG: + from pprint import pprint + print "config vars:" + pprint(self.config_vars) + + # Expand "~" and configuration variables in the installation + # directories. + self.expand_dirs() + + self.dump_dirs("post-expand_dirs()") + + # Create directories in the home dir: + if self.user: + self.create_home_path() + + # Pick the actual directory to install all modules to: either + # install_purelib or install_platlib, depending on whether this + # module distribution is pure or not. Of course, if the user + # already specified install_lib, use their selection. + if self.install_lib is None: + if self.distribution.ext_modules: # has extensions: non-pure + self.install_lib = self.install_platlib + else: + self.install_lib = self.install_purelib + + + # Convert directories from Unix /-separated syntax to the local + # convention. + self.convert_paths('lib', 'purelib', 'platlib', + 'scripts', 'data', 'headers', + 'userbase', 'usersite') + + # Well, we're not actually fully completely finalized yet: we still + # have to deal with 'extra_path', which is the hack for allowing + # non-packagized module distributions (hello, Numerical Python!) to + # get their own directories. + self.handle_extra_path() + self.install_libbase = self.install_lib # needed for .pth file + self.install_lib = os.path.join(self.install_lib, self.extra_dirs) + + # If a new root directory was supplied, make all the installation + # dirs relative to it. + if self.root is not None: + self.change_roots('libbase', 'lib', 'purelib', 'platlib', + 'scripts', 'data', 'headers') + + self.dump_dirs("after prepending root") + + # Find out the build directories, ie. where to install from. + self.set_undefined_options('build', + ('build_base', 'build_base'), + ('build_lib', 'build_lib')) + + # Punt on doc directories for now -- after all, we're punting on + # documentation completely! + + # finalize_options () + + + def dump_dirs (self, msg): + if DEBUG: + from distutils.fancy_getopt import longopt_xlate + print msg + ":" + for opt in self.user_options: + opt_name = opt[0] + if opt_name[-1] == "=": + opt_name = opt_name[0:-1] + if opt_name in self.negative_opt: + opt_name = string.translate(self.negative_opt[opt_name], + longopt_xlate) + val = not getattr(self, opt_name) + else: + opt_name = string.translate(opt_name, longopt_xlate) + val = getattr(self, opt_name) + print " %s: %s" % (opt_name, val) + + + def finalize_unix (self): + + if self.install_base is not None or self.install_platbase is not None: + if ((self.install_lib is None and + self.install_purelib is None and + self.install_platlib is None) or + self.install_headers is None or + self.install_scripts is None or + self.install_data is None): + raise DistutilsOptionError, \ + ("install-base or install-platbase supplied, but " + "installation scheme is incomplete") + return + + if self.user: + if self.install_userbase is None: + raise DistutilsPlatformError( + "User base directory is not specified") + self.install_base = self.install_platbase = self.install_userbase + self.select_scheme("unix_user") + elif self.home is not None: + self.install_base = self.install_platbase = self.home + self.select_scheme("unix_home") + else: + if self.prefix is None: + if self.exec_prefix is not None: + raise DistutilsOptionError, \ + "must not supply exec-prefix without prefix" + + self.prefix = os.path.normpath(sys.prefix) + self.exec_prefix = os.path.normpath(sys.exec_prefix) + + else: + if self.exec_prefix is None: + self.exec_prefix = self.prefix + + self.install_base = self.prefix + self.install_platbase = self.exec_prefix + self.select_scheme("unix_prefix") + + # finalize_unix () + + + def finalize_other (self): # Windows and Mac OS for now + + if self.user: + if self.install_userbase is None: + raise DistutilsPlatformError( + "User base directory is not specified") + self.install_base = self.install_platbase = self.install_userbase + self.select_scheme(os.name + "_user") + elif self.home is not None: + self.install_base = self.install_platbase = self.home + self.select_scheme("unix_home") + else: + if self.prefix is None: + self.prefix = os.path.normpath(sys.prefix) + + self.install_base = self.install_platbase = self.prefix + try: + self.select_scheme(os.name) + except KeyError: + raise DistutilsPlatformError, \ + "I don't know how to install stuff on '%s'" % os.name + + # finalize_other () + + + def select_scheme (self, name): + # it's the caller's problem if they supply a bad name! + scheme = INSTALL_SCHEMES[name] + for key in SCHEME_KEYS: + attrname = 'install_' + key + if getattr(self, attrname) is None: + setattr(self, attrname, scheme[key]) + + + def _expand_attrs (self, attrs): + for attr in attrs: + val = getattr(self, attr) + if val is not None: + if os.name == 'posix' or os.name == 'nt': + val = os.path.expanduser(val) + val = subst_vars(val, self.config_vars) + setattr(self, attr, val) + + + def expand_basedirs (self): + self._expand_attrs(['install_base', + 'install_platbase', + 'root']) + + def expand_dirs (self): + self._expand_attrs(['install_purelib', + 'install_platlib', + 'install_lib', + 'install_headers', + 'install_scripts', + 'install_data',]) + + + def convert_paths (self, *names): + for name in names: + attr = "install_" + name + setattr(self, attr, convert_path(getattr(self, attr))) + + + def handle_extra_path (self): + + if self.extra_path is None: + self.extra_path = self.distribution.extra_path + + if self.extra_path is not None: + if type(self.extra_path) is StringType: + self.extra_path = string.split(self.extra_path, ',') + + if len(self.extra_path) == 1: + path_file = extra_dirs = self.extra_path[0] + elif len(self.extra_path) == 2: + (path_file, extra_dirs) = self.extra_path + else: + raise DistutilsOptionError, \ + ("'extra_path' option must be a list, tuple, or " + "comma-separated string with 1 or 2 elements") + + # convert to local form in case Unix notation used (as it + # should be in setup scripts) + extra_dirs = convert_path(extra_dirs) + + else: + path_file = None + extra_dirs = '' + + # XXX should we warn if path_file and not extra_dirs? (in which + # case the path file would be harmless but pointless) + self.path_file = path_file + self.extra_dirs = extra_dirs + + # handle_extra_path () + + + def change_roots (self, *names): + for name in names: + attr = "install_" + name + setattr(self, attr, change_root(self.root, getattr(self, attr))) + + def create_home_path(self): + """Create directories under ~ + """ + if not self.user: + return + home = convert_path(os.path.expanduser("~")) + for name, path in self.config_vars.iteritems(): + if path.startswith(home) and not os.path.isdir(path): + self.debug_print("os.makedirs('%s', 0700)" % path) + os.makedirs(path, 0700) + + # -- Command execution methods ------------------------------------- + + def run (self): + + # Obviously have to build before we can install + if not self.skip_build: + self.run_command('build') + # If we built for any other platform, we can't install. + build_plat = self.distribution.get_command_obj('build').plat_name + # check warn_dir - it is a clue that the 'install' is happening + # internally, and not to sys.path, so we don't check the platform + # matches what we are running. + if self.warn_dir and build_plat != get_platform(): + raise DistutilsPlatformError("Can't install when " + "cross-compiling") + + # Run all sub-commands (at least those that need to be run) + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + if self.path_file: + self.create_path_file() + + # write list of installed files, if requested. + if self.record: + outputs = self.get_outputs() + if self.root: # strip any package prefix + root_len = len(self.root) + for counter in xrange(len(outputs)): + outputs[counter] = outputs[counter][root_len:] + self.execute(write_file, + (self.record, outputs), + "writing list of installed files to '%s'" % + self.record) + + sys_path = map(os.path.normpath, sys.path) + sys_path = map(os.path.normcase, sys_path) + install_lib = os.path.normcase(os.path.normpath(self.install_lib)) + if (self.warn_dir and + not (self.path_file and self.install_path_file) and + install_lib not in sys_path): + log.debug(("modules installed to '%s', which is not in " + "Python's module search path (sys.path) -- " + "you'll have to change the search path yourself"), + self.install_lib) + + # run () + + def create_path_file (self): + filename = os.path.join(self.install_libbase, + self.path_file + ".pth") + if self.install_path_file: + self.execute(write_file, + (filename, [self.extra_dirs]), + "creating %s" % filename) + else: + self.warn("path file '%s' not created" % filename) + + + # -- Reporting methods --------------------------------------------- + + def get_outputs (self): + # Assemble the outputs of all the sub-commands. + outputs = [] + for cmd_name in self.get_sub_commands(): + cmd = self.get_finalized_command(cmd_name) + # Add the contents of cmd.get_outputs(), ensuring + # that outputs doesn't contain duplicate entries + for filename in cmd.get_outputs(): + if filename not in outputs: + outputs.append(filename) + + if self.path_file and self.install_path_file: + outputs.append(os.path.join(self.install_libbase, + self.path_file + ".pth")) + + return outputs + + def get_inputs (self): + # XXX gee, this looks familiar ;-( + inputs = [] + for cmd_name in self.get_sub_commands(): + cmd = self.get_finalized_command(cmd_name) + inputs.extend(cmd.get_inputs()) + + return inputs + + + # -- Predicates for sub-command list ------------------------------- + + def has_lib (self): + """Return true if the current distribution has any Python + modules to install.""" + return (self.distribution.has_pure_modules() or + self.distribution.has_ext_modules()) + + def has_headers (self): + return self.distribution.has_headers() + + def has_scripts (self): + return self.distribution.has_scripts() + + def has_data (self): + return self.distribution.has_data_files() + + + # 'sub_commands': a list of commands this command might have to run to + # get its work done. See cmd.py for more info. + sub_commands = [('install_lib', has_lib), + ('install_headers', has_headers), + ('install_scripts', has_scripts), + ('install_data', has_data), + ('install_egg_info', lambda self:True), + ] + +# class install diff --git a/PythonHome/Lib/distutils/command/install.pyc b/PythonHome/Lib/distutils/command/install.pyc deleted file mode 100644 index bb03fb85e57f2a3501405059d3e9b71e59b78afa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16755 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 II?!MIKWtX`(*OVf diff --git a/PythonHome/Lib/distutils/command/install_data.py b/PythonHome/Lib/distutils/command/install_data.py new file mode 100644 index 0000000000..ab40797b98 --- /dev/null +++ b/PythonHome/Lib/distutils/command/install_data.py @@ -0,0 +1,81 @@ +"""distutils.command.install_data + +Implements the Distutils 'install_data' command, for installing +platform-independent data files.""" + +# contributed by Bastian Kleineidam + +__revision__ = "$Id$" + +import os +from distutils.core import Command +from distutils.util import change_root, convert_path + +class install_data(Command): + + description = "install data files" + + user_options = [ + ('install-dir=', 'd', + "base directory for installing data files " + "(default: installation base dir)"), + ('root=', None, + "install everything relative to this alternate root directory"), + ('force', 'f', "force installation (overwrite existing files)"), + ] + + boolean_options = ['force'] + + def initialize_options(self): + self.install_dir = None + self.outfiles = [] + self.root = None + self.force = 0 + self.data_files = self.distribution.data_files + self.warn_dir = 1 + + def finalize_options(self): + self.set_undefined_options('install', + ('install_data', 'install_dir'), + ('root', 'root'), + ('force', 'force'), + ) + + def run(self): + self.mkpath(self.install_dir) + for f in self.data_files: + if isinstance(f, str): + # it's a simple file, so copy it + f = convert_path(f) + if self.warn_dir: + self.warn("setup script did not provide a directory for " + "'%s' -- installing right in '%s'" % + (f, self.install_dir)) + (out, _) = self.copy_file(f, self.install_dir) + self.outfiles.append(out) + else: + # it's a tuple with path to install to and a list of files + dir = convert_path(f[0]) + if not os.path.isabs(dir): + dir = os.path.join(self.install_dir, dir) + elif self.root: + dir = change_root(self.root, dir) + self.mkpath(dir) + + if f[1] == []: + # If there are no files listed, the user must be + # trying to create an empty directory, so add the + # directory to the list of output files. + self.outfiles.append(dir) + else: + # Copy files, adding them to the list of output files. + for data in f[1]: + data = convert_path(data) + (out, _) = self.copy_file(data, dir) + self.outfiles.append(out) + + def get_inputs(self): + return self.data_files or [] + + def get_outputs(self): + return self.outfiles diff --git a/PythonHome/Lib/distutils/command/install_data.pyc b/PythonHome/Lib/distutils/command/install_data.pyc deleted file mode 100644 index 92a6a3cb976b748ead4ef199aaccf90e04ea74ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3059 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 diff --git a/PythonHome/Lib/distutils/command/install_headers.py b/PythonHome/Lib/distutils/command/install_headers.py new file mode 100644 index 0000000000..d892416a8c --- /dev/null +++ b/PythonHome/Lib/distutils/command/install_headers.py @@ -0,0 +1,51 @@ +"""distutils.command.install_headers + +Implements the Distutils 'install_headers' command, to install C/C++ header +files to the Python include directory.""" + +__revision__ = "$Id$" + +from distutils.core import Command + + +# XXX force is never used +class install_headers(Command): + + description = "install C/C++ header files" + + user_options = [('install-dir=', 'd', + "directory to install header files to"), + ('force', 'f', + "force installation (overwrite existing files)"), + ] + + boolean_options = ['force'] + + def initialize_options(self): + self.install_dir = None + self.force = 0 + self.outfiles = [] + + def finalize_options(self): + self.set_undefined_options('install', + ('install_headers', 'install_dir'), + ('force', 'force')) + + + def run(self): + headers = self.distribution.headers + if not headers: + return + + self.mkpath(self.install_dir) + for header in headers: + (out, _) = self.copy_file(header, self.install_dir) + self.outfiles.append(out) + + def get_inputs(self): + return self.distribution.headers or [] + + def get_outputs(self): + return self.outfiles + +# class install_headers diff --git a/PythonHome/Lib/distutils/command/install_headers.pyc b/PythonHome/Lib/distutils/command/install_headers.pyc deleted file mode 100644 index 3513c7d21b7458e9d24f294b6bf57f94d3ecff90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2191 zcmb_dQE%Kt5FXoim-w2{s1gN%5SEBkL&>$gR6+uTNM9>?E&NtE^NL zQ(Bi5MS7w$r5igQKUvjjLXdK)iH zq2ZNmXKFUaXallxcMCs^)BB2Z(I{iP|@R;um{(avbqt8=|`n{o1>Gbol6Z zxa?C14Rnw`B%s+LwM$E%p#d^WKn5_j7@66S)V3%iQlThYq{gCble#5JNXb$B4txFp z;->5($^{pb#lHj8Len0G-3_sEQ8l@igA04mJ$I01&H%Q!dZC+_ zjd42CuTT?HE?Xa;=KMmwd|ZdP?8gv5;hZQ19G)mXEn5rVAW(ugPYndc0|>`rT9w+} zg3_Ul1QO<-+lHvtPBLx_#QUu-7BTK5!hQyAGXLHj&wHB9Hx!w79yc_b)MxGvwwuy8 zlNII{omMsHY2Sy{jv&Yj@$Zvkm?XLPpdhnTq$pGe!7rKpoD{QWD%{z;FJW8~b|-mA z*7gQI*=t$18~f7OUTc$o7Y?m<>AF;UVM?vK=w&%!wB8(-J)DNqf1vUazpz6kXi?#q zxC(;G0!oX@sYe$mxkvV{RGO{6tOa!Gk@xCLUVQxH7j)5@2Xx-A`!x6IBA^Qxac)Sb zBRX%-JwKpl0y0B76{sC^pKINiV@#E*6zDf4b{y{N=Q?vIQUDj?Ij`!olv$K;sbou5 z*Sb_OXCuHR+;pxrP z4&@;pH=)Fg;J?OQ!g2oRY1jJbyD5<=^4b$GX1HV~rD>V1becN0r0J?s>w+IS3#Dz| z7?~M9<1m;C{iS=-R8=`L;1g-u=oiMKv0z}%_Hz}V??xxEkhuSU5ekxDwb*?l M72($9NcRSR0Z5SeR{#J2 diff --git a/PythonHome/Lib/distutils/command/install_lib.py b/PythonHome/Lib/distutils/command/install_lib.py new file mode 100644 index 0000000000..043e8b6e27 --- /dev/null +++ b/PythonHome/Lib/distutils/command/install_lib.py @@ -0,0 +1,219 @@ +"""distutils.command.install_lib + +Implements the Distutils 'install_lib' command +(install all Python modules).""" + +__revision__ = "$Id$" + +import os +import sys + +from distutils.core import Command +from distutils.errors import DistutilsOptionError + + +# Extension for Python source files. +if hasattr(os, 'extsep'): + PYTHON_SOURCE_EXTENSION = os.extsep + "py" +else: + PYTHON_SOURCE_EXTENSION = ".py" + +class install_lib(Command): + + description = "install all Python modules (extensions and pure Python)" + + # The byte-compilation options are a tad confusing. Here are the + # possible scenarios: + # 1) no compilation at all (--no-compile --no-optimize) + # 2) compile .pyc only (--compile --no-optimize; default) + # 3) compile .pyc and "level 1" .pyo (--compile --optimize) + # 4) compile "level 1" .pyo only (--no-compile --optimize) + # 5) compile .pyc and "level 2" .pyo (--compile --optimize-more) + # 6) compile "level 2" .pyo only (--no-compile --optimize-more) + # + # The UI for this is two option, 'compile' and 'optimize'. + # 'compile' is strictly boolean, and only decides whether to + # generate .pyc files. 'optimize' is three-way (0, 1, or 2), and + # decides both whether to generate .pyo files and what level of + # optimization to use. + + user_options = [ + ('install-dir=', 'd', "directory to install to"), + ('build-dir=','b', "build directory (where to install from)"), + ('force', 'f', "force installation (overwrite existing files)"), + ('compile', 'c', "compile .py to .pyc [default]"), + ('no-compile', None, "don't compile .py files"), + ('optimize=', 'O', + "also compile with optimization: -O1 for \"python -O\", " + "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), + ('skip-build', None, "skip the build steps"), + ] + + boolean_options = ['force', 'compile', 'skip-build'] + negative_opt = {'no-compile' : 'compile'} + + def initialize_options(self): + # let the 'install' command dictate our installation directory + self.install_dir = None + self.build_dir = None + self.force = 0 + self.compile = None + self.optimize = None + self.skip_build = None + + def finalize_options(self): + # Get all the information we need to install pure Python modules + # from the umbrella 'install' command -- build (source) directory, + # install (target) directory, and whether to compile .py files. + self.set_undefined_options('install', + ('build_lib', 'build_dir'), + ('install_lib', 'install_dir'), + ('force', 'force'), + ('compile', 'compile'), + ('optimize', 'optimize'), + ('skip_build', 'skip_build'), + ) + + if self.compile is None: + self.compile = 1 + if self.optimize is None: + self.optimize = 0 + + if not isinstance(self.optimize, int): + try: + self.optimize = int(self.optimize) + if self.optimize not in (0, 1, 2): + raise AssertionError + except (ValueError, AssertionError): + raise DistutilsOptionError, "optimize must be 0, 1, or 2" + + def run(self): + # Make sure we have built everything we need first + self.build() + + # Install everything: simply dump the entire contents of the build + # directory to the installation directory (that's the beauty of + # having a build directory!) + outfiles = self.install() + + # (Optionally) compile .py to .pyc + if outfiles is not None and self.distribution.has_pure_modules(): + self.byte_compile(outfiles) + + # -- Top-level worker functions ------------------------------------ + # (called from 'run()') + + def build(self): + if not self.skip_build: + if self.distribution.has_pure_modules(): + self.run_command('build_py') + if self.distribution.has_ext_modules(): + self.run_command('build_ext') + + def install(self): + if os.path.isdir(self.build_dir): + outfiles = self.copy_tree(self.build_dir, self.install_dir) + else: + self.warn("'%s' does not exist -- no Python modules to install" % + self.build_dir) + return + return outfiles + + def byte_compile(self, files): + if sys.dont_write_bytecode: + self.warn('byte-compiling is disabled, skipping.') + return + + from distutils.util import byte_compile + + # Get the "--root" directory supplied to the "install" command, + # and use it as a prefix to strip off the purported filename + # encoded in bytecode files. This is far from complete, but it + # should at least generate usable bytecode in RPM distributions. + install_root = self.get_finalized_command('install').root + + if self.compile: + byte_compile(files, optimize=0, + force=self.force, prefix=install_root, + dry_run=self.dry_run) + if self.optimize > 0: + byte_compile(files, optimize=self.optimize, + force=self.force, prefix=install_root, + verbose=self.verbose, dry_run=self.dry_run) + + + # -- Utility methods ----------------------------------------------- + + def _mutate_outputs(self, has_any, build_cmd, cmd_option, output_dir): + if not has_any: + return [] + + build_cmd = self.get_finalized_command(build_cmd) + build_files = build_cmd.get_outputs() + build_dir = getattr(build_cmd, cmd_option) + + prefix_len = len(build_dir) + len(os.sep) + outputs = [] + for file in build_files: + outputs.append(os.path.join(output_dir, file[prefix_len:])) + + return outputs + + def _bytecode_filenames(self, py_filenames): + bytecode_files = [] + for py_file in py_filenames: + # Since build_py handles package data installation, the + # list of outputs can contain more than just .py files. + # Make sure we only report bytecode for the .py files. + ext = os.path.splitext(os.path.normcase(py_file))[1] + if ext != PYTHON_SOURCE_EXTENSION: + continue + if self.compile: + bytecode_files.append(py_file + "c") + if self.optimize > 0: + bytecode_files.append(py_file + "o") + + return bytecode_files + + + # -- External interface -------------------------------------------- + # (called by outsiders) + + def get_outputs(self): + """Return the list of files that would be installed if this command + were actually run. Not affected by the "dry-run" flag or whether + modules have actually been built yet. + """ + pure_outputs = \ + self._mutate_outputs(self.distribution.has_pure_modules(), + 'build_py', 'build_lib', + self.install_dir) + if self.compile: + bytecode_outputs = self._bytecode_filenames(pure_outputs) + else: + bytecode_outputs = [] + + ext_outputs = \ + self._mutate_outputs(self.distribution.has_ext_modules(), + 'build_ext', 'build_lib', + self.install_dir) + + return pure_outputs + bytecode_outputs + ext_outputs + + def get_inputs(self): + """Get the list of files that are input to this command, ie. the + files that get installed as they are named in the build tree. + The files in this list correspond one-to-one to the output + filenames returned by 'get_outputs()'. + """ + inputs = [] + + if self.distribution.has_pure_modules(): + build_py = self.get_finalized_command('build_py') + inputs.extend(build_py.get_outputs()) + + if self.distribution.has_ext_modules(): + build_ext = self.get_finalized_command('build_ext') + inputs.extend(build_ext.get_outputs()) + + return inputs diff --git a/PythonHome/Lib/distutils/command/install_lib.pyc b/PythonHome/Lib/distutils/command/install_lib.pyc deleted file mode 100644 index 146bf0ae32db83a47ceb150d9320aeff2836546e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6604 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 ZZtka?%2Liaa_uypUsi&Z2Cmd7{RfM>(y9Oe diff --git a/PythonHome/Lib/distutils/command/install_scripts.py b/PythonHome/Lib/distutils/command/install_scripts.py new file mode 100644 index 0000000000..29cd9e7a0e --- /dev/null +++ b/PythonHome/Lib/distutils/command/install_scripts.py @@ -0,0 +1,64 @@ +"""distutils.command.install_scripts + +Implements the Distutils 'install_scripts' command, for installing +Python scripts.""" + +# contributed by Bastian Kleineidam + +__revision__ = "$Id$" + +import os +from distutils.core import Command +from distutils import log +from stat import ST_MODE + +class install_scripts (Command): + + description = "install scripts (Python or otherwise)" + + user_options = [ + ('install-dir=', 'd', "directory to install scripts to"), + ('build-dir=','b', "build directory (where to install from)"), + ('force', 'f', "force installation (overwrite existing files)"), + ('skip-build', None, "skip the build steps"), + ] + + boolean_options = ['force', 'skip-build'] + + + def initialize_options (self): + self.install_dir = None + self.force = 0 + self.build_dir = None + self.skip_build = None + + def finalize_options (self): + self.set_undefined_options('build', ('build_scripts', 'build_dir')) + self.set_undefined_options('install', + ('install_scripts', 'install_dir'), + ('force', 'force'), + ('skip_build', 'skip_build'), + ) + + def run (self): + if not self.skip_build: + self.run_command('build_scripts') + self.outfiles = self.copy_tree(self.build_dir, self.install_dir) + if os.name == 'posix': + # Set the executable bits (owner, group, and world) on + # all the scripts we just installed. + for file in self.get_outputs(): + if self.dry_run: + log.info("changing mode of %s", file) + else: + mode = ((os.stat(file)[ST_MODE]) | 0555) & 07777 + log.info("changing mode of %s to %o", file, mode) + os.chmod(file, mode) + + def get_inputs (self): + return self.distribution.scripts or [] + + def get_outputs(self): + return self.outfiles or [] + +# class install_scripts diff --git a/PythonHome/Lib/distutils/command/install_scripts.pyc b/PythonHome/Lib/distutils/command/install_scripts.pyc deleted file mode 100644 index 1adbdeb636ae186506d21012b61e3386dbcd25d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2893 zcmb_e;cgp65T3hp9NTr8&`?lS5GS=!E2@^nw<)(x^Ov7!s@&Po9jS1? zek0tzpt>DaXM7!wO%YbRI-hhNpSmNHht-jLwt<`PK1%QExA^Nt9;R*;!^6^sa)B|) z%w)NH@N@FxPy64yb!=R?dI4k;dk^r~rx+A~g!dSM)JK%wpmdYcn=}#p08iSX37}n} zw95zq#B@yrY+VghRTlGwJ@q&h5rU<6|b~aJGQ&j+)Z_H z&#}j;{enkbsF5?pY3NK1+2S;3YzI2Sxz5t%i$l9zFNVw4qgS|2oj+w@#O=Moe+Cn=OsuP45VGGAPQ+7v8u+Q~uSM0DK;{cut8)PZ8PR;Cy zo#MyG^N^Jy3_$-iQGzgdA|MjwN>B?877ikQtEVwg#3s82&rPn}H3)UM;cmTWiTRG_ zrEirnG5aS8Qdt>uZp4g%pb;}f0$|L!Vc!8q*6k%ZV=n+(DlX_^7gD*wHY_n-km5Y# zH(5owWS*yLtaFvtm`Oxp&Vu)k#s=QTq3^`v4qwQIk+*?Z1o%ia7#=oXqVXq$5`BA1 z1mWVDM_yiT__7+v*x+C>VOPjC=@@mur{_Kuf6&PbQD|`;-T&noy%9bix2Y%y1UyDe zafBzqe(_k|?#kRFMD$kLpa-bd_uu%nc9VBs`*aqN$9G+?=U@vCcmnH$9$XlE5?JBL z%vgP5H?cT68srns)2T^SXvX1|)l(#(ev4?s*Go0HKx~__D38tVTfq(Eh4aM@6Q=N6efIyFDYA`vK!uQZ#~$AwCUgWHcP_PrAr9IOe+a< z?9ptUCY+?K(UVMY%wsMfg&v}Hnq0iCQuRYHoe9lg>YTCs1~bcG(IuvGsVGgIbwDNWKQEHsDwV0FjDqXESWKp4F&XKEkw%*c~ zWq<4aYlDlpU`ie&39~*)r12yPNIK7W$_l9}sQ_ZcoHIg~xm8774CVLB(3ngO@_H@i zK*ro~;*f_sJTUG{?u&HA7AAc{S^{&S={Ex|k%89^xz diff --git a/PythonHome/Lib/distutils/command/register.py b/PythonHome/Lib/distutils/command/register.py new file mode 100644 index 0000000000..edb42b955d --- /dev/null +++ b/PythonHome/Lib/distutils/command/register.py @@ -0,0 +1,315 @@ +"""distutils.command.register + +Implements the Distutils 'register' command (register with the repository). +""" + +# created 2002/10/21, Richard Jones + +__revision__ = "$Id$" + +import urllib2 +import getpass +import urlparse +from warnings import warn + +from distutils.core import PyPIRCCommand +from distutils import log + +class register(PyPIRCCommand): + + description = ("register the distribution with the Python package index") + user_options = PyPIRCCommand.user_options + [ + ('list-classifiers', None, + 'list the valid Trove classifiers'), + ('strict', None , + 'Will stop the registering if the meta-data are not fully compliant') + ] + boolean_options = PyPIRCCommand.boolean_options + [ + 'verify', 'list-classifiers', 'strict'] + + sub_commands = [('check', lambda self: True)] + + def initialize_options(self): + PyPIRCCommand.initialize_options(self) + self.list_classifiers = 0 + self.strict = 0 + + def finalize_options(self): + PyPIRCCommand.finalize_options(self) + # setting options for the `check` subcommand + check_options = {'strict': ('register', self.strict), + 'restructuredtext': ('register', 1)} + self.distribution.command_options['check'] = check_options + + def run(self): + self.finalize_options() + self._set_config() + + # Run sub commands + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + if self.dry_run: + self.verify_metadata() + elif self.list_classifiers: + self.classifiers() + else: + self.send_metadata() + + def check_metadata(self): + """Deprecated API.""" + warn("distutils.command.register.check_metadata is deprecated, \ + use the check command instead", PendingDeprecationWarning) + check = self.distribution.get_command_obj('check') + check.ensure_finalized() + check.strict = self.strict + check.restructuredtext = 1 + check.run() + + def _set_config(self): + ''' Reads the configuration file and set attributes. + ''' + config = self._read_pypirc() + if config != {}: + self.username = config['username'] + self.password = config['password'] + self.repository = config['repository'] + self.realm = config['realm'] + self.has_config = True + else: + if self.repository not in ('pypi', self.DEFAULT_REPOSITORY): + raise ValueError('%s not found in .pypirc' % self.repository) + if self.repository == 'pypi': + self.repository = self.DEFAULT_REPOSITORY + self.has_config = False + + def classifiers(self): + ''' Fetch the list of classifiers from the server. + ''' + response = urllib2.urlopen(self.repository+'?:action=list_classifiers') + log.info(response.read()) + + def verify_metadata(self): + ''' Send the metadata to the package index server to be checked. + ''' + # send the info to the server and report the result + (code, result) = self.post_to_server(self.build_post_data('verify')) + log.info('Server response (%s): %s' % (code, result)) + + + def send_metadata(self): + ''' Send the metadata to the package index server. + + Well, do the following: + 1. figure who the user is, and then + 2. send the data as a Basic auth'ed POST. + + First we try to read the username/password from $HOME/.pypirc, + which is a ConfigParser-formatted file with a section + [distutils] containing username and password entries (both + in clear text). Eg: + + [distutils] + index-servers = + pypi + + [pypi] + username: fred + password: sekrit + + Otherwise, to figure who the user is, we offer the user three + choices: + + 1. use existing login, + 2. register as a new user, or + 3. set the password to a random string and email the user. + + ''' + # see if we can short-cut and get the username/password from the + # config + if self.has_config: + choice = '1' + username = self.username + password = self.password + else: + choice = 'x' + username = password = '' + + # get the user's login info + choices = '1 2 3 4'.split() + while choice not in choices: + self.announce('''\ +We need to know who you are, so please choose either: + 1. use your existing login, + 2. register as a new user, + 3. have the server generate a new password for you (and email it to you), or + 4. quit +Your selection [default 1]: ''', log.INFO) + + choice = raw_input() + if not choice: + choice = '1' + elif choice not in choices: + print 'Please choose one of the four options!' + + if choice == '1': + # get the username and password + while not username: + username = raw_input('Username: ') + while not password: + password = getpass.getpass('Password: ') + + # set up the authentication + auth = urllib2.HTTPPasswordMgr() + host = urlparse.urlparse(self.repository)[1] + auth.add_password(self.realm, host, username, password) + # send the info to the server and report the result + code, result = self.post_to_server(self.build_post_data('submit'), + auth) + self.announce('Server response (%s): %s' % (code, result), + log.INFO) + + # possibly save the login + if code == 200: + if self.has_config: + # sharing the password in the distribution instance + # so the upload command can reuse it + self.distribution.password = password + else: + self.announce(('I can store your PyPI login so future ' + 'submissions will be faster.'), log.INFO) + self.announce('(the login will be stored in %s)' % \ + self._get_rc_file(), log.INFO) + choice = 'X' + while choice.lower() not in 'yn': + choice = raw_input('Save your login (y/N)?') + if not choice: + choice = 'n' + if choice.lower() == 'y': + self._store_pypirc(username, password) + + elif choice == '2': + data = {':action': 'user'} + data['name'] = data['password'] = data['email'] = '' + data['confirm'] = None + while not data['name']: + data['name'] = raw_input('Username: ') + while data['password'] != data['confirm']: + while not data['password']: + data['password'] = getpass.getpass('Password: ') + while not data['confirm']: + data['confirm'] = getpass.getpass(' Confirm: ') + if data['password'] != data['confirm']: + data['password'] = '' + data['confirm'] = None + print "Password and confirm don't match!" + while not data['email']: + data['email'] = raw_input(' EMail: ') + code, result = self.post_to_server(data) + if code != 200: + log.info('Server response (%s): %s' % (code, result)) + else: + log.info('You will receive an email shortly.') + log.info(('Follow the instructions in it to ' + 'complete registration.')) + elif choice == '3': + data = {':action': 'password_reset'} + data['email'] = '' + while not data['email']: + data['email'] = raw_input('Your email address: ') + code, result = self.post_to_server(data) + log.info('Server response (%s): %s' % (code, result)) + + def build_post_data(self, action): + # figure the data to send - the metadata plus some additional + # information used by the package server + meta = self.distribution.metadata + data = { + ':action': action, + 'metadata_version' : '1.0', + 'name': meta.get_name(), + 'version': meta.get_version(), + 'summary': meta.get_description(), + 'home_page': meta.get_url(), + 'author': meta.get_contact(), + 'author_email': meta.get_contact_email(), + 'license': meta.get_licence(), + 'description': meta.get_long_description(), + 'keywords': meta.get_keywords(), + 'platform': meta.get_platforms(), + 'classifiers': meta.get_classifiers(), + 'download_url': meta.get_download_url(), + # PEP 314 + 'provides': meta.get_provides(), + 'requires': meta.get_requires(), + 'obsoletes': meta.get_obsoletes(), + } + if data['provides'] or data['requires'] or data['obsoletes']: + data['metadata_version'] = '1.1' + return data + + def post_to_server(self, data, auth=None): + ''' Post a query to the server, and return a string response. + ''' + if 'name' in data: + self.announce('Registering %s to %s' % (data['name'], + self.repository), + log.INFO) + # Build up the MIME payload for the urllib2 POST data + boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' + sep_boundary = '\n--' + boundary + end_boundary = sep_boundary + '--' + chunks = [] + for key, value in data.items(): + # handle multiple entries for the same name + if type(value) not in (type([]), type( () )): + value = [value] + for value in value: + chunks.append(sep_boundary) + chunks.append('\nContent-Disposition: form-data; name="%s"'%key) + chunks.append("\n\n") + chunks.append(value) + if value and value[-1] == '\r': + chunks.append('\n') # write an extra newline (lurve Macs) + chunks.append(end_boundary) + chunks.append("\n") + + # chunks may be bytes (str) or unicode objects that we need to encode + body = [] + for chunk in chunks: + if isinstance(chunk, unicode): + body.append(chunk.encode('utf-8')) + else: + body.append(chunk) + + body = ''.join(body) + + # build the Request + headers = { + 'Content-type': 'multipart/form-data; boundary=%s; charset=utf-8'%boundary, + 'Content-length': str(len(body)) + } + req = urllib2.Request(self.repository, body, headers) + + # handle HTTP and include the Basic Auth handler + opener = urllib2.build_opener( + urllib2.HTTPBasicAuthHandler(password_mgr=auth) + ) + data = '' + try: + result = opener.open(req) + except urllib2.HTTPError, e: + if self.show_response: + data = e.fp.read() + result = e.code, e.msg + except urllib2.URLError, e: + result = 500, str(e) + else: + if self.show_response: + data = result.read() + result = 200, 'OK' + if self.show_response: + dashes = '-' * 75 + self.announce('%s%s%s' % (dashes, data, dashes)) + + return result diff --git a/PythonHome/Lib/distutils/command/register.pyc b/PythonHome/Lib/distutils/command/register.pyc deleted file mode 100644 index 7535f6dc6b654ed9745c654650377415dbc5eebd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10027 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 diff --git a/PythonHome/Lib/distutils/command/sdist.py b/PythonHome/Lib/distutils/command/sdist.py new file mode 100644 index 0000000000..821420d62b --- /dev/null +++ b/PythonHome/Lib/distutils/command/sdist.py @@ -0,0 +1,477 @@ +"""distutils.command.sdist + +Implements the Distutils 'sdist' command (create a source distribution).""" + +__revision__ = "$Id$" + +import os +import string +import sys +from glob import glob +from warnings import warn + +from distutils.core import Command +from distutils import dir_util, dep_util, file_util, archive_util +from distutils.text_file import TextFile +from distutils.errors import (DistutilsPlatformError, DistutilsOptionError, + DistutilsTemplateError) +from distutils.filelist import FileList +from distutils import log +from distutils.util import convert_path + +def show_formats(): + """Print all possible values for the 'formats' option (used by + the "--help-formats" command-line option). + """ + from distutils.fancy_getopt import FancyGetopt + from distutils.archive_util import ARCHIVE_FORMATS + formats = [] + for format in ARCHIVE_FORMATS.keys(): + formats.append(("formats=" + format, None, + ARCHIVE_FORMATS[format][2])) + formats.sort() + FancyGetopt(formats).print_help( + "List of available source distribution formats:") + +class sdist(Command): + + description = "create a source distribution (tarball, zip file, etc.)" + + def checking_metadata(self): + """Callable used for the check sub-command. + + Placed here so user_options can view it""" + return self.metadata_check + + user_options = [ + ('template=', 't', + "name of manifest template file [default: MANIFEST.in]"), + ('manifest=', 'm', + "name of manifest file [default: MANIFEST]"), + ('use-defaults', None, + "include the default file set in the manifest " + "[default; disable with --no-defaults]"), + ('no-defaults', None, + "don't include the default file set"), + ('prune', None, + "specifically exclude files/directories that should not be " + "distributed (build tree, RCS/CVS dirs, etc.) " + "[default; disable with --no-prune]"), + ('no-prune', None, + "don't automatically exclude anything"), + ('manifest-only', 'o', + "just regenerate the manifest and then stop " + "(implies --force-manifest)"), + ('force-manifest', 'f', + "forcibly regenerate the manifest and carry on as usual. " + "Deprecated: now the manifest is always regenerated."), + ('formats=', None, + "formats for source distribution (comma-separated list)"), + ('keep-temp', 'k', + "keep the distribution tree around after creating " + + "archive file(s)"), + ('dist-dir=', 'd', + "directory to put the source distribution archive(s) in " + "[default: dist]"), + ('metadata-check', None, + "Ensure that all required elements of meta-data " + "are supplied. Warn if any missing. [default]"), + ('owner=', 'u', + "Owner name used when creating a tar file [default: current user]"), + ('group=', 'g', + "Group name used when creating a tar file [default: current group]"), + ] + + boolean_options = ['use-defaults', 'prune', + 'manifest-only', 'force-manifest', + 'keep-temp', 'metadata-check'] + + help_options = [ + ('help-formats', None, + "list available distribution formats", show_formats), + ] + + negative_opt = {'no-defaults': 'use-defaults', + 'no-prune': 'prune' } + + default_format = {'posix': 'gztar', + 'nt': 'zip' } + + sub_commands = [('check', checking_metadata)] + + def initialize_options(self): + # 'template' and 'manifest' are, respectively, the names of + # the manifest template and manifest file. + self.template = None + self.manifest = None + + # 'use_defaults': if true, we will include the default file set + # in the manifest + self.use_defaults = 1 + self.prune = 1 + + self.manifest_only = 0 + self.force_manifest = 0 + + self.formats = None + self.keep_temp = 0 + self.dist_dir = None + + self.archive_files = None + self.metadata_check = 1 + self.owner = None + self.group = None + + def finalize_options(self): + if self.manifest is None: + self.manifest = "MANIFEST" + if self.template is None: + self.template = "MANIFEST.in" + + self.ensure_string_list('formats') + if self.formats is None: + try: + self.formats = [self.default_format[os.name]] + except KeyError: + raise DistutilsPlatformError, \ + "don't know how to create source distributions " + \ + "on platform %s" % os.name + + bad_format = archive_util.check_archive_formats(self.formats) + if bad_format: + raise DistutilsOptionError, \ + "unknown archive format '%s'" % bad_format + + if self.dist_dir is None: + self.dist_dir = "dist" + + def run(self): + # 'filelist' contains the list of files that will make up the + # manifest + self.filelist = FileList() + + # Run sub commands + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + # Do whatever it takes to get the list of files to process + # (process the manifest template, read an existing manifest, + # whatever). File list is accumulated in 'self.filelist'. + self.get_file_list() + + # If user just wanted us to regenerate the manifest, stop now. + if self.manifest_only: + return + + # Otherwise, go ahead and create the source distribution tarball, + # or zipfile, or whatever. + self.make_distribution() + + def check_metadata(self): + """Deprecated API.""" + warn("distutils.command.sdist.check_metadata is deprecated, \ + use the check command instead", PendingDeprecationWarning) + check = self.distribution.get_command_obj('check') + check.ensure_finalized() + check.run() + + def get_file_list(self): + """Figure out the list of files to include in the source + distribution, and put it in 'self.filelist'. This might involve + reading the manifest template (and writing the manifest), or just + reading the manifest, or just using the default file set -- it all + depends on the user's options. + """ + # new behavior when using a template: + # the file list is recalculated every time because + # even if MANIFEST.in or setup.py are not changed + # the user might have added some files in the tree that + # need to be included. + # + # This makes --force the default and only behavior with templates. + template_exists = os.path.isfile(self.template) + if not template_exists and self._manifest_is_not_generated(): + self.read_manifest() + self.filelist.sort() + self.filelist.remove_duplicates() + return + + if not template_exists: + self.warn(("manifest template '%s' does not exist " + + "(using default file list)") % + self.template) + self.filelist.findall() + + if self.use_defaults: + self.add_defaults() + + if template_exists: + self.read_template() + + if self.prune: + self.prune_file_list() + + self.filelist.sort() + self.filelist.remove_duplicates() + self.write_manifest() + + def add_defaults(self): + """Add all the default files to self.filelist: + - README or README.txt + - setup.py + - test/test*.py + - all pure Python modules mentioned in setup script + - all files pointed by package_data (build_py) + - all files defined in data_files. + - all files defined as scripts. + - all C sources listed as part of extensions or C libraries + in the setup script (doesn't catch C headers!) + Warns if (README or README.txt) or setup.py are missing; everything + else is optional. + """ + + standards = [('README', 'README.txt'), self.distribution.script_name] + for fn in standards: + if isinstance(fn, tuple): + alts = fn + got_it = 0 + for fn in alts: + if os.path.exists(fn): + got_it = 1 + self.filelist.append(fn) + break + + if not got_it: + self.warn("standard file not found: should have one of " + + string.join(alts, ', ')) + else: + if os.path.exists(fn): + self.filelist.append(fn) + else: + self.warn("standard file '%s' not found" % fn) + + optional = ['test/test*.py', 'setup.cfg'] + for pattern in optional: + files = filter(os.path.isfile, glob(pattern)) + if files: + self.filelist.extend(files) + + # build_py is used to get: + # - python modules + # - files defined in package_data + build_py = self.get_finalized_command('build_py') + + # getting python files + if self.distribution.has_pure_modules(): + self.filelist.extend(build_py.get_source_files()) + + # getting package_data files + # (computed in build_py.data_files by build_py.finalize_options) + for pkg, src_dir, build_dir, filenames in build_py.data_files: + for filename in filenames: + self.filelist.append(os.path.join(src_dir, filename)) + + # getting distribution.data_files + if self.distribution.has_data_files(): + for item in self.distribution.data_files: + if isinstance(item, str): # plain file + item = convert_path(item) + if os.path.isfile(item): + self.filelist.append(item) + else: # a (dirname, filenames) tuple + dirname, filenames = item + for f in filenames: + f = convert_path(f) + if os.path.isfile(f): + self.filelist.append(f) + + if self.distribution.has_ext_modules(): + build_ext = self.get_finalized_command('build_ext') + self.filelist.extend(build_ext.get_source_files()) + + if self.distribution.has_c_libraries(): + build_clib = self.get_finalized_command('build_clib') + self.filelist.extend(build_clib.get_source_files()) + + if self.distribution.has_scripts(): + build_scripts = self.get_finalized_command('build_scripts') + self.filelist.extend(build_scripts.get_source_files()) + + def read_template(self): + """Read and parse manifest template file named by self.template. + + (usually "MANIFEST.in") The parsing and processing is done by + 'self.filelist', which updates itself accordingly. + """ + log.info("reading manifest template '%s'", self.template) + template = TextFile(self.template, + strip_comments=1, + skip_blanks=1, + join_lines=1, + lstrip_ws=1, + rstrip_ws=1, + collapse_join=1) + + try: + while 1: + line = template.readline() + if line is None: # end of file + break + + try: + self.filelist.process_template_line(line) + # the call above can raise a DistutilsTemplateError for + # malformed lines, or a ValueError from the lower-level + # convert_path function + except (DistutilsTemplateError, ValueError) as msg: + self.warn("%s, line %d: %s" % (template.filename, + template.current_line, + msg)) + finally: + template.close() + + def prune_file_list(self): + """Prune off branches that might slip into the file list as created + by 'read_template()', but really don't belong there: + * the build tree (typically "build") + * the release tree itself (only an issue if we ran "sdist" + previously with --keep-temp, or it aborted) + * any RCS, CVS, .svn, .hg, .git, .bzr, _darcs directories + """ + build = self.get_finalized_command('build') + base_dir = self.distribution.get_fullname() + + self.filelist.exclude_pattern(None, prefix=build.build_base) + self.filelist.exclude_pattern(None, prefix=base_dir) + + # pruning out vcs directories + # both separators are used under win32 + if sys.platform == 'win32': + seps = r'/|\\' + else: + seps = '/' + + vcs_dirs = ['RCS', 'CVS', r'\.svn', r'\.hg', r'\.git', r'\.bzr', + '_darcs'] + vcs_ptrn = r'(^|%s)(%s)(%s).*' % (seps, '|'.join(vcs_dirs), seps) + self.filelist.exclude_pattern(vcs_ptrn, is_regex=1) + + def write_manifest(self): + """Write the file list in 'self.filelist' (presumably as filled in + by 'add_defaults()' and 'read_template()') to the manifest file + named by 'self.manifest'. + """ + if self._manifest_is_not_generated(): + log.info("not writing to manually maintained " + "manifest file '%s'" % self.manifest) + return + + content = self.filelist.files[:] + content.insert(0, '# file GENERATED by distutils, do NOT edit') + self.execute(file_util.write_file, (self.manifest, content), + "writing manifest file '%s'" % self.manifest) + + def _manifest_is_not_generated(self): + # check for special comment used in 2.7.1 and higher + if not os.path.isfile(self.manifest): + return False + + fp = open(self.manifest, 'rU') + try: + first_line = fp.readline() + finally: + fp.close() + return first_line != '# file GENERATED by distutils, do NOT edit\n' + + def read_manifest(self): + """Read the manifest file (named by 'self.manifest') and use it to + fill in 'self.filelist', the list of files to include in the source + distribution. + """ + log.info("reading manifest file '%s'", self.manifest) + manifest = open(self.manifest) + for line in manifest: + # ignore comments and blank lines + line = line.strip() + if line.startswith('#') or not line: + continue + self.filelist.append(line) + manifest.close() + + def make_release_tree(self, base_dir, files): + """Create the directory tree that will become the source + distribution archive. All directories implied by the filenames in + 'files' are created under 'base_dir', and then we hard link or copy + (if hard linking is unavailable) those files into place. + Essentially, this duplicates the developer's source tree, but in a + directory named after the distribution, containing only the files + to be distributed. + """ + # Create all the directories under 'base_dir' necessary to + # put 'files' there; the 'mkpath()' is just so we don't die + # if the manifest happens to be empty. + self.mkpath(base_dir) + dir_util.create_tree(base_dir, files, dry_run=self.dry_run) + + # And walk over the list of files, either making a hard link (if + # os.link exists) to each one that doesn't already exist in its + # corresponding location under 'base_dir', or copying each file + # that's out-of-date in 'base_dir'. (Usually, all files will be + # out-of-date, because by default we blow away 'base_dir' when + # we're done making the distribution archives.) + + if hasattr(os, 'link'): # can make hard links on this system + link = 'hard' + msg = "making hard links in %s..." % base_dir + else: # nope, have to copy + link = None + msg = "copying files to %s..." % base_dir + + if not files: + log.warn("no files to distribute -- empty manifest?") + else: + log.info(msg) + for file in files: + if not os.path.isfile(file): + log.warn("'%s' not a regular file -- skipping" % file) + else: + dest = os.path.join(base_dir, file) + self.copy_file(file, dest, link=link) + + self.distribution.metadata.write_pkg_info(base_dir) + + def make_distribution(self): + """Create the source distribution(s). First, we create the release + tree with 'make_release_tree()'; then, we create all required + archive files (according to 'self.formats') from the release tree. + Finally, we clean up by blowing away the release tree (unless + 'self.keep_temp' is true). The list of archive files created is + stored so it can be retrieved later by 'get_archive_files()'. + """ + # Don't warn about missing meta-data here -- should be (and is!) + # done elsewhere. + base_dir = self.distribution.get_fullname() + base_name = os.path.join(self.dist_dir, base_dir) + + self.make_release_tree(base_dir, self.filelist.files) + archive_files = [] # remember names of files we create + # tar archive must be created last to avoid overwrite and remove + if 'tar' in self.formats: + self.formats.append(self.formats.pop(self.formats.index('tar'))) + + for fmt in self.formats: + file = self.make_archive(base_name, fmt, base_dir=base_dir, + owner=self.owner, group=self.group) + archive_files.append(file) + self.distribution.dist_files.append(('sdist', '', file)) + + self.archive_files = archive_files + + if not self.keep_temp: + dir_util.remove_tree(base_dir, dry_run=self.dry_run) + + def get_archive_files(self): + """Return the list of archive files created when the command + was run, or None if the command hasn't run yet. + """ + return self.archive_files diff --git a/PythonHome/Lib/distutils/command/sdist.pyc b/PythonHome/Lib/distutils/command/sdist.pyc deleted file mode 100644 index bae96454f98a8cb4d6ce6c3c3febae96cc671359..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16430 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 diff --git a/PythonHome/Lib/distutils/config.py b/PythonHome/Lib/distutils/config.py new file mode 100644 index 0000000000..7dbcc46bf4 --- /dev/null +++ b/PythonHome/Lib/distutils/config.py @@ -0,0 +1,116 @@ +"""distutils.pypirc + +Provides the PyPIRCCommand class, the base class for the command classes +that uses .pypirc in the distutils.command package. +""" +import os +from ConfigParser import ConfigParser + +from distutils.cmd import Command + +DEFAULT_PYPIRC = """\ +[distutils] +index-servers = + pypi + +[pypi] +username:%s +password:%s +""" + +class PyPIRCCommand(Command): + """Base command that knows how to handle the .pypirc file + """ + DEFAULT_REPOSITORY = 'https://pypi.python.org/pypi' + DEFAULT_REALM = 'pypi' + repository = None + realm = None + + user_options = [ + ('repository=', 'r', + "url of repository [default: %s]" % \ + DEFAULT_REPOSITORY), + ('show-response', None, + 'display full response text from server')] + + boolean_options = ['show-response'] + + def _get_rc_file(self): + """Returns rc file path.""" + return os.path.join(os.path.expanduser('~'), '.pypirc') + + def _store_pypirc(self, username, password): + """Creates a default .pypirc file.""" + rc = self._get_rc_file() + f = os.fdopen(os.open(rc, os.O_CREAT | os.O_WRONLY, 0600), 'w') + try: + f.write(DEFAULT_PYPIRC % (username, password)) + finally: + f.close() + + def _read_pypirc(self): + """Reads the .pypirc file.""" + rc = self._get_rc_file() + if os.path.exists(rc): + self.announce('Using PyPI login from %s' % rc) + repository = self.repository or self.DEFAULT_REPOSITORY + config = ConfigParser() + config.read(rc) + sections = config.sections() + if 'distutils' in sections: + # let's get the list of servers + index_servers = config.get('distutils', 'index-servers') + _servers = [server.strip() for server in + index_servers.split('\n') + if server.strip() != ''] + if _servers == []: + # nothing set, let's try to get the default pypi + if 'pypi' in sections: + _servers = ['pypi'] + else: + # the file is not properly defined, returning + # an empty dict + return {} + for server in _servers: + current = {'server': server} + current['username'] = config.get(server, 'username') + + # optional params + for key, default in (('repository', + self.DEFAULT_REPOSITORY), + ('realm', self.DEFAULT_REALM), + ('password', None)): + if config.has_option(server, key): + current[key] = config.get(server, key) + else: + current[key] = default + if (current['server'] == repository or + current['repository'] == repository): + return current + elif 'server-login' in sections: + # old format + server = 'server-login' + if config.has_option(server, 'repository'): + repository = config.get(server, 'repository') + else: + repository = self.DEFAULT_REPOSITORY + return {'username': config.get(server, 'username'), + 'password': config.get(server, 'password'), + 'repository': repository, + 'server': server, + 'realm': self.DEFAULT_REALM} + + return {} + + def initialize_options(self): + """Initialize options.""" + self.repository = None + self.realm = None + self.show_response = 0 + + def finalize_options(self): + """Finalizes options.""" + if self.repository is None: + self.repository = self.DEFAULT_REPOSITORY + if self.realm is None: + self.realm = self.DEFAULT_REALM diff --git a/PythonHome/Lib/distutils/config.pyc b/PythonHome/Lib/distutils/config.pyc deleted file mode 100644 index 3a33bb6a64bf2913ce7f358b28163ca956f19808..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3535 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 AyZ`_I diff --git a/PythonHome/Lib/distutils/cygwinccompiler.py b/PythonHome/Lib/distutils/cygwinccompiler.py new file mode 100644 index 0000000000..5d116876a3 --- /dev/null +++ b/PythonHome/Lib/distutils/cygwinccompiler.py @@ -0,0 +1,463 @@ +"""distutils.cygwinccompiler + +Provides the CygwinCCompiler class, a subclass of UnixCCompiler that +handles the Cygwin port of the GNU C compiler to Windows. It also contains +the Mingw32CCompiler class which handles the mingw32 port of GCC (same as +cygwin in no-cygwin mode). +""" + +# problems: +# +# * if you use a msvc compiled python version (1.5.2) +# 1. you have to insert a __GNUC__ section in its config.h +# 2. you have to generate a import library for its dll +# - create a def-file for python??.dll +# - create a import library using +# dlltool --dllname python15.dll --def python15.def \ +# --output-lib libpython15.a +# +# see also http://starship.python.net/crew/kernr/mingw32/Notes.html +# +# * We put export_symbols in a def-file, and don't use +# --export-all-symbols because it doesn't worked reliable in some +# tested configurations. And because other windows compilers also +# need their symbols specified this no serious problem. +# +# tested configurations: +# +# * cygwin gcc 2.91.57/ld 2.9.4/dllwrap 0.2.4 works +# (after patching python's config.h and for C++ some other include files) +# see also http://starship.python.net/crew/kernr/mingw32/Notes.html +# * mingw32 gcc 2.95.2/ld 2.9.4/dllwrap 0.2.4 works +# (ld doesn't support -shared, so we use dllwrap) +# * cygwin gcc 2.95.2/ld 2.10.90/dllwrap 2.10.90 works now +# - its dllwrap doesn't work, there is a bug in binutils 2.10.90 +# see also http://sources.redhat.com/ml/cygwin/2000-06/msg01274.html +# - using gcc -mdll instead dllwrap doesn't work without -static because +# it tries to link against dlls instead their import libraries. (If +# it finds the dll first.) +# By specifying -static we force ld to link against the import libraries, +# this is windows standard and there are normally not the necessary symbols +# in the dlls. +# *** only the version of June 2000 shows these problems +# * cygwin gcc 3.2/ld 2.13.90 works +# (ld supports -shared) +# * mingw gcc 3.2/ld 2.13 works +# (ld supports -shared) + +# This module should be kept compatible with Python 2.1. + +__revision__ = "$Id$" + +import os,sys,copy +from distutils.ccompiler import gen_preprocess_options, gen_lib_options +from distutils.unixccompiler import UnixCCompiler +from distutils.file_util import write_file +from distutils.errors import DistutilsExecError, CompileError, UnknownFileError +from distutils import log + +def get_msvcr(): + """Include the appropriate MSVC runtime library if Python was built + with MSVC 7.0 or later. + """ + msc_pos = sys.version.find('MSC v.') + if msc_pos != -1: + msc_ver = sys.version[msc_pos+6:msc_pos+10] + if msc_ver == '1300': + # MSVC 7.0 + return ['msvcr70'] + elif msc_ver == '1310': + # MSVC 7.1 + return ['msvcr71'] + elif msc_ver == '1400': + # VS2005 / MSVC 8.0 + return ['msvcr80'] + elif msc_ver == '1500': + # VS2008 / MSVC 9.0 + return ['msvcr90'] + else: + raise ValueError("Unknown MS Compiler version %s " % msc_ver) + + +class CygwinCCompiler (UnixCCompiler): + + compiler_type = 'cygwin' + obj_extension = ".o" + static_lib_extension = ".a" + shared_lib_extension = ".dll" + static_lib_format = "lib%s%s" + shared_lib_format = "%s%s" + exe_extension = ".exe" + + def __init__ (self, verbose=0, dry_run=0, force=0): + + UnixCCompiler.__init__ (self, verbose, dry_run, force) + + (status, details) = check_config_h() + self.debug_print("Python's GCC status: %s (details: %s)" % + (status, details)) + if status is not CONFIG_H_OK: + self.warn( + "Python's pyconfig.h doesn't seem to support your compiler. " + "Reason: %s. " + "Compiling may fail because of undefined preprocessor macros." + % details) + + self.gcc_version, self.ld_version, self.dllwrap_version = \ + get_versions() + self.debug_print(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" % + (self.gcc_version, + self.ld_version, + self.dllwrap_version) ) + + # ld_version >= "2.10.90" and < "2.13" should also be able to use + # gcc -mdll instead of dllwrap + # Older dllwraps had own version numbers, newer ones use the + # same as the rest of binutils ( also ld ) + # dllwrap 2.10.90 is buggy + if self.ld_version >= "2.10.90": + self.linker_dll = "gcc" + else: + self.linker_dll = "dllwrap" + + # ld_version >= "2.13" support -shared so use it instead of + # -mdll -static + if self.ld_version >= "2.13": + shared_option = "-shared" + else: + shared_option = "-mdll -static" + + # Hard-code GCC because that's what this is all about. + # XXX optimization, warnings etc. should be customizable. + self.set_executables(compiler='gcc -mcygwin -O -Wall', + compiler_so='gcc -mcygwin -mdll -O -Wall', + compiler_cxx='g++ -mcygwin -O -Wall', + linker_exe='gcc -mcygwin', + linker_so=('%s -mcygwin %s' % + (self.linker_dll, shared_option))) + + # cygwin and mingw32 need different sets of libraries + if self.gcc_version == "2.91.57": + # cygwin shouldn't need msvcrt, but without the dlls will crash + # (gcc version 2.91.57) -- perhaps something about initialization + self.dll_libraries=["msvcrt"] + self.warn( + "Consider upgrading to a newer version of gcc") + else: + # Include the appropriate MSVC runtime library if Python was built + # with MSVC 7.0 or later. + self.dll_libraries = get_msvcr() + + # __init__ () + + + def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): + if ext == '.rc' or ext == '.res': + # gcc needs '.res' and '.rc' compiled to object files !!! + try: + self.spawn(["windres", "-i", src, "-o", obj]) + except DistutilsExecError, msg: + raise CompileError, msg + else: # for other files use the C-compiler + try: + self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + + extra_postargs) + except DistutilsExecError, msg: + raise CompileError, msg + + def link (self, + target_desc, + objects, + output_filename, + output_dir=None, + libraries=None, + library_dirs=None, + runtime_library_dirs=None, + export_symbols=None, + debug=0, + extra_preargs=None, + extra_postargs=None, + build_temp=None, + target_lang=None): + + # use separate copies, so we can modify the lists + extra_preargs = copy.copy(extra_preargs or []) + libraries = copy.copy(libraries or []) + objects = copy.copy(objects or []) + + # Additional libraries + libraries.extend(self.dll_libraries) + + # handle export symbols by creating a def-file + # with executables this only works with gcc/ld as linker + if ((export_symbols is not None) and + (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")): + # (The linker doesn't do anything if output is up-to-date. + # So it would probably better to check if we really need this, + # but for this we had to insert some unchanged parts of + # UnixCCompiler, and this is not what we want.) + + # we want to put some files in the same directory as the + # object files are, build_temp doesn't help much + # where are the object files + temp_dir = os.path.dirname(objects[0]) + # name of dll to give the helper files the same base name + (dll_name, dll_extension) = os.path.splitext( + os.path.basename(output_filename)) + + # generate the filenames for these files + def_file = os.path.join(temp_dir, dll_name + ".def") + lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a") + + # Generate .def file + contents = [ + "LIBRARY %s" % os.path.basename(output_filename), + "EXPORTS"] + for sym in export_symbols: + contents.append(sym) + self.execute(write_file, (def_file, contents), + "writing %s" % def_file) + + # next add options for def-file and to creating import libraries + + # dllwrap uses different options than gcc/ld + if self.linker_dll == "dllwrap": + extra_preargs.extend(["--output-lib", lib_file]) + # for dllwrap we have to use a special option + extra_preargs.extend(["--def", def_file]) + # we use gcc/ld here and can be sure ld is >= 2.9.10 + else: + # doesn't work: bfd_close build\...\libfoo.a: Invalid operation + #extra_preargs.extend(["-Wl,--out-implib,%s" % lib_file]) + # for gcc/ld the def-file is specified as any object files + objects.append(def_file) + + #end: if ((export_symbols is not None) and + # (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")): + + # who wants symbols and a many times larger output file + # should explicitly switch the debug mode on + # otherwise we let dllwrap/ld strip the output file + # (On my machine: 10KB < stripped_file < ??100KB + # unstripped_file = stripped_file + XXX KB + # ( XXX=254 for a typical python extension)) + if not debug: + extra_preargs.append("-s") + + UnixCCompiler.link(self, + target_desc, + objects, + output_filename, + output_dir, + libraries, + library_dirs, + runtime_library_dirs, + None, # export_symbols, we do this in our def-file + debug, + extra_preargs, + extra_postargs, + build_temp, + target_lang) + + # link () + + # -- Miscellaneous methods ----------------------------------------- + + # overwrite the one from CCompiler to support rc and res-files + def object_filenames (self, + source_filenames, + strip_dir=0, + output_dir=''): + if output_dir is None: output_dir = '' + obj_names = [] + for src_name in source_filenames: + # use normcase to make sure '.rc' is really '.rc' and not '.RC' + (base, ext) = os.path.splitext (os.path.normcase(src_name)) + if ext not in (self.src_extensions + ['.rc','.res']): + raise UnknownFileError, \ + "unknown file type '%s' (from '%s')" % \ + (ext, src_name) + if strip_dir: + base = os.path.basename (base) + if ext == '.res' or ext == '.rc': + # these need to be compiled to object files + obj_names.append (os.path.join (output_dir, + base + ext + self.obj_extension)) + else: + obj_names.append (os.path.join (output_dir, + base + self.obj_extension)) + return obj_names + + # object_filenames () + +# class CygwinCCompiler + + +# the same as cygwin plus some additional parameters +class Mingw32CCompiler (CygwinCCompiler): + + compiler_type = 'mingw32' + + def __init__ (self, + verbose=0, + dry_run=0, + force=0): + + CygwinCCompiler.__init__ (self, verbose, dry_run, force) + + # ld_version >= "2.13" support -shared so use it instead of + # -mdll -static + if self.ld_version >= "2.13": + shared_option = "-shared" + else: + shared_option = "-mdll -static" + + # A real mingw32 doesn't need to specify a different entry point, + # but cygwin 2.91.57 in no-cygwin-mode needs it. + if self.gcc_version <= "2.91.57": + entry_point = '--entry _DllMain@12' + else: + entry_point = '' + + if self.gcc_version < '4' or is_cygwingcc(): + no_cygwin = ' -mno-cygwin' + else: + no_cygwin = '' + + self.set_executables(compiler='gcc%s -O -Wall' % no_cygwin, + compiler_so='gcc%s -mdll -O -Wall' % no_cygwin, + compiler_cxx='g++%s -O -Wall' % no_cygwin, + linker_exe='gcc%s' % no_cygwin, + linker_so='%s%s %s %s' + % (self.linker_dll, no_cygwin, + shared_option, entry_point)) + # Maybe we should also append -mthreads, but then the finished + # dlls need another dll (mingwm10.dll see Mingw32 docs) + # (-mthreads: Support thread-safe exception handling on `Mingw32') + + # no additional libraries needed + self.dll_libraries=[] + + # Include the appropriate MSVC runtime library if Python was built + # with MSVC 7.0 or later. + self.dll_libraries = get_msvcr() + + # __init__ () + +# class Mingw32CCompiler + +# Because these compilers aren't configured in Python's pyconfig.h file by +# default, we should at least warn the user if he is using a unmodified +# version. + +CONFIG_H_OK = "ok" +CONFIG_H_NOTOK = "not ok" +CONFIG_H_UNCERTAIN = "uncertain" + +def check_config_h(): + + """Check if the current Python installation (specifically, pyconfig.h) + appears amenable to building extensions with GCC. Returns a tuple + (status, details), where 'status' is one of the following constants: + CONFIG_H_OK + all is well, go ahead and compile + CONFIG_H_NOTOK + doesn't look good + CONFIG_H_UNCERTAIN + not sure -- unable to read pyconfig.h + 'details' is a human-readable string explaining the situation. + + Note there are two ways to conclude "OK": either 'sys.version' contains + the string "GCC" (implying that this Python was built with GCC), or the + installed "pyconfig.h" contains the string "__GNUC__". + """ + + # XXX since this function also checks sys.version, it's not strictly a + # "pyconfig.h" check -- should probably be renamed... + + from distutils import sysconfig + import string + # if sys.version contains GCC then python was compiled with + # GCC, and the pyconfig.h file should be OK + if string.find(sys.version,"GCC") >= 0: + return (CONFIG_H_OK, "sys.version mentions 'GCC'") + + fn = sysconfig.get_config_h_filename() + try: + # It would probably better to read single lines to search. + # But we do this only once, and it is fast enough + f = open(fn) + try: + s = f.read() + finally: + f.close() + + except IOError, exc: + # if we can't read this file, we cannot say it is wrong + # the compiler will complain later about this file as missing + return (CONFIG_H_UNCERTAIN, + "couldn't read '%s': %s" % (fn, exc.strerror)) + + else: + # "pyconfig.h" contains an "#ifdef __GNUC__" or something similar + if string.find(s,"__GNUC__") >= 0: + return (CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn) + else: + return (CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn) + + + +def get_versions(): + """ Try to find out the versions of gcc, ld and dllwrap. + If not possible it returns None for it. + """ + from distutils.version import LooseVersion + from distutils.spawn import find_executable + import re + + gcc_exe = find_executable('gcc') + if gcc_exe: + out = os.popen(gcc_exe + ' -dumpversion','r') + out_string = out.read() + out.close() + result = re.search('(\d+\.\d+(\.\d+)*)',out_string) + if result: + gcc_version = LooseVersion(result.group(1)) + else: + gcc_version = None + else: + gcc_version = None + ld_exe = find_executable('ld') + if ld_exe: + out = os.popen(ld_exe + ' -v','r') + out_string = out.read() + out.close() + result = re.search('(\d+\.\d+(\.\d+)*)',out_string) + if result: + ld_version = LooseVersion(result.group(1)) + else: + ld_version = None + else: + ld_version = None + dllwrap_exe = find_executable('dllwrap') + if dllwrap_exe: + out = os.popen(dllwrap_exe + ' --version','r') + out_string = out.read() + out.close() + result = re.search(' (\d+\.\d+(\.\d+)*)',out_string) + if result: + dllwrap_version = LooseVersion(result.group(1)) + else: + dllwrap_version = None + else: + dllwrap_version = None + return (gcc_version, ld_version, dllwrap_version) + +def is_cygwingcc(): + '''Try to determine if the gcc that would be used is from cygwin.''' + out = os.popen('gcc -dumpmachine', 'r') + out_string = out.read() + out.close() + # out_string is the target triplet cpu-vendor-os + # Cygwin's gcc sets the os to 'cygwin' + return out_string.strip().endswith('cygwin') diff --git a/PythonHome/Lib/distutils/cygwinccompiler.pyc b/PythonHome/Lib/distutils/cygwinccompiler.pyc deleted file mode 100644 index 3cca3fad0799118b1a272982d363c48a247210a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9645 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 F{|m;rV4?s3 diff --git a/PythonHome/Lib/distutils/debug.py b/PythonHome/Lib/distutils/debug.py new file mode 100644 index 0000000000..2886744402 --- /dev/null +++ b/PythonHome/Lib/distutils/debug.py @@ -0,0 +1,7 @@ +import os + +__revision__ = "$Id$" + +# If DISTUTILS_DEBUG is anything other than the empty string, we run in +# debug mode. +DEBUG = os.environ.get('DISTUTILS_DEBUG') diff --git a/PythonHome/Lib/distutils/debug.pyc b/PythonHome/Lib/distutils/debug.pyc deleted file mode 100644 index 35cf785d3c20f59f61ae7076fba236b0a8e00efd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 249 zcmXYrOA5k342IK(52WH9#6?#w+z28fK9GWl&=#Q-Msx<9Qaj?Lf@`nj%{+i+tReaH z5&n=k?{@38+lNQ^hfRG-rF{}kX+aK<5ZI7dAOJEOG6%Q=PYV*)7((AAv;0tOw837$ zd)OgZ1Ys0M!8&A%=nvM6*z>5`g)s x65S=5kJ9Y}&#D*<(_9`>E;W`YbDeT=C{O+C1Dj+UUlcEMF|mk$?|F9J{Q~INH6j22 diff --git a/PythonHome/Lib/distutils/dep_util.py b/PythonHome/Lib/distutils/dep_util.py new file mode 100644 index 0000000000..2b759056ea --- /dev/null +++ b/PythonHome/Lib/distutils/dep_util.py @@ -0,0 +1,89 @@ +"""distutils.dep_util + +Utility functions for simple, timestamp-based dependency of files +and groups of files; also, function based entirely on such +timestamp dependency analysis.""" + +__revision__ = "$Id$" + +import os +from stat import ST_MTIME +from distutils.errors import DistutilsFileError + +def newer(source, target): + """Tells if the target is newer than the source. + + Return true if 'source' exists and is more recently modified than + 'target', or if 'source' exists and 'target' doesn't. + + Return false if both exist and 'target' is the same age or younger + than 'source'. Raise DistutilsFileError if 'source' does not exist. + + Note that this test is not very accurate: files created in the same second + will have the same "age". + """ + if not os.path.exists(source): + raise DistutilsFileError("file '%s' does not exist" % + os.path.abspath(source)) + if not os.path.exists(target): + return True + + return os.stat(source)[ST_MTIME] > os.stat(target)[ST_MTIME] + +def newer_pairwise(sources, targets): + """Walk two filename lists in parallel, testing if each source is newer + than its corresponding target. Return a pair of lists (sources, + targets) where source is newer than target, according to the semantics + of 'newer()'. + """ + if len(sources) != len(targets): + raise ValueError, "'sources' and 'targets' must be same length" + + # build a pair of lists (sources, targets) where source is newer + n_sources = [] + n_targets = [] + for source, target in zip(sources, targets): + if newer(source, target): + n_sources.append(source) + n_targets.append(target) + + return n_sources, n_targets + +def newer_group(sources, target, missing='error'): + """Return true if 'target' is out-of-date with respect to any file + listed in 'sources'. + + In other words, if 'target' exists and is newer + than every file in 'sources', return false; otherwise return true. + 'missing' controls what we do when a source file is missing; the + default ("error") is to blow up with an OSError from inside 'stat()'; + if it is "ignore", we silently drop any missing source files; if it is + "newer", any missing source files make us assume that 'target' is + out-of-date (this is handy in "dry-run" mode: it'll make you pretend to + carry out commands that wouldn't work because inputs are missing, but + that doesn't matter because you're not actually going to run the + commands). + """ + # If the target doesn't even exist, then it's definitely out-of-date. + if not os.path.exists(target): + return True + + # Otherwise we have to find out the hard way: if *any* source file + # is more recent than 'target', then 'target' is out-of-date and + # we can immediately return true. If we fall through to the end + # of the loop, then 'target' is up-to-date and we return false. + target_mtime = os.stat(target)[ST_MTIME] + + for source in sources: + if not os.path.exists(source): + if missing == 'error': # blow up when we stat() the file + pass + elif missing == 'ignore': # missing source dropped from + continue # target's dependency list + elif missing == 'newer': # missing source means target is + return True # out-of-date + + if os.stat(source)[ST_MTIME] > target_mtime: + return True + + return False diff --git a/PythonHome/Lib/distutils/dep_util.pyc b/PythonHome/Lib/distutils/dep_util.pyc deleted file mode 100644 index 724d8eb853e5fd85bab2d469fc49a84d28038374..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3160 zcmbVO-EJF26rNo>PGS-orB&5Py%?-kc7$UUgam33s?;Bpix#vAM2b?G&F5qwve_= zM$Lu#tBT_y&Sy5WJzIy(clOdd*jW6O6*T(?{ig?ePapf4P0T!+-|PuYdTfj~ z33-N*a~GuW;&Er`aGwkVqwKY5T+4U5SwXhno2wnQCQ= zwtLfn0piFOoM<=lr}NU=B-N+^vVL~uISk4ERyFOqYUZ=+1Mf33f@z*mq(#6N09_QJ~@gj|n=V{!V%m7Ov z7*gvbw}wWnZ3c~CE7%O`A*TZwxk!hfFaU0SB2b6Xds-9bj&R^0WI#w6Fcjh<jI20Fkaj`^+bdLO4q6PCnoQL8ChIPuC;Jn5ItYL8WK;VCf4VWH; z^Gx{z_8i9fsdQ7#K`ba{IpZBsoWv&1bCrXW5c{kc5@uAKjHGwpBBL&GmmyOUZH%%L z#GOREdwYxgilH_$L|guxj@Mc5p3N4{n4ET*Z`4x1(#)n<@KebckC$WqSs`NnT(E2E07uE{UxR zfb)!y`RI8@fV`Aq1ln@~Brtsna2|>?KMZ-8iL-n2nHtZW^AQ#M&p`}3w*XjBySc~f zkUE63_dAqQ_IEJC+pO)q*(PY}((UNMP6|?z(+pfns8k8)Oe6LvzhE0i3IWmc)&d+A z1@09RB#e?V1=4JnIdgu(n{|PGf0+l08It)7iL_ALg$-O~nB;f8athXbo~n-rYkQno ziv(&Tp9*I*%Gs2-c&b2-lpckQ=lS8!L2>dTyOa%VOR5HOnLF8OakN|8Bx@3uk3%L-cMo-wOl?hiZ zv%BOsmS$Bg_7xOR5dLky9LJ|hmZ-VbmLMdqL08HjYq=WT4i_j~4fK%Cr~tK6Guts` z(V`NK3YEDwst@Z$t&|gl0m%wiu&yLFsAtd!Uys2dDOFhVwJ!4%1)9Qt3UWx|l1g(i zDd~d%{8U-rl_#ZRO)OTGbsXm$urrs#!EMM;nT-=yf?8*CsF@?RgsqFH&5hXhNQiDw zN)oSl*E8jGh+-lti4mo4L6IpbPR*7Jkk}A_3RV@$c{+PZE znTOtqg5HBBPeJ@?`U!^iHX5;kYS_3QuA?fh1vNYkJj>x$uoCizGTYPdr#k8P*`9vi zsF#_=r*XgU?|6Bs4Jcex;~vA>a{XtwMAxw#ZK1im0{8w$RbPSh=YUO_t1rlfmbkSM QHo~=FBiIO6Z>(Pb8%hLI0{{R3 diff --git a/PythonHome/Lib/distutils/dir_util.py b/PythonHome/Lib/distutils/dir_util.py new file mode 100644 index 0000000000..e2dc6f4826 --- /dev/null +++ b/PythonHome/Lib/distutils/dir_util.py @@ -0,0 +1,214 @@ +"""distutils.dir_util + +Utility functions for manipulating directories and directory trees.""" + +__revision__ = "$Id$" + +import os +import errno +from distutils.errors import DistutilsFileError, DistutilsInternalError +from distutils import log + +# cache for by mkpath() -- in addition to cheapening redundant calls, +# eliminates redundant "creating /foo/bar/baz" messages in dry-run mode +_path_created = {} + +# I don't use os.makedirs because a) it's new to Python 1.5.2, and +# b) it blows up if the directory already exists (I want to silently +# succeed in that case). +def mkpath(name, mode=0777, verbose=1, dry_run=0): + """Create a directory and any missing ancestor directories. + + If the directory already exists (or if 'name' is the empty string, which + means the current directory, which of course exists), then do nothing. + Raise DistutilsFileError if unable to create some directory along the way + (eg. some sub-path exists, but is a file rather than a directory). + If 'verbose' is true, print a one-line summary of each mkdir to stdout. + Return the list of directories actually created. + """ + + global _path_created + + # Detect a common bug -- name is None + if not isinstance(name, basestring): + raise DistutilsInternalError, \ + "mkpath: 'name' must be a string (got %r)" % (name,) + + # XXX what's the better way to handle verbosity? print as we create + # each directory in the path (the current behaviour), or only announce + # the creation of the whole path? (quite easy to do the latter since + # we're not using a recursive algorithm) + + name = os.path.normpath(name) + created_dirs = [] + if os.path.isdir(name) or name == '': + return created_dirs + if _path_created.get(os.path.abspath(name)): + return created_dirs + + (head, tail) = os.path.split(name) + tails = [tail] # stack of lone dirs to create + + while head and tail and not os.path.isdir(head): + (head, tail) = os.path.split(head) + tails.insert(0, tail) # push next higher dir onto stack + + # now 'head' contains the deepest directory that already exists + # (that is, the child of 'head' in 'name' is the highest directory + # that does *not* exist) + for d in tails: + #print "head = %s, d = %s: " % (head, d), + head = os.path.join(head, d) + abs_head = os.path.abspath(head) + + if _path_created.get(abs_head): + continue + + if verbose >= 1: + log.info("creating %s", head) + + if not dry_run: + try: + os.mkdir(head, mode) + except OSError, exc: + if not (exc.errno == errno.EEXIST and os.path.isdir(head)): + raise DistutilsFileError( + "could not create '%s': %s" % (head, exc.args[-1])) + created_dirs.append(head) + + _path_created[abs_head] = 1 + return created_dirs + +def create_tree(base_dir, files, mode=0777, verbose=1, dry_run=0): + """Create all the empty directories under 'base_dir' needed to put 'files' + there. + + 'base_dir' is just the a name of a directory which doesn't necessarily + exist yet; 'files' is a list of filenames to be interpreted relative to + 'base_dir'. 'base_dir' + the directory portion of every file in 'files' + will be created if it doesn't already exist. 'mode', 'verbose' and + 'dry_run' flags are as for 'mkpath()'. + """ + # First get the list of directories to create + need_dir = {} + for file in files: + need_dir[os.path.join(base_dir, os.path.dirname(file))] = 1 + need_dirs = need_dir.keys() + need_dirs.sort() + + # Now create them + for dir in need_dirs: + mkpath(dir, mode, verbose=verbose, dry_run=dry_run) + +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'. + + Both 'src' and 'dst' must be directory names. If 'src' is not a + directory, raise DistutilsFileError. If 'dst' does not exist, it is + created with 'mkpath()'. The end result of the copy is that every + file in 'src' is copied to 'dst', and directories under 'src' are + recursively copied to 'dst'. Return the list of files that were + copied or might have been copied, using their output name. The + return value is unaffected by 'update' or 'dry_run': it is simply + the list of all files under 'src', with the names changed to be + under 'dst'. + + 'preserve_mode' and 'preserve_times' are the same as for + 'copy_file'; note that they only apply to regular files, not to + directories. If 'preserve_symlinks' is true, symlinks will be + copied as symlinks (on platforms that support them!); otherwise + (the default), the destination of the symlink will be copied. + 'update' and 'verbose' are the same as for 'copy_file'. + """ + from distutils.file_util import copy_file + + if not dry_run and not os.path.isdir(src): + raise DistutilsFileError, \ + "cannot copy tree '%s': not a directory" % src + try: + names = os.listdir(src) + except os.error, (errno, errstr): + if dry_run: + names = [] + else: + raise DistutilsFileError, \ + "error listing files in '%s': %s" % (src, errstr) + + if not dry_run: + mkpath(dst, verbose=verbose) + + outputs = [] + + for n in names: + src_name = os.path.join(src, n) + dst_name = os.path.join(dst, n) + + if n.startswith('.nfs'): + # skip NFS rename files + continue + + if preserve_symlinks and os.path.islink(src_name): + link_dest = os.readlink(src_name) + if verbose >= 1: + log.info("linking %s -> %s", dst_name, link_dest) + if not dry_run: + os.symlink(link_dest, dst_name) + outputs.append(dst_name) + + elif os.path.isdir(src_name): + outputs.extend( + copy_tree(src_name, dst_name, preserve_mode, + preserve_times, preserve_symlinks, update, + verbose=verbose, dry_run=dry_run)) + else: + copy_file(src_name, dst_name, preserve_mode, + preserve_times, update, verbose=verbose, + dry_run=dry_run) + outputs.append(dst_name) + + return outputs + +def _build_cmdtuple(path, cmdtuples): + """Helper for remove_tree().""" + for f in os.listdir(path): + real_f = os.path.join(path,f) + if os.path.isdir(real_f) and not os.path.islink(real_f): + _build_cmdtuple(real_f, cmdtuples) + else: + cmdtuples.append((os.remove, real_f)) + cmdtuples.append((os.rmdir, path)) + +def remove_tree(directory, verbose=1, dry_run=0): + """Recursively remove an entire directory tree. + + Any errors are ignored (apart from being reported to stdout if 'verbose' + is true). + """ + global _path_created + + if verbose >= 1: + log.info("removing '%s' (and everything under it)", directory) + if dry_run: + return + cmdtuples = [] + _build_cmdtuple(directory, cmdtuples) + for cmd in cmdtuples: + try: + cmd[0](cmd[1]) + # remove dir from cache if it's already there + abspath = os.path.abspath(cmd[1]) + if abspath in _path_created: + del _path_created[abspath] + except (IOError, OSError), exc: + log.warn("error removing %s: %s", directory, exc) + +def ensure_relative(path): + """Take the full path 'path', and make it a relative path. + + This is useful to make 'path' the second argument to os.path.join(). + """ + drive, path = os.path.splitdrive(path) + if path[0:1] == os.sep: + path = drive + path[1:] + return path diff --git a/PythonHome/Lib/distutils/dir_util.pyc b/PythonHome/Lib/distutils/dir_util.pyc deleted file mode 100644 index 830efd74d602c9e22c0eb29403ca275016be6074..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6753 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 Rt-iCmUf1il=NrqH{sV?sfffJ& diff --git a/PythonHome/Lib/distutils/dist.py b/PythonHome/Lib/distutils/dist.py new file mode 100644 index 0000000000..e025313dbd --- /dev/null +++ b/PythonHome/Lib/distutils/dist.py @@ -0,0 +1,1249 @@ +"""distutils.dist + +Provides the Distribution class, which represents the module distribution +being built/installed/distributed. +""" + +__revision__ = "$Id$" + +import sys, os, re +from email import message_from_file + +try: + import warnings +except ImportError: + warnings = None + +from distutils.errors import (DistutilsOptionError, DistutilsArgError, + DistutilsModuleError, DistutilsClassError) +from distutils.fancy_getopt import FancyGetopt, translate_longopt +from distutils.util import check_environ, strtobool, rfc822_escape +from distutils import log +from distutils.debug import DEBUG + +# Encoding used for the PKG-INFO files +PKG_INFO_ENCODING = 'utf-8' + +# Regex to define acceptable Distutils command names. This is not *quite* +# the same as a Python NAME -- I don't allow leading underscores. The fact +# that they're very similar is no coincidence; the default naming scheme is +# to look for a Python module named after the command. +command_re = re.compile (r'^[a-zA-Z]([a-zA-Z0-9_]*)$') + + +class Distribution: + """The core of the Distutils. Most of the work hiding behind 'setup' + is really done within a Distribution instance, which farms the work out + to the Distutils commands specified on the command line. + + Setup scripts will almost never instantiate Distribution directly, + unless the 'setup()' function is totally inadequate to their needs. + However, it is conceivable that a setup script might wish to subclass + Distribution for some specialized purpose, and then pass the subclass + to 'setup()' as the 'distclass' keyword argument. If so, it is + necessary to respect the expectations that 'setup' has of Distribution. + See the code for 'setup()', in core.py, for details. + """ + + + # 'global_options' describes the command-line options that may be + # supplied to the setup script prior to any actual commands. + # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of + # these global options. This list should be kept to a bare minimum, + # since every global option is also valid as a command option -- and we + # don't want to pollute the commands with too many options that they + # have minimal control over. + # The fourth entry for verbose means that it can be repeated. + global_options = [('verbose', 'v', "run verbosely (default)", 1), + ('quiet', 'q', "run quietly (turns verbosity off)"), + ('dry-run', 'n', "don't actually do anything"), + ('help', 'h', "show detailed help message"), + ('no-user-cfg', None, + 'ignore pydistutils.cfg in your home directory'), + ] + + # 'common_usage' is a short (2-3 line) string describing the common + # usage of the setup script. + common_usage = """\ +Common commands: (see '--help-commands' for more) + + setup.py build will build the package underneath 'build/' + setup.py install will install the package +""" + + # options that are not propagated to the commands + display_options = [ + ('help-commands', None, + "list all available commands"), + ('name', None, + "print package name"), + ('version', 'V', + "print package version"), + ('fullname', None, + "print -"), + ('author', None, + "print the author's name"), + ('author-email', None, + "print the author's email address"), + ('maintainer', None, + "print the maintainer's name"), + ('maintainer-email', None, + "print the maintainer's email address"), + ('contact', None, + "print the maintainer's name if known, else the author's"), + ('contact-email', None, + "print the maintainer's email address if known, else the author's"), + ('url', None, + "print the URL for this package"), + ('license', None, + "print the license of the package"), + ('licence', None, + "alias for --license"), + ('description', None, + "print the package description"), + ('long-description', None, + "print the long package description"), + ('platforms', None, + "print the list of platforms"), + ('classifiers', None, + "print the list of classifiers"), + ('keywords', None, + "print the list of keywords"), + ('provides', None, + "print the list of packages/modules provided"), + ('requires', None, + "print the list of packages/modules required"), + ('obsoletes', None, + "print the list of packages/modules made obsolete") + ] + display_option_names = map(lambda x: translate_longopt(x[0]), + display_options) + + # negative options are options that exclude other options + negative_opt = {'quiet': 'verbose'} + + + # -- Creation/initialization methods ------------------------------- + + def __init__ (self, attrs=None): + """Construct a new Distribution instance: initialize all the + attributes of a Distribution, and then use 'attrs' (a dictionary + mapping attribute names to values) to assign some of those + attributes their "real" values. (Any attributes not mentioned in + 'attrs' will be assigned to some null value: 0, None, an empty list + or dictionary, etc.) Most importantly, initialize the + 'command_obj' attribute to the empty dictionary; this will be + filled in with real command objects by 'parse_command_line()'. + """ + + # Default values for our command-line options + self.verbose = 1 + self.dry_run = 0 + self.help = 0 + for attr in self.display_option_names: + setattr(self, attr, 0) + + # Store the distribution meta-data (name, version, author, and so + # forth) in a separate object -- we're getting to have enough + # information here (and enough command-line options) that it's + # worth it. Also delegate 'get_XXX()' methods to the 'metadata' + # object in a sneaky and underhanded (but efficient!) way. + self.metadata = DistributionMetadata() + for basename in self.metadata._METHOD_BASENAMES: + method_name = "get_" + basename + setattr(self, method_name, getattr(self.metadata, method_name)) + + # 'cmdclass' maps command names to class objects, so we + # can 1) quickly figure out which class to instantiate when + # we need to create a new command object, and 2) have a way + # for the setup script to override command classes + self.cmdclass = {} + + # 'command_packages' is a list of packages in which commands + # are searched for. The factory for command 'foo' is expected + # to be named 'foo' in the module 'foo' in one of the packages + # named here. This list is searched from the left; an error + # is raised if no named package provides the command being + # searched for. (Always access using get_command_packages().) + self.command_packages = None + + # 'script_name' and 'script_args' are usually set to sys.argv[0] + # and sys.argv[1:], but they can be overridden when the caller is + # not necessarily a setup script run from the command-line. + self.script_name = None + self.script_args = None + + # 'command_options' is where we store command options between + # parsing them (from config files, the command-line, etc.) and when + # they are actually needed -- ie. when the command in question is + # instantiated. It is a dictionary of dictionaries of 2-tuples: + # command_options = { command_name : { option : (source, value) } } + self.command_options = {} + + # 'dist_files' is the list of (command, pyversion, file) that + # have been created by any dist commands run so far. This is + # filled regardless of whether the run is dry or not. pyversion + # gives sysconfig.get_python_version() if the dist file is + # specific to a Python version, 'any' if it is good for all + # Python versions on the target platform, and '' for a source + # file. pyversion should not be used to specify minimum or + # maximum required Python versions; use the metainfo for that + # instead. + self.dist_files = [] + + # These options are really the business of various commands, rather + # than of the Distribution itself. We provide aliases for them in + # Distribution as a convenience to the developer. + self.packages = None + self.package_data = {} + self.package_dir = None + self.py_modules = None + self.libraries = None + self.headers = None + self.ext_modules = None + self.ext_package = None + self.include_dirs = None + self.extra_path = None + self.scripts = None + self.data_files = None + self.password = '' + + # And now initialize bookkeeping stuff that can't be supplied by + # the caller at all. 'command_obj' maps command names to + # Command instances -- that's how we enforce that every command + # class is a singleton. + self.command_obj = {} + + # 'have_run' maps command names to boolean values; it keeps track + # of whether we have actually run a particular command, to make it + # cheap to "run" a command whenever we think we might need to -- if + # it's already been done, no need for expensive filesystem + # operations, we just check the 'have_run' dictionary and carry on. + # It's only safe to query 'have_run' for a command class that has + # been instantiated -- a false value will be inserted when the + # command object is created, and replaced with a true value when + # the command is successfully run. Thus it's probably best to use + # '.get()' rather than a straight lookup. + self.have_run = {} + + # Now we'll use the attrs dictionary (ultimately, keyword args from + # the setup script) to possibly override any or all of these + # distribution options. + + if attrs: + # Pull out the set of command options and work on them + # specifically. Note that this order guarantees that aliased + # command options will override any supplied redundantly + # through the general options dictionary. + options = attrs.get('options') + if options is not None: + del attrs['options'] + for (command, cmd_options) in options.items(): + opt_dict = self.get_option_dict(command) + for (opt, val) in cmd_options.items(): + opt_dict[opt] = ("setup script", val) + + if 'licence' in attrs: + attrs['license'] = attrs['licence'] + del attrs['licence'] + msg = "'licence' distribution option is deprecated; use 'license'" + if warnings is not None: + warnings.warn(msg) + else: + sys.stderr.write(msg + "\n") + + # Now work on the rest of the attributes. Any attribute that's + # not already defined is invalid! + for (key, val) in attrs.items(): + if hasattr(self.metadata, "set_" + key): + getattr(self.metadata, "set_" + key)(val) + elif hasattr(self.metadata, key): + setattr(self.metadata, key, val) + elif hasattr(self, key): + setattr(self, key, val) + else: + msg = "Unknown distribution option: %s" % repr(key) + if warnings is not None: + warnings.warn(msg) + else: + sys.stderr.write(msg + "\n") + + # no-user-cfg is handled before other command line args + # because other args override the config files, and this + # one is needed before we can load the config files. + # If attrs['script_args'] wasn't passed, assume false. + # + # This also make sure we just look at the global options + self.want_user_cfg = True + + if self.script_args is not None: + for arg in self.script_args: + if not arg.startswith('-'): + break + if arg == '--no-user-cfg': + self.want_user_cfg = False + break + + self.finalize_options() + + def get_option_dict(self, command): + """Get the option dictionary for a given command. If that + command's option dictionary hasn't been created yet, then create it + and return the new dictionary; otherwise, return the existing + option dictionary. + """ + dict = self.command_options.get(command) + if dict is None: + dict = self.command_options[command] = {} + return dict + + def dump_option_dicts(self, header=None, commands=None, indent=""): + from pprint import pformat + + if commands is None: # dump all command option dicts + commands = self.command_options.keys() + commands.sort() + + if header is not None: + self.announce(indent + header) + indent = indent + " " + + if not commands: + self.announce(indent + "no commands known yet") + return + + for cmd_name in commands: + opt_dict = self.command_options.get(cmd_name) + if opt_dict is None: + self.announce(indent + + "no option dict for '%s' command" % cmd_name) + else: + self.announce(indent + + "option dict for '%s' command:" % cmd_name) + out = pformat(opt_dict) + for line in out.split('\n'): + self.announce(indent + " " + line) + + # -- Config file finding/parsing methods --------------------------- + + def find_config_files(self): + """Find as many configuration files as should be processed for this + platform, and return a list of filenames in the order in which they + should be parsed. The filenames returned are guaranteed to exist + (modulo nasty race conditions). + + There are three possible config files: distutils.cfg in the + Distutils installation directory (ie. where the top-level + Distutils __inst__.py file lives), a file in the user's home + directory named .pydistutils.cfg on Unix and pydistutils.cfg + on Windows/Mac; and setup.cfg in the current directory. + + The file in the user's home directory can be disabled with the + --no-user-cfg option. + """ + files = [] + check_environ() + + # Where to look for the system-wide Distutils config file + sys_dir = os.path.dirname(sys.modules['distutils'].__file__) + + # Look for the system config file + sys_file = os.path.join(sys_dir, "distutils.cfg") + if os.path.isfile(sys_file): + files.append(sys_file) + + # What to call the per-user config file + if os.name == 'posix': + user_filename = ".pydistutils.cfg" + else: + user_filename = "pydistutils.cfg" + + # And look for the user config file + if self.want_user_cfg: + user_file = os.path.join(os.path.expanduser('~'), user_filename) + if os.path.isfile(user_file): + files.append(user_file) + + # All platforms support local setup.cfg + local_file = "setup.cfg" + if os.path.isfile(local_file): + files.append(local_file) + + if DEBUG: + self.announce("using config files: %s" % ', '.join(files)) + + return files + + def parse_config_files(self, filenames=None): + from ConfigParser import ConfigParser + + if filenames is None: + filenames = self.find_config_files() + + if DEBUG: + self.announce("Distribution.parse_config_files():") + + parser = ConfigParser() + for filename in filenames: + if DEBUG: + self.announce(" reading %s" % filename) + parser.read(filename) + for section in parser.sections(): + options = parser.options(section) + opt_dict = self.get_option_dict(section) + + for opt in options: + if opt != '__name__': + val = parser.get(section,opt) + opt = opt.replace('-', '_') + opt_dict[opt] = (filename, val) + + # Make the ConfigParser forget everything (so we retain + # the original filenames that options come from) + parser.__init__() + + # If there was a "global" section in the config file, use it + # to set Distribution options. + + if 'global' in self.command_options: + for (opt, (src, val)) in self.command_options['global'].items(): + alias = self.negative_opt.get(opt) + try: + if alias: + setattr(self, alias, not strtobool(val)) + elif opt in ('verbose', 'dry_run'): # ugh! + setattr(self, opt, strtobool(val)) + else: + setattr(self, opt, val) + except ValueError, msg: + raise DistutilsOptionError, msg + + # -- Command-line parsing methods ---------------------------------- + + def parse_command_line(self): + """Parse the setup script's command line, taken from the + 'script_args' instance attribute (which defaults to 'sys.argv[1:]' + -- see 'setup()' in core.py). This list is first processed for + "global options" -- options that set attributes of the Distribution + instance. Then, it is alternately scanned for Distutils commands + and options for that command. Each new command terminates the + options for the previous command. The allowed options for a + command are determined by the 'user_options' attribute of the + command class -- thus, we have to be able to load command classes + in order to parse the command line. Any error in that 'options' + attribute raises DistutilsGetoptError; any error on the + command-line raises DistutilsArgError. If no Distutils commands + were found on the command line, raises DistutilsArgError. Return + true if command-line was successfully parsed and we should carry + on with executing commands; false if no errors but we shouldn't + execute commands (currently, this only happens if user asks for + help). + """ + # + # We now have enough information to show the Macintosh dialog + # that allows the user to interactively specify the "command line". + # + toplevel_options = self._get_toplevel_options() + + # We have to parse the command line a bit at a time -- global + # options, then the first command, then its options, and so on -- + # because each command will be handled by a different class, and + # the options that are valid for a particular class aren't known + # until we have loaded the command class, which doesn't happen + # until we know what the command is. + + self.commands = [] + parser = FancyGetopt(toplevel_options + self.display_options) + parser.set_negative_aliases(self.negative_opt) + parser.set_aliases({'licence': 'license'}) + args = parser.getopt(args=self.script_args, object=self) + option_order = parser.get_option_order() + log.set_verbosity(self.verbose) + + # for display options we return immediately + if self.handle_display_options(option_order): + return + while args: + args = self._parse_command_opts(parser, args) + if args is None: # user asked for help (and got it) + return + + # Handle the cases of --help as a "global" option, ie. + # "setup.py --help" and "setup.py --help command ...". For the + # former, we show global options (--verbose, --dry-run, etc.) + # and display-only options (--name, --version, etc.); for the + # latter, we omit the display-only options and show help for + # each command listed on the command line. + if self.help: + self._show_help(parser, + display_options=len(self.commands) == 0, + commands=self.commands) + return + + # Oops, no commands found -- an end-user error + if not self.commands: + raise DistutilsArgError, "no commands supplied" + + # All is well: return true + return 1 + + def _get_toplevel_options(self): + """Return the non-display options recognized at the top level. + + This includes options that are recognized *only* at the top + level as well as options recognized for commands. + """ + return self.global_options + [ + ("command-packages=", None, + "list of packages that provide distutils commands"), + ] + + def _parse_command_opts(self, parser, args): + """Parse the command-line options for a single command. + 'parser' must be a FancyGetopt instance; 'args' must be the list + of arguments, starting with the current command (whose options + we are about to parse). Returns a new version of 'args' with + the next command at the front of the list; will be the empty + list if there are no more commands on the command line. Returns + None if the user asked for help on this command. + """ + # late import because of mutual dependence between these modules + from distutils.cmd import Command + + # Pull the current command from the head of the command line + command = args[0] + if not command_re.match(command): + raise SystemExit, "invalid command name '%s'" % command + self.commands.append(command) + + # Dig up the command class that implements this command, so we + # 1) know that it's a valid command, and 2) know which options + # it takes. + try: + cmd_class = self.get_command_class(command) + except DistutilsModuleError, msg: + raise DistutilsArgError, msg + + # Require that the command class be derived from Command -- want + # to be sure that the basic "command" interface is implemented. + if not issubclass(cmd_class, Command): + raise DistutilsClassError, \ + "command class %s must subclass Command" % cmd_class + + # Also make sure that the command object provides a list of its + # known options. + if not (hasattr(cmd_class, 'user_options') and + isinstance(cmd_class.user_options, list)): + raise DistutilsClassError, \ + ("command class %s must provide " + + "'user_options' attribute (a list of tuples)") % \ + cmd_class + + # If the command class has a list of negative alias options, + # merge it in with the global negative aliases. + negative_opt = self.negative_opt + if hasattr(cmd_class, 'negative_opt'): + negative_opt = negative_opt.copy() + negative_opt.update(cmd_class.negative_opt) + + # Check for help_options in command class. They have a different + # format (tuple of four) so we need to preprocess them here. + if (hasattr(cmd_class, 'help_options') and + isinstance(cmd_class.help_options, list)): + help_options = fix_help_options(cmd_class.help_options) + else: + help_options = [] + + + # All commands support the global options too, just by adding + # in 'global_options'. + parser.set_option_table(self.global_options + + cmd_class.user_options + + help_options) + parser.set_negative_aliases(negative_opt) + (args, opts) = parser.getopt(args[1:]) + if hasattr(opts, 'help') and opts.help: + self._show_help(parser, display_options=0, commands=[cmd_class]) + return + + if (hasattr(cmd_class, 'help_options') and + isinstance(cmd_class.help_options, list)): + help_option_found=0 + for (help_option, short, desc, func) in cmd_class.help_options: + if hasattr(opts, parser.get_attr_name(help_option)): + help_option_found=1 + if hasattr(func, '__call__'): + func() + else: + raise DistutilsClassError( + "invalid help function %r for help option '%s': " + "must be a callable object (function, etc.)" + % (func, help_option)) + + if help_option_found: + return + + # Put the options from the command-line into their official + # holding pen, the 'command_options' dictionary. + opt_dict = self.get_option_dict(command) + for (name, value) in vars(opts).items(): + opt_dict[name] = ("command line", value) + + return args + + def finalize_options(self): + """Set final values for all the options on the Distribution + instance, analogous to the .finalize_options() method of Command + objects. + """ + for attr in ('keywords', 'platforms'): + value = getattr(self.metadata, attr) + if value is None: + continue + if isinstance(value, str): + value = [elm.strip() for elm in value.split(',')] + setattr(self.metadata, attr, value) + + def _show_help(self, parser, global_options=1, display_options=1, + commands=[]): + """Show help for the setup script command-line in the form of + several lists of command-line options. 'parser' should be a + FancyGetopt instance; do not expect it to be returned in the + same state, as its option table will be reset to make it + generate the correct help text. + + If 'global_options' is true, lists the global options: + --verbose, --dry-run, etc. If 'display_options' is true, lists + the "display-only" options: --name, --version, etc. Finally, + lists per-command help for every command name or command class + in 'commands'. + """ + # late import because of mutual dependence between these modules + from distutils.core import gen_usage + from distutils.cmd import Command + + if global_options: + if display_options: + options = self._get_toplevel_options() + else: + options = self.global_options + parser.set_option_table(options) + parser.print_help(self.common_usage + "\nGlobal options:") + print('') + + if display_options: + parser.set_option_table(self.display_options) + parser.print_help( + "Information display options (just display " + + "information, ignore any commands)") + print('') + + for command in self.commands: + if isinstance(command, type) and issubclass(command, Command): + klass = command + else: + klass = self.get_command_class(command) + if (hasattr(klass, 'help_options') and + isinstance(klass.help_options, list)): + parser.set_option_table(klass.user_options + + fix_help_options(klass.help_options)) + else: + parser.set_option_table(klass.user_options) + parser.print_help("Options for '%s' command:" % klass.__name__) + print('') + + print(gen_usage(self.script_name)) + + def handle_display_options(self, option_order): + """If there were any non-global "display-only" options + (--help-commands or the metadata display options) on the command + line, display the requested info and return true; else return + false. + """ + from distutils.core import gen_usage + + # User just wants a list of commands -- we'll print it out and stop + # processing now (ie. if they ran "setup --help-commands foo bar", + # we ignore "foo bar"). + if self.help_commands: + self.print_commands() + print('') + print(gen_usage(self.script_name)) + return 1 + + # If user supplied any of the "display metadata" options, then + # display that metadata in the order in which the user supplied the + # metadata options. + any_display_options = 0 + is_display_option = {} + for option in self.display_options: + is_display_option[option[0]] = 1 + + for (opt, val) in option_order: + if val and is_display_option.get(opt): + opt = translate_longopt(opt) + value = getattr(self.metadata, "get_"+opt)() + if opt in ['keywords', 'platforms']: + print(','.join(value)) + elif opt in ('classifiers', 'provides', 'requires', + 'obsoletes'): + print('\n'.join(value)) + else: + print(value) + any_display_options = 1 + + return any_display_options + + def print_command_list(self, commands, header, max_length): + """Print a subset of the list of all commands -- used by + 'print_commands()'. + """ + print(header + ":") + + for cmd in commands: + klass = self.cmdclass.get(cmd) + if not klass: + klass = self.get_command_class(cmd) + try: + description = klass.description + except AttributeError: + description = "(no description available)" + + print(" %-*s %s" % (max_length, cmd, description)) + + def print_commands(self): + """Print out a help message listing all available commands with a + description of each. The list is divided into "standard commands" + (listed in distutils.command.__all__) and "extra commands" + (mentioned in self.cmdclass, but not a standard command). The + descriptions come from the command class attribute + 'description'. + """ + import distutils.command + std_commands = distutils.command.__all__ + is_std = {} + for cmd in std_commands: + is_std[cmd] = 1 + + extra_commands = [] + for cmd in self.cmdclass.keys(): + if not is_std.get(cmd): + extra_commands.append(cmd) + + max_length = 0 + for cmd in (std_commands + extra_commands): + if len(cmd) > max_length: + max_length = len(cmd) + + self.print_command_list(std_commands, + "Standard commands", + max_length) + if extra_commands: + print + self.print_command_list(extra_commands, + "Extra commands", + max_length) + + def get_command_list(self): + """Get a list of (command, description) tuples. + The list is divided into "standard commands" (listed in + distutils.command.__all__) and "extra commands" (mentioned in + self.cmdclass, but not a standard command). The descriptions come + from the command class attribute 'description'. + """ + # Currently this is only used on Mac OS, for the Mac-only GUI + # Distutils interface (by Jack Jansen) + + import distutils.command + std_commands = distutils.command.__all__ + is_std = {} + for cmd in std_commands: + is_std[cmd] = 1 + + extra_commands = [] + for cmd in self.cmdclass.keys(): + if not is_std.get(cmd): + extra_commands.append(cmd) + + rv = [] + for cmd in (std_commands + extra_commands): + klass = self.cmdclass.get(cmd) + if not klass: + klass = self.get_command_class(cmd) + try: + description = klass.description + except AttributeError: + description = "(no description available)" + rv.append((cmd, description)) + return rv + + # -- Command class/object methods ---------------------------------- + + def get_command_packages(self): + """Return a list of packages from which commands are loaded.""" + pkgs = self.command_packages + if not isinstance(pkgs, list): + if pkgs is None: + pkgs = '' + pkgs = [pkg.strip() for pkg in pkgs.split(',') if pkg != ''] + if "distutils.command" not in pkgs: + pkgs.insert(0, "distutils.command") + self.command_packages = pkgs + return pkgs + + def get_command_class(self, command): + """Return the class that implements the Distutils command named by + 'command'. First we check the 'cmdclass' dictionary; if the + command is mentioned there, we fetch the class object from the + dictionary and return it. Otherwise we load the command module + ("distutils.command." + command) and fetch the command class from + the module. The loaded class is also stored in 'cmdclass' + to speed future calls to 'get_command_class()'. + + Raises DistutilsModuleError if the expected module could not be + found, or if that module does not define the expected class. + """ + klass = self.cmdclass.get(command) + if klass: + return klass + + for pkgname in self.get_command_packages(): + module_name = "%s.%s" % (pkgname, command) + klass_name = command + + try: + __import__ (module_name) + module = sys.modules[module_name] + except ImportError: + continue + + try: + klass = getattr(module, klass_name) + except AttributeError: + raise DistutilsModuleError, \ + "invalid command '%s' (no class '%s' in module '%s')" \ + % (command, klass_name, module_name) + + self.cmdclass[command] = klass + return klass + + raise DistutilsModuleError("invalid command '%s'" % command) + + + def get_command_obj(self, command, create=1): + """Return the command object for 'command'. Normally this object + is cached on a previous call to 'get_command_obj()'; if no command + object for 'command' is in the cache, then we either create and + return it (if 'create' is true) or return None. + """ + cmd_obj = self.command_obj.get(command) + if not cmd_obj and create: + if DEBUG: + self.announce("Distribution.get_command_obj(): " \ + "creating '%s' command object" % command) + + klass = self.get_command_class(command) + cmd_obj = self.command_obj[command] = klass(self) + self.have_run[command] = 0 + + # Set any options that were supplied in config files + # or on the command line. (NB. support for error + # reporting is lame here: any errors aren't reported + # until 'finalize_options()' is called, which means + # we won't report the source of the error.) + options = self.command_options.get(command) + if options: + self._set_command_options(cmd_obj, options) + + return cmd_obj + + def _set_command_options(self, command_obj, option_dict=None): + """Set the options for 'command_obj' from 'option_dict'. Basically + this means copying elements of a dictionary ('option_dict') to + attributes of an instance ('command'). + + 'command_obj' must be a Command instance. If 'option_dict' is not + supplied, uses the standard option dictionary for this command + (from 'self.command_options'). + """ + command_name = command_obj.get_command_name() + if option_dict is None: + option_dict = self.get_option_dict(command_name) + + if DEBUG: + self.announce(" setting options for '%s' command:" % command_name) + for (option, (source, value)) in option_dict.items(): + if DEBUG: + self.announce(" %s = %s (from %s)" % (option, value, + source)) + try: + bool_opts = map(translate_longopt, command_obj.boolean_options) + except AttributeError: + bool_opts = [] + try: + neg_opt = command_obj.negative_opt + except AttributeError: + neg_opt = {} + + try: + is_string = isinstance(value, str) + if option in neg_opt and is_string: + setattr(command_obj, neg_opt[option], not strtobool(value)) + elif option in bool_opts and is_string: + setattr(command_obj, option, strtobool(value)) + elif hasattr(command_obj, option): + setattr(command_obj, option, value) + else: + raise DistutilsOptionError, \ + ("error in %s: command '%s' has no such option '%s'" + % (source, command_name, option)) + except ValueError, msg: + raise DistutilsOptionError, msg + + def reinitialize_command(self, command, reinit_subcommands=0): + """Reinitializes a command to the state it was in when first + returned by 'get_command_obj()': ie., initialized but not yet + finalized. This provides the opportunity to sneak option + values in programmatically, overriding or supplementing + user-supplied values from the config files and command line. + You'll have to re-finalize the command object (by calling + 'finalize_options()' or 'ensure_finalized()') before using it for + real. + + 'command' should be a command name (string) or command object. If + 'reinit_subcommands' is true, also reinitializes the command's + sub-commands, as declared by the 'sub_commands' class attribute (if + it has one). See the "install" command for an example. Only + reinitializes the sub-commands that actually matter, ie. those + whose test predicates return true. + + Returns the reinitialized command object. + """ + from distutils.cmd import Command + if not isinstance(command, Command): + command_name = command + command = self.get_command_obj(command_name) + else: + command_name = command.get_command_name() + + if not command.finalized: + return command + command.initialize_options() + command.finalized = 0 + self.have_run[command_name] = 0 + self._set_command_options(command) + + if reinit_subcommands: + for sub in command.get_sub_commands(): + self.reinitialize_command(sub, reinit_subcommands) + + return command + + # -- Methods that operate on the Distribution ---------------------- + + def announce(self, msg, level=log.INFO): + log.log(level, msg) + + def run_commands(self): + """Run each command that was seen on the setup script command line. + Uses the list of commands found and cache of command objects + created by 'get_command_obj()'. + """ + for cmd in self.commands: + self.run_command(cmd) + + # -- Methods that operate on its Commands -------------------------- + + def run_command(self, command): + """Do whatever it takes to run a command (including nothing at all, + if the command has already been run). Specifically: if we have + already created and run the command named by 'command', return + silently without doing anything. If the command named by 'command' + doesn't even have a command object yet, create one. Then invoke + 'run()' on that command object (or an existing one). + """ + # Already been here, done that? then return silently. + if self.have_run.get(command): + return + + log.info("running %s", command) + cmd_obj = self.get_command_obj(command) + cmd_obj.ensure_finalized() + cmd_obj.run() + self.have_run[command] = 1 + + + # -- Distribution query methods ------------------------------------ + + def has_pure_modules(self): + return len(self.packages or self.py_modules or []) > 0 + + def has_ext_modules(self): + return self.ext_modules and len(self.ext_modules) > 0 + + def has_c_libraries(self): + return self.libraries and len(self.libraries) > 0 + + def has_modules(self): + return self.has_pure_modules() or self.has_ext_modules() + + def has_headers(self): + return self.headers and len(self.headers) > 0 + + def has_scripts(self): + return self.scripts and len(self.scripts) > 0 + + def has_data_files(self): + return self.data_files and len(self.data_files) > 0 + + def is_pure(self): + return (self.has_pure_modules() and + not self.has_ext_modules() and + not self.has_c_libraries()) + + # -- Metadata query methods ---------------------------------------- + + # If you're looking for 'get_name()', 'get_version()', and so forth, + # they are defined in a sneaky way: the constructor binds self.get_XXX + # to self.metadata.get_XXX. The actual code is in the + # DistributionMetadata class, below. + +class DistributionMetadata: + """Dummy class to hold the distribution meta-data: name, version, + author, and so forth. + """ + + _METHOD_BASENAMES = ("name", "version", "author", "author_email", + "maintainer", "maintainer_email", "url", + "license", "description", "long_description", + "keywords", "platforms", "fullname", "contact", + "contact_email", "license", "classifiers", + "download_url", + # PEP 314 + "provides", "requires", "obsoletes", + ) + + def __init__(self, path=None): + if path is not None: + self.read_pkg_file(open(path)) + else: + self.name = None + self.version = None + self.author = None + self.author_email = None + self.maintainer = None + self.maintainer_email = None + self.url = None + self.license = None + self.description = None + self.long_description = None + self.keywords = None + self.platforms = None + self.classifiers = None + self.download_url = None + # PEP 314 + self.provides = None + self.requires = None + self.obsoletes = None + + def read_pkg_file(self, file): + """Reads the metadata values from a file object.""" + msg = message_from_file(file) + + def _read_field(name): + value = msg[name] + if value == 'UNKNOWN': + return None + return value + + def _read_list(name): + values = msg.get_all(name, None) + if values == []: + return None + return values + + metadata_version = msg['metadata-version'] + self.name = _read_field('name') + self.version = _read_field('version') + self.description = _read_field('summary') + # we are filling author only. + self.author = _read_field('author') + self.maintainer = None + self.author_email = _read_field('author-email') + self.maintainer_email = None + self.url = _read_field('home-page') + self.license = _read_field('license') + + if 'download-url' in msg: + self.download_url = _read_field('download-url') + else: + self.download_url = None + + self.long_description = _read_field('description') + self.description = _read_field('summary') + + if 'keywords' in msg: + self.keywords = _read_field('keywords').split(',') + + self.platforms = _read_list('platform') + self.classifiers = _read_list('classifier') + + # PEP 314 - these fields only exist in 1.1 + if metadata_version == '1.1': + self.requires = _read_list('requires') + self.provides = _read_list('provides') + self.obsoletes = _read_list('obsoletes') + else: + self.requires = None + self.provides = None + self.obsoletes = None + + def write_pkg_info(self, base_dir): + """Write the PKG-INFO file into the release tree. + """ + pkg_info = open(os.path.join(base_dir, 'PKG-INFO'), 'w') + try: + self.write_pkg_file(pkg_info) + finally: + pkg_info.close() + + def write_pkg_file(self, file): + """Write the PKG-INFO format data to a file object. + """ + version = '1.0' + if (self.provides or self.requires or self.obsoletes or + self.classifiers or self.download_url): + version = '1.1' + + self._write_field(file, 'Metadata-Version', version) + self._write_field(file, 'Name', self.get_name()) + self._write_field(file, 'Version', self.get_version()) + self._write_field(file, 'Summary', self.get_description()) + self._write_field(file, 'Home-page', self.get_url()) + self._write_field(file, 'Author', self.get_contact()) + self._write_field(file, 'Author-email', self.get_contact_email()) + self._write_field(file, 'License', self.get_license()) + if self.download_url: + self._write_field(file, 'Download-URL', self.download_url) + + long_desc = rfc822_escape(self.get_long_description()) + self._write_field(file, 'Description', long_desc) + + keywords = ','.join(self.get_keywords()) + if keywords: + self._write_field(file, 'Keywords', keywords) + + self._write_list(file, 'Platform', self.get_platforms()) + self._write_list(file, 'Classifier', self.get_classifiers()) + + # PEP 314 + self._write_list(file, 'Requires', self.get_requires()) + self._write_list(file, 'Provides', self.get_provides()) + self._write_list(file, 'Obsoletes', self.get_obsoletes()) + + def _write_field(self, file, name, value): + file.write('%s: %s\n' % (name, self._encode_field(value))) + + def _write_list (self, file, name, values): + for value in values: + self._write_field(file, name, value) + + def _encode_field(self, value): + if value is None: + return None + if isinstance(value, unicode): + return value.encode(PKG_INFO_ENCODING) + return str(value) + + # -- Metadata query methods ---------------------------------------- + + def get_name(self): + return self.name or "UNKNOWN" + + def get_version(self): + return self.version or "0.0.0" + + def get_fullname(self): + return "%s-%s" % (self.get_name(), self.get_version()) + + def get_author(self): + return self._encode_field(self.author) or "UNKNOWN" + + def get_author_email(self): + return self.author_email or "UNKNOWN" + + def get_maintainer(self): + return self._encode_field(self.maintainer) or "UNKNOWN" + + def get_maintainer_email(self): + return self.maintainer_email or "UNKNOWN" + + def get_contact(self): + return (self._encode_field(self.maintainer) or + self._encode_field(self.author) or "UNKNOWN") + + def get_contact_email(self): + return self.maintainer_email or self.author_email or "UNKNOWN" + + def get_url(self): + return self.url or "UNKNOWN" + + def get_license(self): + return self.license or "UNKNOWN" + get_licence = get_license + + def get_description(self): + return self._encode_field(self.description) or "UNKNOWN" + + def get_long_description(self): + return self._encode_field(self.long_description) or "UNKNOWN" + + def get_keywords(self): + return self.keywords or [] + + def get_platforms(self): + return self.platforms or ["UNKNOWN"] + + def get_classifiers(self): + return self.classifiers or [] + + def get_download_url(self): + return self.download_url or "UNKNOWN" + + # PEP 314 + def get_requires(self): + return self.requires or [] + + def set_requires(self, value): + import distutils.versionpredicate + for v in value: + distutils.versionpredicate.VersionPredicate(v) + self.requires = value + + def get_provides(self): + return self.provides or [] + + def set_provides(self, value): + value = [v.strip() for v in value] + for v in value: + import distutils.versionpredicate + distutils.versionpredicate.split_provision(v) + self.provides = value + + def get_obsoletes(self): + return self.obsoletes or [] + + def set_obsoletes(self, value): + import distutils.versionpredicate + for v in value: + distutils.versionpredicate.VersionPredicate(v) + self.obsoletes = value + +def fix_help_options(options): + """Convert a 4-tuple 'help_options' list as found in various command + classes to the 3-tuple form required by FancyGetopt. + """ + new_options = [] + for help_tuple in options: + new_options.append(help_tuple[0:3]) + return new_options diff --git a/PythonHome/Lib/distutils/dist.pyc b/PythonHome/Lib/distutils/dist.pyc deleted file mode 100644 index f124d415f579fdeb422f457ae813af9eed61b0ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39231 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 WV`t#f@bGwP*WWt+|GT^X^#1`AT`vp( diff --git a/PythonHome/Lib/distutils/emxccompiler.py b/PythonHome/Lib/distutils/emxccompiler.py new file mode 100644 index 0000000000..a0172058a3 --- /dev/null +++ b/PythonHome/Lib/distutils/emxccompiler.py @@ -0,0 +1,319 @@ +"""distutils.emxccompiler + +Provides the EMXCCompiler class, a subclass of UnixCCompiler that +handles the EMX port of the GNU C compiler to OS/2. +""" + +# issues: +# +# * OS/2 insists that DLLs can have names no longer than 8 characters +# We put export_symbols in a def-file, as though the DLL can have +# an arbitrary length name, but truncate the output filename. +# +# * only use OMF objects and use LINK386 as the linker (-Zomf) +# +# * always build for multithreading (-Zmt) as the accompanying OS/2 port +# of Python is only distributed with threads enabled. +# +# tested configurations: +# +# * EMX gcc 2.81/EMX 0.9d fix03 + +__revision__ = "$Id$" + +import os,sys,copy +from distutils.ccompiler import gen_preprocess_options, gen_lib_options +from distutils.unixccompiler import UnixCCompiler +from distutils.file_util import write_file +from distutils.errors import DistutilsExecError, CompileError, UnknownFileError +from distutils import log + +class EMXCCompiler (UnixCCompiler): + + compiler_type = 'emx' + obj_extension = ".obj" + static_lib_extension = ".lib" + shared_lib_extension = ".dll" + static_lib_format = "%s%s" + shared_lib_format = "%s%s" + res_extension = ".res" # compiled resource file + exe_extension = ".exe" + + def __init__ (self, + verbose=0, + dry_run=0, + force=0): + + UnixCCompiler.__init__ (self, verbose, dry_run, force) + + (status, details) = check_config_h() + self.debug_print("Python's GCC status: %s (details: %s)" % + (status, details)) + if status is not CONFIG_H_OK: + self.warn( + "Python's pyconfig.h doesn't seem to support your compiler. " + + ("Reason: %s." % details) + + "Compiling may fail because of undefined preprocessor macros.") + + (self.gcc_version, self.ld_version) = \ + get_versions() + self.debug_print(self.compiler_type + ": gcc %s, ld %s\n" % + (self.gcc_version, + self.ld_version) ) + + # Hard-code GCC because that's what this is all about. + # XXX optimization, warnings etc. should be customizable. + self.set_executables(compiler='gcc -Zomf -Zmt -O3 -fomit-frame-pointer -mprobe -Wall', + compiler_so='gcc -Zomf -Zmt -O3 -fomit-frame-pointer -mprobe -Wall', + linker_exe='gcc -Zomf -Zmt -Zcrtdll', + linker_so='gcc -Zomf -Zmt -Zcrtdll -Zdll') + + # want the gcc library statically linked (so that we don't have + # to distribute a version dependent on the compiler we have) + self.dll_libraries=["gcc"] + + # __init__ () + + def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): + if ext == '.rc': + # gcc requires '.rc' compiled to binary ('.res') files !!! + try: + self.spawn(["rc", "-r", src]) + except DistutilsExecError, msg: + raise CompileError, msg + else: # for other files use the C-compiler + try: + self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + + extra_postargs) + except DistutilsExecError, msg: + raise CompileError, msg + + def link (self, + target_desc, + objects, + output_filename, + output_dir=None, + libraries=None, + library_dirs=None, + runtime_library_dirs=None, + export_symbols=None, + debug=0, + extra_preargs=None, + extra_postargs=None, + build_temp=None, + target_lang=None): + + # use separate copies, so we can modify the lists + extra_preargs = copy.copy(extra_preargs or []) + libraries = copy.copy(libraries or []) + objects = copy.copy(objects or []) + + # Additional libraries + libraries.extend(self.dll_libraries) + + # handle export symbols by creating a def-file + # with executables this only works with gcc/ld as linker + if ((export_symbols is not None) and + (target_desc != self.EXECUTABLE)): + # (The linker doesn't do anything if output is up-to-date. + # So it would probably better to check if we really need this, + # but for this we had to insert some unchanged parts of + # UnixCCompiler, and this is not what we want.) + + # we want to put some files in the same directory as the + # object files are, build_temp doesn't help much + # where are the object files + temp_dir = os.path.dirname(objects[0]) + # name of dll to give the helper files the same base name + (dll_name, dll_extension) = os.path.splitext( + os.path.basename(output_filename)) + + # generate the filenames for these files + def_file = os.path.join(temp_dir, dll_name + ".def") + + # Generate .def file + contents = [ + "LIBRARY %s INITINSTANCE TERMINSTANCE" % \ + os.path.splitext(os.path.basename(output_filename))[0], + "DATA MULTIPLE NONSHARED", + "EXPORTS"] + for sym in export_symbols: + contents.append(' "%s"' % sym) + self.execute(write_file, (def_file, contents), + "writing %s" % def_file) + + # next add options for def-file and to creating import libraries + # for gcc/ld the def-file is specified as any other object files + objects.append(def_file) + + #end: if ((export_symbols is not None) and + # (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")): + + # who wants symbols and a many times larger output file + # should explicitly switch the debug mode on + # otherwise we let dllwrap/ld strip the output file + # (On my machine: 10KB < stripped_file < ??100KB + # unstripped_file = stripped_file + XXX KB + # ( XXX=254 for a typical python extension)) + if not debug: + extra_preargs.append("-s") + + UnixCCompiler.link(self, + target_desc, + objects, + output_filename, + output_dir, + libraries, + library_dirs, + runtime_library_dirs, + None, # export_symbols, we do this in our def-file + debug, + extra_preargs, + extra_postargs, + build_temp, + target_lang) + + # link () + + # -- Miscellaneous methods ----------------------------------------- + + # override the object_filenames method from CCompiler to + # support rc and res-files + def object_filenames (self, + source_filenames, + strip_dir=0, + output_dir=''): + if output_dir is None: output_dir = '' + obj_names = [] + for src_name in source_filenames: + # use normcase to make sure '.rc' is really '.rc' and not '.RC' + (base, ext) = os.path.splitext (os.path.normcase(src_name)) + if ext not in (self.src_extensions + ['.rc']): + raise UnknownFileError, \ + "unknown file type '%s' (from '%s')" % \ + (ext, src_name) + if strip_dir: + base = os.path.basename (base) + if ext == '.rc': + # these need to be compiled to object files + obj_names.append (os.path.join (output_dir, + base + self.res_extension)) + else: + obj_names.append (os.path.join (output_dir, + base + self.obj_extension)) + return obj_names + + # object_filenames () + + # override the find_library_file method from UnixCCompiler + # to deal with file naming/searching differences + def find_library_file(self, dirs, lib, debug=0): + shortlib = '%s.lib' % lib + longlib = 'lib%s.lib' % lib # this form very rare + + # get EMX's default library directory search path + try: + emx_dirs = os.environ['LIBRARY_PATH'].split(';') + except KeyError: + emx_dirs = [] + + for dir in dirs + emx_dirs: + shortlibp = os.path.join(dir, shortlib) + longlibp = os.path.join(dir, longlib) + if os.path.exists(shortlibp): + return shortlibp + elif os.path.exists(longlibp): + return longlibp + + # Oops, didn't find it in *any* of 'dirs' + return None + +# class EMXCCompiler + + +# Because these compilers aren't configured in Python's pyconfig.h file by +# default, we should at least warn the user if he is using a unmodified +# version. + +CONFIG_H_OK = "ok" +CONFIG_H_NOTOK = "not ok" +CONFIG_H_UNCERTAIN = "uncertain" + +def check_config_h(): + + """Check if the current Python installation (specifically, pyconfig.h) + appears amenable to building extensions with GCC. Returns a tuple + (status, details), where 'status' is one of the following constants: + CONFIG_H_OK + all is well, go ahead and compile + CONFIG_H_NOTOK + doesn't look good + CONFIG_H_UNCERTAIN + not sure -- unable to read pyconfig.h + 'details' is a human-readable string explaining the situation. + + Note there are two ways to conclude "OK": either 'sys.version' contains + the string "GCC" (implying that this Python was built with GCC), or the + installed "pyconfig.h" contains the string "__GNUC__". + """ + + # XXX since this function also checks sys.version, it's not strictly a + # "pyconfig.h" check -- should probably be renamed... + + from distutils import sysconfig + import string + # if sys.version contains GCC then python was compiled with + # GCC, and the pyconfig.h file should be OK + if string.find(sys.version,"GCC") >= 0: + return (CONFIG_H_OK, "sys.version mentions 'GCC'") + + fn = sysconfig.get_config_h_filename() + try: + # It would probably better to read single lines to search. + # But we do this only once, and it is fast enough + f = open(fn) + try: + s = f.read() + finally: + f.close() + + except IOError, exc: + # if we can't read this file, we cannot say it is wrong + # the compiler will complain later about this file as missing + return (CONFIG_H_UNCERTAIN, + "couldn't read '%s': %s" % (fn, exc.strerror)) + + else: + # "pyconfig.h" contains an "#ifdef __GNUC__" or something similar + if string.find(s,"__GNUC__") >= 0: + return (CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn) + else: + return (CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn) + + +def get_versions(): + """ Try to find out the versions of gcc and ld. + If not possible it returns None for it. + """ + from distutils.version import StrictVersion + from distutils.spawn import find_executable + import re + + gcc_exe = find_executable('gcc') + if gcc_exe: + out = os.popen(gcc_exe + ' -dumpversion','r') + try: + out_string = out.read() + finally: + out.close() + result = re.search('(\d+\.\d+\.\d+)',out_string) + if result: + gcc_version = StrictVersion(result.group(1)) + else: + gcc_version = None + else: + gcc_version = None + # EMX ld has no way of reporting version number, and we use GCC + # anyway - so we can link OMF DLLs + ld_version = None + return (gcc_version, ld_version) diff --git a/PythonHome/Lib/distutils/emxccompiler.pyc b/PythonHome/Lib/distutils/emxccompiler.pyc deleted file mode 100644 index 688d34377d22a550410bbe5270532d2a66a88e21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7332 zcmb7JOK&6Db-qPXlt?{WGc8Sz$MA*FZL#B)9M}^CnK1%u)S4M(x~Wc49krPrRH&+= zSW>a7x^8hK8tO&dg8Z)sXJO)Hd6?y?9~$GOSrMg)DOSs&I69s5wH(e_M)7NVvfWK| zU*=H}dVL(T#Wyb2Q9PX7!ogMOALKc3-rvk`NUCMb1OLsv95TS+&(6oOG>T^&w z6(oQ!yT~X0wLg&E?16kVDNdXY;wAMtL>B~TF00S6fmP*pTD-}E2Z0#KE9|DH=eB~& zwUr=_rE<^QGqxwkWAMp#!>cgDxANJlWYw~0%~jo`Xbf*3t=S+7*h!9AVH_C0hdXwM4H)He4} zJ{cE-G}$)#qy2qtie51?@9BF+w}PsUK|(P?1YVH(t=7CN6AH)dk_<|`CAxw{k(v56_lEi)THL? zUrvb)k)8sJO}414u7Cy4;CWFJ6`oh{o%})QUwHP)y@6~l2v0|6fD>$9+WSZC4-Y@` zKK712fv5o?dU+zsd=?hoXJKvxYj`ZIHR-U&3Z_jW&h*s9I12@w3^?G>{;24k0t^M0 zuyGGMmG|-}G%YHNtZKrzU(BP06;D%4WIf2oUOq~SIn?`U?uQU_D3u7BC9rbVLa&m- zd;_)J=Z~V(=TmHdeiPewv$0EU{~dhH778`DQCW2w&Wf|-)GLe5V)eGO>eQXp8q2yf zU-P*Y-YmBvTK#vZK#ifT7ZsI%tj2GPu3^JgIVxa{HCG_{4IdChJ`$E}Jf=xqRUkkLkXRLWBz-DBlLm$TYkv^_Oc|Q9*Lxk&LrAQc;>X}--bA6CrApO#8!xkl@2}&nRvn)L z&OyGXyvtw0`VnpMI!%?Wsx!C-j(XXgbk3>l?xb^W(pgd2A51#&HghFdp97x>z`#T$ z0Q|l~{04X6aaHB-JGjO3x;h7>iYdFprB-;i>|K~t8UpwZnGx())yuWXP*Yv6sOwcq z&E_kN-BPfE|Id8L+no(a2Cy8G@p4^VeM4b?4?o>hFW*qt>*^c`U02s{SljX9SL%fO zU7|y9eTxJzD?oVEH(ph7whCvU#e>3#TsM^YV+U79J`0mxyz==f4?ZZw4|<=)vFcwXS5T9v$oj9(tw72a~FM&4nJ`B+#djR^D zfSN3Z9|d)w!kqR@C?h04r&ZvtdRc~LWTwTy(4`Jppe7}uzD4=93P=5;4goXadHOOD z3K;s(BuaQXDzZ@_uA3~zi?U-6qo&|Ggwkjjmhf8+P>I4T8eY$g zho@<51Rcam2w;~Ao`=+L_nRP>%Q_uJao`oUs-2aO4V$Sy8GM5VY?j%4`0W%*FkvEvW|FjOEH*XF~*V4XxWSck9lZ_}q3x z@~G@n_v7EtV5EQ;0fL6tmf9TM5XdTG4M@x#$Qw+B6^oN(6TU-L+>noy<2V#iNDJJC ztAXHpU2Q)6^f|?l93VCb7a&()0J{Vcy4g7=osCH+BuZ>W{tv8lN>cPTxO(1UrSqbr zPM|5Bmi18hrtst$TUn>~)V2h-O8ekF**pFiva8hl_AMzl7EY7Tq8uqh#pxfPLng%DGTr-EtGP~ z1aT+SnUIv^*=q{OEigp15=?=aYV=EVns-nrr|C4SbbgkdX5|(E4X{Dw6F}cN^10AVQ|!Q?mxr>08w1?fjTvykhrObZ-Wj>= zbsuvH>LrZbjD`5x?tOI23kW>B$87p2X7?nuujIV*taS1X!J}TGi+an@H|mQbEcJhK~t&eC_A?&7Di3xGe+f@FYLg!hvc z7VEU=d6<8MzqHS2QAajQ<&W|lhFIGmUq?tdA-;w9q={~sEcBy( zx<0+!XaH@($dA#z_zQH+rncYc%cvMIcYq+@4U18pV2UnASsV(R7G-aQ2)#@v+<%}i z2VoB5Vh6T$WHg+&NnWj=#&LSdHQ+>m1YX2@!bs~IL2lWDUB)pPT!wM{K%b?$Hwb%y zM&1t7CHnZ{-1gD&(I?aClk`QLrWcr=245t93a8dR-aBkhr%>R`2nX2NL5gB>Gw`gC zr^6l*J1ubYa$(SIU0kO6 zvNuLfGv)pG@hAxO*3l6>6~YKF;cr*n!h>z;Ry54wv0b`X zU>V$GDJhpdBd=Xd-xm*u>#85J(dK)C$hACA)9mN5&PjdV8R+w876rZeV-U6NY zF|+xTG32}^gOmf!mo2IE_LRux6}i)CGQu6AC5Fj9qJ$U(e>nj*Eq14T1b3apw^1-E zut)Uq=0aLM*!(tbqWPBM1Old^YB{?Jebzg8F z45<2vSmeHxHo_0D{27jaB?zZO^gsB>9je=F&QkSjFl|dtwTcgX@zu&Ifc$ptEoY_T zgHZCRG}-%{_3tRY6p)7qjN#UD9RGqqY85bvI(!xZTOe!xFJ+8P=N*0z0%AHjH34Fv zxP|FC05QCDai9f=ftXCA0=TXJ0|%$B@_&-R81cSjq_GBeNmnmq>OtWOGnI;sB*94<$GdDb6U^?j?HND~{8bGq5WDK!(rq zbd*`Ij`}6cT{3e2g49eyFGq6{&vizmN^Wa2vNZ&ezVdbRGf2q&^J&kIr?o*MJEo|lK8MGS@Et4U;J(CdDS zv~Qr8-PQEpQ!cud%iAvK+|4LP_&3yyiWm9?7W6AU{=Z8y5fYfpW(y3M8wo*PkejjK zZMt;41dv=fGs^uT3u>~M~2>g7{`l){?t~_D8eyc8#5byFGK*7e(#k;FC G-u*u+V0{1p diff --git a/PythonHome/Lib/distutils/errors.py b/PythonHome/Lib/distutils/errors.py new file mode 100644 index 0000000000..d9c47c761c --- /dev/null +++ b/PythonHome/Lib/distutils/errors.py @@ -0,0 +1,88 @@ +"""distutils.errors + +Provides exceptions used by the Distutils modules. Note that Distutils +modules may raise standard exceptions; in particular, SystemExit is +usually raised for errors that are obviously the end-user's fault +(eg. bad command-line arguments). + +This module is safe to use in "from ... import *" mode; it only exports +symbols whose names start with "Distutils" and end with "Error".""" + +__revision__ = "$Id$" + +class DistutilsError(Exception): + """The root of all Distutils evil.""" + +class DistutilsModuleError(DistutilsError): + """Unable to load an expected module, or to find an expected class + within some module (in particular, command modules and classes).""" + +class DistutilsClassError(DistutilsError): + """Some command class (or possibly distribution class, if anyone + feels a need to subclass Distribution) is found not to be holding + up its end of the bargain, ie. implementing some part of the + "command "interface.""" + +class DistutilsGetoptError(DistutilsError): + """The option table provided to 'fancy_getopt()' is bogus.""" + +class DistutilsArgError(DistutilsError): + """Raised by fancy_getopt in response to getopt.error -- ie. an + error in the command line usage.""" + +class DistutilsFileError(DistutilsError): + """Any problems in the filesystem: expected file not found, etc. + Typically this is for problems that we detect before IOError or + OSError could be raised.""" + +class DistutilsOptionError(DistutilsError): + """Syntactic/semantic errors in command options, such as use of + mutually conflicting options, or inconsistent options, + badly-spelled values, etc. No distinction is made between option + values originating in the setup script, the command line, config + files, or what-have-you -- but if we *know* something originated in + the setup script, we'll raise DistutilsSetupError instead.""" + +class DistutilsSetupError(DistutilsError): + """For errors that can be definitely blamed on the setup script, + such as invalid keyword arguments to 'setup()'.""" + +class DistutilsPlatformError(DistutilsError): + """We don't know how to do something on the current platform (but + we do know how to do it on some platform) -- eg. trying to compile + C files on a platform not supported by a CCompiler subclass.""" + +class DistutilsExecError(DistutilsError): + """Any problems executing an external program (such as the C + compiler, when compiling C files).""" + +class DistutilsInternalError(DistutilsError): + """Internal inconsistencies or impossibilities (obviously, this + should never be seen if the code is working!).""" + +class DistutilsTemplateError(DistutilsError): + """Syntax error in a file list template.""" + +class DistutilsByteCompileError(DistutilsError): + """Byte compile error.""" + +# Exception classes used by the CCompiler implementation classes +class CCompilerError(Exception): + """Some compile/link operation failed.""" + +class PreprocessError(CCompilerError): + """Failure to preprocess one or more C/C++ files.""" + +class CompileError(CCompilerError): + """Failure to compile one or more C/C++ source files.""" + +class LibError(CCompilerError): + """Failure to create a static library from one or more C/C++ object + files.""" + +class LinkError(CCompilerError): + """Failure to link one or more C/C++ object files into an executable + or shared library file.""" + +class UnknownFileError(CCompilerError): + """Attempt to process an unknown file type.""" diff --git a/PythonHome/Lib/distutils/errors.pyc b/PythonHome/Lib/distutils/errors.pyc deleted file mode 100644 index 48f9309cb0b010cbf0c912f101ca538f128409c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6185 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 ... [ ...] [ ...] [ ...] + file = TextFile(filename, + strip_comments=1, skip_blanks=1, join_lines=1, + lstrip_ws=1, rstrip_ws=1) + try: + extensions = [] + + while 1: + line = file.readline() + if line is None: # eof + break + if _variable_rx.match(line): # VAR=VALUE, handled in first pass + continue + + if line[0] == line[-1] == "*": + file.warn("'%s' lines not handled yet" % line) + continue + + #print "original line: " + line + line = expand_makefile_vars(line, vars) + words = split_quoted(line) + #print "expanded line: " + line + + # NB. this parses a slightly different syntax than the old + # makesetup script: here, there must be exactly one extension per + # line, and it must be the first word of the line. I have no idea + # why the old syntax supported multiple extensions per line, as + # they all wind up being the same. + + module = words[0] + ext = Extension(module, []) + append_next_word = None + + for word in words[1:]: + if append_next_word is not None: + append_next_word.append(word) + append_next_word = None + continue + + suffix = os.path.splitext(word)[1] + switch = word[0:2] ; value = word[2:] + + if suffix in (".c", ".cc", ".cpp", ".cxx", ".c++", ".m", ".mm"): + # hmm, should we do something about C vs. C++ sources? + # or leave it up to the CCompiler implementation to + # worry about? + ext.sources.append(word) + elif switch == "-I": + ext.include_dirs.append(value) + elif switch == "-D": + equals = string.find(value, "=") + if equals == -1: # bare "-DFOO" -- no value + ext.define_macros.append((value, None)) + else: # "-DFOO=blah" + ext.define_macros.append((value[0:equals], + value[equals+2:])) + elif switch == "-U": + ext.undef_macros.append(value) + elif switch == "-C": # only here 'cause makesetup has it! + ext.extra_compile_args.append(word) + elif switch == "-l": + ext.libraries.append(value) + elif switch == "-L": + ext.library_dirs.append(value) + elif switch == "-R": + ext.runtime_library_dirs.append(value) + elif word == "-rpath": + append_next_word = ext.runtime_library_dirs + elif word == "-Xlinker": + append_next_word = ext.extra_link_args + elif word == "-Xcompiler": + append_next_word = ext.extra_compile_args + elif switch == "-u": + ext.extra_link_args.append(word) + if not value: + append_next_word = ext.extra_link_args + elif word == "-Xcompiler": + append_next_word = ext.extra_compile_args + elif switch == "-u": + ext.extra_link_args.append(word) + if not value: + append_next_word = ext.extra_link_args + elif suffix in (".a", ".so", ".sl", ".o", ".dylib"): + # NB. a really faithful emulation of makesetup would + # append a .o file to extra_objects only if it + # had a slash in it; otherwise, it would s/.o/.c/ + # and append it to sources. Hmmmm. + ext.extra_objects.append(word) + else: + file.warn("unrecognized argument '%s'" % word) + + extensions.append(ext) + finally: + file.close() + + #print "module:", module + #print "source files:", source_files + #print "cpp args:", cpp_args + #print "lib args:", library_args + + #extensions[module] = { 'sources': source_files, + # 'cpp_args': cpp_args, + # 'lib_args': library_args } + + return extensions + +# read_setup_file () diff --git a/PythonHome/Lib/distutils/extension.pyc b/PythonHome/Lib/distutils/extension.pyc deleted file mode 100644 index c3ac9d429312153332a7b21ea3a2a60d2447a4a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7391 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 ha_j3BmM= 2") % long + + if (not ((short is None) or + (isinstance(short, str) and len(short) == 1))): + raise DistutilsGetoptError, \ + ("invalid short option '%s': " + "must a single character or None") % short + + self.repeat[long] = repeat + self.long_opts.append(long) + + if long[-1] == '=': # option takes an argument? + if short: short = short + ':' + long = long[0:-1] + self.takes_arg[long] = 1 + else: + + # Is option is a "negative alias" for some other option (eg. + # "quiet" == "!verbose")? + alias_to = self.negative_alias.get(long) + if alias_to is not None: + if self.takes_arg[alias_to]: + raise DistutilsGetoptError, \ + ("invalid negative alias '%s': " + "aliased option '%s' takes a value") % \ + (long, alias_to) + + self.long_opts[-1] = long # XXX redundant?! + self.takes_arg[long] = 0 + + else: + self.takes_arg[long] = 0 + + # If this is an alias option, make sure its "takes arg" flag is + # the same as the option it's aliased to. + alias_to = self.alias.get(long) + if alias_to is not None: + if self.takes_arg[long] != self.takes_arg[alias_to]: + raise DistutilsGetoptError, \ + ("invalid alias '%s': inconsistent with " + "aliased option '%s' (one of them takes a value, " + "the other doesn't") % (long, alias_to) + + + # Now enforce some bondage on the long option name, so we can + # later translate it to an attribute name on some object. Have + # to do this a bit late to make sure we've removed any trailing + # '='. + if not longopt_re.match(long): + raise DistutilsGetoptError, \ + ("invalid long option name '%s' " + + "(must be letters, numbers, hyphens only") % long + + self.attr_name[long] = self.get_attr_name(long) + if short: + self.short_opts.append(short) + self.short2long[short[0]] = long + + # for option_table + + # _grok_option_table() + + + def getopt (self, args=None, object=None): + """Parse command-line options in args. Store as attributes on object. + + If 'args' is None or not supplied, uses 'sys.argv[1:]'. If + 'object' is None or not supplied, creates a new OptionDummy + object, stores option values there, and returns a tuple (args, + object). If 'object' is supplied, it is modified in place and + 'getopt()' just returns 'args'; in both cases, the returned + 'args' is a modified copy of the passed-in 'args' list, which + is left untouched. + """ + if args is None: + args = sys.argv[1:] + if object is None: + object = OptionDummy() + created_object = 1 + else: + created_object = 0 + + self._grok_option_table() + + short_opts = string.join(self.short_opts) + try: + opts, args = getopt.getopt(args, short_opts, self.long_opts) + except getopt.error, msg: + raise DistutilsArgError, msg + + for opt, val in opts: + if len(opt) == 2 and opt[0] == '-': # it's a short option + opt = self.short2long[opt[1]] + else: + assert len(opt) > 2 and opt[:2] == '--' + opt = opt[2:] + + alias = self.alias.get(opt) + if alias: + opt = alias + + if not self.takes_arg[opt]: # boolean option? + assert val == '', "boolean option can't have value" + alias = self.negative_alias.get(opt) + if alias: + opt = alias + val = 0 + else: + val = 1 + + attr = self.attr_name[opt] + # The only repeating option at the moment is 'verbose'. + # It has a negative option -q quiet, which should set verbose = 0. + if val and self.repeat.get(attr) is not None: + val = getattr(object, attr, 0) + 1 + setattr(object, attr, val) + self.option_order.append((opt, val)) + + # for opts + if created_object: + return args, object + else: + return args + + # getopt() + + + def get_option_order (self): + """Returns the list of (option, value) tuples processed by the + previous run of 'getopt()'. Raises RuntimeError if + 'getopt()' hasn't been called yet. + """ + if self.option_order is None: + raise RuntimeError, "'getopt()' hasn't been called yet" + else: + return self.option_order + + + def generate_help (self, header=None): + """Generate help text (a list of strings, one per suggested line of + output) from the option table for this FancyGetopt object. + """ + # Blithely assume the option table is good: probably wouldn't call + # 'generate_help()' unless you've already called 'getopt()'. + + # First pass: determine maximum length of long option names + max_opt = 0 + for option in self.option_table: + long = option[0] + short = option[1] + l = len(long) + if long[-1] == '=': + l = l - 1 + if short is not None: + l = l + 5 # " (-x)" where short == 'x' + if l > max_opt: + max_opt = l + + opt_width = max_opt + 2 + 2 + 2 # room for indent + dashes + gutter + + # Typical help block looks like this: + # --foo controls foonabulation + # Help block for longest option looks like this: + # --flimflam set the flim-flam level + # and with wrapped text: + # --flimflam set the flim-flam level (must be between + # 0 and 100, except on Tuesdays) + # Options with short names will have the short name shown (but + # it doesn't contribute to max_opt): + # --foo (-f) controls foonabulation + # If adding the short option would make the left column too wide, + # we push the explanation off to the next line + # --flimflam (-l) + # set the flim-flam level + # Important parameters: + # - 2 spaces before option block start lines + # - 2 dashes for each long option name + # - min. 2 spaces between option and explanation (gutter) + # - 5 characters (incl. space) for short option name + + # Now generate lines of help text. (If 80 columns were good enough + # for Jesus, then 78 columns are good enough for me!) + line_width = 78 + text_width = line_width - opt_width + big_indent = ' ' * opt_width + if header: + lines = [header] + else: + lines = ['Option summary:'] + + for option in self.option_table: + long, short, help = option[:3] + text = wrap_text(help, text_width) + if long[-1] == '=': + long = long[0:-1] + + # Case 1: no short option at all (makes life easy) + if short is None: + if text: + lines.append(" --%-*s %s" % (max_opt, long, text[0])) + else: + lines.append(" --%-*s " % (max_opt, long)) + + # Case 2: we have a short option, so we have to include it + # just after the long option + else: + opt_names = "%s (-%s)" % (long, short) + if text: + lines.append(" --%-*s %s" % + (max_opt, opt_names, text[0])) + else: + lines.append(" --%-*s" % opt_names) + + for l in text[1:]: + lines.append(big_indent + l) + + # for self.option_table + + return lines + + # generate_help () + + def print_help (self, header=None, file=None): + if file is None: + file = sys.stdout + for line in self.generate_help(header): + file.write(line + "\n") + +# class FancyGetopt + + +def fancy_getopt (options, negative_opt, object, args): + parser = FancyGetopt(options) + parser.set_negative_aliases(negative_opt) + return parser.getopt(args, object) + + +WS_TRANS = string.maketrans(string.whitespace, ' ' * len(string.whitespace)) + +def wrap_text (text, width): + """wrap_text(text : string, width : int) -> [string] + + Split 'text' into multiple lines of no more than 'width' characters + each, and return the list of strings that results. + """ + + if text is None: + return [] + if len(text) <= width: + return [text] + + text = string.expandtabs(text) + text = string.translate(text, WS_TRANS) + chunks = re.split(r'( +|-+)', text) + chunks = filter(None, chunks) # ' - ' results in empty strings + lines = [] + + while chunks: + + cur_line = [] # list of chunks (to-be-joined) + cur_len = 0 # length of current line + + while chunks: + l = len(chunks[0]) + if cur_len + l <= width: # can squeeze (at least) this chunk in + cur_line.append(chunks[0]) + del chunks[0] + cur_len = cur_len + l + else: # this line is full + # drop last chunk if all space + if cur_line and cur_line[-1][0] == ' ': + del cur_line[-1] + break + + if chunks: # any chunks left to process? + + # if the current line is still empty, then we had a single + # chunk that's too big too fit on a line -- so we break + # down and break it up at the line width + if cur_len == 0: + cur_line.append(chunks[0][0:width]) + chunks[0] = chunks[0][width:] + + # all-whitespace chunks at the end of a line can be discarded + # (and we know from the re.split above that if a chunk has + # *any* whitespace, it is *all* whitespace) + if chunks[0][0] == ' ': + del chunks[0] + + # and store this line in the list-of-all-lines -- as a single + # string, of course! + lines.append(string.join(cur_line, '')) + + # while chunks + + return lines + + +def translate_longopt(opt): + """Convert a long option name to a valid Python identifier by + changing "-" to "_". + """ + return string.translate(opt, longopt_xlate) + + +class OptionDummy: + """Dummy class just used as a place to hold command-line option + values as instance attributes.""" + + def __init__ (self, options=[]): + """Create a new OptionDummy instance. The attributes listed in + 'options' will be initialized to None.""" + for opt in options: + setattr(self, opt, None) diff --git a/PythonHome/Lib/distutils/fancy_getopt.pyc b/PythonHome/Lib/distutils/fancy_getopt.pyc deleted file mode 100644 index 40e79346eeed1c09748a76a0c75074fce6dcac6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11853 zcmb_iO>i8?b?%w{0d@%xAovT~5(kKwT}oKQW@0ObNJTUm%SuwPGGK`^1ZXqZ8DIz4 zomouJl7I`y!Bn}TDqrkls#2*+xtv3eN#&BNTzt$m$|03Qa!jtNROOJA^L?*pW``mz zTTn<~(9`qgb@zL(zxUHq`On$r-#q%Gjh@Q>)$sQ%{ObS3#aC(*S4(YL%D0tYQ3G3T zqG8$S{QpHmB5ZT5V1%%g3{Z3aV}@*COOX6|lJ83^~bm~REm-vpMafY!!9t3#grOqgcABTRRg>W|>4B{tY zwAb`}KTN|o@&?Xs;HBdv&}&V{dDYSVI7uDwa|Us==U_-sX^aMbVSw>s4AKu0A{WA;^^2Z&)ez6IYn!N75P2?h@w508hVL4f91dwW>X zcsTSD(!5$sK?j&u3jRCe6zhq1@!H7KI`BJTX|6&I{!S_mVy7)r;u;!0UYPUT1T={X1(}^DCWibhcl;B?EkTQ@^5T zK=xt#roMG|iPu+BC{1GZtF*@3meW`;Y1z|V$soZTcIa)S(uN#s0#C8Lvx zW9BYZg8 ze5dm`NOoc!tZ=rGvz)!NTri0v+346#L)pV&gv}JB+G%BPwy=Y-GY8t}qsI-B|K6vn zQ(R6gb)r;PsSs^6JajcUVcShH39t+OTnYds2!YU7Zi zwy&c>-QdR(^&Bl{x_YpERh>eExf0O;(k$LNys93F;K^qln#Q~dPi`HTl#F|@=ESUu zG%leawT_raZ+yI1(&MV)yRkR|HZFN#nyA^d> z%`~%LQ72VK2^Rhs<>8Gx6Q$@DIGc&ULq@xUu$Qg@L*O-mq6N}8t(&^l=Cnk2E*eUN zAj)F65czEplxUD!EH{5FQLMVy9qb?hQL}5jxqA`!XH|B}?S*I~ljjcZ#B(ZZ&Z=0m z_S_4VKMS(5L=8IV9=hEC(F#y583#a5LAy*s0u|0~oS+jRI`R^YIH~U;dWj|gDQb0| zglXSIINat=t0a%ssz8y5vSd_OF!mP`0w$6PVL&0!dR3*c`@)z+MPlv{Knkd}Gi=m9 z#tRP7>IL`uepI=Tf`AELuZwc4XJ zY48LX*`hx{1D=f{1&-KCU#4uoZ>ghwc48+!MU1$;rM7H!YPKjgC)7|?2U99}kATPx zEqmB(W7*kYX|}GRTNXMH8M-RBJLwLW`D5Ugb6eLmr7(I7|KvM2;hwRB*K&38#);z8 z@q=ABa9@ArMZ_kQ@PE-uZLVE*U#P=~DMBwui4i_PM4aS3#6bx`&IH4hSC|GvJpqvt zXb`i_h+4QjL2}_va|o^n+CB5$U=ZHz^@HAl@zz~V@Cconal5iETZ@7f73*U5_xVlp z5(okafryrpWCUGjvK>wP}?6&Lr%2L<|0o|4Fz}^Ad!?8vxmw7RakePYG1nC@K z%6JK^uj+DGXO>mg4nw+=!lFpe9CO+!Wk4qNX1L(f7m* z5jbZJ6LZ-azE}vdV5QxvI@-2rt~Ef8Ya=)Ve!^T43BYy_Y?bWrb_+O^qY-TQw5Foh zOOzF%{8%Wf6H1cJs}xBhfXPz3CImrv2}}YuV`t3hzY{j_Ef}z-4iMP?1EB)hB#3fc zLzQJ-9Zajye<{9Q$=;4}3pxNMUY_C{^t8p7g(iQwmVqbu-7y<;e}>HQl7&A=P8X4v za;bp@Udgw4MQVB#;ETk9Bto?W31Aemm}T#s=s<4HtNpo*-zjE;3>kB6sN`o>Mp{>k z$xmfoGA<}s-C-~$+|8UYjXM~p#2s03`JPYaf5A{oqC%O~;$+YREN023Jmkq_+`}as zL!;!dzmQE_KM*?9mgdw|tSz4%#=Mx3knbf~H-&UtW(seGC5ikgN|N9zH8BMBw-tUK zK^hxv0;~QrT;7dGV~H8Ks~&qv7>~8%d#T5A&A2DkAM7|(iw=TdB1*!Q4?t>-D|F>!pY#5n8UtQ6RM?DfHZx>zaPE#4m>p15%l1f0476yb|y# zps0Zu#j1oldozp>`D;|KP&hMT>x+1`F)gkX8b&3932V++N(Byp81whzKu4`qzg!xt zEI|`TGWrl#+0JE&3>?cxRWBM3cchU8g)o!B@p}6*__=gyE~9;y$+^oyri6t_FhY^f zvI_(wu#UtDP$5OZ25-JisGe<$&ULP3Fy{EzTGrFvwP>#yL(A|@JtfP@Ll`3sG6ko zRs-IC0U=ET*UQ!U$}$q7iq*7dtfj1l%osFvHOm~iwqVWRFKFy}8~2sjDtoR=&&4UG zQx)sHeZ{IXrJ^*ck-|M)#omEG089hZlP@z425!LL+<^bdAlE!wqnMv6x)eMnAOl{- z5fN*Uup%gf0QZ5rxSt}XBc(k?>^rUY;RWFIOiT=KQ;~qW#sb8n=!UA21i0T+$)76= z$Za9n1V$24{WT%zf_OtL*{Ji$7c5i zS{vZM(dO3DQ!tQsnKQE(&+1`k!0Mp^M(rRdLkUc;IvXibo>_IN7@rs5SDOW}zq9MK z_(qErP3~pFC$kzo9*qV#OISg%A2`+0$9ffnk3ab8+IDNzao(BKL|dk;{~0XI2?EhB z3Z6LMk?j5fP7loa0v(TGffEVN8;;Es01W67FB4Q#8Jhw@P*@WwPbMh<2atxbW zGC!w0ugP-Y`LI-+zJ$9xDuKjC1Fr{JMUzr<$zSd>49-V2qI!cbNz~k9nb=^rAt{xs zCt~#`qxIs^apnO^$08Z&0RCgef#>b@iv?k-gJ3sBGM~m{Oql z|6z_6#Jvb?2RyoQIYW1a7x6YrY!SR&=E`p2FvJTOXs0UxFIp|4V=Th7-8sHMHzT!Y zQ{?0OsI4WU>anI^e+`C};ANbYZ z!bP2%0m9F)6l~Y+ro8~%Uxp8vwJ+lDCA$qDvH&m8fS0(2{<^erS9uw!^t^SwQU^tk z667!SdLO@F@eo3 zvz<_nOX6O@<2r_opf3z@lmw3@Bu&PE5uk?AI1ZDr*<3FqNVu@laA?AX@}bFumW4iA z;7)*pk)DZ9kArk#)S5Q(OX=554P1;uY*);yG`cAcvPySWZKiw~Ys{kqIZAjHsxbBN z+MG3GONoP%prwj-{tX258@4(+$<*{<`;hLLu|HfN%gQDTKne)&Zc59{j&Pz_DIDg8 zWJ|WXh9`7usB6uMiy6p+8r+I`fEQr~aGvmqb&h*D&!0!=MWT2$|Alvi`-3ZjuYt$8 z2G7YJ_3kR#yOUYz#C zg~sD_G)`|7XPmhM{8Y8PbXc8v%*oC%o`6^(nU8ymEh!fgJHmBbBoA^lE!Nyc-Vas`e|R%63VZ1%K=KaJK>%j zI7X@XA`)x&Yvf0aCvm}2YG7x^2vgoRHqfOFe2oAh@ITD}zlr~J1GAD8ATh8Pt^wBZ zzYh3dYQbvhJko?2^eoxeQL}XLk^%UR3)J+#DiQelN<|1qerQg|$;zVj^3ZqPx>;<4rfc&S^wg=gA8$is74 zBN)uu*f<(B%HmYkfut9>Pa5=~tSZ@{5f*O29{%j8&gxupZ1EOO2$VH-lycJ~|0Dhx zdkuLk0jJ2)E=w>M1l4jrqR24|aP-C!ntcMrGu9SGtMaHFW;)-W9r zl>kC2S?7k-Vf5cZDFte`<&&H>mLO4PLvlg{c5wO_!C7_QbUrW-woO90fs8SAT6_n| zATkylA`H@yd75A_`$3XPcUX=`(m}!iljTh9k zr?&IjN$0g&A)1*Zq`A4jjf?qi#X!RfJ0+JP?gU38q<<`_x?jevpv31T%c?bU>=HXrtozK1g3`dkS_~Xil?H@_xj`LK)V}!GR^yO(xotDKgvxIx$Agv z*6rs0K3@J)ZZXzN)zpktMLIEsGy4VnpR?-lGe|D%2K|h6!J4vWE7#$HYIeOggVf`4 z?GnCRd8yh13rRJIAmVF?@_-*g4jLtt(eINaj_|b-j)y^IeUDj~kI1 zAmL7sS4d8QdTq4FL#pM@GS9)6yURw4CbXw&L>KN$Xqj;SCR_M5m(K}G^aaInc{eLa z@{76bG}?Uw1U+)+KkA&AsOc^Oe3*w27FU4{fXYYs0_iD|Mh^lb-{ZN;j(lmlcddNI0ZKks5Emt;CuOZoS!Pf6eA*&dx)J@Dj6|blp;xy2evXF(gGF?20VJ? z*HHLaH2fY2u}T(^R8VKyhI%N@@X;LKfeWtx8Em zOXXY&BT`?= 1: + log.debug("not copying %s (output up-to-date)", src) + return dst, 0 + + try: + action = _copy_action[link] + except KeyError: + raise ValueError("invalid value '%s' for 'link' argument" % link) + + if verbose >= 1: + if os.path.basename(dst) == os.path.basename(src): + log.info("%s %s -> %s", action, src, dir) + else: + log.info("%s %s -> %s", action, src, dst) + + if dry_run: + return (dst, 1) + + # If linking (hard or symbolic), use the appropriate system call + # (Unix only, of course, but that's the caller's responsibility) + if link == 'hard': + if not (os.path.exists(dst) and os.path.samefile(src, dst)): + os.link(src, dst) + elif link == 'sym': + if not (os.path.exists(dst) and os.path.samefile(src, dst)): + os.symlink(src, dst) + + # Otherwise (non-Mac, not linking), copy the file contents and + # (optionally) copy the times and mode. + else: + _copy_file_contents(src, dst) + if preserve_mode or preserve_times: + st = os.stat(src) + + # According to David Ascher , utime() should be done + # before chmod() (at least under NT). + if preserve_times: + os.utime(dst, (st[ST_ATIME], st[ST_MTIME])) + if preserve_mode: + os.chmod(dst, S_IMODE(st[ST_MODE])) + + return (dst, 1) + +# XXX I suspect this is Unix-specific -- need porting help! +def move_file (src, dst, verbose=1, dry_run=0): + """Move a file 'src' to 'dst'. + + If 'dst' is a directory, the file will be moved into it with the same + name; otherwise, 'src' is just renamed to 'dst'. Return the new + full name of the file. + + Handles cross-device moves on Unix using 'copy_file()'. What about + other systems??? + """ + from os.path import exists, isfile, isdir, basename, dirname + import errno + + if verbose >= 1: + log.info("moving %s -> %s", src, dst) + + if dry_run: + return dst + + if not isfile(src): + raise DistutilsFileError("can't move '%s': not a regular file" % src) + + if isdir(dst): + dst = os.path.join(dst, basename(src)) + elif exists(dst): + raise DistutilsFileError( + "can't move '%s': destination '%s' already exists" % + (src, dst)) + + if not isdir(dirname(dst)): + raise DistutilsFileError( + "can't move '%s': destination '%s' not a valid path" % \ + (src, dst)) + + copy_it = 0 + try: + os.rename(src, dst) + except os.error, (num, msg): + if num == errno.EXDEV: + copy_it = 1 + else: + raise DistutilsFileError( + "couldn't move '%s' to '%s': %s" % (src, dst, msg)) + + if copy_it: + copy_file(src, dst, verbose=verbose) + try: + os.unlink(src) + except os.error, (num, msg): + try: + os.unlink(dst) + except os.error: + pass + raise DistutilsFileError( + ("couldn't move '%s' to '%s' by copy/delete: " + + "delete '%s' failed: %s") % + (src, dst, src, msg)) + return dst + + +def write_file (filename, contents): + """Create a file with the specified name and write 'contents' (a + sequence of strings without line terminators) to it. + """ + f = open(filename, "w") + try: + for line in contents: + f.write(line + "\n") + finally: + f.close() diff --git a/PythonHome/Lib/distutils/file_util.pyc b/PythonHome/Lib/distutils/file_util.pyc deleted file mode 100644 index 1f2fd224aefaada09d0344f8a953b75e2089d3c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6601 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 diff --git a/PythonHome/Lib/distutils/filelist.py b/PythonHome/Lib/distutils/filelist.py new file mode 100644 index 0000000000..2f1c457ea0 --- /dev/null +++ b/PythonHome/Lib/distutils/filelist.py @@ -0,0 +1,343 @@ +"""distutils.filelist + +Provides the FileList class, used for poking about the filesystem +and building lists of files. +""" + +__revision__ = "$Id$" + +import os, re +import fnmatch +from distutils.util import convert_path +from distutils.errors import DistutilsTemplateError, DistutilsInternalError +from distutils import log + +class FileList: + """A list of files built by on exploring the filesystem and filtered by + applying various patterns to what we find there. + + Instance attributes: + dir + directory from which files will be taken -- only used if + 'allfiles' not supplied to constructor + files + list of filenames currently being built/filtered/manipulated + allfiles + complete list of files under consideration (ie. without any + filtering applied) + """ + + def __init__(self, warn=None, debug_print=None): + # ignore argument to FileList, but keep them for backwards + # compatibility + self.allfiles = None + self.files = [] + + def set_allfiles(self, allfiles): + self.allfiles = allfiles + + def findall(self, dir=os.curdir): + self.allfiles = findall(dir) + + def debug_print(self, msg): + """Print 'msg' to stdout if the global DEBUG (taken from the + DISTUTILS_DEBUG environment variable) flag is true. + """ + from distutils.debug import DEBUG + if DEBUG: + print msg + + # -- List-like methods --------------------------------------------- + + def append(self, item): + self.files.append(item) + + def extend(self, items): + self.files.extend(items) + + def sort(self): + # Not a strict lexical sort! + sortable_files = map(os.path.split, self.files) + sortable_files.sort() + self.files = [] + for sort_tuple in sortable_files: + self.files.append(os.path.join(*sort_tuple)) + + + # -- Other miscellaneous utility methods --------------------------- + + def remove_duplicates(self): + # Assumes list has been sorted! + for i in range(len(self.files) - 1, 0, -1): + if self.files[i] == self.files[i - 1]: + del self.files[i] + + + # -- "File template" methods --------------------------------------- + + def _parse_template_line(self, line): + words = line.split() + action = words[0] + + patterns = dir = dir_pattern = None + + if action in ('include', 'exclude', + 'global-include', 'global-exclude'): + if len(words) < 2: + raise DistutilsTemplateError, \ + "'%s' expects ..." % action + + patterns = map(convert_path, words[1:]) + + elif action in ('recursive-include', 'recursive-exclude'): + if len(words) < 3: + raise DistutilsTemplateError, \ + "'%s' expects

..." % action + + dir = convert_path(words[1]) + patterns = map(convert_path, words[2:]) + + elif action in ('graft', 'prune'): + if len(words) != 2: + raise DistutilsTemplateError, \ + "'%s' expects a single " % action + + dir_pattern = convert_path(words[1]) + + else: + raise DistutilsTemplateError, "unknown action '%s'" % action + + return (action, patterns, dir, dir_pattern) + + def process_template_line(self, line): + # Parse the line: split it up, make sure the right number of words + # is there, and return the relevant words. 'action' is always + # defined: it's the first word of the line. Which of the other + # three are defined depends on the action; it'll be either + # patterns, (dir and patterns), or (dir_pattern). + action, patterns, dir, dir_pattern = self._parse_template_line(line) + + # OK, now we know that the action is valid and we have the + # right number of words on the line for that action -- so we + # can proceed with minimal error-checking. + if action == 'include': + self.debug_print("include " + ' '.join(patterns)) + for pattern in patterns: + if not self.include_pattern(pattern, anchor=1): + log.warn("warning: no files found matching '%s'", + pattern) + + elif action == 'exclude': + self.debug_print("exclude " + ' '.join(patterns)) + for pattern in patterns: + if not self.exclude_pattern(pattern, anchor=1): + log.warn(("warning: no previously-included files " + "found matching '%s'"), pattern) + + elif action == 'global-include': + self.debug_print("global-include " + ' '.join(patterns)) + for pattern in patterns: + if not self.include_pattern(pattern, anchor=0): + log.warn(("warning: no files found matching '%s' " + + "anywhere in distribution"), pattern) + + elif action == 'global-exclude': + self.debug_print("global-exclude " + ' '.join(patterns)) + for pattern in patterns: + if not self.exclude_pattern(pattern, anchor=0): + log.warn(("warning: no previously-included files matching " + "'%s' found anywhere in distribution"), + pattern) + + elif action == 'recursive-include': + self.debug_print("recursive-include %s %s" % + (dir, ' '.join(patterns))) + for pattern in patterns: + if not self.include_pattern(pattern, prefix=dir): + log.warn(("warning: no files found matching '%s' " + + "under directory '%s'"), + pattern, dir) + + elif action == 'recursive-exclude': + self.debug_print("recursive-exclude %s %s" % + (dir, ' '.join(patterns))) + for pattern in patterns: + if not self.exclude_pattern(pattern, prefix=dir): + log.warn(("warning: no previously-included files matching " + "'%s' found under directory '%s'"), + pattern, dir) + + elif action == 'graft': + self.debug_print("graft " + dir_pattern) + if not self.include_pattern(None, prefix=dir_pattern): + log.warn("warning: no directories found matching '%s'", + dir_pattern) + + elif action == 'prune': + self.debug_print("prune " + dir_pattern) + if not self.exclude_pattern(None, prefix=dir_pattern): + log.warn(("no previously-included directories found " + + "matching '%s'"), dir_pattern) + else: + raise DistutilsInternalError, \ + "this cannot happen: invalid action '%s'" % action + + # -- Filtering/selection methods ----------------------------------- + + def include_pattern(self, pattern, anchor=1, prefix=None, is_regex=0): + """Select strings (presumably filenames) from 'self.files' that + match 'pattern', a Unix-style wildcard (glob) pattern. + + Patterns are not quite the same as implemented by the 'fnmatch' + module: '*' and '?' match non-special characters, where "special" + is platform-dependent: slash on Unix; colon, slash, and backslash on + DOS/Windows; and colon on Mac OS. + + If 'anchor' is true (the default), then the pattern match is more + stringent: "*.py" will match "foo.py" but not "foo/bar.py". If + 'anchor' is false, both of these will match. + + If 'prefix' is supplied, then only filenames starting with 'prefix' + (itself a pattern) and ending with 'pattern', with anything in between + them, will match. 'anchor' is ignored in this case. + + If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and + 'pattern' is assumed to be either a string containing a regex or a + regex object -- no translation is done, the regex is just compiled + and used as-is. + + Selected strings will be added to self.files. + + Return 1 if files are found. + """ + # XXX docstring lying about what the special chars are? + files_found = 0 + pattern_re = translate_pattern(pattern, anchor, prefix, is_regex) + self.debug_print("include_pattern: applying regex r'%s'" % + pattern_re.pattern) + + # delayed loading of allfiles list + if self.allfiles is None: + self.findall() + + for name in self.allfiles: + if pattern_re.search(name): + self.debug_print(" adding " + name) + self.files.append(name) + files_found = 1 + + return files_found + + + def exclude_pattern(self, pattern, anchor=1, prefix=None, is_regex=0): + """Remove strings (presumably filenames) from 'files' that match + 'pattern'. + + Other parameters are the same as for 'include_pattern()', above. + The list 'self.files' is modified in place. Return 1 if files are + found. + """ + files_found = 0 + pattern_re = translate_pattern(pattern, anchor, prefix, is_regex) + self.debug_print("exclude_pattern: applying regex r'%s'" % + pattern_re.pattern) + for i in range(len(self.files)-1, -1, -1): + if pattern_re.search(self.files[i]): + self.debug_print(" removing " + self.files[i]) + del self.files[i] + files_found = 1 + + return files_found + + +# ---------------------------------------------------------------------- +# Utility functions + +def findall(dir = os.curdir): + """Find all files under 'dir' and return the list of full filenames + (relative to 'dir'). + """ + from stat import ST_MODE, S_ISREG, S_ISDIR, S_ISLNK + + list = [] + stack = [dir] + pop = stack.pop + push = stack.append + + while stack: + dir = pop() + names = os.listdir(dir) + + for name in names: + if dir != os.curdir: # avoid the dreaded "./" syndrome + fullname = os.path.join(dir, name) + else: + fullname = name + + # Avoid excess stat calls -- just one will do, thank you! + stat = os.stat(fullname) + mode = stat[ST_MODE] + if S_ISREG(mode): + list.append(fullname) + elif S_ISDIR(mode) and not S_ISLNK(mode): + push(fullname) + + return list + + +def glob_to_re(pattern): + """Translate a shell-like glob pattern to a regular expression. + + Return a string containing the regex. Differs from + 'fnmatch.translate()' in that '*' does not match "special characters" + (which are platform-specific). + """ + pattern_re = fnmatch.translate(pattern) + + # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which + # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix, + # and by extension they shouldn't match such "special characters" under + # any OS. So change all non-escaped dots in the RE to match any + # character except the special characters (currently: just os.sep). + sep = os.sep + if os.sep == '\\': + # we're using a regex to manipulate a regex, so we need + # to escape the backslash twice + sep = r'\\\\' + escaped = r'\1[^%s]' % sep + pattern_re = re.sub(r'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 gF}!ovhG+N0SToM5f#a*= self.threshold: + if args: + msg = msg % args + if level in (WARN, ERROR, FATAL): + stream = sys.stderr + else: + stream = sys.stdout + stream.write('%s\n' % msg) + stream.flush() + + def log(self, level, msg, *args): + self._log(level, msg, args) + + def debug(self, msg, *args): + self._log(DEBUG, msg, args) + + def info(self, msg, *args): + self._log(INFO, msg, args) + + def warn(self, msg, *args): + self._log(WARN, msg, args) + + def error(self, msg, *args): + self._log(ERROR, msg, args) + + def fatal(self, msg, *args): + self._log(FATAL, msg, args) + +_global_log = Log() +log = _global_log.log +debug = _global_log.debug +info = _global_log.info +warn = _global_log.warn +error = _global_log.error +fatal = _global_log.fatal + +def set_threshold(level): + # return the old threshold for use from tests + old = _global_log.threshold + _global_log.threshold = level + return old + +def set_verbosity(v): + if v <= 0: + set_threshold(WARN) + elif v == 1: + set_threshold(INFO) + elif v >= 2: + set_threshold(DEBUG) diff --git a/PythonHome/Lib/distutils/log.pyc b/PythonHome/Lib/distutils/log.pyc deleted file mode 100644 index 8838752b8242174dac5179718384e97a16150077..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2726 zcmb_eQEwYX5T3oW&pF3QTS@}~AzXKl`oQr^UzT=l3l3 z4^}Br%vw>bDD^1zDD^4!DXmakp|nbImC}IH8s!1S3^pijP#V$;qHCgG;~ME2P`p8U zgU&*VLjiS)>jE|@-W1TFxFKMR;w=H&6mL^nhpqS)rJDk7W3z5+3k*MH)o$8s@;ukg zycjkoxH9IG7k!;%qmb-sDJs>ad`Qp820%g zAIyBnV!Ny~vrwej14J*_A?yStjMxvJ0Ct5hfc;PrP=kv=pWPA&2tglj>J)Wb8*I0a zU6yiy-Eg)`MVCa0M4;OO?~Z5}GIS%O?WoAp7S=f&!|HqxVOoo&RJO_J;Omp)xf>PJ z{Vz}Q?DQnfted$kwY8(X(+f3d|9EhO}LxaV+Vy74dj>Nol@e&@R?@EzQuaaHZM#u9ZF{8`dsH0gL}3v z*~5g1emH#i%VTlikDW(H0-m*_j*J~f(NQGmQTyli6IbW?PkZ@H9~x5_NfzsjIKBKa zw|so|pi8weOIXaD*tjs6(}D*1%#K>vJ(BPN2|ckgu|uKJGsC4hqkEH^h85vUIK+2B z=xtV{-dDTcEfuIObx$?CP~A~|_yaQ`k6G+HtT^w^%CJe0u6D6i63p~IKbFY{zbv`E!i$p+cf+Gscwvd~ioi?Kpd|OkybzaEpU#FKF<1*T zSX>7)oG_aXijUVt3~9SAVi!F#{bXIlYHK0}&-0}$%xCLjhPt^9mx0-!=X&|)D`u@t z#*4~4?M-x&NbyOMNs-QS{uv=)5pGDC^7nvtpm2esccFHn-ea}8kAhySEkwMIwplFh zcHlMqa69yu-#$tKE*#{5#bR&n3}=e2q;WA$A!_o`!xh-IoE6#vYk{ z8Q@BTfn6Ek?!;Z}CmHa|fkofJo$O@TboDQzERi4byE0&iby=Q3hbtM;`J0~hT$|Iv zW^UeQE4IOkRD)}KDWz4EK8GumBx%v-v;oOTSV#h4DB6HRWF+R%2SERuPmvtxKF?cm k7xY@0C29R_naJP41F|Zp2HctC>ovT)dx+c1uNMaY0pn!E9smFU diff --git a/PythonHome/Lib/distutils/msvc9compiler.py b/PythonHome/Lib/distutils/msvc9compiler.py new file mode 100644 index 0000000000..7ec9b92a5d --- /dev/null +++ b/PythonHome/Lib/distutils/msvc9compiler.py @@ -0,0 +1,801 @@ +"""distutils.msvc9compiler + +Contains MSVCCompiler, an implementation of the abstract CCompiler class +for the Microsoft Visual Studio 2008. + +The module is compatible with VS 2005 and VS 2008. You can find legacy support +for older versions of VS in distutils.msvccompiler. +""" + +# Written by Perry Stoll +# hacked by Robin Becker and Thomas Heller to do a better job of +# finding DevStudio (through the registry) +# ported to VS2005 and VS 2008 by Christian Heimes + +__revision__ = "$Id$" + +import os +import subprocess +import sys +import re + +from distutils.errors import (DistutilsExecError, DistutilsPlatformError, + CompileError, LibError, LinkError) +from distutils.ccompiler import CCompiler, gen_lib_options +from distutils import log +from distutils.util import get_platform + +import _winreg + +RegOpenKeyEx = _winreg.OpenKeyEx +RegEnumKey = _winreg.EnumKey +RegEnumValue = _winreg.EnumValue +RegError = _winreg.error + +HKEYS = (_winreg.HKEY_USERS, + _winreg.HKEY_CURRENT_USER, + _winreg.HKEY_LOCAL_MACHINE, + _winreg.HKEY_CLASSES_ROOT) + +NATIVE_WIN64 = (sys.platform == 'win32' and sys.maxsize > 2**32) +if NATIVE_WIN64: + # Visual C++ is a 32-bit application, so we need to look in + # the corresponding registry branch, if we're running a + # 64-bit Python on Win64 + VS_BASE = r"Software\Wow6432Node\Microsoft\VisualStudio\%0.1f" + VSEXPRESS_BASE = r"Software\Wow6432Node\Microsoft\VCExpress\%0.1f" + WINSDK_BASE = r"Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows" + NET_BASE = r"Software\Wow6432Node\Microsoft\.NETFramework" +else: + VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f" + VSEXPRESS_BASE = r"Software\Microsoft\VCExpress\%0.1f" + WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows" + NET_BASE = r"Software\Microsoft\.NETFramework" + +# A map keyed by get_platform() return values to values accepted by +# 'vcvarsall.bat'. Note a cross-compile may combine these (eg, 'x86_amd64' is +# the param to cross-compile on x86 targetting amd64.) +PLAT_TO_VCVARS = { + 'win32' : 'x86', + 'win-amd64' : 'amd64', + 'win-ia64' : 'ia64', +} + +class Reg: + """Helper class to read values from the registry + """ + + def get_value(cls, path, key): + for base in HKEYS: + d = cls.read_values(base, path) + if d and key in d: + return d[key] + raise KeyError(key) + get_value = classmethod(get_value) + + def read_keys(cls, base, key): + """Return list of registry keys.""" + try: + handle = RegOpenKeyEx(base, key) + except RegError: + return None + L = [] + i = 0 + while True: + try: + k = RegEnumKey(handle, i) + except RegError: + break + L.append(k) + i += 1 + return L + read_keys = classmethod(read_keys) + + def read_values(cls, base, key): + """Return dict of registry keys and values. + + All names are converted to lowercase. + """ + try: + handle = RegOpenKeyEx(base, key) + except RegError: + return None + d = {} + i = 0 + while True: + try: + name, value, type = RegEnumValue(handle, i) + except RegError: + break + name = name.lower() + d[cls.convert_mbcs(name)] = cls.convert_mbcs(value) + i += 1 + return d + read_values = classmethod(read_values) + + def convert_mbcs(s): + dec = getattr(s, "decode", None) + if dec is not None: + try: + s = dec("mbcs") + except UnicodeError: + pass + return s + convert_mbcs = staticmethod(convert_mbcs) + +class MacroExpander: + + def __init__(self, version): + self.macros = {} + self.vsbase = VS_BASE % version + self.load_macros(version) + + def set_macro(self, macro, path, key): + self.macros["$(%s)" % macro] = Reg.get_value(path, key) + + def load_macros(self, version): + self.set_macro("VCInstallDir", self.vsbase + r"\Setup\VC", "productdir") + self.set_macro("VSInstallDir", self.vsbase + r"\Setup\VS", "productdir") + self.set_macro("FrameworkDir", NET_BASE, "installroot") + try: + if version >= 8.0: + self.set_macro("FrameworkSDKDir", NET_BASE, + "sdkinstallrootv2.0") + else: + raise KeyError("sdkinstallrootv2.0") + except KeyError: + raise DistutilsPlatformError( + """Python was built with Visual Studio 2008; +extensions must be built with a compiler than can generate compatible binaries. +Visual Studio 2008 was not found on this system. If you have Cygwin installed, +you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""") + + if version >= 9.0: + self.set_macro("FrameworkVersion", self.vsbase, "clr version") + self.set_macro("WindowsSdkDir", WINSDK_BASE, "currentinstallfolder") + else: + p = r"Software\Microsoft\NET Framework Setup\Product" + for base in HKEYS: + try: + h = RegOpenKeyEx(base, p) + except RegError: + continue + key = RegEnumKey(h, 0) + d = Reg.get_value(base, r"%s\%s" % (p, key)) + self.macros["$(FrameworkVersion)"] = d["version"] + + def sub(self, s): + for k, v in self.macros.items(): + s = s.replace(k, v) + return s + +def get_build_version(): + """Return the version of MSVC that was used to build Python. + + For Python 2.3 and up, the version number is included in + sys.version. For earlier versions, assume the compiler is MSVC 6. + """ + prefix = "MSC v." + i = sys.version.find(prefix) + if i == -1: + return 6 + i = i + len(prefix) + s, rest = sys.version[i:].split(" ", 1) + majorVersion = int(s[:-2]) - 6 + minorVersion = int(s[2:3]) / 10.0 + # I don't think paths are affected by minor version in version 6 + if majorVersion == 6: + minorVersion = 0 + if majorVersion >= 6: + return majorVersion + minorVersion + # else we don't know what version of the compiler this is + return None + +def normalize_and_reduce_paths(paths): + """Return a list of normalized paths with duplicates removed. + + The current order of paths is maintained. + """ + # Paths are normalized so things like: /a and /a/ aren't both preserved. + reduced_paths = [] + for p in paths: + np = os.path.normpath(p) + # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set. + if np not in reduced_paths: + reduced_paths.append(np) + return reduced_paths + +def removeDuplicates(variable): + """Remove duplicate values of an environment variable. + """ + oldList = variable.split(os.pathsep) + newList = [] + for i in oldList: + if i not in newList: + newList.append(i) + newVariable = os.pathsep.join(newList) + return newVariable + +def find_vcvarsall(version): + """Find the vcvarsall.bat file + + At first it tries to find the productdir of VS 2008 in the registry. If + that fails it falls back to the VS90COMNTOOLS env var. + """ + vsbase = VS_BASE % version + try: + productdir = Reg.get_value(r"%s\Setup\VC" % vsbase, + "productdir") + except KeyError: + productdir = None + + # trying Express edition + if productdir is None: + vsbase = VSEXPRESS_BASE % version + try: + productdir = Reg.get_value(r"%s\Setup\VC" % vsbase, + "productdir") + except KeyError: + productdir = None + log.debug("Unable to find productdir in registry") + + if not productdir or not os.path.isdir(productdir): + toolskey = "VS%0.f0COMNTOOLS" % version + toolsdir = os.environ.get(toolskey, None) + + if toolsdir and os.path.isdir(toolsdir): + productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC") + productdir = os.path.abspath(productdir) + if not os.path.isdir(productdir): + log.debug("%s is not a valid directory" % productdir) + return None + else: + log.debug("Env var %s is not set or invalid" % toolskey) + if not productdir: + log.debug("No productdir found") + return None + vcvarsall = os.path.join(productdir, "vcvarsall.bat") + if os.path.isfile(vcvarsall): + return vcvarsall + log.debug("Unable to find vcvarsall.bat") + return None + +def query_vcvarsall(version, arch="x86"): + """Launch vcvarsall.bat and read the settings from its environment + """ + vcvarsall = find_vcvarsall(version) + interesting = set(("include", "lib", "libpath", "path")) + result = {} + + if vcvarsall is None: + raise DistutilsPlatformError("Unable to find vcvarsall.bat") + log.debug("Calling 'vcvarsall.bat %s' (version=%s)", arch, version) + popen = subprocess.Popen('"%s" %s & set' % (vcvarsall, arch), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + try: + stdout, stderr = popen.communicate() + if popen.wait() != 0: + raise DistutilsPlatformError(stderr.decode("mbcs")) + + stdout = stdout.decode("mbcs") + for line in stdout.split("\n"): + line = Reg.convert_mbcs(line) + if '=' not in line: + continue + line = line.strip() + key, value = line.split('=', 1) + key = key.lower() + if key in interesting: + if value.endswith(os.pathsep): + value = value[:-1] + result[key] = removeDuplicates(value) + + finally: + popen.stdout.close() + popen.stderr.close() + + if len(result) != len(interesting): + raise ValueError(str(list(result.keys()))) + + return result + +# More globals +VERSION = get_build_version() +if VERSION < 8.0: + raise DistutilsPlatformError("VC %0.1f is not supported by this module" % VERSION) +# MACROS = MacroExpander(VERSION) + +class MSVCCompiler(CCompiler) : + """Concrete class that implements an interface to Microsoft Visual C++, + as defined by the CCompiler abstract class.""" + + compiler_type = 'msvc' + + # Just set this so CCompiler's constructor doesn't barf. We currently + # don't use the 'set_executables()' bureaucracy provided by CCompiler, + # as it really isn't necessary for this sort of single-compiler class. + # Would be nice to have a consistent interface with UnixCCompiler, + # though, so it's worth thinking about. + executables = {} + + # Private class data (need to distinguish C from C++ source for compiler) + _c_extensions = ['.c'] + _cpp_extensions = ['.cc', '.cpp', '.cxx'] + _rc_extensions = ['.rc'] + _mc_extensions = ['.mc'] + + # Needed for the filename generation methods provided by the + # base class, CCompiler. + src_extensions = (_c_extensions + _cpp_extensions + + _rc_extensions + _mc_extensions) + res_extension = '.res' + obj_extension = '.obj' + static_lib_extension = '.lib' + shared_lib_extension = '.dll' + static_lib_format = shared_lib_format = '%s%s' + exe_extension = '.exe' + + def __init__(self, verbose=0, dry_run=0, force=0): + CCompiler.__init__ (self, verbose, dry_run, force) + self.__version = VERSION + self.__root = r"Software\Microsoft\VisualStudio" + # self.__macros = MACROS + self.__paths = [] + # target platform (.plat_name is consistent with 'bdist') + self.plat_name = None + self.__arch = None # deprecated name + self.initialized = False + + def initialize(self, plat_name=None): + # multi-init means we would need to check platform same each time... + assert not self.initialized, "don't init multiple times" + if plat_name is None: + plat_name = get_platform() + # sanity check for platforms to prevent obscure errors later. + ok_plats = 'win32', 'win-amd64', 'win-ia64' + if plat_name not in ok_plats: + raise DistutilsPlatformError("--plat-name must be one of %s" % + (ok_plats,)) + + if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"): + # Assume that the SDK set up everything alright; don't try to be + # smarter + self.cc = "cl.exe" + self.linker = "link.exe" + self.lib = "lib.exe" + self.rc = "rc.exe" + self.mc = "mc.exe" + else: + # On x86, 'vcvars32.bat amd64' creates an env that doesn't work; + # to cross compile, you use 'x86_amd64'. + # On AMD64, 'vcvars32.bat amd64' is a native build env; to cross + # compile use 'x86' (ie, it runs the x86 compiler directly) + # No idea how itanium handles this, if at all. + if plat_name == get_platform() or plat_name == 'win32': + # native build or cross-compile to win32 + plat_spec = PLAT_TO_VCVARS[plat_name] + else: + # cross compile from win32 -> some 64bit + plat_spec = PLAT_TO_VCVARS[get_platform()] + '_' + \ + PLAT_TO_VCVARS[plat_name] + + vc_env = query_vcvarsall(VERSION, plat_spec) + + # take care to only use strings in the environment. + self.__paths = vc_env['path'].encode('mbcs').split(os.pathsep) + os.environ['lib'] = vc_env['lib'].encode('mbcs') + os.environ['include'] = vc_env['include'].encode('mbcs') + + if len(self.__paths) == 0: + raise DistutilsPlatformError("Python was built with %s, " + "and extensions need to be built with the same " + "version of the compiler, but it isn't installed." + % self.__product) + + self.cc = self.find_exe("cl.exe") + self.linker = self.find_exe("link.exe") + self.lib = self.find_exe("lib.exe") + self.rc = self.find_exe("rc.exe") # resource compiler + self.mc = self.find_exe("mc.exe") # message compiler + #self.set_path_env_var('lib') + #self.set_path_env_var('include') + + # extend the MSVC path with the current path + try: + for p in os.environ['path'].split(';'): + self.__paths.append(p) + except KeyError: + pass + self.__paths = normalize_and_reduce_paths(self.__paths) + os.environ['path'] = ";".join(self.__paths) + + self.preprocess_options = None + if self.__arch == "x86": + self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', + '/DNDEBUG'] + self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', + '/Z7', '/D_DEBUG'] + else: + # Win64 + self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' , + '/DNDEBUG'] + self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-', + '/Z7', '/D_DEBUG'] + + self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO'] + if self.__version >= 7: + self.ldflags_shared_debug = [ + '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG', '/pdb:None' + ] + self.ldflags_static = [ '/nologo'] + + self.initialized = True + + # -- Worker methods ------------------------------------------------ + + def object_filenames(self, + source_filenames, + strip_dir=0, + output_dir=''): + # Copied from ccompiler.py, extended to return .res as 'object'-file + # for .rc input file + if output_dir is None: output_dir = '' + obj_names = [] + for src_name in source_filenames: + (base, ext) = os.path.splitext (src_name) + base = os.path.splitdrive(base)[1] # Chop off the drive + base = base[os.path.isabs(base):] # If abs, chop off leading / + if ext not in self.src_extensions: + # Better to raise an exception instead of silently continuing + # and later complain about sources and targets having + # different lengths + raise CompileError ("Don't know how to compile %s" % src_name) + if strip_dir: + base = os.path.basename (base) + if ext in self._rc_extensions: + obj_names.append (os.path.join (output_dir, + base + self.res_extension)) + elif ext in self._mc_extensions: + obj_names.append (os.path.join (output_dir, + base + self.res_extension)) + else: + obj_names.append (os.path.join (output_dir, + base + self.obj_extension)) + return obj_names + + + def compile(self, sources, + output_dir=None, macros=None, include_dirs=None, debug=0, + extra_preargs=None, extra_postargs=None, depends=None): + + if not self.initialized: + self.initialize() + compile_info = self._setup_compile(output_dir, macros, include_dirs, + sources, depends, extra_postargs) + macros, objects, extra_postargs, pp_opts, build = compile_info + + compile_opts = extra_preargs or [] + compile_opts.append ('/c') + if debug: + compile_opts.extend(self.compile_options_debug) + else: + compile_opts.extend(self.compile_options) + + for obj in objects: + try: + src, ext = build[obj] + except KeyError: + continue + if debug: + # pass the full pathname to MSVC in debug mode, + # this allows the debugger to find the source file + # without asking the user to browse for it + src = os.path.abspath(src) + + if ext in self._c_extensions: + input_opt = "/Tc" + src + elif ext in self._cpp_extensions: + input_opt = "/Tp" + src + elif ext in self._rc_extensions: + # compile .RC to .RES file + input_opt = src + output_opt = "/fo" + obj + try: + self.spawn([self.rc] + pp_opts + + [output_opt] + [input_opt]) + except DistutilsExecError, msg: + raise CompileError(msg) + continue + elif ext in self._mc_extensions: + # Compile .MC to .RC file to .RES file. + # * '-h dir' specifies the directory for the + # generated include file + # * '-r dir' specifies the target directory of the + # generated RC file and the binary message resource + # it includes + # + # For now (since there are no options to change this), + # we use the source-directory for the include file and + # the build directory for the RC file and message + # resources. This works at least for win32all. + h_dir = os.path.dirname(src) + rc_dir = os.path.dirname(obj) + try: + # first compile .MC to .RC and .H file + self.spawn([self.mc] + + ['-h', h_dir, '-r', rc_dir] + [src]) + base, _ = os.path.splitext (os.path.basename (src)) + rc_file = os.path.join (rc_dir, base + '.rc') + # then compile .RC to .RES file + self.spawn([self.rc] + + ["/fo" + obj] + [rc_file]) + + except DistutilsExecError, msg: + raise CompileError(msg) + continue + else: + # how to handle this file? + raise CompileError("Don't know how to compile %s to %s" + % (src, obj)) + + output_opt = "/Fo" + obj + try: + self.spawn([self.cc] + compile_opts + pp_opts + + [input_opt, output_opt] + + extra_postargs) + except DistutilsExecError, msg: + raise CompileError(msg) + + return objects + + + def create_static_lib(self, + objects, + output_libname, + output_dir=None, + debug=0, + target_lang=None): + + if not self.initialized: + self.initialize() + (objects, output_dir) = self._fix_object_args(objects, output_dir) + output_filename = self.library_filename(output_libname, + output_dir=output_dir) + + if self._need_link(objects, output_filename): + lib_args = objects + ['/OUT:' + output_filename] + if debug: + pass # XXX what goes here? + try: + self.spawn([self.lib] + lib_args) + except DistutilsExecError, msg: + raise LibError(msg) + else: + log.debug("skipping %s (up-to-date)", output_filename) + + + def link(self, + target_desc, + objects, + output_filename, + output_dir=None, + libraries=None, + library_dirs=None, + runtime_library_dirs=None, + export_symbols=None, + debug=0, + extra_preargs=None, + extra_postargs=None, + build_temp=None, + target_lang=None): + + if not self.initialized: + self.initialize() + (objects, output_dir) = self._fix_object_args(objects, output_dir) + fixed_args = self._fix_lib_args(libraries, library_dirs, + runtime_library_dirs) + (libraries, library_dirs, runtime_library_dirs) = fixed_args + + if runtime_library_dirs: + self.warn ("I don't know what to do with 'runtime_library_dirs': " + + str (runtime_library_dirs)) + + lib_opts = gen_lib_options(self, + library_dirs, runtime_library_dirs, + libraries) + if output_dir is not None: + output_filename = os.path.join(output_dir, output_filename) + + if self._need_link(objects, output_filename): + if target_desc == CCompiler.EXECUTABLE: + if debug: + ldflags = self.ldflags_shared_debug[1:] + else: + ldflags = self.ldflags_shared[1:] + else: + if debug: + ldflags = self.ldflags_shared_debug + else: + ldflags = self.ldflags_shared + + export_opts = [] + for sym in (export_symbols or []): + export_opts.append("/EXPORT:" + sym) + + ld_args = (ldflags + lib_opts + export_opts + + objects + ['/OUT:' + output_filename]) + + # The MSVC linker generates .lib and .exp files, which cannot be + # suppressed by any linker switches. The .lib files may even be + # needed! Make sure they are generated in the temporary build + # directory. Since they have different names for debug and release + # builds, they can go into the same directory. + build_temp = os.path.dirname(objects[0]) + if export_symbols is not None: + (dll_name, dll_ext) = os.path.splitext( + os.path.basename(output_filename)) + implib_file = os.path.join( + build_temp, + self.library_filename(dll_name)) + ld_args.append ('/IMPLIB:' + implib_file) + + self.manifest_setup_ldargs(output_filename, build_temp, ld_args) + + if extra_preargs: + ld_args[:0] = extra_preargs + if extra_postargs: + ld_args.extend(extra_postargs) + + self.mkpath(os.path.dirname(output_filename)) + try: + self.spawn([self.linker] + ld_args) + except DistutilsExecError, msg: + raise LinkError(msg) + + # embed the manifest + # XXX - this is somewhat fragile - if mt.exe fails, distutils + # will still consider the DLL up-to-date, but it will not have a + # manifest. Maybe we should link to a temp file? OTOH, that + # implies a build environment error that shouldn't go undetected. + mfinfo = self.manifest_get_embed_info(target_desc, ld_args) + if mfinfo is not None: + mffilename, mfid = mfinfo + out_arg = '-outputresource:%s;%s' % (output_filename, mfid) + try: + self.spawn(['mt.exe', '-nologo', '-manifest', + mffilename, out_arg]) + except DistutilsExecError, msg: + raise LinkError(msg) + else: + log.debug("skipping %s (up-to-date)", output_filename) + + def manifest_setup_ldargs(self, output_filename, build_temp, ld_args): + # If we need a manifest at all, an embedded manifest is recommended. + # See MSDN article titled + # "How to: Embed a Manifest Inside a C/C++ Application" + # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx) + # Ask the linker to generate the manifest in the temp dir, so + # we can check it, and possibly embed it, later. + temp_manifest = os.path.join( + build_temp, + os.path.basename(output_filename) + ".manifest") + ld_args.append('/MANIFESTFILE:' + temp_manifest) + + def manifest_get_embed_info(self, target_desc, ld_args): + # If a manifest should be embedded, return a tuple of + # (manifest_filename, resource_id). Returns None if no manifest + # should be embedded. See http://bugs.python.org/issue7833 for why + # we want to avoid any manifest for extension modules if we can) + for arg in ld_args: + if arg.startswith("/MANIFESTFILE:"): + temp_manifest = arg.split(":", 1)[1] + break + else: + # no /MANIFESTFILE so nothing to do. + return None + if target_desc == CCompiler.EXECUTABLE: + # by default, executables always get the manifest with the + # CRT referenced. + mfid = 1 + else: + # Extension modules try and avoid any manifest if possible. + mfid = 2 + temp_manifest = self._remove_visual_c_ref(temp_manifest) + if temp_manifest is None: + return None + return temp_manifest, mfid + + def _remove_visual_c_ref(self, manifest_file): + try: + # Remove references to the Visual C runtime, so they will + # fall through to the Visual C dependency of Python.exe. + # This way, when installed for a restricted user (e.g. + # runtimes are not in WinSxS folder, but in Python's own + # folder), the runtimes do not need to be in every folder + # with .pyd's. + # Returns either the filename of the modified manifest or + # None if no manifest should be embedded. + manifest_f = open(manifest_file) + try: + manifest_buf = manifest_f.read() + finally: + manifest_f.close() + pattern = re.compile( + r"""|)""", + re.DOTALL) + manifest_buf = re.sub(pattern, "", manifest_buf) + pattern = "\s*" + manifest_buf = re.sub(pattern, "", manifest_buf) + # Now see if any other assemblies are referenced - if not, we + # don't want a manifest embedded. + pattern = re.compile( + r"""|)""", re.DOTALL) + if re.search(pattern, manifest_buf) is None: + return None + + manifest_f = open(manifest_file, 'w') + try: + manifest_f.write(manifest_buf) + return manifest_file + finally: + manifest_f.close() + except IOError: + pass + + # -- Miscellaneous methods ----------------------------------------- + # These are all used by the 'gen_lib_options() function, in + # ccompiler.py. + + def library_dir_option(self, dir): + return "/LIBPATH:" + dir + + def runtime_library_dir_option(self, dir): + raise DistutilsPlatformError( + "don't know how to set runtime library search path for MSVC++") + + def library_option(self, lib): + return self.library_filename(lib) + + + def find_library_file(self, dirs, lib, debug=0): + # Prefer a debugging library if found (and requested), but deal + # with it if we don't have one. + if debug: + try_names = [lib + "_d", lib] + else: + try_names = [lib] + for dir in dirs: + for name in try_names: + libfile = os.path.join(dir, self.library_filename (name)) + if os.path.exists(libfile): + return libfile + else: + # Oops, didn't find it in *any* of 'dirs' + return None + + # Helper methods for using the MSVC registry settings + + def find_exe(self, exe): + """Return path to an MSVC executable program. + + Tries to find the program in several places: first, one of the + MSVC program search paths from the registry; next, the directories + in the PATH environment variable. If any of those work, return an + absolute path that is known to exist. If none of them work, just + return the original program name, 'exe'. + """ + for p in self.__paths: + fn = os.path.join(os.path.abspath(p), exe) + if os.path.isfile(fn): + return fn + + # didn't find it; try existing path + for p in os.environ['Path'].split(';'): + fn = os.path.join(os.path.abspath(p),exe) + if os.path.isfile(fn): + return fn + + return exe diff --git a/PythonHome/Lib/distutils/msvc9compiler.pyc b/PythonHome/Lib/distutils/msvc9compiler.pyc deleted file mode 100644 index 3e3a255ae5eb08e630ff217f94ec053aef38d3e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21387 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�VT@Ls#+OFZdhuXd!WBysM3$P4a z9dLJH)W>&Q=|#x+vVFuCU|DwkiSbRPb~`r4Obwb>NRY_;+>eD&;-$WS8&{{^ zpPid&D}4QGK0lK$csFm(d*s(pGg@Czo;VGwQrwC0-lve}+|~Kng_#20v%mDJM}?WU z#^5syt}*x`1D;a7fbHF3O#U`c;HEdGTffSZ0b4KWo*2W)(O9qF8ubShu#^=b&qx*>OR 7.0: + self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1") + else: + self.set_macro("FrameworkSDKDir", net, "sdkinstallroot") + except KeyError: + raise DistutilsPlatformError, \ + ("""Python was built with Visual Studio 2003; +extensions must be built with a compiler than can generate compatible binaries. +Visual Studio 2003 was not found on this system. If you have Cygwin installed, +you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""") + + p = r"Software\Microsoft\NET Framework Setup\Product" + for base in HKEYS: + try: + h = RegOpenKeyEx(base, p) + except RegError: + continue + key = RegEnumKey(h, 0) + d = read_values(base, r"%s\%s" % (p, key)) + self.macros["$(FrameworkVersion)"] = d["version"] + + def sub(self, s): + for k, v in self.macros.items(): + s = string.replace(s, k, v) + return s + +def get_build_version(): + """Return the version of MSVC that was used to build Python. + + For Python 2.3 and up, the version number is included in + sys.version. For earlier versions, assume the compiler is MSVC 6. + """ + + prefix = "MSC v." + i = string.find(sys.version, prefix) + if i == -1: + return 6 + i = i + len(prefix) + s, rest = sys.version[i:].split(" ", 1) + majorVersion = int(s[:-2]) - 6 + minorVersion = int(s[2:3]) / 10.0 + # I don't think paths are affected by minor version in version 6 + if majorVersion == 6: + minorVersion = 0 + if majorVersion >= 6: + return majorVersion + minorVersion + # else we don't know what version of the compiler this is + return None + +def get_build_architecture(): + """Return the processor architecture. + + Possible results are "Intel", "Itanium", or "AMD64". + """ + + prefix = " bit (" + i = string.find(sys.version, prefix) + if i == -1: + return "Intel" + j = string.find(sys.version, ")", i) + return sys.version[i+len(prefix):j] + +def normalize_and_reduce_paths(paths): + """Return a list of normalized paths with duplicates removed. + + The current order of paths is maintained. + """ + # Paths are normalized so things like: /a and /a/ aren't both preserved. + reduced_paths = [] + for p in paths: + np = os.path.normpath(p) + # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set. + if np not in reduced_paths: + reduced_paths.append(np) + return reduced_paths + + +class MSVCCompiler (CCompiler) : + """Concrete class that implements an interface to Microsoft Visual C++, + as defined by the CCompiler abstract class.""" + + compiler_type = 'msvc' + + # Just set this so CCompiler's constructor doesn't barf. We currently + # don't use the 'set_executables()' bureaucracy provided by CCompiler, + # as it really isn't necessary for this sort of single-compiler class. + # Would be nice to have a consistent interface with UnixCCompiler, + # though, so it's worth thinking about. + executables = {} + + # Private class data (need to distinguish C from C++ source for compiler) + _c_extensions = ['.c'] + _cpp_extensions = ['.cc', '.cpp', '.cxx'] + _rc_extensions = ['.rc'] + _mc_extensions = ['.mc'] + + # Needed for the filename generation methods provided by the + # base class, CCompiler. + src_extensions = (_c_extensions + _cpp_extensions + + _rc_extensions + _mc_extensions) + res_extension = '.res' + obj_extension = '.obj' + static_lib_extension = '.lib' + shared_lib_extension = '.dll' + static_lib_format = shared_lib_format = '%s%s' + exe_extension = '.exe' + + def __init__ (self, verbose=0, dry_run=0, force=0): + CCompiler.__init__ (self, verbose, dry_run, force) + self.__version = get_build_version() + self.__arch = get_build_architecture() + if self.__arch == "Intel": + # x86 + if self.__version >= 7: + self.__root = r"Software\Microsoft\VisualStudio" + self.__macros = MacroExpander(self.__version) + else: + self.__root = r"Software\Microsoft\Devstudio" + self.__product = "Visual Studio version %s" % self.__version + else: + # Win64. Assume this was built with the platform SDK + self.__product = "Microsoft SDK compiler %s" % (self.__version + 6) + + self.initialized = False + + def initialize(self): + self.__paths = [] + if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"): + # Assume that the SDK set up everything alright; don't try to be + # smarter + self.cc = "cl.exe" + self.linker = "link.exe" + self.lib = "lib.exe" + self.rc = "rc.exe" + self.mc = "mc.exe" + else: + self.__paths = self.get_msvc_paths("path") + + if len (self.__paths) == 0: + raise DistutilsPlatformError, \ + ("Python was built with %s, " + "and extensions need to be built with the same " + "version of the compiler, but it isn't installed." % self.__product) + + self.cc = self.find_exe("cl.exe") + self.linker = self.find_exe("link.exe") + self.lib = self.find_exe("lib.exe") + self.rc = self.find_exe("rc.exe") # resource compiler + self.mc = self.find_exe("mc.exe") # message compiler + self.set_path_env_var('lib') + self.set_path_env_var('include') + + # extend the MSVC path with the current path + try: + for p in string.split(os.environ['path'], ';'): + self.__paths.append(p) + except KeyError: + pass + self.__paths = normalize_and_reduce_paths(self.__paths) + os.environ['path'] = string.join(self.__paths, ';') + + self.preprocess_options = None + if self.__arch == "Intel": + self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' , + '/DNDEBUG'] + self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX', + '/Z7', '/D_DEBUG'] + else: + # Win64 + self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' , + '/DNDEBUG'] + self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-', + '/Z7', '/D_DEBUG'] + + self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO'] + if self.__version >= 7: + self.ldflags_shared_debug = [ + '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG' + ] + else: + self.ldflags_shared_debug = [ + '/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG' + ] + self.ldflags_static = [ '/nologo'] + + self.initialized = True + + # -- Worker methods ------------------------------------------------ + + def object_filenames (self, + source_filenames, + strip_dir=0, + output_dir=''): + # Copied from ccompiler.py, extended to return .res as 'object'-file + # for .rc input file + if output_dir is None: output_dir = '' + obj_names = [] + for src_name in source_filenames: + (base, ext) = os.path.splitext (src_name) + base = os.path.splitdrive(base)[1] # Chop off the drive + base = base[os.path.isabs(base):] # If abs, chop off leading / + if ext not in self.src_extensions: + # Better to raise an exception instead of silently continuing + # and later complain about sources and targets having + # different lengths + raise CompileError ("Don't know how to compile %s" % src_name) + if strip_dir: + base = os.path.basename (base) + if ext in self._rc_extensions: + obj_names.append (os.path.join (output_dir, + base + self.res_extension)) + elif ext in self._mc_extensions: + obj_names.append (os.path.join (output_dir, + base + self.res_extension)) + else: + obj_names.append (os.path.join (output_dir, + base + self.obj_extension)) + return obj_names + + # object_filenames () + + + def compile(self, sources, + output_dir=None, macros=None, include_dirs=None, debug=0, + extra_preargs=None, extra_postargs=None, depends=None): + + if not self.initialized: self.initialize() + macros, objects, extra_postargs, pp_opts, build = \ + self._setup_compile(output_dir, macros, include_dirs, sources, + depends, extra_postargs) + + compile_opts = extra_preargs or [] + compile_opts.append ('/c') + if debug: + compile_opts.extend(self.compile_options_debug) + else: + compile_opts.extend(self.compile_options) + + for obj in objects: + try: + src, ext = build[obj] + except KeyError: + continue + if debug: + # pass the full pathname to MSVC in debug mode, + # this allows the debugger to find the source file + # without asking the user to browse for it + src = os.path.abspath(src) + + if ext in self._c_extensions: + input_opt = "/Tc" + src + elif ext in self._cpp_extensions: + input_opt = "/Tp" + src + elif ext in self._rc_extensions: + # compile .RC to .RES file + input_opt = src + output_opt = "/fo" + obj + try: + self.spawn ([self.rc] + pp_opts + + [output_opt] + [input_opt]) + except DistutilsExecError, msg: + raise CompileError, msg + continue + elif ext in self._mc_extensions: + + # Compile .MC to .RC file to .RES file. + # * '-h dir' specifies the directory for the + # generated include file + # * '-r dir' specifies the target directory of the + # generated RC file and the binary message resource + # it includes + # + # For now (since there are no options to change this), + # we use the source-directory for the include file and + # the build directory for the RC file and message + # resources. This works at least for win32all. + + h_dir = os.path.dirname (src) + rc_dir = os.path.dirname (obj) + try: + # first compile .MC to .RC and .H file + self.spawn ([self.mc] + + ['-h', h_dir, '-r', rc_dir] + [src]) + base, _ = os.path.splitext (os.path.basename (src)) + rc_file = os.path.join (rc_dir, base + '.rc') + # then compile .RC to .RES file + self.spawn ([self.rc] + + ["/fo" + obj] + [rc_file]) + + except DistutilsExecError, msg: + raise CompileError, msg + continue + else: + # how to handle this file? + raise CompileError ( + "Don't know how to compile %s to %s" % \ + (src, obj)) + + output_opt = "/Fo" + obj + try: + self.spawn ([self.cc] + compile_opts + pp_opts + + [input_opt, output_opt] + + extra_postargs) + except DistutilsExecError, msg: + raise CompileError, msg + + return objects + + # compile () + + + def create_static_lib (self, + objects, + output_libname, + output_dir=None, + debug=0, + target_lang=None): + + if not self.initialized: self.initialize() + (objects, output_dir) = self._fix_object_args (objects, output_dir) + output_filename = \ + self.library_filename (output_libname, output_dir=output_dir) + + if self._need_link (objects, output_filename): + lib_args = objects + ['/OUT:' + output_filename] + if debug: + pass # XXX what goes here? + try: + self.spawn ([self.lib] + lib_args) + except DistutilsExecError, msg: + raise LibError, msg + + else: + log.debug("skipping %s (up-to-date)", output_filename) + + # create_static_lib () + + def link (self, + target_desc, + objects, + output_filename, + output_dir=None, + libraries=None, + library_dirs=None, + runtime_library_dirs=None, + export_symbols=None, + debug=0, + extra_preargs=None, + extra_postargs=None, + build_temp=None, + target_lang=None): + + if not self.initialized: self.initialize() + (objects, output_dir) = self._fix_object_args (objects, output_dir) + (libraries, library_dirs, runtime_library_dirs) = \ + self._fix_lib_args (libraries, library_dirs, runtime_library_dirs) + + if runtime_library_dirs: + self.warn ("I don't know what to do with 'runtime_library_dirs': " + + str (runtime_library_dirs)) + + lib_opts = gen_lib_options (self, + library_dirs, runtime_library_dirs, + libraries) + if output_dir is not None: + output_filename = os.path.join (output_dir, output_filename) + + if self._need_link (objects, output_filename): + + if target_desc == CCompiler.EXECUTABLE: + if debug: + ldflags = self.ldflags_shared_debug[1:] + else: + ldflags = self.ldflags_shared[1:] + else: + if debug: + ldflags = self.ldflags_shared_debug + else: + ldflags = self.ldflags_shared + + export_opts = [] + for sym in (export_symbols or []): + export_opts.append("/EXPORT:" + sym) + + ld_args = (ldflags + lib_opts + export_opts + + objects + ['/OUT:' + output_filename]) + + # The MSVC linker generates .lib and .exp files, which cannot be + # suppressed by any linker switches. The .lib files may even be + # needed! Make sure they are generated in the temporary build + # directory. Since they have different names for debug and release + # builds, they can go into the same directory. + if export_symbols is not None: + (dll_name, dll_ext) = os.path.splitext( + os.path.basename(output_filename)) + implib_file = os.path.join( + os.path.dirname(objects[0]), + self.library_filename(dll_name)) + ld_args.append ('/IMPLIB:' + implib_file) + + if extra_preargs: + ld_args[:0] = extra_preargs + if extra_postargs: + ld_args.extend(extra_postargs) + + self.mkpath (os.path.dirname (output_filename)) + try: + self.spawn ([self.linker] + ld_args) + except DistutilsExecError, msg: + raise LinkError, msg + + else: + log.debug("skipping %s (up-to-date)", output_filename) + + # link () + + + # -- Miscellaneous methods ----------------------------------------- + # These are all used by the 'gen_lib_options() function, in + # ccompiler.py. + + def library_dir_option (self, dir): + return "/LIBPATH:" + dir + + def runtime_library_dir_option (self, dir): + raise DistutilsPlatformError, \ + "don't know how to set runtime library search path for MSVC++" + + def library_option (self, lib): + return self.library_filename (lib) + + + def find_library_file (self, dirs, lib, debug=0): + # Prefer a debugging library if found (and requested), but deal + # with it if we don't have one. + if debug: + try_names = [lib + "_d", lib] + else: + try_names = [lib] + for dir in dirs: + for name in try_names: + libfile = os.path.join(dir, self.library_filename (name)) + if os.path.exists(libfile): + return libfile + else: + # Oops, didn't find it in *any* of 'dirs' + return None + + # find_library_file () + + # Helper methods for using the MSVC registry settings + + def find_exe(self, exe): + """Return path to an MSVC executable program. + + Tries to find the program in several places: first, one of the + MSVC program search paths from the registry; next, the directories + in the PATH environment variable. If any of those work, return an + absolute path that is known to exist. If none of them work, just + return the original program name, 'exe'. + """ + + for p in self.__paths: + fn = os.path.join(os.path.abspath(p), exe) + if os.path.isfile(fn): + return fn + + # didn't find it; try existing path + for p in string.split(os.environ['Path'],';'): + fn = os.path.join(os.path.abspath(p),exe) + if os.path.isfile(fn): + return fn + + return exe + + def get_msvc_paths(self, path, platform='x86'): + """Get a list of devstudio directories (include, lib or path). + + Return a list of strings. The list will be empty if unable to + access the registry or appropriate registry keys not found. + """ + + if not _can_read_reg: + return [] + + path = path + " dirs" + if self.__version >= 7: + key = (r"%s\%0.1f\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories" + % (self.__root, self.__version)) + else: + key = (r"%s\6.0\Build System\Components\Platforms" + r"\Win32 (%s)\Directories" % (self.__root, platform)) + + for base in HKEYS: + d = read_values(base, key) + if d: + if self.__version >= 7: + return string.split(self.__macros.sub(d[path]), ";") + else: + return string.split(d[path], ";") + # MSVC 6 seems to create the registry entries we need only when + # the GUI is run. + if self.__version == 6: + for base in HKEYS: + if read_values(base, r"%s\6.0" % self.__root) is not None: + self.warn("It seems you have Visual Studio 6 installed, " + "but the expected registry settings are not present.\n" + "You must at least run the Visual Studio GUI once " + "so that these entries are created.") + break + return [] + + def set_path_env_var(self, name): + """Set environment variable 'name' to an MSVC path type value. + + This is equivalent to a SET command prior to execution of spawned + commands. + """ + + if name == "lib": + p = self.get_msvc_paths("library") + else: + p = self.get_msvc_paths(name) + if p: + os.environ[name] = string.join(p, ';') + + +if get_build_version() >= 8.0: + log.debug("Importing new compiler from distutils.msvc9compiler") + OldMSVCCompiler = MSVCCompiler + from distutils.msvc9compiler import MSVCCompiler + # get_build_architecture not really relevant now we support cross-compile + from distutils.msvc9compiler import MacroExpander diff --git a/PythonHome/Lib/distutils/msvccompiler.pyc b/PythonHome/Lib/distutils/msvccompiler.pyc deleted file mode 100644 index 2c7c6924563723d03ea2af2c972f0f6b7ef77dd6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17393 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 Le1`^vj+6fdb>GT6 diff --git a/PythonHome/Lib/distutils/spawn.py b/PythonHome/Lib/distutils/spawn.py new file mode 100644 index 0000000000..321344a3a5 --- /dev/null +++ b/PythonHome/Lib/distutils/spawn.py @@ -0,0 +1,226 @@ +"""distutils.spawn + +Provides the 'spawn()' function, a front-end to various platform- +specific functions for launching another program in a sub-process. +Also provides the 'find_executable()' to search the path for a given +executable name. +""" + +__revision__ = "$Id$" + +import sys +import os + +from distutils.errors import DistutilsPlatformError, DistutilsExecError +from distutils.debug import DEBUG +from distutils import log + +def spawn(cmd, search_path=1, verbose=0, dry_run=0): + """Run another program, specified as a command list 'cmd', in a new process. + + 'cmd' is just the argument list for the new process, ie. + cmd[0] is the program to run and cmd[1:] are the rest of its arguments. + There is no way to run a program with a name different from that of its + executable. + + If 'search_path' is true (the default), the system's executable + search path will be used to find the program; otherwise, cmd[0] + must be the exact path to the executable. If 'dry_run' is true, + the command will not actually be run. + + Raise DistutilsExecError if running the program fails in any way; just + return on success. + """ + # cmd is documented as a list, but just in case some code passes a tuple + # in, protect our %-formatting code against horrible death + cmd = list(cmd) + if os.name == 'posix': + _spawn_posix(cmd, search_path, dry_run=dry_run) + elif os.name == 'nt': + _spawn_nt(cmd, search_path, dry_run=dry_run) + elif os.name == 'os2': + _spawn_os2(cmd, search_path, dry_run=dry_run) + else: + raise DistutilsPlatformError, \ + "don't know how to spawn programs on platform '%s'" % os.name + +def _nt_quote_args(args): + """Quote command-line arguments for DOS/Windows conventions. + + Just wraps every argument which contains blanks in double quotes, and + returns a new argument list. + """ + # XXX this doesn't seem very robust to me -- but if the Windows guys + # say it'll work, I guess I'll have to accept it. (What if an arg + # contains quotes? What other magic characters, other than spaces, + # have to be escaped? Is there an escaping mechanism other than + # quoting?) + for i, arg in enumerate(args): + if ' ' in arg: + args[i] = '"%s"' % arg + return args + +def _spawn_nt(cmd, search_path=1, verbose=0, dry_run=0): + executable = cmd[0] + cmd = _nt_quote_args(cmd) + if search_path: + # either we find one or it stays the same + executable = find_executable(executable) or executable + log.info(' '.join([executable] + cmd[1:])) + if not dry_run: + # spawn for NT requires a full path to the .exe + try: + rc = os.spawnv(os.P_WAIT, executable, cmd) + except OSError, exc: + # this seems to happen when the command isn't found + if not DEBUG: + cmd = executable + raise DistutilsExecError, \ + "command %r failed: %s" % (cmd, exc[-1]) + if rc != 0: + # and this reflects the command running but failing + if not DEBUG: + cmd = executable + raise DistutilsExecError, \ + "command %r failed with exit status %d" % (cmd, rc) + +def _spawn_os2(cmd, search_path=1, verbose=0, dry_run=0): + executable = cmd[0] + if search_path: + # either we find one or it stays the same + executable = find_executable(executable) or executable + log.info(' '.join([executable] + cmd[1:])) + if not dry_run: + # spawnv for OS/2 EMX requires a full path to the .exe + try: + rc = os.spawnv(os.P_WAIT, executable, cmd) + except OSError, exc: + # this seems to happen when the command isn't found + if not DEBUG: + cmd = executable + raise DistutilsExecError, \ + "command %r failed: %s" % (cmd, exc[-1]) + if rc != 0: + # and this reflects the command running but failing + if not DEBUG: + cmd = executable + log.debug("command %r failed with exit status %d" % (cmd, rc)) + raise DistutilsExecError, \ + "command %r failed with exit status %d" % (cmd, rc) + +if sys.platform == 'darwin': + from distutils import sysconfig + _cfg_target = None + _cfg_target_split = None + +def _spawn_posix(cmd, search_path=1, verbose=0, dry_run=0): + log.info(' '.join(cmd)) + if dry_run: + return + executable = cmd[0] + exec_fn = search_path and os.execvp or os.execv + env = None + if sys.platform == 'darwin': + global _cfg_target, _cfg_target_split + if _cfg_target is None: + _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: + # ensure that the deployment target of build process is not less + # than that used when the interpreter was built. This ensures + # extension modules are built with correct compatibility values + cur_target = os.environ.get('MACOSX_DEPLOYMENT_TARGET', _cfg_target) + if _cfg_target_split > [int(x) for x in cur_target.split('.')]: + my_msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: ' + 'now "%s" but "%s" during configure' + % (cur_target, _cfg_target)) + raise DistutilsPlatformError(my_msg) + env = dict(os.environ, + MACOSX_DEPLOYMENT_TARGET=cur_target) + exec_fn = search_path and os.execvpe or os.execve + pid = os.fork() + + if pid == 0: # in the child + try: + if env is None: + exec_fn(executable, cmd) + else: + exec_fn(executable, cmd, env) + except OSError, e: + if not DEBUG: + cmd = executable + sys.stderr.write("unable to execute %r: %s\n" % + (cmd, e.strerror)) + os._exit(1) + + if not DEBUG: + cmd = executable + sys.stderr.write("unable to execute %r for unknown reasons" % cmd) + os._exit(1) + else: # in the parent + # Loop until the child either exits or is terminated by a signal + # (ie. keep waiting if it's merely stopped) + while 1: + try: + pid, status = os.waitpid(pid, 0) + except OSError, exc: + import errno + if exc.errno == errno.EINTR: + continue + if not DEBUG: + cmd = executable + raise DistutilsExecError, \ + "command %r failed: %s" % (cmd, exc[-1]) + if os.WIFSIGNALED(status): + if not DEBUG: + cmd = executable + raise DistutilsExecError, \ + "command %r terminated by signal %d" % \ + (cmd, os.WTERMSIG(status)) + + elif os.WIFEXITED(status): + exit_status = os.WEXITSTATUS(status) + if exit_status == 0: + return # hey, it succeeded! + else: + if not DEBUG: + cmd = executable + raise DistutilsExecError, \ + "command %r failed with exit status %d" % \ + (cmd, exit_status) + + elif os.WIFSTOPPED(status): + continue + + else: + if not DEBUG: + cmd = executable + raise DistutilsExecError, \ + "unknown error executing %r: termination status %d" % \ + (cmd, status) + +def find_executable(executable, path=None): + """Tries to find 'executable' in the directories listed in 'path'. + + A string listing directories separated by 'os.pathsep'; defaults to + os.environ['PATH']. Returns the complete filename or None if not found. + """ + if path is None: + path = os.environ['PATH'] + paths = path.split(os.pathsep) + base, ext = os.path.splitext(executable) + + if (sys.platform == 'win32' or os.name == 'os2') and (ext != '.exe'): + executable = executable + '.exe' + + if not os.path.isfile(executable): + for p in paths: + f = os.path.join(p, executable) + if os.path.isfile(f): + # the file exists, we have a shot at spawn working + return f + return None + else: + return executable diff --git a/PythonHome/Lib/distutils/spawn.pyc b/PythonHome/Lib/distutils/spawn.pyc deleted file mode 100644 index 5cc2b90eb2c812e4d7522fad8bb387fc09dc580d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6363 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 diff --git a/PythonHome/Lib/distutils/sysconfig.py b/PythonHome/Lib/distutils/sysconfig.py new file mode 100644 index 0000000000..4aa93346d5 --- /dev/null +++ b/PythonHome/Lib/distutils/sysconfig.py @@ -0,0 +1,482 @@ +"""Provide access to Python's configuration information. The specific +configuration variables available depend heavily on the platform and +configuration. The values may be retrieved using +get_config_var(name), and the list of variables is available via +get_config_vars().keys(). Additional convenience functions are also +available. + +Written by: Fred L. Drake, Jr. +Email: +""" + +__revision__ = "$Id$" + +import os +import re +import string +import sys + +from distutils.errors import DistutilsPlatformError + +# These are needed in a couple of spots, so just compute them once. +PREFIX = os.path.normpath(sys.prefix) +EXEC_PREFIX = os.path.normpath(sys.exec_prefix) + +# Path to the base directory of the project. On Windows the binary may +# live in project/PCBuild9. If we're dealing with an x64 Windows build, +# it'll live in project/PCbuild/amd64. +project_base = os.path.dirname(os.path.abspath(sys.executable)) +if os.name == "nt" and "pcbuild" in project_base[-8:].lower(): + project_base = os.path.abspath(os.path.join(project_base, os.path.pardir)) +# PC/VS7.1 +if os.name == "nt" and "\\pc\\v" in project_base[-10:].lower(): + project_base = os.path.abspath(os.path.join(project_base, os.path.pardir, + os.path.pardir)) +# PC/AMD64 +if os.name == "nt" and "\\pcbuild\\amd64" in project_base[-14:].lower(): + project_base = os.path.abspath(os.path.join(project_base, os.path.pardir, + os.path.pardir)) + +# set for cross builds +if "_PYTHON_PROJECT_BASE" in os.environ: + # this is the build directory, at least for posix + project_base = os.path.normpath(os.environ["_PYTHON_PROJECT_BASE"]) + +# python_build: (Boolean) if true, we're either building Python or +# building an extension with an un-installed Python, so we use +# different (hard-wired) directories. +# Setup.local is available for Makefile builds including VPATH builds, +# Setup.dist is available on Windows +def _python_build(): + for fn in ("Setup.dist", "Setup.local"): + if os.path.isfile(os.path.join(project_base, "Modules", fn)): + return True + return False +python_build = _python_build() + + +def get_python_version(): + """Return a string containing the major and minor Python version, + leaving off the patchlevel. Sample return values could be '1.5' + or '2.2'. + """ + return sys.version[:3] + + +def get_python_inc(plat_specific=0, prefix=None): + """Return the directory containing installed Python header files. + + If 'plat_specific' is false (the default), this is the path to the + non-platform-specific header files, i.e. Python.h and so on; + otherwise, this is the path to platform-specific header files + (namely pyconfig.h). + + If 'prefix' is supplied, use it instead of sys.prefix or + sys.exec_prefix -- i.e., ignore 'plat_specific'. + """ + if prefix is None: + prefix = plat_specific and EXEC_PREFIX or PREFIX + + if os.name == "posix": + if python_build: + buildir = os.path.dirname(sys.executable) + if plat_specific: + # python.h is located in the buildir + inc_dir = buildir + else: + # the source dir is relative to the buildir + srcdir = os.path.abspath(os.path.join(buildir, + get_config_var('srcdir'))) + # Include is located in the srcdir + inc_dir = os.path.join(srcdir, "Include") + return inc_dir + return os.path.join(prefix, "include", "python" + get_python_version()) + elif os.name == "nt": + return os.path.join(prefix, "include") + elif os.name == "os2": + return os.path.join(prefix, "Include") + else: + raise DistutilsPlatformError( + "I don't know where Python installs its C header files " + "on platform '%s'" % os.name) + + +def get_python_lib(plat_specific=0, standard_lib=0, prefix=None): + """Return the directory containing the Python library (standard or + site additions). + + If 'plat_specific' is true, return the directory containing + platform-specific modules, i.e. any module from a non-pure-Python + module distribution; otherwise, return the platform-shared library + directory. If 'standard_lib' is true, return the directory + containing standard Python library modules; otherwise, return the + directory for site-specific modules. + + If 'prefix' is supplied, use it instead of sys.prefix or + sys.exec_prefix -- i.e., ignore 'plat_specific'. + """ + if prefix is None: + prefix = plat_specific and EXEC_PREFIX or PREFIX + + if os.name == "posix": + libpython = os.path.join(prefix, + "lib", "python" + get_python_version()) + if standard_lib: + return libpython + else: + return os.path.join(libpython, "site-packages") + + elif os.name == "nt": + if standard_lib: + return os.path.join(prefix, "Lib") + else: + if get_python_version() < "2.2": + return prefix + else: + return os.path.join(prefix, "Lib", "site-packages") + + elif os.name == "os2": + if standard_lib: + return os.path.join(prefix, "Lib") + else: + return os.path.join(prefix, "Lib", "site-packages") + + else: + raise DistutilsPlatformError( + "I don't know where Python installs its library " + "on platform '%s'" % os.name) + + + +def customize_compiler(compiler): + """Do any platform-specific customization of a CCompiler instance. + + Mainly needed on Unix, so we can plug in the information that + varies across Unices and is stored in Python's Makefile. + """ + if compiler.compiler_type == "unix": + if sys.platform == "darwin": + # Perform first-time customization of compiler-related + # config vars on OS X now that we know we need a compiler. + # This is primarily to support Pythons from binary + # installers. The kind and paths to build tools on + # the user system may vary significantly from the system + # that Python itself was built on. Also the user OS + # version and build tools may not support the same set + # of CPU architectures for universal builds. + global _config_vars + if not _config_vars.get('CUSTOMIZED_OSX_COMPILER', ''): + import _osx_support + _osx_support.customize_compiler(_config_vars) + _config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True' + + (cc, cxx, opt, cflags, ccshared, ldshared, so_ext, ar, ar_flags) = \ + get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS', + 'CCSHARED', 'LDSHARED', 'SO', 'AR', + 'ARFLAGS') + + if 'CC' in os.environ: + newcc = os.environ['CC'] + if (sys.platform == 'darwin' + and 'LDSHARED' not in os.environ + and ldshared.startswith(cc)): + # On OS X, if CC is overridden, use that as the default + # command for LDSHARED as well + ldshared = newcc + ldshared[len(cc):] + cc = newcc + if 'CXX' in os.environ: + cxx = os.environ['CXX'] + if 'LDSHARED' in os.environ: + ldshared = os.environ['LDSHARED'] + if 'CPP' in os.environ: + cpp = os.environ['CPP'] + else: + cpp = cc + " -E" # not always + if 'LDFLAGS' in os.environ: + ldshared = ldshared + ' ' + os.environ['LDFLAGS'] + if 'CFLAGS' in os.environ: + cflags = opt + ' ' + os.environ['CFLAGS'] + ldshared = ldshared + ' ' + os.environ['CFLAGS'] + if 'CPPFLAGS' in os.environ: + cpp = cpp + ' ' + os.environ['CPPFLAGS'] + cflags = cflags + ' ' + os.environ['CPPFLAGS'] + ldshared = ldshared + ' ' + os.environ['CPPFLAGS'] + if 'AR' in os.environ: + ar = os.environ['AR'] + if 'ARFLAGS' in os.environ: + archiver = ar + ' ' + os.environ['ARFLAGS'] + else: + archiver = ar + ' ' + ar_flags + + cc_cmd = cc + ' ' + cflags + compiler.set_executables( + preprocessor=cpp, + compiler=cc_cmd, + compiler_so=cc_cmd + ' ' + ccshared, + compiler_cxx=cxx, + linker_so=ldshared, + linker_exe=cc, + archiver=archiver) + + compiler.shared_lib_extension = so_ext + + +def get_config_h_filename(): + """Return full pathname of installed pyconfig.h file.""" + if python_build: + if os.name == "nt": + inc_dir = os.path.join(project_base, "PC") + else: + inc_dir = project_base + else: + inc_dir = get_python_inc(plat_specific=1) + if get_python_version() < '2.2': + config_h = 'config.h' + else: + # The name of the config.h file changed in 2.2 + config_h = 'pyconfig.h' + return os.path.join(inc_dir, config_h) + + +def get_makefile_filename(): + """Return full pathname of installed Makefile from the Python build.""" + if python_build: + return os.path.join(project_base, "Makefile") + lib_dir = get_python_lib(plat_specific=1, standard_lib=1) + return os.path.join(lib_dir, "config", "Makefile") + + +def parse_config_h(fp, g=None): + """Parse a config.h-style file. + + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + if g is None: + g = {} + define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n") + undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n") + # + while 1: + line = fp.readline() + if not line: + break + m = define_rx.match(line) + if m: + n, v = m.group(1, 2) + try: v = int(v) + except ValueError: pass + g[n] = v + else: + m = undef_rx.match(line) + if m: + g[m.group(1)] = 0 + return g + + +# Regexes needed for parsing Makefile (and similar syntaxes, +# like old-style Setup files). +_variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)") +_findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)") +_findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}") + +def parse_makefile(fn, g=None): + """Parse a Makefile-style file. + + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + from distutils.text_file import TextFile + fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1) + + if g is None: + g = {} + done = {} + notdone = {} + + while 1: + line = fp.readline() + if line is None: # eof + break + m = _variable_rx.match(line) + if m: + n, v = m.group(1, 2) + v = v.strip() + # `$$' is a literal `$' in make + tmpv = v.replace('$$', '') + + if "$" in tmpv: + notdone[n] = v + else: + try: + v = int(v) + except ValueError: + # insert literal `$' + done[n] = v.replace('$$', '$') + else: + done[n] = v + + # do variable interpolation here + while notdone: + for name in notdone.keys(): + value = notdone[name] + m = _findvar1_rx.search(value) or _findvar2_rx.search(value) + if m: + n = m.group(1) + found = True + if n in done: + item = str(done[n]) + elif n in notdone: + # get it on a subsequent round + found = False + elif n in os.environ: + # do it like make: fall back to environment + item = os.environ[n] + else: + done[n] = item = "" + if found: + after = value[m.end():] + value = value[:m.start()] + item + after + if "$" in after: + notdone[name] = value + else: + try: value = int(value) + except ValueError: + done[name] = value.strip() + else: + done[name] = value + del notdone[name] + else: + # bogus variable reference; just drop it since we can't deal + del notdone[name] + + fp.close() + + # strip spurious spaces + for k, v in done.items(): + if isinstance(v, str): + done[k] = v.strip() + + # save the results in the global dictionary + g.update(done) + return g + + +def expand_makefile_vars(s, vars): + """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in + 'string' according to 'vars' (a dictionary mapping variable names to + values). Variables not present in 'vars' are silently expanded to the + empty string. The variable values in 'vars' should not contain further + variable expansions; if 'vars' is the output of 'parse_makefile()', + you're fine. Returns a variable-expanded version of 's'. + """ + + # This algorithm does multiple expansion, so if vars['foo'] contains + # "${bar}", it will expand ${foo} to ${bar}, and then expand + # ${bar}... and so forth. This is fine as long as 'vars' comes from + # 'parse_makefile()', which takes care of such expansions eagerly, + # according to make's variable expansion semantics. + + while 1: + m = _findvar1_rx.search(s) or _findvar2_rx.search(s) + if m: + (beg, end) = m.span() + s = s[0:beg] + vars.get(m.group(1)) + s[end:] + else: + break + return s + + +_config_vars = None + +def _init_posix(): + """Initialize the module as appropriate for POSIX systems.""" + # _sysconfigdata is generated at build time, see the sysconfig module + from _sysconfigdata import build_time_vars + global _config_vars + _config_vars = {} + _config_vars.update(build_time_vars) + + +def _init_nt(): + """Initialize the module as appropriate for NT""" + g = {} + # set basic install directories + g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1) + g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1) + + # XXX hmmm.. a normal install puts include files here + g['INCLUDEPY'] = get_python_inc(plat_specific=0) + + g['SO'] = '.pyd' + g['EXE'] = ".exe" + g['VERSION'] = get_python_version().replace(".", "") + g['BINDIR'] = os.path.dirname(os.path.abspath(sys.executable)) + + global _config_vars + _config_vars = g + + +def _init_os2(): + """Initialize the module as appropriate for OS/2""" + g = {} + # set basic install directories + g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1) + g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1) + + # XXX hmmm.. a normal install puts include files here + g['INCLUDEPY'] = get_python_inc(plat_specific=0) + + g['SO'] = '.pyd' + g['EXE'] = ".exe" + + global _config_vars + _config_vars = g + + +def get_config_vars(*args): + """With no arguments, return a dictionary of all configuration + variables relevant for the current platform. Generally this includes + everything needed to build extensions and install both pure modules and + extensions. On Unix, this means every variable defined in Python's + installed Makefile; on Windows and Mac OS it's a much smaller set. + + With arguments, return a list of values that result from looking up + each argument in the configuration variable dictionary. + """ + global _config_vars + if _config_vars is None: + func = globals().get("_init_" + os.name) + if func: + func() + else: + _config_vars = {} + + # Normalized versions of prefix and exec_prefix are handy to have; + # in fact, these are the standard versions used most places in the + # Distutils. + _config_vars['prefix'] = PREFIX + _config_vars['exec_prefix'] = EXEC_PREFIX + + # OS X platforms require special customization to handle + # multi-architecture, multi-os-version installers + if sys.platform == 'darwin': + import _osx_support + _osx_support.customize_config_vars(_config_vars) + + if args: + vals = [] + for name in args: + vals.append(_config_vars.get(name)) + return vals + else: + return _config_vars + +def get_config_var(name): + """Return the value of a single variable using the dictionary + returned by 'get_config_vars()'. Equivalent to + get_config_vars().get(name) + """ + return get_config_vars().get(name) diff --git a/PythonHome/Lib/distutils/sysconfig.pyc b/PythonHome/Lib/distutils/sysconfig.pyc deleted file mode 100644 index 26d896a1a0a157aaecc3e64b04c607a32a39dfb1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13137 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 YI5>1cF6nYZ)#3ym&=rfPQ2Nq;0kVzp<^TWy diff --git a/PythonHome/Lib/distutils/text_file.py b/PythonHome/Lib/distutils/text_file.py new file mode 100644 index 0000000000..09a798b190 --- /dev/null +++ b/PythonHome/Lib/distutils/text_file.py @@ -0,0 +1,304 @@ +"""text_file + +provides the TextFile class, which gives an interface to text files +that (optionally) takes care of stripping comments, ignoring blank +lines, and joining lines with backslashes.""" + +__revision__ = "$Id$" + +import sys + + +class TextFile: + + """Provides a file-like object that takes care of all the things you + commonly want to do when processing a text file that has some + line-by-line syntax: strip comments (as long as "#" is your + comment character), skip blank lines, join adjacent lines by + escaping the newline (ie. backslash at end of line), strip + leading and/or trailing whitespace. All of these are optional + and independently controllable. + + Provides a 'warn()' method so you can generate warning messages that + report physical line number, even if the logical line in question + spans multiple physical lines. Also provides 'unreadline()' for + implementing line-at-a-time lookahead. + + Constructor is called as: + + TextFile (filename=None, file=None, **options) + + It bombs (RuntimeError) if both 'filename' and 'file' are None; + 'filename' should be a string, and 'file' a file object (or + something that provides 'readline()' and 'close()' methods). It is + recommended that you supply at least 'filename', so that TextFile + can include it in warning messages. If 'file' is not supplied, + TextFile creates its own using the 'open()' builtin. + + The options are all boolean, and affect the value returned by + 'readline()': + strip_comments [default: true] + strip from "#" to end-of-line, as well as any whitespace + leading up to the "#" -- unless it is escaped by a backslash + lstrip_ws [default: false] + strip leading whitespace from each line before returning it + rstrip_ws [default: true] + strip trailing whitespace (including line terminator!) from + each line before returning it + skip_blanks [default: true} + skip lines that are empty *after* stripping comments and + whitespace. (If both lstrip_ws and rstrip_ws are false, + then some lines may consist of solely whitespace: these will + *not* be skipped, even if 'skip_blanks' is true.) + join_lines [default: false] + if a backslash is the last non-newline character on a line + after stripping comments and whitespace, join the following line + to it to form one "logical line"; if N consecutive lines end + with a backslash, then N+1 physical lines will be joined to + form one logical line. + collapse_join [default: false] + strip leading whitespace from lines that are joined to their + predecessor; only matters if (join_lines and not lstrip_ws) + + Note that since 'rstrip_ws' can strip the trailing newline, the + semantics of 'readline()' must differ from those of the builtin file + object's 'readline()' method! In particular, 'readline()' returns + None for end-of-file: an empty string might just be a blank line (or + an all-whitespace line), if 'rstrip_ws' is true but 'skip_blanks' is + not.""" + + default_options = { 'strip_comments': 1, + 'skip_blanks': 1, + 'lstrip_ws': 0, + 'rstrip_ws': 1, + 'join_lines': 0, + 'collapse_join': 0, + } + + def __init__ (self, filename=None, file=None, **options): + """Construct a new TextFile object. At least one of 'filename' + (a string) and 'file' (a file-like object) must be supplied. + They keyword argument options are described above and affect + the values returned by 'readline()'.""" + + if filename is None and file is None: + raise RuntimeError, \ + "you must supply either or both of 'filename' and 'file'" + + # set values for all options -- either from client option hash + # or fallback to default_options + for opt in self.default_options.keys(): + if opt in options: + setattr (self, opt, options[opt]) + + else: + setattr (self, opt, self.default_options[opt]) + + # sanity check client option hash + for opt in options.keys(): + if opt not in self.default_options: + raise KeyError, "invalid TextFile option '%s'" % opt + + if file is None: + self.open (filename) + else: + self.filename = filename + self.file = file + self.current_line = 0 # assuming that file is at BOF! + + # 'linebuf' is a stack of lines that will be emptied before we + # actually read from the file; it's only populated by an + # 'unreadline()' operation + self.linebuf = [] + + + def open (self, filename): + """Open a new file named 'filename'. This overrides both the + 'filename' and 'file' arguments to the constructor.""" + + self.filename = filename + self.file = open (self.filename, 'r') + self.current_line = 0 + + + def close (self): + """Close the current file and forget everything we know about it + (filename, current line number).""" + + self.file.close () + self.file = None + self.filename = None + self.current_line = None + + + def gen_error (self, msg, line=None): + outmsg = [] + if line is None: + line = self.current_line + outmsg.append(self.filename + ", ") + if isinstance(line, (list, tuple)): + outmsg.append("lines %d-%d: " % tuple (line)) + else: + outmsg.append("line %d: " % line) + outmsg.append(str(msg)) + return ''.join(outmsg) + + + def error (self, msg, line=None): + raise ValueError, "error: " + self.gen_error(msg, line) + + def warn (self, msg, line=None): + """Print (to stderr) a warning message tied to the current logical + line in the current file. If the current logical line in the + file spans multiple physical lines, the warning refers to the + whole range, eg. "lines 3-5". If 'line' supplied, it overrides + the current line number; it may be a list or tuple to indicate a + range of physical lines, or an integer for a single physical + line.""" + sys.stderr.write("warning: " + self.gen_error(msg, line) + "\n") + + + def readline (self): + """Read and return a single logical line from the current file (or + from an internal buffer if lines have previously been "unread" + with 'unreadline()'). If the 'join_lines' option is true, this + may involve reading multiple physical lines concatenated into a + single string. Updates the current line number, so calling + 'warn()' after 'readline()' emits a warning about the physical + line(s) just read. Returns None on end-of-file, since the empty + string can occur if 'rstrip_ws' is true but 'strip_blanks' is + not.""" + + # If any "unread" lines waiting in 'linebuf', return the top + # one. (We don't actually buffer read-ahead data -- lines only + # get put in 'linebuf' if the client explicitly does an + # 'unreadline()'. + if self.linebuf: + line = self.linebuf[-1] + del self.linebuf[-1] + return line + + buildup_line = '' + + while 1: + # read the line, make it None if EOF + line = self.file.readline() + if line == '': line = None + + if self.strip_comments and line: + + # Look for the first "#" in the line. If none, never + # mind. If we find one and it's the first character, or + # is not preceded by "\", then it starts a comment -- + # strip the comment, strip whitespace before it, and + # carry on. Otherwise, it's just an escaped "#", so + # unescape it (and any other escaped "#"'s that might be + # lurking in there) and otherwise leave the line alone. + + pos = line.find("#") + if pos == -1: # no "#" -- no comments + pass + + # It's definitely a comment -- either "#" is the first + # character, or it's elsewhere and unescaped. + elif pos == 0 or line[pos-1] != "\\": + # Have to preserve the trailing newline, because it's + # the job of a later step (rstrip_ws) to remove it -- + # and if rstrip_ws is false, we'd better preserve it! + # (NB. this means that if the final line is all comment + # and has no trailing newline, we will think that it's + # EOF; I think that's OK.) + eol = (line[-1] == '\n') and '\n' or '' + line = line[0:pos] + eol + + # If all that's left is whitespace, then skip line + # *now*, before we try to join it to 'buildup_line' -- + # that way constructs like + # hello \\ + # # comment that should be ignored + # there + # result in "hello there". + if line.strip() == "": + continue + + else: # it's an escaped "#" + line = line.replace("\\#", "#") + + + # did previous line end with a backslash? then accumulate + if self.join_lines and buildup_line: + # oops: end of file + if line is None: + self.warn ("continuation line immediately precedes " + "end-of-file") + return buildup_line + + if self.collapse_join: + line = line.lstrip() + line = buildup_line + line + + # careful: pay attention to line number when incrementing it + if isinstance(self.current_line, list): + self.current_line[1] = self.current_line[1] + 1 + else: + self.current_line = [self.current_line, + self.current_line+1] + # just an ordinary line, read it as usual + else: + if line is None: # eof + return None + + # still have to be careful about incrementing the line number! + if isinstance(self.current_line, list): + self.current_line = self.current_line[1] + 1 + else: + self.current_line = self.current_line + 1 + + + # strip whitespace however the client wants (leading and + # trailing, or one or the other, or neither) + if self.lstrip_ws and self.rstrip_ws: + line = line.strip() + elif self.lstrip_ws: + line = line.lstrip() + elif self.rstrip_ws: + line = line.rstrip() + + # blank line (whether we rstrip'ed or not)? skip to next line + # if appropriate + if (line == '' or line == '\n') and self.skip_blanks: + continue + + if self.join_lines: + if line[-1] == '\\': + buildup_line = line[:-1] + continue + + if line[-2:] == '\\\n': + buildup_line = line[0:-2] + '\n' + continue + + # well, I guess there's some actual content there: return it + return line + + # readline () + + + def readlines (self): + """Read and return the list of all logical lines remaining in the + current file.""" + + lines = [] + while 1: + line = self.readline() + if line is None: + return lines + lines.append (line) + + + def unreadline (self, line): + """Push 'line' (a string) onto an internal buffer that will be + checked by future 'readline()' calls. Handy for implementing + a parser with line-at-a-time lookahead.""" + + self.linebuf.append (line) diff --git a/PythonHome/Lib/distutils/text_file.pyc b/PythonHome/Lib/distutils/text_file.pyc deleted file mode 100644 index 2703891965173ba2b4f41742325e601acf72d6c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9079 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 z

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 "5": # SunOS 5 == Solaris 2 + osname = "solaris" + release = "%d.%s" % (int(release[0]) - 3, release[2:]) + # We can't use "platform.architecture()[0]" because a + # bootstrap problem. We use a dict to get an error + # if some suspicious happens. + bitness = {2147483647:"32bit", 9223372036854775807:"64bit"} + machine += ".%s" % bitness[sys.maxint] + # fall through to standard osname-release-machine representation + elif osname[:4] == "irix": # could be "irix64"! + return "%s-%s" % (osname, release) + elif osname[:3] == "aix": + return "%s-%s.%s" % (osname, version, release) + elif osname[:6] == "cygwin": + osname = "cygwin" + rel_re = re.compile (r'[\d.]+') + m = rel_re.match(release) + if m: + release = m.group() + elif osname[:6] == "darwin": + import _osx_support, distutils.sysconfig + osname, release, machine = _osx_support.get_platform_osx( + distutils.sysconfig.get_config_vars(), + osname, release, machine) + + return "%s-%s-%s" % (osname, release, machine) + +# get_platform () + + +def convert_path (pathname): + """Return 'pathname' as a name that will work on the native filesystem, + i.e. split it on '/' and put it back together again using the current + directory separator. Needed because filenames in the setup script are + always supplied in Unix style, and have to be converted to the local + convention before we can actually use them in the filesystem. Raises + ValueError on non-Unix-ish systems if 'pathname' either starts or + ends with a slash. + """ + if os.sep == '/': + return pathname + if not pathname: + return pathname + if pathname[0] == '/': + raise ValueError, "path '%s' cannot be absolute" % pathname + if pathname[-1] == '/': + raise ValueError, "path '%s' cannot end with '/'" % pathname + + paths = string.split(pathname, '/') + while '.' in paths: + paths.remove('.') + if not paths: + return os.curdir + return os.path.join(*paths) + +# convert_path () + + +def change_root (new_root, pathname): + """Return 'pathname' with 'new_root' prepended. If 'pathname' is + relative, this is equivalent to "os.path.join(new_root,pathname)". + Otherwise, it requires making 'pathname' relative and then joining the + two, which is tricky on DOS/Windows and Mac OS. + """ + if os.name == 'posix': + if not os.path.isabs(pathname): + return os.path.join(new_root, pathname) + else: + return os.path.join(new_root, pathname[1:]) + + elif os.name == 'nt': + (drive, path) = os.path.splitdrive(pathname) + if path[0] == '\\': + path = path[1:] + return os.path.join(new_root, path) + + elif os.name == 'os2': + (drive, path) = os.path.splitdrive(pathname) + if path[0] == os.sep: + path = path[1:] + return os.path.join(new_root, path) + + else: + raise DistutilsPlatformError, \ + "nothing known about platform '%s'" % os.name + + +_environ_checked = 0 +def check_environ (): + """Ensure that 'os.environ' has all the environment variables we + guarantee that users can use in config files, command-line options, + etc. Currently this includes: + HOME - user's home directory (Unix only) + PLAT - description of the current platform, including hardware + and OS (see 'get_platform()') + """ + global _environ_checked + if _environ_checked: + return + + if os.name == 'posix' and 'HOME' not in os.environ: + import pwd + os.environ['HOME'] = pwd.getpwuid(os.getuid())[5] + + if 'PLAT' not in os.environ: + os.environ['PLAT'] = get_platform() + + _environ_checked = 1 + + +def subst_vars (s, local_vars): + """Perform shell/Perl-style variable substitution on 'string'. Every + occurrence of '$' followed by a name is considered a variable, and + variable is substituted by the value found in the 'local_vars' + dictionary, or in 'os.environ' if it's not in 'local_vars'. + 'os.environ' is first checked/augmented to guarantee that it contains + certain values: see 'check_environ()'. Raise ValueError for any + variables not found in either 'local_vars' or 'os.environ'. + """ + check_environ() + def _subst (match, local_vars=local_vars): + var_name = match.group(1) + if var_name in local_vars: + return str(local_vars[var_name]) + else: + return os.environ[var_name] + + try: + return re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, s) + except KeyError, var: + raise ValueError, "invalid variable '$%s'" % var + +# subst_vars () + + +def grok_environment_error (exc, prefix="error: "): + # Function kept for backward compatibility. + # Used to try clever things with EnvironmentErrors, + # but nowadays str(exception) produces good messages. + return prefix + str(exc) + + +# Needed by 'split_quoted()' +_wordchars_re = _squote_re = _dquote_re = None +def _init_regex(): + global _wordchars_re, _squote_re, _dquote_re + _wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace) + _squote_re = re.compile(r"'(?:[^'\\]|\\.)*'") + _dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"') + +def split_quoted (s): + """Split a string up according to Unix shell-like rules for quotes and + backslashes. In short: words are delimited by spaces, as long as those + spaces are not escaped by a backslash, or inside a quoted string. + Single and double quotes are equivalent, and the quote characters can + be backslash-escaped. The backslash is stripped from any two-character + escape sequence, leaving only the escaped character. The quote + characters are stripped from any quoted string. Returns a list of + words. + """ + + # This is a nice algorithm for splitting up a single string, since it + # doesn't require character-by-character examination. It was a little + # bit of a brain-bender to get it working right, though... + if _wordchars_re is None: _init_regex() + + s = string.strip(s) + words = [] + pos = 0 + + while s: + m = _wordchars_re.match(s, pos) + end = m.end() + if end == len(s): + words.append(s[:end]) + break + + if s[end] in string.whitespace: # unescaped, unquoted whitespace: now + words.append(s[:end]) # we definitely have a word delimiter + s = string.lstrip(s[end:]) + pos = 0 + + elif s[end] == '\\': # preserve whatever is being escaped; + # will become part of the current word + s = s[:end] + s[end+1:] + pos = end+1 + + else: + if s[end] == "'": # slurp singly-quoted string + m = _squote_re.match(s, end) + elif s[end] == '"': # slurp doubly-quoted string + m = _dquote_re.match(s, end) + else: + raise RuntimeError, \ + "this can't happen (bad char '%c')" % s[end] + + if m is None: + raise ValueError, \ + "bad string (mismatched %s quotes?)" % s[end] + + (beg, end) = m.span() + s = s[:beg] + s[beg+1:end-1] + s[end:] + pos = m.end() - 2 + + if pos >= len(s): + words.append(s) + break + + return words + +# split_quoted () + + +def execute (func, args, msg=None, verbose=0, dry_run=0): + """Perform some action that affects the outside world (eg. by + writing to the filesystem). Such actions are special because they + are disabled by the 'dry_run' flag. This method takes care of all + that bureaucracy for you; all you have to do is supply the + function to call and an argument tuple for it (to embody the + "external action" being performed), and an optional message to + print. + """ + if msg is None: + msg = "%s%r" % (func.__name__, args) + if msg[-2:] == ',)': # correct for singleton tuple + msg = msg[0:-2] + ')' + + log.info(msg) + if not dry_run: + func(*args) + + +def strtobool (val): + """Convert a string representation of truth to true (1) or false (0). + + True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values + are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if + 'val' is anything else. + """ + val = string.lower(val) + if val in ('y', 'yes', 't', 'true', 'on', '1'): + return 1 + elif val in ('n', 'no', 'f', 'false', 'off', '0'): + return 0 + else: + raise ValueError, "invalid truth value %r" % (val,) + + +def byte_compile (py_files, + optimize=0, force=0, + prefix=None, base_dir=None, + verbose=1, dry_run=0, + direct=None): + """Byte-compile a collection of Python source files to either .pyc + or .pyo files in the same directory. 'py_files' is a list of files + to compile; any files that don't end in ".py" are silently skipped. + 'optimize' must be one of the following: + 0 - don't optimize (generate .pyc) + 1 - normal optimization (like "python -O") + 2 - extra optimization (like "python -OO") + If 'force' is true, all files are recompiled regardless of + timestamps. + + The source filename encoded in each bytecode file defaults to the + filenames listed in 'py_files'; you can modify these with 'prefix' and + 'basedir'. 'prefix' is a string that will be stripped off of each + source filename, and 'base_dir' is a directory name that will be + prepended (after 'prefix' is stripped). You can supply either or both + (or neither) of 'prefix' and 'base_dir', as you wish. + + If 'dry_run' is true, doesn't actually do anything that would + affect the filesystem. + + Byte-compilation is either done directly in this interpreter process + with the standard py_compile module, or indirectly by writing a + temporary script and executing it. Normally, you should let + 'byte_compile()' figure out to use direct compilation or not (see + the source for details). The 'direct' flag is used by the script + generated in indirect mode; unless you know what you're doing, leave + it set to None. + """ + # nothing is done if sys.dont_write_bytecode is True + if sys.dont_write_bytecode: + raise DistutilsByteCompileError('byte-compiling is disabled.') + + # First, if the caller didn't force us into direct or indirect mode, + # figure out which mode we should be in. We take a conservative + # approach: choose direct mode *only* if the current interpreter is + # in debug mode and optimize is 0. If we're not in debug mode (-O + # or -OO), we don't know which level of optimization this + # interpreter is running with, so we can't do direct + # byte-compilation and be certain that it's the right thing. Thus, + # always compile indirectly if the current interpreter is in either + # optimize mode, or if either optimization level was requested by + # the caller. + if direct is None: + direct = (__debug__ and optimize == 0) + + # "Indirect" byte-compilation: write a temporary script and then + # run it with the appropriate flags. + if not direct: + try: + from tempfile import mkstemp + (script_fd, script_name) = mkstemp(".py") + except ImportError: + from tempfile import mktemp + (script_fd, script_name) = None, mktemp(".py") + log.info("writing byte-compilation script '%s'", script_name) + if not dry_run: + if script_fd is not None: + script = os.fdopen(script_fd, "w") + else: + script = open(script_name, "w") + + script.write("""\ +from distutils.util import byte_compile +files = [ +""") + + # XXX would be nice to write absolute filenames, just for + # safety's sake (script should be more robust in the face of + # chdir'ing before running it). But this requires abspath'ing + # 'prefix' as well, and that breaks the hack in build_lib's + # 'byte_compile()' method that carefully tacks on a trailing + # slash (os.sep really) to make sure the prefix here is "just + # right". This whole prefix business is rather delicate -- the + # problem is that it's really a directory, but I'm treating it + # as a dumb string, so trailing slashes and so forth matter. + + #py_files = map(os.path.abspath, py_files) + #if prefix: + # prefix = os.path.abspath(prefix) + + script.write(string.join(map(repr, py_files), ",\n") + "]\n") + script.write(""" +byte_compile(files, optimize=%r, force=%r, + prefix=%r, base_dir=%r, + verbose=%r, dry_run=0, + direct=1) +""" % (optimize, force, prefix, base_dir, verbose)) + + script.close() + + cmd = [sys.executable, script_name] + if optimize == 1: + cmd.insert(1, "-O") + elif optimize == 2: + cmd.insert(1, "-OO") + spawn(cmd, dry_run=dry_run) + execute(os.remove, (script_name,), "removing %s" % script_name, + dry_run=dry_run) + + # "Direct" byte-compilation: use the py_compile module to compile + # right here, right now. Note that the script generated in indirect + # mode simply calls 'byte_compile()' in direct mode, a weird sort of + # cross-process recursion. Hey, it works! + else: + from py_compile import compile + + for file in py_files: + if file[-3:] != ".py": + # This lets us be lazy and not filter filenames in + # the "install_lib" command. + continue + + # Terminology from the py_compile module: + # cfile - byte-compiled file + # dfile - purported source filename (same as 'file' by default) + cfile = file + (__debug__ and "c" or "o") + dfile = file + if prefix: + if file[:len(prefix)] != prefix: + raise ValueError, \ + ("invalid prefix: filename %r doesn't start with %r" + % (file, prefix)) + dfile = dfile[len(prefix):] + if base_dir: + dfile = os.path.join(base_dir, dfile) + + cfile_base = os.path.basename(cfile) + if direct: + if force or newer(file, cfile): + log.info("byte-compiling %s to %s", file, cfile_base) + if not dry_run: + compile(file, cfile, dfile) + else: + log.debug("skipping byte-compilation of %s to %s", + file, cfile_base) + +# byte_compile () + +def rfc822_escape (header): + """Return a version of the string escaped for inclusion in an + RFC-822 header, by ensuring there are 8 spaces space after each newline. + """ + lines = string.split(header, '\n') + header = string.join(lines, '\n' + 8*' ') + return header diff --git a/PythonHome/Lib/distutils/util.pyc b/PythonHome/Lib/distutils/util.pyc deleted file mode 100644 index 1088e8c1cbccd0e79e2468392a451fcf4fe57e57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14295 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 F{~I23=u!Xx diff --git a/PythonHome/Lib/distutils/version.py b/PythonHome/Lib/distutils/version.py new file mode 100644 index 0000000000..0fb5b6e204 --- /dev/null +++ b/PythonHome/Lib/distutils/version.py @@ -0,0 +1,299 @@ +# +# distutils/version.py +# +# Implements multiple version numbering conventions for the +# Python Module Distribution Utilities. +# +# $Id$ +# + +"""Provides classes to represent module version numbers (one class for +each style of version numbering). There are currently two such classes +implemented: StrictVersion and LooseVersion. + +Every version number class implements the following interface: + * the 'parse' method takes a string and parses it to some internal + representation; if the string is an invalid version number, + 'parse' raises a ValueError exception + * the class constructor takes an optional string argument which, + if supplied, is passed to 'parse' + * __str__ reconstructs the string that was passed to 'parse' (or + an equivalent string -- ie. one that will generate an equivalent + version number instance) + * __repr__ generates Python code to recreate the version number instance + * __cmp__ compares the current instance with either another instance + of the same class or a string (which will be parsed to an instance + of the same class, thus must follow the same rules) +""" + +import string, re +from types import StringType + +class Version: + """Abstract base class for version numbering classes. Just provides + constructor (__init__) and reproducer (__repr__), because those + seem to be the same for all version numbering classes. + """ + + def __init__ (self, vstring=None): + if vstring: + self.parse(vstring) + + def __repr__ (self): + return "%s ('%s')" % (self.__class__.__name__, str(self)) + + +# Interface for version-number classes -- must be implemented +# by the following classes (the concrete ones -- Version should +# be treated as an abstract class). +# __init__ (string) - create and take same action as 'parse' +# (string parameter is optional) +# parse (string) - convert a string representation to whatever +# internal representation is appropriate for +# this style of version numbering +# __str__ (self) - convert back to a string; should be very similar +# (if not identical to) the string supplied to parse +# __repr__ (self) - generate Python code to recreate +# the instance +# __cmp__ (self, other) - compare two version numbers ('other' may +# be an unparsed version string, or another +# instance of your version class) + + +class StrictVersion (Version): + + """Version numbering for anal retentives and software idealists. + Implements the standard interface for version number classes as + described above. A version number consists of two or three + dot-separated numeric components, with an optional "pre-release" tag + on the end. The pre-release tag consists of the letter 'a' or 'b' + followed by a number. If the numeric components of two version + numbers are equal, then one with a pre-release tag will always + be deemed earlier (lesser) than one without. + + The following are valid version numbers (shown in the order that + would be obtained by sorting according to the supplied cmp function): + + 0.4 0.4.0 (these two are equivalent) + 0.4.1 + 0.5a1 + 0.5b3 + 0.5 + 0.9.6 + 1.0 + 1.0.4a3 + 1.0.4b1 + 1.0.4 + + The following are examples of invalid version numbers: + + 1 + 2.7.2.2 + 1.3.a4 + 1.3pl1 + 1.3c4 + + The rationale for this version numbering system will be explained + in the distutils documentation. + """ + + version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$', + re.VERBOSE) + + + def parse (self, vstring): + match = self.version_re.match(vstring) + if not match: + raise ValueError, "invalid version number '%s'" % vstring + + (major, minor, patch, prerelease, prerelease_num) = \ + match.group(1, 2, 4, 5, 6) + + if patch: + self.version = tuple(map(string.atoi, [major, minor, patch])) + else: + self.version = tuple(map(string.atoi, [major, minor]) + [0]) + + if prerelease: + self.prerelease = (prerelease[0], string.atoi(prerelease_num)) + else: + self.prerelease = None + + + def __str__ (self): + + if self.version[2] == 0: + vstring = string.join(map(str, self.version[0:2]), '.') + else: + vstring = string.join(map(str, self.version), '.') + + if self.prerelease: + vstring = vstring + self.prerelease[0] + str(self.prerelease[1]) + + return vstring + + + def __cmp__ (self, other): + if isinstance(other, StringType): + other = StrictVersion(other) + + compare = cmp(self.version, other.version) + if (compare == 0): # have to compare prerelease + + # case 1: neither has prerelease; they're equal + # case 2: self has prerelease, other doesn't; other is greater + # case 3: self doesn't have prerelease, other does: self is greater + # case 4: both have prerelease: must compare them! + + if (not self.prerelease and not other.prerelease): + return 0 + elif (self.prerelease and not other.prerelease): + return -1 + elif (not self.prerelease and other.prerelease): + return 1 + elif (self.prerelease and other.prerelease): + return cmp(self.prerelease, other.prerelease) + + else: # numeric versions don't match -- + return compare # prerelease stuff doesn't matter + + +# end class StrictVersion + + +# The rules according to Greg Stein: +# 1) a version number has 1 or more numbers separated by a period or by +# sequences of letters. If only periods, then these are compared +# left-to-right to determine an ordering. +# 2) sequences of letters are part of the tuple for comparison and are +# compared lexicographically +# 3) recognize the numeric components may have leading zeroes +# +# The LooseVersion class below implements these rules: a version number +# string is split up into a tuple of integer and string components, and +# comparison is a simple tuple comparison. This means that version +# numbers behave in a predictable and obvious way, but a way that might +# not necessarily be how people *want* version numbers to behave. There +# wouldn't be a problem if people could stick to purely numeric version +# numbers: just split on period and compare the numbers as tuples. +# However, people insist on putting letters into their version numbers; +# the most common purpose seems to be: +# - indicating a "pre-release" version +# ('alpha', 'beta', 'a', 'b', 'pre', 'p') +# - indicating a post-release patch ('p', 'pl', 'patch') +# but of course this can't cover all version number schemes, and there's +# no way to know what a programmer means without asking him. +# +# The problem is what to do with letters (and other non-numeric +# characters) in a version number. The current implementation does the +# obvious and predictable thing: keep them as strings and compare +# lexically within a tuple comparison. This has the desired effect if +# an appended letter sequence implies something "post-release": +# eg. "0.99" < "0.99pl14" < "1.0", and "5.001" < "5.001m" < "5.002". +# +# However, if letters in a version number imply a pre-release version, +# the "obvious" thing isn't correct. Eg. you would expect that +# "1.5.1" < "1.5.2a2" < "1.5.2", but under the tuple/lexical comparison +# implemented here, this just isn't so. +# +# Two possible solutions come to mind. The first is to tie the +# comparison algorithm to a particular set of semantic rules, as has +# been done in the StrictVersion class above. This works great as long +# as everyone can go along with bondage and discipline. Hopefully a +# (large) subset of Python module programmers will agree that the +# particular flavour of bondage and discipline provided by StrictVersion +# provides enough benefit to be worth using, and will submit their +# version numbering scheme to its domination. The free-thinking +# anarchists in the lot will never give in, though, and something needs +# to be done to accommodate them. +# +# Perhaps a "moderately strict" version class could be implemented that +# lets almost anything slide (syntactically), and makes some heuristic +# assumptions about non-digits in version number strings. This could +# sink into special-case-hell, though; if I was as talented and +# idiosyncratic as Larry Wall, I'd go ahead and implement a class that +# somehow knows that "1.2.1" < "1.2.2a2" < "1.2.2" < "1.2.2pl3", and is +# just as happy dealing with things like "2g6" and "1.13++". I don't +# think I'm smart enough to do it right though. +# +# In any case, I've coded the test suite for this module (see +# ../test/test_version.py) specifically to fail on things like comparing +# "1.2a2" and "1.2". That's not because the *code* is doing anything +# wrong, it's because the simple, obvious design doesn't match my +# complicated, hairy expectations for real-world version numbers. It +# would be a snap to fix the test suite to say, "Yep, LooseVersion does +# the Right Thing" (ie. the code matches the conception). But I'd rather +# have a conception that matches common notions about version numbers. + +class LooseVersion (Version): + + """Version numbering for anarchists and software realists. + Implements the standard interface for version number classes as + described above. A version number consists of a series of numbers, + separated by either periods or strings of letters. When comparing + version numbers, the numeric components will be compared + numerically, and the alphabetic components lexically. The following + are all valid version numbers, in no particular order: + + 1.5.1 + 1.5.2b2 + 161 + 3.10a + 8.02 + 3.4j + 1996.07.12 + 3.2.pl0 + 3.1.1.6 + 2g6 + 11g + 0.960923 + 2.2beta29 + 1.13++ + 5.5.kw + 2.0b1pl0 + + In fact, there is no such thing as an invalid version number under + this scheme; the rules for comparison are simple and predictable, + but may not always give the results you want (for some definition + of "want"). + """ + + component_re = re.compile(r'(\d+ | [a-z]+ | \.)', re.VERBOSE) + + def __init__ (self, vstring=None): + if vstring: + self.parse(vstring) + + + def parse (self, vstring): + # I've given up on thinking I can reconstruct the version string + # from the parsed tuple -- so I just store the string here for + # use by __str__ + self.vstring = vstring + components = filter(lambda x: x and x != '.', + self.component_re.split(vstring)) + for i in range(len(components)): + try: + components[i] = int(components[i]) + except ValueError: + pass + + self.version = components + + + def __str__ (self): + return self.vstring + + + def __repr__ (self): + return "LooseVersion ('%s')" % str(self) + + + def __cmp__ (self, other): + if isinstance(other, StringType): + other = LooseVersion(other) + + return cmp(self.version, other.version) + + +# end class LooseVersion diff --git a/PythonHome/Lib/distutils/version.pyc b/PythonHome/Lib/distutils/version.pyc deleted file mode 100644 index 9c99d4561b02d0a17e73d8aeb99bf798953d7282..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7133 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 diff --git a/PythonHome/Lib/distutils/versionpredicate.py b/PythonHome/Lib/distutils/versionpredicate.py new file mode 100644 index 0000000000..ba8b6c021b --- /dev/null +++ b/PythonHome/Lib/distutils/versionpredicate.py @@ -0,0 +1,164 @@ +"""Module for parsing and testing package version predicate strings. +""" +import re +import distutils.version +import operator + + +re_validPackage = re.compile(r"(?i)^\s*([a-z_]\w*(?:\.[a-z_]\w*)*)(.*)") +# (package) (rest) + +re_paren = re.compile(r"^\s*\((.*)\)\s*$") # (list) inside of parentheses +re_splitComparison = re.compile(r"^\s*(<=|>=|<|>|!=|==)\s*([^\s,]+)\s*$") +# (comp) (version) + + +def splitUp(pred): + """Parse a single version comparison. + + Return (comparison string, StrictVersion) + """ + res = re_splitComparison.match(pred) + if not res: + raise ValueError("bad package restriction syntax: %r" % pred) + comp, verStr = res.groups() + return (comp, distutils.version.StrictVersion(verStr)) + +compmap = {"<": operator.lt, "<=": operator.le, "==": operator.eq, + ">": operator.gt, ">=": operator.ge, "!=": operator.ne} + +class VersionPredicate: + """Parse and test package version predicates. + + >>> v = VersionPredicate('pyepat.abc (>1.0, <3333.3a1, !=1555.1b3)') + + The `name` attribute provides the full dotted name that is given:: + + >>> v.name + 'pyepat.abc' + + The str() of a `VersionPredicate` provides a normalized + human-readable version of the expression:: + + >>> print v + pyepat.abc (> 1.0, < 3333.3a1, != 1555.1b3) + + The `satisfied_by()` method can be used to determine with a given + version number is included in the set described by the version + restrictions:: + + >>> v.satisfied_by('1.1') + True + >>> v.satisfied_by('1.4') + True + >>> v.satisfied_by('1.0') + False + >>> v.satisfied_by('4444.4') + False + >>> v.satisfied_by('1555.1b3') + False + + `VersionPredicate` is flexible in accepting extra whitespace:: + + >>> v = VersionPredicate(' pat( == 0.1 ) ') + >>> v.name + 'pat' + >>> v.satisfied_by('0.1') + True + >>> v.satisfied_by('0.2') + False + + If any version numbers passed in do not conform to the + restrictions of `StrictVersion`, a `ValueError` is raised:: + + >>> v = VersionPredicate('p1.p2.p3.p4(>=1.0, <=1.3a1, !=1.2zb3)') + Traceback (most recent call last): + ... + ValueError: invalid version number '1.2zb3' + + It the module or package name given does not conform to what's + allowed as a legal module or package name, `ValueError` is + raised:: + + >>> v = VersionPredicate('foo-bar') + Traceback (most recent call last): + ... + ValueError: expected parenthesized list: '-bar' + + >>> v = VersionPredicate('foo bar (12.21)') + Traceback (most recent call last): + ... + ValueError: expected parenthesized list: 'bar (12.21)' + + """ + + def __init__(self, versionPredicateStr): + """Parse a version predicate string. + """ + # Fields: + # name: package name + # pred: list of (comparison string, StrictVersion) + + versionPredicateStr = versionPredicateStr.strip() + if not versionPredicateStr: + raise ValueError("empty package restriction") + match = re_validPackage.match(versionPredicateStr) + if not match: + raise ValueError("bad package name in %r" % versionPredicateStr) + self.name, paren = match.groups() + paren = paren.strip() + if paren: + match = re_paren.match(paren) + if not match: + raise ValueError("expected parenthesized list: %r" % paren) + str = match.groups()[0] + self.pred = [splitUp(aPred) for aPred in str.split(",")] + if not self.pred: + raise ValueError("empty parenthesized list in %r" + % versionPredicateStr) + else: + self.pred = [] + + def __str__(self): + if self.pred: + seq = [cond + " " + str(ver) for cond, ver in self.pred] + return self.name + " (" + ", ".join(seq) + ")" + else: + return self.name + + def satisfied_by(self, version): + """True if version is compatible with all the predicates in self. + The parameter version must be acceptable to the StrictVersion + constructor. It may be either a string or StrictVersion. + """ + for cond, ver in self.pred: + if not compmap[cond](version, ver): + return False + return True + + +_provision_rx = None + +def split_provision(value): + """Return the name and optional version number of a provision. + + The version number, if given, will be returned as a `StrictVersion` + instance, otherwise it will be `None`. + + >>> split_provision('mypkg') + ('mypkg', None) + >>> split_provision(' mypkg( 1.2 ) ') + ('mypkg', StrictVersion ('1.2')) + """ + global _provision_rx + if _provision_rx is None: + _provision_rx = re.compile( + "([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)(?:\s*\(\s*([^)\s]+)\s*\))?$") + value = value.strip() + m = _provision_rx.match(value) + if not m: + raise ValueError("illegal provides specification: %r" % value) + ver = m.group(2) or None + if ver: + ver = distutils.version.StrictVersion(ver) + return m.group(1), ver diff --git a/PythonHome/Lib/distutils/versionpredicate.pyc b/PythonHome/Lib/distutils/versionpredicate.pyc deleted file mode 100644 index 5e3040a33e102230926ea5c98f36a44d200ca7d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5437 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 Xxn<9d&5t2rkI!6Ksw`C((#h(NiyuvN diff --git a/PythonHome/Lib/doctest.py b/PythonHome/Lib/doctest.py new file mode 100644 index 0000000000..86c9839b2a --- /dev/null +++ b/PythonHome/Lib/doctest.py @@ -0,0 +1,2817 @@ +# Module doctest. +# Released to the public domain 16-Jan-2001, by Tim Peters (tim@python.org). +# Major enhancements and refactoring by: +# Jim Fulton +# Edward Loper + +# Provided as-is; use at your own risk; no warranty; no promises; enjoy! + +r"""Module doctest -- a framework for running examples in docstrings. + +In simplest use, end each module M to be tested with: + +def _test(): + import doctest + doctest.testmod() + +if __name__ == "__main__": + _test() + +Then running the module as a script will cause the examples in the +docstrings to get executed and verified: + +python M.py + +This won't display anything unless an example fails, in which case the +failing example(s) and the cause(s) of the failure(s) are printed to stdout +(why not stderr? because stderr is a lame hack <0.2 wink>), and the final +line of output is "Test failed.". + +Run it with the -v switch instead: + +python M.py -v + +and a detailed report of all examples tried is printed to stdout, along +with assorted summaries at the end. + +You can force verbose mode by passing "verbose=True" to testmod, or prohibit +it by passing "verbose=False". In either of those cases, sys.argv is not +examined by testmod. + +There are a variety of other ways to run doctests, including integration +with the unittest framework, and support for running non-Python text +files containing doctests. There are also many ways to override parts +of doctest's default behaviors. See the Library Reference Manual for +details. +""" + +__docformat__ = 'reStructuredText en' + +__all__ = [ + # 0, Option Flags + 'register_optionflag', + 'DONT_ACCEPT_TRUE_FOR_1', + 'DONT_ACCEPT_BLANKLINE', + 'NORMALIZE_WHITESPACE', + 'ELLIPSIS', + 'SKIP', + 'IGNORE_EXCEPTION_DETAIL', + 'COMPARISON_FLAGS', + 'REPORT_UDIFF', + 'REPORT_CDIFF', + 'REPORT_NDIFF', + 'REPORT_ONLY_FIRST_FAILURE', + 'REPORTING_FLAGS', + # 1. Utility Functions + # 2. Example & DocTest + 'Example', + 'DocTest', + # 3. Doctest Parser + 'DocTestParser', + # 4. Doctest Finder + 'DocTestFinder', + # 5. Doctest Runner + 'DocTestRunner', + 'OutputChecker', + 'DocTestFailure', + 'UnexpectedException', + 'DebugRunner', + # 6. Test Functions + 'testmod', + 'testfile', + 'run_docstring_examples', + # 7. Tester + 'Tester', + # 8. Unittest Support + 'DocTestSuite', + 'DocFileSuite', + 'set_unittest_reportflags', + # 9. Debugging Support + 'script_from_examples', + 'testsource', + 'debug_src', + 'debug', +] + +import __future__ + +import sys, traceback, inspect, linecache, os, re +import unittest, difflib, pdb, tempfile +import warnings +from StringIO import StringIO +from collections import namedtuple + +TestResults = namedtuple('TestResults', 'failed attempted') + +# There are 4 basic classes: +# - Example: a pair, plus an intra-docstring line number. +# - DocTest: a collection of examples, parsed from a docstring, plus +# info about where the docstring came from (name, filename, lineno). +# - DocTestFinder: extracts DocTests from a given object's docstring and +# its contained objects' docstrings. +# - DocTestRunner: runs DocTest cases, and accumulates statistics. +# +# So the basic picture is: +# +# list of: +# +------+ +---------+ +-------+ +# |object| --DocTestFinder-> | DocTest | --DocTestRunner-> |results| +# +------+ +---------+ +-------+ +# | Example | +# | ... | +# | Example | +# +---------+ + +# Option constants. + +OPTIONFLAGS_BY_NAME = {} +def register_optionflag(name): + # Create a new flag unless `name` is already known. + return OPTIONFLAGS_BY_NAME.setdefault(name, 1 << len(OPTIONFLAGS_BY_NAME)) + +DONT_ACCEPT_TRUE_FOR_1 = register_optionflag('DONT_ACCEPT_TRUE_FOR_1') +DONT_ACCEPT_BLANKLINE = register_optionflag('DONT_ACCEPT_BLANKLINE') +NORMALIZE_WHITESPACE = register_optionflag('NORMALIZE_WHITESPACE') +ELLIPSIS = register_optionflag('ELLIPSIS') +SKIP = register_optionflag('SKIP') +IGNORE_EXCEPTION_DETAIL = register_optionflag('IGNORE_EXCEPTION_DETAIL') + +COMPARISON_FLAGS = (DONT_ACCEPT_TRUE_FOR_1 | + DONT_ACCEPT_BLANKLINE | + NORMALIZE_WHITESPACE | + ELLIPSIS | + SKIP | + IGNORE_EXCEPTION_DETAIL) + +REPORT_UDIFF = register_optionflag('REPORT_UDIFF') +REPORT_CDIFF = register_optionflag('REPORT_CDIFF') +REPORT_NDIFF = register_optionflag('REPORT_NDIFF') +REPORT_ONLY_FIRST_FAILURE = register_optionflag('REPORT_ONLY_FIRST_FAILURE') + +REPORTING_FLAGS = (REPORT_UDIFF | + REPORT_CDIFF | + REPORT_NDIFF | + REPORT_ONLY_FIRST_FAILURE) + +# Special string markers for use in `want` strings: +BLANKLINE_MARKER = '' +ELLIPSIS_MARKER = '...' + +###################################################################### +## Table of Contents +###################################################################### +# 1. Utility Functions +# 2. Example & DocTest -- store test cases +# 3. DocTest Parser -- extracts examples from strings +# 4. DocTest Finder -- extracts test cases from objects +# 5. DocTest Runner -- runs test cases +# 6. Test Functions -- convenient wrappers for testing +# 7. Tester Class -- for backwards compatibility +# 8. Unittest Support +# 9. Debugging Support +# 10. Example Usage + +###################################################################### +## 1. Utility Functions +###################################################################### + +def _extract_future_flags(globs): + """ + Return the compiler-flags associated with the future features that + have been imported into the given namespace (globs). + """ + flags = 0 + for fname in __future__.all_feature_names: + feature = globs.get(fname, None) + if feature is getattr(__future__, fname): + flags |= feature.compiler_flag + return flags + +def _normalize_module(module, depth=2): + """ + Return the module specified by `module`. In particular: + - If `module` is a module, then return module. + - If `module` is a string, then import and return the + module with that name. + - If `module` is None, then return the calling module. + The calling module is assumed to be the module of + the stack frame at the given depth in the call stack. + """ + if inspect.ismodule(module): + return module + elif isinstance(module, (str, unicode)): + return __import__(module, globals(), locals(), ["*"]) + elif module is None: + return sys.modules[sys._getframe(depth).f_globals['__name__']] + else: + raise TypeError("Expected a module, string, or None") + +def _load_testfile(filename, package, module_relative): + if module_relative: + package = _normalize_module(package, 3) + filename = _module_relative_path(package, filename) + if hasattr(package, '__loader__'): + if hasattr(package.__loader__, 'get_data'): + file_contents = package.__loader__.get_data(filename) + # get_data() opens files as 'rb', so one must do the equivalent + # conversion as universal newlines would do. + return file_contents.replace(os.linesep, '\n'), filename + with open(filename) as f: + return f.read(), filename + +# Use sys.stdout encoding for ouput. +_encoding = getattr(sys.__stdout__, 'encoding', None) or 'utf-8' + +def _indent(s, indent=4): + """ + Add the given number of space characters to the beginning of + every non-blank line in `s`, and return the result. + If the string `s` is Unicode, it is encoded using the stdout + encoding and the `backslashreplace` error handler. + """ + if isinstance(s, unicode): + s = s.encode(_encoding, 'backslashreplace') + # This regexp matches the start of non-blank lines: + return re.sub('(?m)^(?!$)', indent*' ', s) + +def _exception_traceback(exc_info): + """ + Return a string containing a traceback message for the given + exc_info tuple (as returned by sys.exc_info()). + """ + # Get a traceback message. + excout = StringIO() + exc_type, exc_val, exc_tb = exc_info + traceback.print_exception(exc_type, exc_val, exc_tb, file=excout) + return excout.getvalue() + +# Override some StringIO methods. +class _SpoofOut(StringIO): + def getvalue(self): + result = StringIO.getvalue(self) + # If anything at all was written, make sure there's a trailing + # newline. There's no way for the expected output to indicate + # that a trailing newline is missing. + if result and not result.endswith("\n"): + result += "\n" + # Prevent softspace from screwing up the next test case, in + # case they used print with a trailing comma in an example. + if hasattr(self, "softspace"): + del self.softspace + return result + + def truncate(self, size=None): + StringIO.truncate(self, size) + if hasattr(self, "softspace"): + del self.softspace + if not self.buf: + # Reset it to an empty string, to make sure it's not unicode. + self.buf = '' + +# Worst-case linear-time ellipsis matching. +def _ellipsis_match(want, got): + """ + Essentially the only subtle case: + >>> _ellipsis_match('aa...aa', 'aaa') + False + """ + if ELLIPSIS_MARKER not in want: + return want == got + + # Find "the real" strings. + ws = want.split(ELLIPSIS_MARKER) + assert len(ws) >= 2 + + # Deal with exact matches possibly needed at one or both ends. + startpos, endpos = 0, len(got) + w = ws[0] + if w: # starts with exact match + if got.startswith(w): + startpos = len(w) + del ws[0] + else: + return False + w = ws[-1] + if w: # ends with exact match + if got.endswith(w): + endpos -= len(w) + del ws[-1] + else: + return False + + if startpos > endpos: + # Exact end matches required more characters than we have, as in + # _ellipsis_match('aa...aa', 'aaa') + return False + + # For the rest, we only need to find the leftmost non-overlapping + # match for each piece. If there's no overall match that way alone, + # there's no overall match period. + for w in ws: + # w may be '' at times, if there are consecutive ellipses, or + # due to an ellipsis at the start or end of `want`. That's OK. + # Search for an empty string succeeds, and doesn't change startpos. + startpos = got.find(w, startpos, endpos) + if startpos < 0: + return False + startpos += len(w) + + return True + +def _comment_line(line): + "Return a commented form of the given line" + line = line.rstrip() + if line: + return '# '+line + else: + return '#' + +def _strip_exception_details(msg): + # Support for IGNORE_EXCEPTION_DETAIL. + # Get rid of everything except the exception name; in particular, drop + # the possibly dotted module path (if any) and the exception message (if + # any). We assume that a colon is never part of a dotted name, or of an + # exception name. + # E.g., given + # "foo.bar.MyError: la di da" + # return "MyError" + # Or for "abc.def" or "abc.def:\n" return "def". + + start, end = 0, len(msg) + # The exception name must appear on the first line. + i = msg.find("\n") + if i >= 0: + end = i + # retain up to the first colon (if any) + i = msg.find(':', 0, end) + if i >= 0: + end = i + # retain just the exception name + i = msg.rfind('.', 0, end) + if i >= 0: + start = i+1 + return msg[start: end] + +class _OutputRedirectingPdb(pdb.Pdb): + """ + A specialized version of the python debugger that redirects stdout + to a given stream when interacting with the user. Stdout is *not* + redirected when traced code is executed. + """ + def __init__(self, out): + self.__out = out + self.__debugger_used = False + pdb.Pdb.__init__(self, stdout=out) + # still use input() to get user input + self.use_rawinput = 1 + + def set_trace(self, frame=None): + self.__debugger_used = True + if frame is None: + frame = sys._getframe().f_back + pdb.Pdb.set_trace(self, frame) + + def set_continue(self): + # Calling set_continue unconditionally would break unit test + # coverage reporting, as Bdb.set_continue calls sys.settrace(None). + if self.__debugger_used: + pdb.Pdb.set_continue(self) + + def trace_dispatch(self, *args): + # Redirect stdout to the given stream. + save_stdout = sys.stdout + sys.stdout = self.__out + # Call Pdb's trace dispatch method. + try: + return pdb.Pdb.trace_dispatch(self, *args) + finally: + sys.stdout = save_stdout + +# [XX] Normalize with respect to os.path.pardir? +def _module_relative_path(module, path): + if not inspect.ismodule(module): + raise TypeError, 'Expected a module: %r' % module + if path.startswith('/'): + raise ValueError, 'Module-relative files may not have absolute paths' + + # Find the base directory for the path. + if hasattr(module, '__file__'): + # A normal module/package + basedir = os.path.split(module.__file__)[0] + elif module.__name__ == '__main__': + # An interactive session. + if len(sys.argv)>0 and sys.argv[0] != '': + basedir = os.path.split(sys.argv[0])[0] + else: + basedir = os.curdir + else: + # A module w/o __file__ (this includes builtins) + raise ValueError("Can't resolve paths relative to the module " + + module + " (it has no __file__)") + + # Combine the base directory and the path. + return os.path.join(basedir, *(path.split('/'))) + +###################################################################### +## 2. Example & DocTest +###################################################################### +## - An "example" is a pair, where "source" is a +## fragment of source code, and "want" is the expected output for +## "source." The Example class also includes information about +## where the example was extracted from. +## +## - A "doctest" is a collection of examples, typically extracted from +## a string (such as an object's docstring). The DocTest class also +## includes information about where the string was extracted from. + +class Example: + """ + A single doctest example, consisting of source code and expected + output. `Example` defines the following attributes: + + - source: A single Python statement, always ending with a newline. + The constructor adds a newline if needed. + + - want: The expected output from running the source code (either + from stdout, or a traceback in case of exception). `want` ends + with a newline unless it's empty, in which case it's an empty + string. The constructor adds a newline if needed. + + - exc_msg: The exception message generated by the example, if + the example is expected to generate an exception; or `None` if + it is not expected to generate an exception. This exception + message is compared against the return value of + `traceback.format_exception_only()`. `exc_msg` ends with a + newline unless it's `None`. The constructor adds a newline + if needed. + + - lineno: The line number within the DocTest string containing + this Example where the Example begins. This line number is + zero-based, with respect to the beginning of the DocTest. + + - indent: The example's indentation in the DocTest string. + I.e., the number of space characters that precede the + example's first prompt. + + - options: A dictionary mapping from option flags to True or + False, which is used to override default options for this + example. Any option flags not contained in this dictionary + are left at their default value (as specified by the + DocTestRunner's optionflags). By default, no options are set. + """ + def __init__(self, source, want, exc_msg=None, lineno=0, indent=0, + options=None): + # Normalize inputs. + if not source.endswith('\n'): + source += '\n' + if want and not want.endswith('\n'): + want += '\n' + if exc_msg is not None and not exc_msg.endswith('\n'): + exc_msg += '\n' + # Store properties. + self.source = source + self.want = want + self.lineno = lineno + self.indent = indent + if options is None: options = {} + self.options = options + self.exc_msg = exc_msg + + def __eq__(self, other): + if type(self) is not type(other): + return NotImplemented + + return self.source == other.source and \ + self.want == other.want and \ + self.lineno == other.lineno and \ + self.indent == other.indent and \ + self.options == other.options and \ + self.exc_msg == other.exc_msg + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.source, self.want, self.lineno, self.indent, + self.exc_msg)) + + +class DocTest: + """ + A collection of doctest examples that should be run in a single + namespace. Each `DocTest` defines the following attributes: + + - examples: the list of examples. + + - globs: The namespace (aka globals) that the examples should + be run in. + + - name: A name identifying the DocTest (typically, the name of + the object whose docstring this DocTest was extracted from). + + - filename: The name of the file that this DocTest was extracted + from, or `None` if the filename is unknown. + + - lineno: The line number within filename where this DocTest + begins, or `None` if the line number is unavailable. This + line number is zero-based, with respect to the beginning of + the file. + + - docstring: The string that the examples were extracted from, + or `None` if the string is unavailable. + """ + def __init__(self, examples, globs, name, filename, lineno, docstring): + """ + Create a new DocTest containing the given examples. The + DocTest's globals are initialized with a copy of `globs`. + """ + assert not isinstance(examples, basestring), \ + "DocTest no longer accepts str; use DocTestParser instead" + self.examples = examples + self.docstring = docstring + self.globs = globs.copy() + self.name = name + self.filename = filename + self.lineno = lineno + + def __repr__(self): + if len(self.examples) == 0: + examples = 'no examples' + elif len(self.examples) == 1: + examples = '1 example' + else: + examples = '%d examples' % len(self.examples) + return ('' % + (self.name, self.filename, self.lineno, examples)) + + def __eq__(self, other): + if type(self) is not type(other): + return NotImplemented + + return self.examples == other.examples and \ + self.docstring == other.docstring and \ + self.globs == other.globs and \ + self.name == other.name and \ + self.filename == other.filename and \ + self.lineno == other.lineno + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.docstring, self.name, self.filename, self.lineno)) + + # This lets us sort tests by name: + def __cmp__(self, other): + if not isinstance(other, DocTest): + return -1 + return cmp((self.name, self.filename, self.lineno, id(self)), + (other.name, other.filename, other.lineno, id(other))) + +###################################################################### +## 3. DocTestParser +###################################################################### + +class DocTestParser: + """ + A class used to parse strings containing doctest examples. + """ + # This regular expression is used to find doctest examples in a + # string. It defines three groups: `source` is the source code + # (including leading indentation and prompts); `indent` is the + # indentation of the first (PS1) line of the source code; and + # `want` is the expected output (including leading indentation). + _EXAMPLE_RE = re.compile(r''' + # Source consists of a PS1 line followed by zero or more PS2 lines. + (?P + (?:^(?P [ ]*) >>> .*) # PS1 line + (?:\n [ ]* \.\.\. .*)*) # PS2 lines + \n? + # Want consists of any non-blank lines that do not start with PS1. + (?P (?:(?![ ]*$) # Not a blank line + (?![ ]*>>>) # Not a line starting with PS1 + .+$\n? # But any other line + )*) + ''', re.MULTILINE | re.VERBOSE) + + # A regular expression for handling `want` strings that contain + # expected exceptions. It divides `want` into three pieces: + # - the traceback header line (`hdr`) + # - the traceback stack (`stack`) + # - the exception message (`msg`), as generated by + # traceback.format_exception_only() + # `msg` may have multiple lines. We assume/require that the + # exception message is the first non-indented line starting with a word + # character following the traceback header line. + _EXCEPTION_RE = re.compile(r""" + # Grab the traceback header. Different versions of Python have + # said different things on the first traceback line. + ^(?P Traceback\ \( + (?: most\ recent\ call\ last + | innermost\ last + ) \) : + ) + \s* $ # toss trailing whitespace on the header. + (?P .*?) # don't blink: absorb stuff until... + ^ (?P \w+ .*) # a line *starts* with alphanum. + """, re.VERBOSE | re.MULTILINE | re.DOTALL) + + # A callable returning a true value iff its argument is a blank line + # or contains a single comment. + _IS_BLANK_OR_COMMENT = re.compile(r'^[ ]*(#.*)?$').match + + def parse(self, string, name=''): + """ + Divide the given string into examples and intervening text, + and return them as a list of alternating Examples and strings. + Line numbers for the Examples are 0-based. The optional + argument `name` is a name identifying this string, and is only + used for error messages. + """ + string = string.expandtabs() + # If all lines begin with the same indentation, then strip it. + min_indent = self._min_indent(string) + if min_indent > 0: + string = '\n'.join([l[min_indent:] for l in string.split('\n')]) + + output = [] + charno, lineno = 0, 0 + # Find all doctest examples in the string: + for m in self._EXAMPLE_RE.finditer(string): + # Add the pre-example text to `output`. + output.append(string[charno:m.start()]) + # Update lineno (lines before this example) + lineno += string.count('\n', charno, m.start()) + # Extract info from the regexp match. + (source, options, want, exc_msg) = \ + self._parse_example(m, name, lineno) + # Create an Example, and add it to the list. + if not self._IS_BLANK_OR_COMMENT(source): + output.append( Example(source, want, exc_msg, + lineno=lineno, + indent=min_indent+len(m.group('indent')), + options=options) ) + # Update lineno (lines inside this example) + lineno += string.count('\n', m.start(), m.end()) + # Update charno. + charno = m.end() + # Add any remaining post-example text to `output`. + output.append(string[charno:]) + return output + + def get_doctest(self, string, globs, name, filename, lineno): + """ + Extract all doctest examples from the given string, and + collect them into a `DocTest` object. + + `globs`, `name`, `filename`, and `lineno` are attributes for + the new `DocTest` object. See the documentation for `DocTest` + for more information. + """ + return DocTest(self.get_examples(string, name), globs, + name, filename, lineno, string) + + def get_examples(self, string, name=''): + """ + Extract all doctest examples from the given string, and return + them as a list of `Example` objects. Line numbers are + 0-based, because it's most common in doctests that nothing + interesting appears on the same line as opening triple-quote, + and so the first interesting line is called \"line 1\" then. + + The optional argument `name` is a name identifying this + string, and is only used for error messages. + """ + return [x for x in self.parse(string, name) + if isinstance(x, Example)] + + def _parse_example(self, m, name, lineno): + """ + Given a regular expression match from `_EXAMPLE_RE` (`m`), + return a pair `(source, want)`, where `source` is the matched + example's source code (with prompts and indentation stripped); + and `want` is the example's expected output (with indentation + stripped). + + `name` is the string's name, and `lineno` is the line number + where the example starts; both are used for error messages. + """ + # Get the example's indentation level. + indent = len(m.group('indent')) + + # Divide source into lines; check that they're properly + # indented; and then strip their indentation & prompts. + source_lines = m.group('source').split('\n') + self._check_prompt_blank(source_lines, indent, name, lineno) + self._check_prefix(source_lines[1:], ' '*indent + '.', name, lineno) + source = '\n'.join([sl[indent+4:] for sl in source_lines]) + + # Divide want into lines; check that it's properly indented; and + # then strip the indentation. Spaces before the last newline should + # be preserved, so plain rstrip() isn't good enough. + want = m.group('want') + want_lines = want.split('\n') + if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]): + del want_lines[-1] # forget final newline & spaces after it + self._check_prefix(want_lines, ' '*indent, name, + lineno + len(source_lines)) + want = '\n'.join([wl[indent:] for wl in want_lines]) + + # If `want` contains a traceback message, then extract it. + m = self._EXCEPTION_RE.match(want) + if m: + exc_msg = m.group('msg') + else: + exc_msg = None + + # Extract options from the source. + options = self._find_options(source, name, lineno) + + return source, options, want, exc_msg + + # This regular expression looks for option directives in the + # source code of an example. Option directives are comments + # starting with "doctest:". Warning: this may give false + # positives for string-literals that contain the string + # "#doctest:". Eliminating these false positives would require + # actually parsing the string; but we limit them by ignoring any + # line containing "#doctest:" that is *followed* by a quote mark. + _OPTION_DIRECTIVE_RE = re.compile(r'#\s*doctest:\s*([^\n\'"]*)$', + re.MULTILINE) + + def _find_options(self, source, name, lineno): + """ + Return a dictionary containing option overrides extracted from + option directives in the given source string. + + `name` is the string's name, and `lineno` is the line number + where the example starts; both are used for error messages. + """ + options = {} + # (note: with the current regexp, this will match at most once:) + for m in self._OPTION_DIRECTIVE_RE.finditer(source): + option_strings = m.group(1).replace(',', ' ').split() + for option in option_strings: + if (option[0] not in '+-' or + option[1:] not in OPTIONFLAGS_BY_NAME): + raise ValueError('line %r of the doctest for %s ' + 'has an invalid option: %r' % + (lineno+1, name, option)) + flag = OPTIONFLAGS_BY_NAME[option[1:]] + options[flag] = (option[0] == '+') + if options and self._IS_BLANK_OR_COMMENT(source): + raise ValueError('line %r of the doctest for %s has an option ' + 'directive on a line with no example: %r' % + (lineno, name, source)) + return options + + # This regular expression finds the indentation of every non-blank + # line in a string. + _INDENT_RE = re.compile('^([ ]*)(?=\S)', re.MULTILINE) + + def _min_indent(self, s): + "Return the minimum indentation of any non-blank line in `s`" + indents = [len(indent) for indent in self._INDENT_RE.findall(s)] + if len(indents) > 0: + return min(indents) + else: + return 0 + + def _check_prompt_blank(self, lines, indent, name, lineno): + """ + Given the lines of a source string (including prompts and + leading indentation), check to make sure that every prompt is + followed by a space character. If any line is not followed by + a space character, then raise ValueError. + """ + for i, line in enumerate(lines): + if len(line) >= indent+4 and line[indent+3] != ' ': + raise ValueError('line %r of the docstring for %s ' + 'lacks blank after %s: %r' % + (lineno+i+1, name, + line[indent:indent+3], line)) + + def _check_prefix(self, lines, prefix, name, lineno): + """ + Check that every line in the given list starts with the given + prefix; if any line does not, then raise a ValueError. + """ + for i, line in enumerate(lines): + if line and not line.startswith(prefix): + raise ValueError('line %r of the docstring for %s has ' + 'inconsistent leading whitespace: %r' % + (lineno+i+1, name, line)) + + +###################################################################### +## 4. DocTest Finder +###################################################################### + +class DocTestFinder: + """ + A class used to extract the DocTests that are relevant to a given + object, from its docstring and the docstrings of its contained + objects. Doctests can currently be extracted from the following + object types: modules, functions, classes, methods, staticmethods, + classmethods, and properties. + """ + + def __init__(self, verbose=False, parser=DocTestParser(), + recurse=True, exclude_empty=True): + """ + Create a new doctest finder. + + The optional argument `parser` specifies a class or + function that should be used to create new DocTest objects (or + objects that implement the same interface as DocTest). The + signature for this factory function should match the signature + of the DocTest constructor. + + If the optional argument `recurse` is false, then `find` will + only examine the given object, and not any contained objects. + + If the optional argument `exclude_empty` is false, then `find` + will include tests for objects with empty docstrings. + """ + self._parser = parser + self._verbose = verbose + self._recurse = recurse + self._exclude_empty = exclude_empty + + def find(self, obj, name=None, module=None, globs=None, extraglobs=None): + """ + Return a list of the DocTests that are defined by the given + object's docstring, or by any of its contained objects' + docstrings. + + The optional parameter `module` is the module that contains + the given object. If the module is not specified or is None, then + the test finder will attempt to automatically determine the + correct module. The object's module is used: + + - As a default namespace, if `globs` is not specified. + - To prevent the DocTestFinder from extracting DocTests + from objects that are imported from other modules. + - To find the name of the file containing the object. + - To help find the line number of the object within its + file. + + Contained objects whose module does not match `module` are ignored. + + If `module` is False, no attempt to find the module will be made. + This is obscure, of use mostly in tests: if `module` is False, or + is None but cannot be found automatically, then all objects are + considered to belong to the (non-existent) module, so all contained + objects will (recursively) be searched for doctests. + + The globals for each DocTest is formed by combining `globs` + and `extraglobs` (bindings in `extraglobs` override bindings + in `globs`). A new copy of the globals dictionary is created + for each DocTest. If `globs` is not specified, then it + defaults to the module's `__dict__`, if specified, or {} + otherwise. If `extraglobs` is not specified, then it defaults + to {}. + + """ + # If name was not specified, then extract it from the object. + if name is None: + name = getattr(obj, '__name__', None) + if name is None: + raise ValueError("DocTestFinder.find: name must be given " + "when obj.__name__ doesn't exist: %r" % + (type(obj),)) + + # Find the module that contains the given object (if obj is + # a module, then module=obj.). Note: this may fail, in which + # case module will be None. + if module is False: + module = None + elif module is None: + module = inspect.getmodule(obj) + + # Read the module's source code. This is used by + # DocTestFinder._find_lineno to find the line number for a + # given object's docstring. + try: + file = inspect.getsourcefile(obj) or inspect.getfile(obj) + if module is not None: + # Supply the module globals in case the module was + # originally loaded via a PEP 302 loader and + # file is not a valid filesystem path + source_lines = linecache.getlines(file, module.__dict__) + else: + # No access to a loader, so assume it's a normal + # filesystem path + source_lines = linecache.getlines(file) + if not source_lines: + source_lines = None + except TypeError: + source_lines = None + + # Initialize globals, and merge in extraglobs. + if globs is None: + if module is None: + globs = {} + else: + globs = module.__dict__.copy() + else: + globs = globs.copy() + if extraglobs is not None: + globs.update(extraglobs) + if '__name__' not in globs: + globs['__name__'] = '__main__' # provide a default module name + + # Recursively explore `obj`, extracting DocTests. + tests = [] + self._find(tests, obj, name, module, source_lines, globs, {}) + # Sort the tests by alpha order of names, for consistency in + # verbose-mode output. This was a feature of doctest in Pythons + # <= 2.3 that got lost by accident in 2.4. It was repaired in + # 2.4.4 and 2.5. + tests.sort() + return tests + + def _from_module(self, module, object): + """ + Return true if the given object is defined in the given + module. + """ + if module is None: + return True + elif inspect.getmodule(object) is not None: + return module is inspect.getmodule(object) + elif inspect.isfunction(object): + return module.__dict__ is object.func_globals + elif inspect.isclass(object): + return module.__name__ == object.__module__ + elif hasattr(object, '__module__'): + return module.__name__ == object.__module__ + elif isinstance(object, property): + return True # [XX] no way not be sure. + else: + raise ValueError("object must be a class or function") + + def _find(self, tests, obj, name, module, source_lines, globs, seen): + """ + Find tests for the given object and any contained objects, and + add them to `tests`. + """ + if self._verbose: + print 'Finding tests in %s' % name + + # If we've already processed this object, then ignore it. + if id(obj) in seen: + return + seen[id(obj)] = 1 + + # Find a test for this object, and add it to the list of tests. + test = self._get_test(obj, name, module, globs, source_lines) + if test is not None: + tests.append(test) + + # Look for tests in a module's contained objects. + if inspect.ismodule(obj) and self._recurse: + for valname, val in obj.__dict__.items(): + valname = '%s.%s' % (name, valname) + # Recurse to functions & classes. + if ((inspect.isfunction(val) or inspect.isclass(val)) and + self._from_module(module, val)): + self._find(tests, val, valname, module, source_lines, + globs, seen) + + # Look for tests in a module's __test__ dictionary. + if inspect.ismodule(obj) and self._recurse: + for valname, val in getattr(obj, '__test__', {}).items(): + if not isinstance(valname, basestring): + raise ValueError("DocTestFinder.find: __test__ keys " + "must be strings: %r" % + (type(valname),)) + if not (inspect.isfunction(val) or inspect.isclass(val) or + inspect.ismethod(val) or inspect.ismodule(val) or + isinstance(val, basestring)): + raise ValueError("DocTestFinder.find: __test__ values " + "must be strings, functions, methods, " + "classes, or modules: %r" % + (type(val),)) + valname = '%s.__test__.%s' % (name, valname) + self._find(tests, val, valname, module, source_lines, + globs, seen) + + # Look for tests in a class's contained objects. + if inspect.isclass(obj) and self._recurse: + for valname, val in obj.__dict__.items(): + # Special handling for staticmethod/classmethod. + if isinstance(val, staticmethod): + val = getattr(obj, valname) + if isinstance(val, classmethod): + val = getattr(obj, valname).im_func + + # Recurse to methods, properties, and nested classes. + if ((inspect.isfunction(val) or inspect.isclass(val) or + isinstance(val, property)) and + self._from_module(module, val)): + valname = '%s.%s' % (name, valname) + self._find(tests, val, valname, module, source_lines, + globs, seen) + + def _get_test(self, obj, name, module, globs, source_lines): + """ + Return a DocTest for the given object, if it defines a docstring; + otherwise, return None. + """ + # Extract the object's docstring. If it doesn't have one, + # then return None (no test for this object). + if isinstance(obj, basestring): + docstring = obj + else: + try: + if obj.__doc__ is None: + docstring = '' + else: + docstring = obj.__doc__ + if not isinstance(docstring, basestring): + docstring = str(docstring) + except (TypeError, AttributeError): + docstring = '' + + # Find the docstring's location in the file. + lineno = self._find_lineno(obj, source_lines) + + # Don't bother if the docstring is empty. + if self._exclude_empty and not docstring: + return None + + # Return a DocTest for this object. + if module is None: + filename = None + else: + filename = getattr(module, '__file__', module.__name__) + if filename[-4:] in (".pyc", ".pyo"): + filename = filename[:-1] + return self._parser.get_doctest(docstring, globs, name, + filename, lineno) + + def _find_lineno(self, obj, source_lines): + """ + Return a line number of the given object's docstring. Note: + this method assumes that the object has a docstring. + """ + lineno = None + + # Find the line number for modules. + if inspect.ismodule(obj): + lineno = 0 + + # Find the line number for classes. + # Note: this could be fooled if a class is defined multiple + # times in a single file. + if inspect.isclass(obj): + if source_lines is None: + return None + pat = re.compile(r'^\s*class\s*%s\b' % + getattr(obj, '__name__', '-')) + for i, line in enumerate(source_lines): + if pat.match(line): + lineno = i + break + + # Find the line number for functions & methods. + if inspect.ismethod(obj): obj = obj.im_func + if inspect.isfunction(obj): obj = obj.func_code + if inspect.istraceback(obj): obj = obj.tb_frame + if inspect.isframe(obj): obj = obj.f_code + if inspect.iscode(obj): + lineno = getattr(obj, 'co_firstlineno', None)-1 + + # Find the line number where the docstring starts. Assume + # that it's the first line that begins with a quote mark. + # Note: this could be fooled by a multiline function + # signature, where a continuation line begins with a quote + # mark. + if lineno is not None: + if source_lines is None: + return lineno+1 + pat = re.compile('(^|.*:)\s*\w*("|\')') + for lineno in range(lineno, len(source_lines)): + if pat.match(source_lines[lineno]): + return lineno + + # We couldn't find the line number. + return None + +###################################################################### +## 5. DocTest Runner +###################################################################### + +class DocTestRunner: + """ + A class used to run DocTest test cases, and accumulate statistics. + The `run` method is used to process a single DocTest case. It + returns a tuple `(f, t)`, where `t` is the number of test cases + tried, and `f` is the number of test cases that failed. + + >>> tests = DocTestFinder().find(_TestClass) + >>> runner = DocTestRunner(verbose=False) + >>> tests.sort(key = lambda test: test.name) + >>> for test in tests: + ... print test.name, '->', runner.run(test) + _TestClass -> TestResults(failed=0, attempted=2) + _TestClass.__init__ -> TestResults(failed=0, attempted=2) + _TestClass.get -> TestResults(failed=0, attempted=2) + _TestClass.square -> TestResults(failed=0, attempted=1) + + The `summarize` method prints a summary of all the test cases that + have been run by the runner, and returns an aggregated `(f, t)` + tuple: + + >>> runner.summarize(verbose=1) + 4 items passed all tests: + 2 tests in _TestClass + 2 tests in _TestClass.__init__ + 2 tests in _TestClass.get + 1 tests in _TestClass.square + 7 tests in 4 items. + 7 passed and 0 failed. + Test passed. + TestResults(failed=0, attempted=7) + + The aggregated number of tried examples and failed examples is + also available via the `tries` and `failures` attributes: + + >>> runner.tries + 7 + >>> runner.failures + 0 + + The comparison between expected outputs and actual outputs is done + by an `OutputChecker`. This comparison may be customized with a + number of option flags; see the documentation for `testmod` for + more information. If the option flags are insufficient, then the + comparison may also be customized by passing a subclass of + `OutputChecker` to the constructor. + + The test runner's display output can be controlled in two ways. + First, an output function (`out) can be passed to + `TestRunner.run`; this function will be called with strings that + should be displayed. It defaults to `sys.stdout.write`. If + capturing the output is not sufficient, then the display output + can be also customized by subclassing DocTestRunner, and + overriding the methods `report_start`, `report_success`, + `report_unexpected_exception`, and `report_failure`. + """ + # This divider string is used to separate failure messages, and to + # separate sections of the summary. + DIVIDER = "*" * 70 + + def __init__(self, checker=None, verbose=None, optionflags=0): + """ + Create a new test runner. + + Optional keyword arg `checker` is the `OutputChecker` that + should be used to compare the expected outputs and actual + outputs of doctest examples. + + Optional keyword arg 'verbose' prints lots of stuff if true, + only failures if false; by default, it's true iff '-v' is in + sys.argv. + + Optional argument `optionflags` can be used to control how the + test runner compares expected output to actual output, and how + it displays failures. See the documentation for `testmod` for + more information. + """ + self._checker = checker or OutputChecker() + if verbose is None: + verbose = '-v' in sys.argv + self._verbose = verbose + self.optionflags = optionflags + self.original_optionflags = optionflags + + # Keep track of the examples we've run. + self.tries = 0 + self.failures = 0 + self._name2ft = {} + + # Create a fake output target for capturing doctest output. + self._fakeout = _SpoofOut() + + #///////////////////////////////////////////////////////////////// + # Reporting methods + #///////////////////////////////////////////////////////////////// + + def report_start(self, out, test, example): + """ + Report that the test runner is about to process the given + example. (Only displays a message if verbose=True) + """ + if self._verbose: + if example.want: + out('Trying:\n' + _indent(example.source) + + 'Expecting:\n' + _indent(example.want)) + else: + out('Trying:\n' + _indent(example.source) + + 'Expecting nothing\n') + + def report_success(self, out, test, example, got): + """ + Report that the given example ran successfully. (Only + displays a message if verbose=True) + """ + if self._verbose: + out("ok\n") + + def report_failure(self, out, test, example, got): + """ + Report that the given example failed. + """ + out(self._failure_header(test, example) + + self._checker.output_difference(example, got, self.optionflags)) + + def report_unexpected_exception(self, out, test, example, exc_info): + """ + Report that the given example raised an unexpected exception. + """ + out(self._failure_header(test, example) + + 'Exception raised:\n' + _indent(_exception_traceback(exc_info))) + + def _failure_header(self, test, example): + out = [self.DIVIDER] + if test.filename: + if test.lineno is not None and example.lineno is not None: + lineno = test.lineno + example.lineno + 1 + else: + lineno = '?' + out.append('File "%s", line %s, in %s' % + (test.filename, lineno, test.name)) + else: + out.append('Line %s, in %s' % (example.lineno+1, test.name)) + out.append('Failed example:') + source = example.source + out.append(_indent(source)) + return '\n'.join(out) + + #///////////////////////////////////////////////////////////////// + # DocTest Running + #///////////////////////////////////////////////////////////////// + + def __run(self, test, compileflags, out): + """ + Run the examples in `test`. Write the outcome of each example + with one of the `DocTestRunner.report_*` methods, using the + writer function `out`. `compileflags` is the set of compiler + flags that should be used to execute examples. Return a tuple + `(f, t)`, where `t` is the number of examples tried, and `f` + is the number of examples that failed. The examples are run + in the namespace `test.globs`. + """ + # Keep track of the number of failures and tries. + failures = tries = 0 + + # Save the option flags (since option directives can be used + # to modify them). + original_optionflags = self.optionflags + + SUCCESS, FAILURE, BOOM = range(3) # `outcome` state + + check = self._checker.check_output + + # Process each example. + for examplenum, example in enumerate(test.examples): + + # If REPORT_ONLY_FIRST_FAILURE is set, then suppress + # reporting after the first failure. + quiet = (self.optionflags & REPORT_ONLY_FIRST_FAILURE and + failures > 0) + + # Merge in the example's options. + self.optionflags = original_optionflags + if example.options: + for (optionflag, val) in example.options.items(): + if val: + self.optionflags |= optionflag + else: + self.optionflags &= ~optionflag + + # If 'SKIP' is set, then skip this example. + if self.optionflags & SKIP: + continue + + # Record that we started this example. + tries += 1 + if not quiet: + self.report_start(out, test, example) + + # Use a special filename for compile(), so we can retrieve + # the source code during interactive debugging (see + # __patched_linecache_getlines). + filename = '' % (test.name, examplenum) + + # Run the example in the given context (globs), and record + # any exception that gets raised. (But don't intercept + # keyboard interrupts.) + try: + # Don't blink! This is where the user's code gets run. + exec compile(example.source, filename, "single", + compileflags, 1) in test.globs + self.debugger.set_continue() # ==== Example Finished ==== + exception = None + except KeyboardInterrupt: + raise + except: + exception = sys.exc_info() + self.debugger.set_continue() # ==== Example Finished ==== + + got = self._fakeout.getvalue() # the actual output + self._fakeout.truncate(0) + outcome = FAILURE # guilty until proved innocent or insane + + # If the example executed without raising any exceptions, + # verify its output. + if exception is None: + if check(example.want, got, self.optionflags): + outcome = SUCCESS + + # The example raised an exception: check if it was expected. + else: + exc_info = sys.exc_info() + exc_msg = traceback.format_exception_only(*exc_info[:2])[-1] + if not quiet: + got += _exception_traceback(exc_info) + + # If `example.exc_msg` is None, then we weren't expecting + # an exception. + if example.exc_msg is None: + outcome = BOOM + + # We expected an exception: see whether it matches. + elif check(example.exc_msg, exc_msg, self.optionflags): + outcome = SUCCESS + + # Another chance if they didn't care about the detail. + elif self.optionflags & IGNORE_EXCEPTION_DETAIL: + if check(_strip_exception_details(example.exc_msg), + _strip_exception_details(exc_msg), + self.optionflags): + outcome = SUCCESS + + # Report the outcome. + if outcome is SUCCESS: + if not quiet: + self.report_success(out, test, example, got) + elif outcome is FAILURE: + if not quiet: + self.report_failure(out, test, example, got) + failures += 1 + elif outcome is BOOM: + if not quiet: + self.report_unexpected_exception(out, test, example, + exc_info) + failures += 1 + else: + assert False, ("unknown outcome", outcome) + + # Restore the option flags (in case they were modified) + self.optionflags = original_optionflags + + # Record and return the number of failures and tries. + self.__record_outcome(test, failures, tries) + return TestResults(failures, tries) + + def __record_outcome(self, test, f, t): + """ + Record the fact that the given DocTest (`test`) generated `f` + failures out of `t` tried examples. + """ + f2, t2 = self._name2ft.get(test.name, (0,0)) + self._name2ft[test.name] = (f+f2, t+t2) + self.failures += f + self.tries += t + + __LINECACHE_FILENAME_RE = re.compile(r'.+)' + r'\[(?P\d+)\]>$') + def __patched_linecache_getlines(self, filename, module_globals=None): + m = self.__LINECACHE_FILENAME_RE.match(filename) + if m and m.group('name') == self.test.name: + example = self.test.examples[int(m.group('examplenum'))] + source = example.source + if isinstance(source, unicode): + source = source.encode('ascii', 'backslashreplace') + return source.splitlines(True) + else: + return self.save_linecache_getlines(filename, module_globals) + + def run(self, test, compileflags=None, out=None, clear_globs=True): + """ + Run the examples in `test`, and display the results using the + writer function `out`. + + The examples are run in the namespace `test.globs`. If + `clear_globs` is true (the default), then this namespace will + be cleared after the test runs, to help with garbage + collection. If you would like to examine the namespace after + the test completes, then use `clear_globs=False`. + + `compileflags` gives the set of flags that should be used by + the Python compiler when running the examples. If not + specified, then it will default to the set of future-import + flags that apply to `globs`. + + The output of each example is checked using + `DocTestRunner.check_output`, and the results are formatted by + the `DocTestRunner.report_*` methods. + """ + self.test = test + + if compileflags is None: + compileflags = _extract_future_flags(test.globs) + + save_stdout = sys.stdout + if out is None: + out = save_stdout.write + sys.stdout = self._fakeout + + # Patch pdb.set_trace to restore sys.stdout during interactive + # debugging (so it's not still redirected to self._fakeout). + # Note that the interactive output will go to *our* + # save_stdout, even if that's not the real sys.stdout; this + # allows us to write test cases for the set_trace behavior. + save_set_trace = pdb.set_trace + self.debugger = _OutputRedirectingPdb(save_stdout) + self.debugger.reset() + pdb.set_trace = self.debugger.set_trace + + # Patch linecache.getlines, so we can see the example's source + # when we're inside the debugger. + self.save_linecache_getlines = linecache.getlines + linecache.getlines = self.__patched_linecache_getlines + + # Make sure sys.displayhook just prints the value to stdout + save_displayhook = sys.displayhook + sys.displayhook = sys.__displayhook__ + + try: + return self.__run(test, compileflags, out) + finally: + sys.stdout = save_stdout + pdb.set_trace = save_set_trace + linecache.getlines = self.save_linecache_getlines + sys.displayhook = save_displayhook + if clear_globs: + test.globs.clear() + + #///////////////////////////////////////////////////////////////// + # Summarization + #///////////////////////////////////////////////////////////////// + def summarize(self, verbose=None): + """ + Print a summary of all the test cases that have been run by + this DocTestRunner, and return a tuple `(f, t)`, where `f` is + the total number of failed examples, and `t` is the total + number of tried examples. + + The optional `verbose` argument controls how detailed the + summary is. If the verbosity is not specified, then the + DocTestRunner's verbosity is used. + """ + if verbose is None: + verbose = self._verbose + notests = [] + passed = [] + failed = [] + totalt = totalf = 0 + for x in self._name2ft.items(): + name, (f, t) = x + assert f <= t + totalt += t + totalf += f + if t == 0: + notests.append(name) + elif f == 0: + passed.append( (name, t) ) + else: + failed.append(x) + if verbose: + if notests: + print len(notests), "items had no tests:" + notests.sort() + for thing in notests: + print " ", thing + if passed: + print len(passed), "items passed all tests:" + passed.sort() + for thing, count in passed: + print " %3d tests in %s" % (count, thing) + if failed: + print self.DIVIDER + print len(failed), "items had failures:" + failed.sort() + for thing, (f, t) in failed: + print " %3d of %3d in %s" % (f, t, thing) + if verbose: + print totalt, "tests in", len(self._name2ft), "items." + print totalt - totalf, "passed and", totalf, "failed." + if totalf: + print "***Test Failed***", totalf, "failures." + elif verbose: + print "Test passed." + return TestResults(totalf, totalt) + + #///////////////////////////////////////////////////////////////// + # Backward compatibility cruft to maintain doctest.master. + #///////////////////////////////////////////////////////////////// + def merge(self, other): + d = self._name2ft + for name, (f, t) in other._name2ft.items(): + if name in d: + # Don't print here by default, since doing + # so breaks some of the buildbots + #print "*** DocTestRunner.merge: '" + name + "' in both" \ + # " testers; summing outcomes." + f2, t2 = d[name] + f = f + f2 + t = t + t2 + d[name] = f, t + +class OutputChecker: + """ + A class used to check the whether the actual output from a doctest + example matches the expected output. `OutputChecker` defines two + methods: `check_output`, which compares a given pair of outputs, + and returns true if they match; and `output_difference`, which + returns a string describing the differences between two outputs. + """ + def check_output(self, want, got, optionflags): + """ + Return True iff the actual output from an example (`got`) + matches the expected output (`want`). These strings are + always considered to match if they are identical; but + depending on what option flags the test runner is using, + several non-exact match types are also possible. See the + documentation for `TestRunner` for more information about + option flags. + """ + # Handle the common case first, for efficiency: + # if they're string-identical, always return true. + if got == want: + return True + + # The values True and False replaced 1 and 0 as the return + # value for boolean comparisons in Python 2.3. + if not (optionflags & DONT_ACCEPT_TRUE_FOR_1): + if (got,want) == ("True\n", "1\n"): + return True + if (got,want) == ("False\n", "0\n"): + return True + + # can be used as a special sequence to signify a + # blank line, unless the DONT_ACCEPT_BLANKLINE flag is used. + if not (optionflags & DONT_ACCEPT_BLANKLINE): + # Replace in want with a blank line. + want = re.sub('(?m)^%s\s*?$' % re.escape(BLANKLINE_MARKER), + '', want) + # If a line in got contains only spaces, then remove the + # spaces. + got = re.sub('(?m)^\s*?$', '', got) + if got == want: + return True + + # This flag causes doctest to ignore any differences in the + # contents of whitespace strings. Note that this can be used + # in conjunction with the ELLIPSIS flag. + if optionflags & NORMALIZE_WHITESPACE: + got = ' '.join(got.split()) + want = ' '.join(want.split()) + if got == want: + return True + + # The ELLIPSIS flag says to let the sequence "..." in `want` + # match any substring in `got`. + if optionflags & ELLIPSIS: + if _ellipsis_match(want, got): + return True + + # We didn't find any match; return false. + return False + + # Should we do a fancy diff? + def _do_a_fancy_diff(self, want, got, optionflags): + # Not unless they asked for a fancy diff. + if not optionflags & (REPORT_UDIFF | + REPORT_CDIFF | + REPORT_NDIFF): + return False + + # If expected output uses ellipsis, a meaningful fancy diff is + # too hard ... or maybe not. In two real-life failures Tim saw, + # a diff was a major help anyway, so this is commented out. + # [todo] _ellipsis_match() knows which pieces do and don't match, + # and could be the basis for a kick-ass diff in this case. + ##if optionflags & ELLIPSIS and ELLIPSIS_MARKER in want: + ## return False + + # ndiff does intraline difference marking, so can be useful even + # for 1-line differences. + if optionflags & REPORT_NDIFF: + return True + + # The other diff types need at least a few lines to be helpful. + return want.count('\n') > 2 and got.count('\n') > 2 + + def output_difference(self, example, got, optionflags): + """ + Return a string describing the differences between the + expected output for a given example (`example`) and the actual + output (`got`). `optionflags` is the set of option flags used + to compare `want` and `got`. + """ + want = example.want + # If s are being used, then replace blank lines + # with in the actual output string. + if not (optionflags & DONT_ACCEPT_BLANKLINE): + got = re.sub('(?m)^[ ]*(?=\n)', BLANKLINE_MARKER, got) + + # Check if we should use diff. + if self._do_a_fancy_diff(want, got, optionflags): + # Split want & got into lines. + want_lines = want.splitlines(True) # True == keep line ends + got_lines = got.splitlines(True) + # Use difflib to find their differences. + if optionflags & REPORT_UDIFF: + diff = difflib.unified_diff(want_lines, got_lines, n=2) + diff = list(diff)[2:] # strip the diff header + kind = 'unified diff with -expected +actual' + elif optionflags & REPORT_CDIFF: + diff = difflib.context_diff(want_lines, got_lines, n=2) + diff = list(diff)[2:] # strip the diff header + kind = 'context diff with expected followed by actual' + elif optionflags & REPORT_NDIFF: + engine = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) + diff = list(engine.compare(want_lines, got_lines)) + kind = 'ndiff with -expected +actual' + else: + assert 0, 'Bad diff option' + # Remove trailing whitespace on diff output. + diff = [line.rstrip() + '\n' for line in diff] + return 'Differences (%s):\n' % kind + _indent(''.join(diff)) + + # If we're not using diff, then simply list the expected + # output followed by the actual output. + if want and got: + return 'Expected:\n%sGot:\n%s' % (_indent(want), _indent(got)) + elif want: + return 'Expected:\n%sGot nothing\n' % _indent(want) + elif got: + return 'Expected nothing\nGot:\n%s' % _indent(got) + else: + return 'Expected nothing\nGot nothing\n' + +class DocTestFailure(Exception): + """A DocTest example has failed in debugging mode. + + The exception instance has variables: + + - test: the DocTest object being run + + - example: the Example object that failed + + - got: the actual output + """ + def __init__(self, test, example, got): + self.test = test + self.example = example + self.got = got + + def __str__(self): + return str(self.test) + +class UnexpectedException(Exception): + """A DocTest example has encountered an unexpected exception + + The exception instance has variables: + + - test: the DocTest object being run + + - example: the Example object that failed + + - exc_info: the exception info + """ + def __init__(self, test, example, exc_info): + self.test = test + self.example = example + self.exc_info = exc_info + + def __str__(self): + return str(self.test) + +class DebugRunner(DocTestRunner): + r"""Run doc tests but raise an exception as soon as there is a failure. + + If an unexpected exception occurs, an UnexpectedException is raised. + It contains the test, the example, and the original exception: + + >>> runner = DebugRunner(verbose=False) + >>> test = DocTestParser().get_doctest('>>> raise KeyError\n42', + ... {}, 'foo', 'foo.py', 0) + >>> try: + ... runner.run(test) + ... except UnexpectedException, failure: + ... pass + + >>> failure.test is test + True + + >>> failure.example.want + '42\n' + + >>> exc_info = failure.exc_info + >>> raise exc_info[0], exc_info[1], exc_info[2] + Traceback (most recent call last): + ... + KeyError + + We wrap the original exception to give the calling application + access to the test and example information. + + If the output doesn't match, then a DocTestFailure is raised: + + >>> test = DocTestParser().get_doctest(''' + ... >>> x = 1 + ... >>> x + ... 2 + ... ''', {}, 'foo', 'foo.py', 0) + + >>> try: + ... runner.run(test) + ... except DocTestFailure, failure: + ... pass + + DocTestFailure objects provide access to the test: + + >>> failure.test is test + True + + As well as to the example: + + >>> failure.example.want + '2\n' + + and the actual output: + + >>> failure.got + '1\n' + + If a failure or error occurs, the globals are left intact: + + >>> del test.globs['__builtins__'] + >>> test.globs + {'x': 1} + + >>> test = DocTestParser().get_doctest(''' + ... >>> x = 2 + ... >>> raise KeyError + ... ''', {}, 'foo', 'foo.py', 0) + + >>> runner.run(test) + Traceback (most recent call last): + ... + UnexpectedException: + + >>> del test.globs['__builtins__'] + >>> test.globs + {'x': 2} + + But the globals are cleared if there is no error: + + >>> test = DocTestParser().get_doctest(''' + ... >>> x = 2 + ... ''', {}, 'foo', 'foo.py', 0) + + >>> runner.run(test) + TestResults(failed=0, attempted=1) + + >>> test.globs + {} + + """ + + def run(self, test, compileflags=None, out=None, clear_globs=True): + r = DocTestRunner.run(self, test, compileflags, out, False) + if clear_globs: + test.globs.clear() + return r + + def report_unexpected_exception(self, out, test, example, exc_info): + raise UnexpectedException(test, example, exc_info) + + def report_failure(self, out, test, example, got): + raise DocTestFailure(test, example, got) + +###################################################################### +## 6. Test Functions +###################################################################### +# These should be backwards compatible. + +# For backward compatibility, a global instance of a DocTestRunner +# class, updated by testmod. +master = None + +def testmod(m=None, name=None, globs=None, verbose=None, + report=True, optionflags=0, extraglobs=None, + raise_on_error=False, exclude_empty=False): + """m=None, name=None, globs=None, verbose=None, report=True, + optionflags=0, extraglobs=None, raise_on_error=False, + exclude_empty=False + + Test examples in docstrings in functions and classes reachable + from module m (or the current module if m is not supplied), starting + with m.__doc__. + + Also test examples reachable from dict m.__test__ if it exists and is + not None. m.__test__ maps names to functions, classes and strings; + function and class docstrings are tested even if the name is private; + strings are tested directly, as if they were docstrings. + + Return (#failures, #tests). + + See help(doctest) for an overview. + + Optional keyword arg "name" gives the name of the module; by default + use m.__name__. + + Optional keyword arg "globs" gives a dict to be used as the globals + when executing examples; by default, use m.__dict__. A copy of this + dict is actually used for each docstring, so that each docstring's + examples start with a clean slate. + + Optional keyword arg "extraglobs" gives a dictionary that should be + merged into the globals that are used to execute examples. By + default, no extra globals are used. This is new in 2.4. + + Optional keyword arg "verbose" prints lots of stuff if true, prints + only failures if false; by default, it's true iff "-v" is in sys.argv. + + Optional keyword arg "report" prints a summary at the end when true, + else prints nothing at the end. In verbose mode, the summary is + detailed, else very brief (in fact, empty if all tests passed). + + Optional keyword arg "optionflags" or's together module constants, + and defaults to 0. This is new in 2.3. Possible values (see the + docs for details): + + DONT_ACCEPT_TRUE_FOR_1 + DONT_ACCEPT_BLANKLINE + NORMALIZE_WHITESPACE + ELLIPSIS + SKIP + IGNORE_EXCEPTION_DETAIL + REPORT_UDIFF + REPORT_CDIFF + REPORT_NDIFF + REPORT_ONLY_FIRST_FAILURE + + Optional keyword arg "raise_on_error" raises an exception on the + first unexpected exception or failure. This allows failures to be + post-mortem debugged. + + Advanced tomfoolery: testmod runs methods of a local instance of + class doctest.Tester, then merges the results into (or creates) + global Tester instance doctest.master. Methods of doctest.master + can be called directly too, if you want to do something unusual. + Passing report=0 to testmod is especially useful then, to delay + displaying a summary. Invoke doctest.master.summarize(verbose) + when you're done fiddling. + """ + global master + + # If no module was given, then use __main__. + if m is None: + # DWA - m will still be None if this wasn't invoked from the command + # line, in which case the following TypeError is about as good an error + # as we should expect + m = sys.modules.get('__main__') + + # Check that we were actually given a module. + if not inspect.ismodule(m): + raise TypeError("testmod: module required; %r" % (m,)) + + # If no name was given, then use the module's name. + if name is None: + name = m.__name__ + + # Find, parse, and run all tests in the given module. + finder = DocTestFinder(exclude_empty=exclude_empty) + + if raise_on_error: + runner = DebugRunner(verbose=verbose, optionflags=optionflags) + else: + runner = DocTestRunner(verbose=verbose, optionflags=optionflags) + + for test in finder.find(m, name, globs=globs, extraglobs=extraglobs): + runner.run(test) + + if report: + runner.summarize() + + if master is None: + master = runner + else: + master.merge(runner) + + return TestResults(runner.failures, runner.tries) + +def testfile(filename, module_relative=True, name=None, package=None, + globs=None, verbose=None, report=True, optionflags=0, + extraglobs=None, raise_on_error=False, parser=DocTestParser(), + encoding=None): + """ + Test examples in the given file. Return (#failures, #tests). + + Optional keyword arg "module_relative" specifies how filenames + should be interpreted: + + - If "module_relative" is True (the default), then "filename" + specifies a module-relative path. By default, this path is + relative to the calling module's directory; but if the + "package" argument is specified, then it is relative to that + package. To ensure os-independence, "filename" should use + "/" characters to separate path segments, and should not + be an absolute path (i.e., it may not begin with "/"). + + - If "module_relative" is False, then "filename" specifies an + os-specific path. The path may be absolute or relative (to + the current working directory). + + Optional keyword arg "name" gives the name of the test; by default + use the file's basename. + + Optional keyword argument "package" is a Python package or the + name of a Python package whose directory should be used as the + base directory for a module relative filename. If no package is + specified, then the calling module's directory is used as the base + directory for module relative filenames. It is an error to + specify "package" if "module_relative" is False. + + Optional keyword arg "globs" gives a dict to be used as the globals + when executing examples; by default, use {}. A copy of this dict + is actually used for each docstring, so that each docstring's + examples start with a clean slate. + + Optional keyword arg "extraglobs" gives a dictionary that should be + merged into the globals that are used to execute examples. By + default, no extra globals are used. + + Optional keyword arg "verbose" prints lots of stuff if true, prints + only failures if false; by default, it's true iff "-v" is in sys.argv. + + Optional keyword arg "report" prints a summary at the end when true, + else prints nothing at the end. In verbose mode, the summary is + detailed, else very brief (in fact, empty if all tests passed). + + Optional keyword arg "optionflags" or's together module constants, + and defaults to 0. Possible values (see the docs for details): + + DONT_ACCEPT_TRUE_FOR_1 + DONT_ACCEPT_BLANKLINE + NORMALIZE_WHITESPACE + ELLIPSIS + SKIP + IGNORE_EXCEPTION_DETAIL + REPORT_UDIFF + REPORT_CDIFF + REPORT_NDIFF + REPORT_ONLY_FIRST_FAILURE + + Optional keyword arg "raise_on_error" raises an exception on the + first unexpected exception or failure. This allows failures to be + post-mortem debugged. + + Optional keyword arg "parser" specifies a DocTestParser (or + subclass) that should be used to extract tests from the files. + + Optional keyword arg "encoding" specifies an encoding that should + be used to convert the file to unicode. + + Advanced tomfoolery: testmod runs methods of a local instance of + class doctest.Tester, then merges the results into (or creates) + global Tester instance doctest.master. Methods of doctest.master + can be called directly too, if you want to do something unusual. + Passing report=0 to testmod is especially useful then, to delay + displaying a summary. Invoke doctest.master.summarize(verbose) + when you're done fiddling. + """ + global master + + if package and not module_relative: + raise ValueError("Package may only be specified for module-" + "relative paths.") + + # Relativize the path + text, filename = _load_testfile(filename, package, module_relative) + + # If no name was given, then use the file's name. + if name is None: + name = os.path.basename(filename) + + # Assemble the globals. + if globs is None: + globs = {} + else: + globs = globs.copy() + if extraglobs is not None: + globs.update(extraglobs) + if '__name__' not in globs: + globs['__name__'] = '__main__' + + if raise_on_error: + runner = DebugRunner(verbose=verbose, optionflags=optionflags) + else: + runner = DocTestRunner(verbose=verbose, optionflags=optionflags) + + if encoding is not None: + text = text.decode(encoding) + + # Read the file, convert it to a test, and run it. + test = parser.get_doctest(text, globs, name, filename, 0) + runner.run(test) + + if report: + runner.summarize() + + if master is None: + master = runner + else: + master.merge(runner) + + return TestResults(runner.failures, runner.tries) + +def run_docstring_examples(f, globs, verbose=False, name="NoName", + compileflags=None, optionflags=0): + """ + Test examples in the given object's docstring (`f`), using `globs` + as globals. Optional argument `name` is used in failure messages. + If the optional argument `verbose` is true, then generate output + even if there are no failures. + + `compileflags` gives the set of flags that should be used by the + Python compiler when running the examples. If not specified, then + it will default to the set of future-import flags that apply to + `globs`. + + Optional keyword arg `optionflags` specifies options for the + testing and output. See the documentation for `testmod` for more + information. + """ + # Find, parse, and run all tests in the given module. + finder = DocTestFinder(verbose=verbose, recurse=False) + runner = DocTestRunner(verbose=verbose, optionflags=optionflags) + for test in finder.find(f, name, globs=globs): + runner.run(test, compileflags=compileflags) + +###################################################################### +## 7. Tester +###################################################################### +# This is provided only for backwards compatibility. It's not +# actually used in any way. + +class Tester: + def __init__(self, mod=None, globs=None, verbose=None, optionflags=0): + + warnings.warn("class Tester is deprecated; " + "use class doctest.DocTestRunner instead", + DeprecationWarning, stacklevel=2) + if mod is None and globs is None: + raise TypeError("Tester.__init__: must specify mod or globs") + if mod is not None and not inspect.ismodule(mod): + raise TypeError("Tester.__init__: mod must be a module; %r" % + (mod,)) + if globs is None: + globs = mod.__dict__ + self.globs = globs + + self.verbose = verbose + self.optionflags = optionflags + self.testfinder = DocTestFinder() + self.testrunner = DocTestRunner(verbose=verbose, + optionflags=optionflags) + + def runstring(self, s, name): + test = DocTestParser().get_doctest(s, self.globs, name, None, None) + if self.verbose: + print "Running string", name + (f,t) = self.testrunner.run(test) + if self.verbose: + print f, "of", t, "examples failed in string", name + return TestResults(f,t) + + def rundoc(self, object, name=None, module=None): + f = t = 0 + tests = self.testfinder.find(object, name, module=module, + globs=self.globs) + for test in tests: + (f2, t2) = self.testrunner.run(test) + (f,t) = (f+f2, t+t2) + return TestResults(f,t) + + def rundict(self, d, name, module=None): + import types + m = types.ModuleType(name) + m.__dict__.update(d) + if module is None: + module = False + return self.rundoc(m, name, module) + + def run__test__(self, d, name): + import types + m = types.ModuleType(name) + m.__test__ = d + return self.rundoc(m, name) + + def summarize(self, verbose=None): + return self.testrunner.summarize(verbose) + + def merge(self, other): + self.testrunner.merge(other.testrunner) + +###################################################################### +## 8. Unittest Support +###################################################################### + +_unittest_reportflags = 0 + +def set_unittest_reportflags(flags): + """Sets the unittest option flags. + + The old flag is returned so that a runner could restore the old + value if it wished to: + + >>> import doctest + >>> old = doctest._unittest_reportflags + >>> doctest.set_unittest_reportflags(REPORT_NDIFF | + ... REPORT_ONLY_FIRST_FAILURE) == old + True + + >>> doctest._unittest_reportflags == (REPORT_NDIFF | + ... REPORT_ONLY_FIRST_FAILURE) + True + + Only reporting flags can be set: + + >>> doctest.set_unittest_reportflags(ELLIPSIS) + Traceback (most recent call last): + ... + ValueError: ('Only reporting flags allowed', 8) + + >>> doctest.set_unittest_reportflags(old) == (REPORT_NDIFF | + ... REPORT_ONLY_FIRST_FAILURE) + True + """ + global _unittest_reportflags + + if (flags & REPORTING_FLAGS) != flags: + raise ValueError("Only reporting flags allowed", flags) + old = _unittest_reportflags + _unittest_reportflags = flags + return old + + +class DocTestCase(unittest.TestCase): + + def __init__(self, test, optionflags=0, setUp=None, tearDown=None, + checker=None): + + unittest.TestCase.__init__(self) + self._dt_optionflags = optionflags + self._dt_checker = checker + self._dt_test = test + self._dt_setUp = setUp + self._dt_tearDown = tearDown + + def setUp(self): + test = self._dt_test + + if self._dt_setUp is not None: + self._dt_setUp(test) + + def tearDown(self): + test = self._dt_test + + if self._dt_tearDown is not None: + self._dt_tearDown(test) + + test.globs.clear() + + def runTest(self): + test = self._dt_test + old = sys.stdout + new = StringIO() + optionflags = self._dt_optionflags + + if not (optionflags & REPORTING_FLAGS): + # The option flags don't include any reporting flags, + # so add the default reporting flags + optionflags |= _unittest_reportflags + + runner = DocTestRunner(optionflags=optionflags, + checker=self._dt_checker, verbose=False) + + try: + runner.DIVIDER = "-"*70 + failures, tries = runner.run( + test, out=new.write, clear_globs=False) + finally: + sys.stdout = old + + if failures: + raise self.failureException(self.format_failure(new.getvalue())) + + def format_failure(self, err): + test = self._dt_test + if test.lineno is None: + lineno = 'unknown line number' + else: + lineno = '%s' % test.lineno + lname = '.'.join(test.name.split('.')[-1:]) + return ('Failed doctest test for %s\n' + ' File "%s", line %s, in %s\n\n%s' + % (test.name, test.filename, lineno, lname, err) + ) + + def debug(self): + r"""Run the test case without results and without catching exceptions + + The unit test framework includes a debug method on test cases + and test suites to support post-mortem debugging. The test code + is run in such a way that errors are not caught. This way a + caller can catch the errors and initiate post-mortem debugging. + + The DocTestCase provides a debug method that raises + UnexpectedException errors if there is an unexpected + exception: + + >>> test = DocTestParser().get_doctest('>>> raise KeyError\n42', + ... {}, 'foo', 'foo.py', 0) + >>> case = DocTestCase(test) + >>> try: + ... case.debug() + ... except UnexpectedException, failure: + ... pass + + The UnexpectedException contains the test, the example, and + the original exception: + + >>> failure.test is test + True + + >>> failure.example.want + '42\n' + + >>> exc_info = failure.exc_info + >>> raise exc_info[0], exc_info[1], exc_info[2] + Traceback (most recent call last): + ... + KeyError + + If the output doesn't match, then a DocTestFailure is raised: + + >>> test = DocTestParser().get_doctest(''' + ... >>> x = 1 + ... >>> x + ... 2 + ... ''', {}, 'foo', 'foo.py', 0) + >>> case = DocTestCase(test) + + >>> try: + ... case.debug() + ... except DocTestFailure, failure: + ... pass + + DocTestFailure objects provide access to the test: + + >>> failure.test is test + True + + As well as to the example: + + >>> failure.example.want + '2\n' + + and the actual output: + + >>> failure.got + '1\n' + + """ + + self.setUp() + runner = DebugRunner(optionflags=self._dt_optionflags, + checker=self._dt_checker, verbose=False) + runner.run(self._dt_test, clear_globs=False) + self.tearDown() + + def id(self): + return self._dt_test.name + + def __eq__(self, other): + if type(self) is not type(other): + return NotImplemented + + return self._dt_test == other._dt_test and \ + self._dt_optionflags == other._dt_optionflags and \ + self._dt_setUp == other._dt_setUp and \ + self._dt_tearDown == other._dt_tearDown and \ + self._dt_checker == other._dt_checker + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self._dt_optionflags, self._dt_setUp, self._dt_tearDown, + self._dt_checker)) + + def __repr__(self): + name = self._dt_test.name.split('.') + return "%s (%s)" % (name[-1], '.'.join(name[:-1])) + + __str__ = __repr__ + + def shortDescription(self): + return "Doctest: " + self._dt_test.name + +class SkipDocTestCase(DocTestCase): + def __init__(self, module): + self.module = module + DocTestCase.__init__(self, None) + + def setUp(self): + self.skipTest("DocTestSuite will not work with -O2 and above") + + def test_skip(self): + pass + + def shortDescription(self): + return "Skipping tests from %s" % self.module.__name__ + + __str__ = shortDescription + + +def DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None, + **options): + """ + Convert doctest tests for a module to a unittest test suite. + + This converts each documentation string in a module that + contains doctest tests to a unittest test case. If any of the + tests in a doc string fail, then the test case fails. An exception + is raised showing the name of the file containing the test and a + (sometimes approximate) line number. + + The `module` argument provides the module to be tested. The argument + can be either a module or a module name. + + If no argument is given, the calling module is used. + + A number of options may be provided as keyword arguments: + + setUp + A set-up function. This is called before running the + tests in each file. The setUp function will be passed a DocTest + object. The setUp function can access the test globals as the + globs attribute of the test passed. + + tearDown + A tear-down function. This is called after running the + tests in each file. The tearDown function will be passed a DocTest + object. The tearDown function can access the test globals as the + globs attribute of the test passed. + + globs + A dictionary containing initial global variables for the tests. + + optionflags + A set of doctest option flags expressed as an integer. + """ + + if test_finder is None: + test_finder = DocTestFinder() + + module = _normalize_module(module) + tests = test_finder.find(module, globs=globs, extraglobs=extraglobs) + + if not tests and sys.flags.optimize >=2: + # Skip doctests when running with -O2 + suite = unittest.TestSuite() + suite.addTest(SkipDocTestCase(module)) + return suite + elif not tests: + # Why do we want to do this? Because it reveals a bug that might + # otherwise be hidden. + # It is probably a bug that this exception is not also raised if the + # number of doctest examples in tests is zero (i.e. if no doctest + # examples were found). However, we should probably not be raising + # an exception at all here, though it is too late to make this change + # for a maintenance release. See also issue #14649. + raise ValueError(module, "has no docstrings") + + tests.sort() + suite = unittest.TestSuite() + + for test in tests: + if len(test.examples) == 0: + continue + if not test.filename: + filename = module.__file__ + if filename[-4:] in (".pyc", ".pyo"): + filename = filename[:-1] + test.filename = filename + suite.addTest(DocTestCase(test, **options)) + + return suite + +class DocFileCase(DocTestCase): + + def id(self): + return '_'.join(self._dt_test.name.split('.')) + + def __repr__(self): + return self._dt_test.filename + __str__ = __repr__ + + def format_failure(self, err): + return ('Failed doctest test for %s\n File "%s", line 0\n\n%s' + % (self._dt_test.name, self._dt_test.filename, err) + ) + +def DocFileTest(path, module_relative=True, package=None, + globs=None, parser=DocTestParser(), + encoding=None, **options): + if globs is None: + globs = {} + else: + globs = globs.copy() + + if package and not module_relative: + raise ValueError("Package may only be specified for module-" + "relative paths.") + + # Relativize the path. + doc, path = _load_testfile(path, package, module_relative) + + if "__file__" not in globs: + globs["__file__"] = path + + # Find the file and read it. + name = os.path.basename(path) + + # If an encoding is specified, use it to convert the file to unicode + if encoding is not None: + doc = doc.decode(encoding) + + # Convert it to a test, and wrap it in a DocFileCase. + test = parser.get_doctest(doc, globs, name, path, 0) + return DocFileCase(test, **options) + +def DocFileSuite(*paths, **kw): + """A unittest suite for one or more doctest files. + + The path to each doctest file is given as a string; the + interpretation of that string depends on the keyword argument + "module_relative". + + A number of options may be provided as keyword arguments: + + module_relative + If "module_relative" is True, then the given file paths are + interpreted as os-independent module-relative paths. By + default, these paths are relative to the calling module's + directory; but if the "package" argument is specified, then + they are relative to that package. To ensure os-independence, + "filename" should use "/" characters to separate path + segments, and may not be an absolute path (i.e., it may not + begin with "/"). + + If "module_relative" is False, then the given file paths are + interpreted as os-specific paths. These paths may be absolute + or relative (to the current working directory). + + package + A Python package or the name of a Python package whose directory + should be used as the base directory for module relative paths. + If "package" is not specified, then the calling module's + directory is used as the base directory for module relative + filenames. It is an error to specify "package" if + "module_relative" is False. + + setUp + A set-up function. This is called before running the + tests in each file. The setUp function will be passed a DocTest + object. The setUp function can access the test globals as the + globs attribute of the test passed. + + tearDown + A tear-down function. This is called after running the + tests in each file. The tearDown function will be passed a DocTest + object. The tearDown function can access the test globals as the + globs attribute of the test passed. + + globs + A dictionary containing initial global variables for the tests. + + optionflags + A set of doctest option flags expressed as an integer. + + parser + A DocTestParser (or subclass) that should be used to extract + tests from the files. + + encoding + An encoding that will be used to convert the files to unicode. + """ + suite = unittest.TestSuite() + + # We do this here so that _normalize_module is called at the right + # level. If it were called in DocFileTest, then this function + # would be the caller and we might guess the package incorrectly. + if kw.get('module_relative', True): + kw['package'] = _normalize_module(kw.get('package')) + + for path in paths: + suite.addTest(DocFileTest(path, **kw)) + + return suite + +###################################################################### +## 9. Debugging Support +###################################################################### + +def script_from_examples(s): + r"""Extract script from text with examples. + + Converts text with examples to a Python script. Example input is + converted to regular code. Example output and all other words + are converted to comments: + + >>> text = ''' + ... Here are examples of simple math. + ... + ... Python has super accurate integer addition + ... + ... >>> 2 + 2 + ... 5 + ... + ... And very friendly error messages: + ... + ... >>> 1/0 + ... To Infinity + ... And + ... Beyond + ... + ... You can use logic if you want: + ... + ... >>> if 0: + ... ... blah + ... ... blah + ... ... + ... + ... Ho hum + ... ''' + + >>> print script_from_examples(text) + # Here are examples of simple math. + # + # Python has super accurate integer addition + # + 2 + 2 + # Expected: + ## 5 + # + # And very friendly error messages: + # + 1/0 + # Expected: + ## To Infinity + ## And + ## Beyond + # + # You can use logic if you want: + # + if 0: + blah + blah + # + # Ho hum + + """ + output = [] + for piece in DocTestParser().parse(s): + if isinstance(piece, Example): + # Add the example's source code (strip trailing NL) + output.append(piece.source[:-1]) + # Add the expected output: + want = piece.want + if want: + output.append('# Expected:') + output += ['## '+l for l in want.split('\n')[:-1]] + else: + # Add non-example text. + output += [_comment_line(l) + for l in piece.split('\n')[:-1]] + + # Trim junk on both ends. + while output and output[-1] == '#': + output.pop() + while output and output[0] == '#': + output.pop(0) + # Combine the output, and return it. + # Add a courtesy newline to prevent exec from choking (see bug #1172785) + return '\n'.join(output) + '\n' + +def testsource(module, name): + """Extract the test sources from a doctest docstring as a script. + + Provide the module (or dotted name of the module) containing the + test to be debugged and the name (within the module) of the object + with the doc string with tests to be debugged. + """ + module = _normalize_module(module) + tests = DocTestFinder().find(module) + test = [t for t in tests if t.name == name] + if not test: + raise ValueError(name, "not found in tests") + test = test[0] + testsrc = script_from_examples(test.docstring) + return testsrc + +def debug_src(src, pm=False, globs=None): + """Debug a single doctest docstring, in argument `src`'""" + testsrc = script_from_examples(src) + debug_script(testsrc, pm, globs) + +def debug_script(src, pm=False, globs=None): + "Debug a test script. `src` is the script, as a string." + import pdb + + # Note that tempfile.NameTemporaryFile() cannot be used. As the + # docs say, a file so created cannot be opened by name a second time + # on modern Windows boxes, and execfile() needs to open it. + srcfilename = tempfile.mktemp(".py", "doctestdebug") + f = open(srcfilename, 'w') + f.write(src) + f.close() + + try: + if globs: + globs = globs.copy() + else: + globs = {} + + if pm: + try: + execfile(srcfilename, globs, globs) + except: + print sys.exc_info()[1] + pdb.post_mortem(sys.exc_info()[2]) + else: + # Note that %r is vital here. '%s' instead can, e.g., cause + # backslashes to get treated as metacharacters on Windows. + pdb.run("execfile(%r)" % srcfilename, globs, globs) + + finally: + os.remove(srcfilename) + +def debug(module, name, pm=False): + """Debug a single doctest docstring. + + Provide the module (or dotted name of the module) containing the + test to be debugged and the name (within the module) of the object + with the docstring with tests to be debugged. + """ + module = _normalize_module(module) + testsrc = testsource(module, name) + debug_script(testsrc, pm, module.__dict__) + +###################################################################### +## 10. Example Usage +###################################################################### +class _TestClass: + """ + A pointless class, for sanity-checking of docstring testing. + + Methods: + square() + get() + + >>> _TestClass(13).get() + _TestClass(-12).get() + 1 + >>> hex(_TestClass(13).square().get()) + '0xa9' + """ + + def __init__(self, val): + """val -> _TestClass object with associated value val. + + >>> t = _TestClass(123) + >>> print t.get() + 123 + """ + + self.val = val + + def square(self): + """square() -> square TestClass's associated value + + >>> _TestClass(13).square().get() + 169 + """ + + self.val = self.val ** 2 + return self + + def get(self): + """get() -> return TestClass's associated value. + + >>> x = _TestClass(-42) + >>> print x.get() + -42 + """ + + return self.val + +__test__ = {"_TestClass": _TestClass, + "string": r""" + Example of a string object, searched as-is. + >>> x = 1; y = 2 + >>> x + y, x * y + (3, 2) + """, + + "bool-int equivalence": r""" + In 2.2, boolean expressions displayed + 0 or 1. By default, we still accept + them. This can be disabled by passing + DONT_ACCEPT_TRUE_FOR_1 to the new + optionflags argument. + >>> 4 == 4 + 1 + >>> 4 == 4 + True + >>> 4 > 4 + 0 + >>> 4 > 4 + False + """, + + "blank lines": r""" + Blank lines can be marked with : + >>> print 'foo\n\nbar\n' + foo + + bar + + """, + + "ellipsis": r""" + If the ellipsis flag is used, then '...' can be used to + elide substrings in the desired output: + >>> print range(1000) #doctest: +ELLIPSIS + [0, 1, 2, ..., 999] + """, + + "whitespace normalization": r""" + If the whitespace normalization flag is used, then + differences in whitespace are ignored. + >>> print range(30) #doctest: +NORMALIZE_WHITESPACE + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29] + """, + } + + +def _test(): + testfiles = [arg for arg in sys.argv[1:] if arg and arg[0] != '-'] + if not testfiles: + name = os.path.basename(sys.argv[0]) + if '__loader__' in globals(): # python -m + name, _ = os.path.splitext(name) + print("usage: {0} [-v] file ...".format(name)) + return 2 + for filename in testfiles: + if filename.endswith(".py"): + # It is a module -- insert its dir into sys.path and try to + # import it. If it is part of a package, that possibly + # won't work because of package imports. + dirname, filename = os.path.split(filename) + sys.path.insert(0, dirname) + m = __import__(filename[:-3]) + del sys.path[0] + failures, _ = testmod(m) + else: + failures, _ = testfile(filename, module_relative=False) + if failures: + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(_test()) diff --git a/PythonHome/Lib/doctest.pyc b/PythonHome/Lib/doctest.pyc deleted file mode 100644 index faeedb901d495e9fbf2af8485d41e91703ade31b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81866 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

6`Q?K3lcV@~f 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 diff --git a/PythonHome/Lib/dumbdbm.py b/PythonHome/Lib/dumbdbm.py new file mode 100644 index 0000000000..4a0c3a7852 --- /dev/null +++ b/PythonHome/Lib/dumbdbm.py @@ -0,0 +1,246 @@ +"""A dumb and slow but simple dbm clone. + +For database spam, spam.dir contains the index (a text file), +spam.bak *may* contain a backup of the index (also a text file), +while spam.dat contains the data (a binary file). + +XXX TO DO: + +- seems to contain a bug when updating... + +- reclaim free space (currently, space once occupied by deleted or expanded +items is never reused) + +- support concurrent access (currently, if two processes take turns making +updates, they can mess up the index) + +- support efficient access to large databases (currently, the whole index +is read when the database is opened, and some updates rewrite the whole index) + +- support opening for read-only (flag = 'm') + +""" + +import os as _os +import __builtin__ +import UserDict + +_open = __builtin__.open + +_BLOCKSIZE = 512 + +error = IOError # For anydbm + +class _Database(UserDict.DictMixin): + + # The on-disk directory and data files can remain in mutually + # inconsistent states for an arbitrarily long time (see comments + # at the end of __setitem__). This is only repaired when _commit() + # gets called. One place _commit() gets called is from __del__(), + # and if that occurs at program shutdown time, module globals may + # already have gotten rebound to None. Since it's crucial that + # _commit() finish successfully, we can't ignore shutdown races + # here, and _commit() must not reference any globals. + _os = _os # for _commit() + _open = _open # for _commit() + + def __init__(self, filebasename, mode): + self._mode = mode + + # The directory file is a text file. Each line looks like + # "%r, (%d, %d)\n" % (key, pos, siz) + # where key is the string key, pos is the offset into the dat + # file of the associated value's first byte, and siz is the number + # of bytes in the associated value. + self._dirfile = filebasename + _os.extsep + 'dir' + + # The data file is a binary file pointed into by the directory + # file, and holds the values associated with keys. Each value + # begins at a _BLOCKSIZE-aligned byte offset, and is a raw + # binary 8-bit string value. + self._datfile = filebasename + _os.extsep + 'dat' + self._bakfile = filebasename + _os.extsep + 'bak' + + # The index is an in-memory dict, mirroring the directory file. + self._index = None # maps keys to (pos, siz) pairs + + # Mod by Jack: create data file if needed + try: + f = _open(self._datfile, 'r') + except IOError: + with _open(self._datfile, 'w') as f: + self._chmod(self._datfile) + else: + f.close() + self._update() + + # Read directory file into the in-memory index dict. + def _update(self): + self._index = {} + try: + f = _open(self._dirfile) + except IOError: + pass + else: + with f: + for line in f: + line = line.rstrip() + key, pos_and_siz_pair = eval(line) + self._index[key] = pos_and_siz_pair + + # Write the index dict to the directory file. The original directory + # file (if any) is renamed with a .bak extension first. If a .bak + # file currently exists, it's deleted. + def _commit(self): + # CAUTION: It's vital that _commit() succeed, and _commit() can + # be called from __del__(). Therefore we must never reference a + # global in this routine. + if self._index is None: + return # nothing to do + + try: + self._os.unlink(self._bakfile) + except self._os.error: + pass + + try: + self._os.rename(self._dirfile, self._bakfile) + except self._os.error: + pass + + with self._open(self._dirfile, 'w') as f: + self._chmod(self._dirfile) + for key, pos_and_siz_pair in self._index.iteritems(): + f.write("%r, %r\n" % (key, pos_and_siz_pair)) + + sync = _commit + + def __getitem__(self, key): + pos, siz = self._index[key] # may raise KeyError + with _open(self._datfile, 'rb') as f: + f.seek(pos) + dat = f.read(siz) + return dat + + # Append val to the data file, starting at a _BLOCKSIZE-aligned + # offset. The data file is first padded with NUL bytes (if needed) + # to get to an aligned offset. Return pair + # (starting offset of val, len(val)) + def _addval(self, val): + with _open(self._datfile, 'rb+') as f: + f.seek(0, 2) + pos = int(f.tell()) + npos = ((pos + _BLOCKSIZE - 1) // _BLOCKSIZE) * _BLOCKSIZE + f.write('\0'*(npos-pos)) + pos = npos + f.write(val) + return (pos, len(val)) + + # Write val to the data file, starting at offset pos. The caller + # is responsible for ensuring that there's enough room starting at + # pos to hold val, without overwriting some other value. Return + # pair (pos, len(val)). + def _setval(self, pos, val): + with _open(self._datfile, 'rb+') as f: + f.seek(pos) + f.write(val) + return (pos, len(val)) + + # key is a new key whose associated value starts in the data file + # at offset pos and with length siz. Add an index record to + # the in-memory index dict, and append one to the directory file. + def _addkey(self, key, pos_and_siz_pair): + self._index[key] = pos_and_siz_pair + with _open(self._dirfile, 'a') as f: + self._chmod(self._dirfile) + f.write("%r, %r\n" % (key, pos_and_siz_pair)) + + def __setitem__(self, key, val): + if not type(key) == type('') == type(val): + raise TypeError, "keys and values must be strings" + if key not in self._index: + self._addkey(key, self._addval(val)) + else: + # See whether the new value is small enough to fit in the + # (padded) space currently occupied by the old value. + pos, siz = self._index[key] + oldblocks = (siz + _BLOCKSIZE - 1) // _BLOCKSIZE + newblocks = (len(val) + _BLOCKSIZE - 1) // _BLOCKSIZE + if newblocks <= oldblocks: + self._index[key] = self._setval(pos, val) + else: + # The new value doesn't fit in the (padded) space used + # by the old value. The blocks used by the old value are + # forever lost. + self._index[key] = self._addval(val) + + # Note that _index may be out of synch with the directory + # file now: _setval() and _addval() don't update the directory + # file. This also means that the on-disk directory and data + # files are in a mutually inconsistent state, and they'll + # remain that way until _commit() is called. Note that this + # is a disaster (for the database) if the program crashes + # (so that _commit() never gets called). + + def __delitem__(self, key): + # The blocks used by the associated value are lost. + del self._index[key] + # XXX It's unclear why we do a _commit() here (the code always + # XXX has, so I'm not changing it). _setitem__ doesn't try to + # XXX keep the directory file in synch. Why should we? Or + # XXX why shouldn't __setitem__? + self._commit() + + def keys(self): + return self._index.keys() + + def has_key(self, key): + return key in self._index + + def __contains__(self, key): + return key in self._index + + def iterkeys(self): + return self._index.iterkeys() + __iter__ = iterkeys + + def __len__(self): + return len(self._index) + + def close(self): + self._commit() + self._index = self._datfile = self._dirfile = self._bakfile = None + + __del__ = close + + def _chmod (self, file): + if hasattr(self._os, 'chmod'): + self._os.chmod(file, self._mode) + + +def open(file, flag=None, mode=0666): + """Open the database file, filename, and return corresponding object. + + The flag argument, used to control how the database is opened in the + other DBM implementations, is ignored in the dumbdbm module; the + database is always opened for update, and will be created if it does + not exist. + + The optional mode argument is the UNIX mode of the file, used only when + the database has to be created. It defaults to octal code 0666 (and + will be modified by the prevailing umask). + + """ + # flag argument is currently ignored + + # Modify mode depending on the umask + try: + um = _os.umask(0) + _os.umask(um) + except AttributeError: + pass + else: + # Turn off any bits that are set in the umask + mode = mode & (~um) + + return _Database(file, mode) diff --git a/PythonHome/Lib/dumbdbm.pyc b/PythonHome/Lib/dumbdbm.pyc deleted file mode 100644 index c12f4872d65e76b56f205a8ce9b1110f39a7095a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6242 zcmcgw&2QYs6(5qTm3AfDvMoza;xv<_Y1WRcBuEh;iIXP&DB#wSQOZG7!70HdXC->M zVd+X`b?<@O8t0ek>p}bomZc^YG;nktCdpaHs zx;o5aU8ecI?v5&5CWB#Wble^2D9tmo(Qbb~FLWGMVK*#|E{EY@UCNC(DRh))RhVR@ zuJ(*hve?|!olsZiZl!xkYR<2>xnQFk_VtB9IKD7hphMjaqyA{9^WLGgX_;f}Ac6fo z5UO_!s|f+SBiZ7H-6RW(vE33JZ*OnwTQ~L9n{T$;7jNyhQquNL2A-Ej3QH(hqg)p%YLqhMb04u{=>e})u;g0 zgRl>l+rqmk*NNX)M`5N1qykK*$~d&4>GhH*fhd#x07)7ayU=#6-NP)9%Klys@I|q0 z2ve9aw!m?4vW#NpLz9_!-5OIqFcw+xU6}m>Uriy@Kj0YPqYG0)Pm?)1`d zSHG=a9K49x$$#*-nJCz8)q({FS8JvtG~~}gc^O~%1quU)a+HD9yL1^kk)mI~gWzSX zh&Qm(RHjK+f}SMZfzqPXX(dypCx zM^%oxoM zorolf289+&xQ|L=m8jJCG%bNxy9%1P??8hmp+QeH_%bz^{Qzol)aUOh=k6OciK`#I zs_w&-TxuSwLLFkG2?Dpp3hu*n@E=sMkEbqu{Eqt2>R5D1mNrGBK9%JkXF-SbPoNMq zi?S+`p#Wn(3DXWG@K3W?cg%-yx zJ>rVs>8S1T(~|{Fsmx0$PV|UnpH7yMm~}aX8b|zTlR9I6t0u&q?|xSr=xtL$S3i1Q z6eGHU0^wme#TgAe)pOM-vSF-J#`Lok@*DqOMT}ZS?&` zwzy_xSv7ykgjsT4rI5! zPodHDsP;9S0%!62B)%2Ggh{wKA~Xm-XIE%vsB?h~0cm#Ckbwr=K)PU*b;K`eh(-4$ z1S~`?ik>ifNT^qG4YkpO!uj9k2p1$-C74zwO)Cxsmv7v>^24p`JJ&BBT- zL!hw`e}{7#C^Ddb6xMWtAdF+I{u!zgvlUQYMg&>KZxfjR?|FQUTRepJvo)58#Wgel zc4lccPB^;-TRSM`>GYv9+j_KtB3d(rw zpls~C!qF`h(D2lqEPcX-QZveSBq)jM!$VPtX8iC; z!Z0I(ACP$(P99%o=oQDyFDaFkndj=V)h88CBN3UuLWTMi`$dHg=R|v^|GJVfMHC6lvl?iaX-(xAEFR~G9Uy4 zhx*Zp|2T>qRs2N=!QsRiLEG*Rx|gz5X-xK=4Tusb@g@WWBF~@zI;Gs$VHzXc)d!=p z(p|iKaDHdIrFg6OsrXYh9vTV$w@{J0lhxa6pya>8Vx0wT)qfR5hZx%fL6j#3E2jG* z282?c#@#fJ`lYlovu|5RS+tFiFliehe+6>&JzxW8{|V<@<23yDEb8axBv#VR_=&c8 z<03Aixwlz^y5SLmkiFh;t`+V%)Z{Rj3G#T{;ZbP0`#mU>1YWuAxrp>9pK!xt#d2fW z*y=pQf?!Wg$$+qN1PA_Gp!o-UCFM}|z+{!*Y*TBYu!1Js({9RAtQ`3848Gy|{ zqWXW^mlv5Jm?R;B;Lis(pP-ZF6dikYDP9u3<&|3pQhR$rv=uKU zflY)*JeK)zvrn|z2=THkd>h1V-7j9A}ZwO>LxPeDo!7zQNj?Ea@oH=U;2dZxA9TE*{T>v*fxYPOz2iAN~@ zx#;y;ji#G?0S}tqfrz;n*9}z0nwo<**#i@IL))|$YCMMc8g=FM^qM?_mhc+IY2~RC z@ABa(Hwd0}yfRX!<-f7lO}x-0T{O)vQDN(n-6Qfg$y697!;sTMcCH-eSNp2$n?DBTB}*SGCRoouyu3K)`UV=7c=AHo6w zomkB{+0gnr7%{zYlvXm9M-?`Wxaljezy3N>u~{sHCNhAZq*td&Nqkr!Baq;|xvNKm zu z{Qt!4l3S={4;P1%Od)uSuFXS{lOTxm2)<6Tc_}_#+3QDll%z-N&N%&g*OeVES&MpySAG$y=`P`hv*glMo9+`| F{uh9NtW*F1 diff --git a/PythonHome/Lib/dummy_thread.py b/PythonHome/Lib/dummy_thread.py new file mode 100644 index 0000000000..198dc49dba --- /dev/null +++ b/PythonHome/Lib/dummy_thread.py @@ -0,0 +1,145 @@ +"""Drop-in replacement for the thread module. + +Meant to be used as a brain-dead substitute so that threaded code does +not need to be rewritten for when the thread module is not present. + +Suggested usage is:: + + try: + import thread + except ImportError: + import dummy_thread as thread + +""" +# Exports only things specified by thread documentation; +# skipping obsolete synonyms allocate(), start_new(), exit_thread(). +__all__ = ['error', 'start_new_thread', 'exit', 'get_ident', 'allocate_lock', + 'interrupt_main', 'LockType'] + +import traceback as _traceback + +class error(Exception): + """Dummy implementation of thread.error.""" + + def __init__(self, *args): + self.args = args + +def start_new_thread(function, args, kwargs={}): + """Dummy implementation of thread.start_new_thread(). + + Compatibility is maintained by making sure that ``args`` is a + tuple and ``kwargs`` is a dictionary. If an exception is raised + and it is SystemExit (which can be done by thread.exit()) it is + caught and nothing is done; all other exceptions are printed out + by using traceback.print_exc(). + + If the executed function calls interrupt_main the KeyboardInterrupt will be + raised when the function returns. + + """ + if type(args) != type(tuple()): + raise TypeError("2nd arg must be a tuple") + if type(kwargs) != type(dict()): + raise TypeError("3rd arg must be a dict") + global _main + _main = False + try: + function(*args, **kwargs) + except SystemExit: + pass + except: + _traceback.print_exc() + _main = True + global _interrupt + if _interrupt: + _interrupt = False + raise KeyboardInterrupt + +def exit(): + """Dummy implementation of thread.exit().""" + raise SystemExit + +def get_ident(): + """Dummy implementation of thread.get_ident(). + + Since this module should only be used when threadmodule is not + available, it is safe to assume that the current process is the + only thread. Thus a constant can be safely returned. + """ + return -1 + +def allocate_lock(): + """Dummy implementation of thread.allocate_lock().""" + return LockType() + +def stack_size(size=None): + """Dummy implementation of thread.stack_size().""" + if size is not None: + raise error("setting thread stack size not supported") + return 0 + +class LockType(object): + """Class implementing dummy implementation of thread.LockType. + + Compatibility is maintained by maintaining self.locked_status + which is a boolean that stores the state of the lock. Pickling of + the lock, though, should not be done since if the thread module is + then used with an unpickled ``lock()`` from here problems could + occur from this class not having atomic methods. + + """ + + def __init__(self): + self.locked_status = False + + def acquire(self, waitflag=None): + """Dummy implementation of acquire(). + + For blocking calls, self.locked_status is automatically set to + True and returned appropriately based on value of + ``waitflag``. If it is non-blocking, then the value is + actually checked and not set if it is already acquired. This + is all done so that threading.Condition's assert statements + aren't triggered and throw a little fit. + + """ + if waitflag is None or waitflag: + self.locked_status = True + return True + else: + if not self.locked_status: + self.locked_status = True + return True + else: + return False + + __enter__ = acquire + + def __exit__(self, typ, val, tb): + self.release() + + def release(self): + """Release the dummy lock.""" + # XXX Perhaps shouldn't actually bother to test? Could lead + # to problems for complex, threaded code. + if not self.locked_status: + raise error + self.locked_status = False + return True + + def locked(self): + return self.locked_status + +# Used to signal that interrupt_main was called in a "thread" +_interrupt = False +# True when not executing in a "thread" +_main = True + +def interrupt_main(): + """Set _interrupt flag to True to have start_new_thread raise + KeyboardInterrupt upon exiting.""" + if _main: + raise KeyboardInterrupt + else: + global _interrupt + _interrupt = True diff --git a/PythonHome/Lib/dummy_thread.pyc b/PythonHome/Lib/dummy_thread.pyc deleted file mode 100644 index 8108412edf995a25f09932594012f6cbf144f1fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5169 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 E0`IUoFaQ7m diff --git a/PythonHome/Lib/email/__init__.py b/PythonHome/Lib/email/__init__.py new file mode 100644 index 0000000000..a780ebe339 --- /dev/null +++ b/PythonHome/Lib/email/__init__.py @@ -0,0 +1,123 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""A package for parsing, handling, and generating email messages.""" + +__version__ = '4.0.3' + +__all__ = [ + # Old names + 'base64MIME', + 'Charset', + 'Encoders', + 'Errors', + 'Generator', + 'Header', + 'Iterators', + 'Message', + 'MIMEAudio', + 'MIMEBase', + 'MIMEImage', + 'MIMEMessage', + 'MIMEMultipart', + 'MIMENonMultipart', + 'MIMEText', + 'Parser', + 'quopriMIME', + 'Utils', + 'message_from_string', + 'message_from_file', + # new names + 'base64mime', + 'charset', + 'encoders', + 'errors', + 'generator', + 'header', + 'iterators', + 'message', + 'mime', + 'parser', + 'quoprimime', + 'utils', + ] + + + +# Some convenience routines. Don't import Parser and Message as side-effects +# of importing email since those cascadingly import most of the rest of the +# email package. +def message_from_string(s, *args, **kws): + """Parse a string into a Message object model. + + Optional _class and strict are passed to the Parser constructor. + """ + from email.parser import Parser + return Parser(*args, **kws).parsestr(s) + + +def message_from_file(fp, *args, **kws): + """Read a file and parse its contents into a Message object model. + + Optional _class and strict are passed to the Parser constructor. + """ + from email.parser import Parser + return Parser(*args, **kws).parse(fp) + + + +# Lazy loading to provide name mapping from new-style names (PEP 8 compatible +# email 4.0 module names), to old-style names (email 3.0 module names). +import sys + +class LazyImporter(object): + def __init__(self, module_name): + self.__name__ = 'email.' + module_name + + def __getattr__(self, name): + __import__(self.__name__) + mod = sys.modules[self.__name__] + self.__dict__.update(mod.__dict__) + return getattr(mod, name) + + +_LOWERNAMES = [ + # email. -> email. + 'Charset', + 'Encoders', + 'Errors', + 'FeedParser', + 'Generator', + 'Header', + 'Iterators', + 'Message', + 'Parser', + 'Utils', + 'base64MIME', + 'quopriMIME', + ] + +_MIMENAMES = [ + # email.MIME -> email.mime. + 'Audio', + 'Base', + 'Image', + 'Message', + 'Multipart', + 'NonMultipart', + 'Text', + ] + +for _name in _LOWERNAMES: + importer = LazyImporter(_name.lower()) + sys.modules['email.' + _name] = importer + setattr(sys.modules['email'], _name, importer) + + +import email.mime +for _name in _MIMENAMES: + importer = LazyImporter('mime.' + _name.lower()) + sys.modules['email.MIME' + _name] = importer + setattr(sys.modules['email'], 'MIME' + _name, importer) + setattr(sys.modules['email.mime'], _name, importer) diff --git a/PythonHome/Lib/email/__init__.pyc b/PythonHome/Lib/email/__init__.pyc index c037387473c77cbd74acd3a9ff9d3ab1023627dd..b6bfa1303e5e7f2573f23682f2a8730dca29f05a 100644 GIT binary patch delta 353 zcmbOw_Dp=k4;Djb1_p*ytC;l6l8n-%nDG1xJ+EMYzn}o;82{3eg3^*0m(--v^q7Fk zl8pR3kNn)!$?+Uwn`K!I7|GK*xrpr|SvtihXR<#hOJ^2Yy2LiW= 0: + data[0] = data[0][i+1:] + if len(data) == 3: # RFC 850 date, deprecated + stuff = data[0].split('-') + if len(stuff) == 3: + data = stuff + data[1:] + if len(data) == 4: + s = data[3] + i = s.find('+') + if i > 0: + data[3:] = [s[:i], s[i+1:]] + else: + data.append('') # Dummy tz + if len(data) < 5: + return None + data = data[:5] + [dd, mm, yy, tm, tz] = data + mm = mm.lower() + if mm not in _monthnames: + dd, mm = mm, dd.lower() + if mm not in _monthnames: + return None + mm = _monthnames.index(mm) + 1 + if mm > 12: + mm -= 12 + if dd[-1] == ',': + dd = dd[:-1] + i = yy.find(':') + if i > 0: + yy, tm = tm, yy + if yy[-1] == ',': + yy = yy[:-1] + if not yy[0].isdigit(): + yy, tz = tz, yy + if tm[-1] == ',': + tm = tm[:-1] + tm = tm.split(':') + if len(tm) == 2: + [thh, tmm] = tm + tss = '0' + elif len(tm) == 3: + [thh, tmm, tss] = tm + else: + return None + try: + yy = int(yy) + dd = int(dd) + thh = int(thh) + tmm = int(tmm) + tss = int(tss) + except ValueError: + return None + # Check for a yy specified in two-digit format, then convert it to the + # appropriate four-digit format, according to the POSIX standard. RFC 822 + # calls for a two-digit yy, but RFC 2822 (which obsoletes RFC 822) + # mandates a 4-digit yy. For more information, see the documentation for + # the time module. + if yy < 100: + # The year is between 1969 and 1999 (inclusive). + if yy > 68: + yy += 1900 + # The year is between 2000 and 2068 (inclusive). + else: + yy += 2000 + tzoffset = None + tz = tz.upper() + if tz in _timezones: + tzoffset = _timezones[tz] + else: + try: + tzoffset = int(tz) + except ValueError: + pass + # Convert a timezone offset into seconds ; -0500 -> -18000 + if tzoffset: + if tzoffset < 0: + tzsign = -1 + tzoffset = -tzoffset + else: + tzsign = 1 + tzoffset = tzsign * ( (tzoffset//100)*3600 + (tzoffset % 100)*60) + # Daylight Saving Time flag is set to -1, since DST is unknown. + return yy, mm, dd, thh, tmm, tss, 0, 1, -1, tzoffset + + +def parsedate(data): + """Convert a time string to a time tuple.""" + t = parsedate_tz(data) + if isinstance(t, tuple): + return t[:9] + else: + return t + + +def mktime_tz(data): + """Turn a 10-tuple as returned by parsedate_tz() into a POSIX timestamp.""" + if data[9] is None: + # No zone info, so localtime is better assumption than GMT + return time.mktime(data[:8] + (-1,)) + else: + t = calendar.timegm(data) + return t - data[9] + + +def quote(str): + """Prepare string to be used in a quoted string. + + Turns backslash and double quote characters into quoted pairs. These + are the only characters that need to be quoted inside a quoted string. + Does not add the surrounding double quotes. + """ + return str.replace('\\', '\\\\').replace('"', '\\"') + + +class AddrlistClass: + """Address parser class by Ben Escoto. + + To understand what this class does, it helps to have a copy of RFC 2822 in + front of you. + + Note: this class interface is deprecated and may be removed in the future. + Use rfc822.AddressList instead. + """ + + def __init__(self, field): + """Initialize a new instance. + + `field' is an unparsed address header field, containing + one or more addresses. + """ + self.specials = '()<>@,:;.\"[]' + self.pos = 0 + self.LWS = ' \t' + self.CR = '\r\n' + self.FWS = self.LWS + self.CR + self.atomends = self.specials + self.LWS + self.CR + # Note that RFC 2822 now specifies `.' as obs-phrase, meaning that it + # is obsolete syntax. RFC 2822 requires that we recognize obsolete + # syntax, so allow dots in phrases. + self.phraseends = self.atomends.replace('.', '') + self.field = field + self.commentlist = [] + + def gotonext(self): + """Parse up to the start of the next address.""" + while self.pos < len(self.field): + if self.field[self.pos] in self.LWS + '\n\r': + self.pos += 1 + elif self.field[self.pos] == '(': + self.commentlist.append(self.getcomment()) + else: + break + + def getaddrlist(self): + """Parse all addresses. + + Returns a list containing all of the addresses. + """ + result = [] + while self.pos < len(self.field): + ad = self.getaddress() + if ad: + result += ad + else: + result.append(('', '')) + return result + + def getaddress(self): + """Parse the next address.""" + self.commentlist = [] + self.gotonext() + + oldpos = self.pos + oldcl = self.commentlist + plist = self.getphraselist() + + self.gotonext() + returnlist = [] + + if self.pos >= len(self.field): + # Bad email address technically, no domain. + if plist: + returnlist = [(SPACE.join(self.commentlist), plist[0])] + + elif self.field[self.pos] in '.@': + # email address is just an addrspec + # this isn't very efficient since we start over + self.pos = oldpos + self.commentlist = oldcl + addrspec = self.getaddrspec() + returnlist = [(SPACE.join(self.commentlist), addrspec)] + + elif self.field[self.pos] == ':': + # address is a group + returnlist = [] + + fieldlen = len(self.field) + self.pos += 1 + while self.pos < len(self.field): + self.gotonext() + if self.pos < fieldlen and self.field[self.pos] == ';': + self.pos += 1 + break + returnlist = returnlist + self.getaddress() + + elif self.field[self.pos] == '<': + # Address is a phrase then a route addr + routeaddr = self.getrouteaddr() + + if self.commentlist: + returnlist = [(SPACE.join(plist) + ' (' + + ' '.join(self.commentlist) + ')', routeaddr)] + else: + returnlist = [(SPACE.join(plist), routeaddr)] + + else: + if plist: + returnlist = [(SPACE.join(self.commentlist), plist[0])] + elif self.field[self.pos] in self.specials: + self.pos += 1 + + self.gotonext() + if self.pos < len(self.field) and self.field[self.pos] == ',': + self.pos += 1 + return returnlist + + def getrouteaddr(self): + """Parse a route address (Return-path value). + + This method just skips all the route stuff and returns the addrspec. + """ + if self.field[self.pos] != '<': + return + + expectroute = False + self.pos += 1 + self.gotonext() + adlist = '' + while self.pos < len(self.field): + if expectroute: + self.getdomain() + expectroute = False + elif self.field[self.pos] == '>': + self.pos += 1 + break + elif self.field[self.pos] == '@': + self.pos += 1 + expectroute = True + elif self.field[self.pos] == ':': + self.pos += 1 + else: + adlist = self.getaddrspec() + self.pos += 1 + break + self.gotonext() + + return adlist + + def getaddrspec(self): + """Parse an RFC 2822 addr-spec.""" + aslist = [] + + self.gotonext() + while self.pos < len(self.field): + if self.field[self.pos] == '.': + aslist.append('.') + self.pos += 1 + elif self.field[self.pos] == '"': + aslist.append('"%s"' % quote(self.getquote())) + elif self.field[self.pos] in self.atomends: + break + else: + aslist.append(self.getatom()) + self.gotonext() + + if self.pos >= len(self.field) or self.field[self.pos] != '@': + return EMPTYSTRING.join(aslist) + + aslist.append('@') + self.pos += 1 + self.gotonext() + return EMPTYSTRING.join(aslist) + self.getdomain() + + def getdomain(self): + """Get the complete domain name from an address.""" + sdlist = [] + while self.pos < len(self.field): + if self.field[self.pos] in self.LWS: + self.pos += 1 + elif self.field[self.pos] == '(': + self.commentlist.append(self.getcomment()) + elif self.field[self.pos] == '[': + sdlist.append(self.getdomainliteral()) + elif self.field[self.pos] == '.': + self.pos += 1 + sdlist.append('.') + elif self.field[self.pos] in self.atomends: + break + else: + sdlist.append(self.getatom()) + return EMPTYSTRING.join(sdlist) + + def getdelimited(self, beginchar, endchars, allowcomments=True): + """Parse a header fragment delimited by special characters. + + `beginchar' is the start character for the fragment. + If self is not looking at an instance of `beginchar' then + getdelimited returns the empty string. + + `endchars' is a sequence of allowable end-delimiting characters. + Parsing stops when one of these is encountered. + + If `allowcomments' is non-zero, embedded RFC 2822 comments are allowed + within the parsed fragment. + """ + if self.field[self.pos] != beginchar: + return '' + + slist = [''] + quote = False + self.pos += 1 + while self.pos < len(self.field): + if quote: + slist.append(self.field[self.pos]) + quote = False + elif self.field[self.pos] in endchars: + self.pos += 1 + break + elif allowcomments and self.field[self.pos] == '(': + slist.append(self.getcomment()) + continue # have already advanced pos from getcomment + elif self.field[self.pos] == '\\': + quote = True + else: + slist.append(self.field[self.pos]) + self.pos += 1 + + return EMPTYSTRING.join(slist) + + def getquote(self): + """Get a quote-delimited fragment from self's field.""" + return self.getdelimited('"', '"\r', False) + + def getcomment(self): + """Get a parenthesis-delimited fragment from self's field.""" + return self.getdelimited('(', ')\r', True) + + def getdomainliteral(self): + """Parse an RFC 2822 domain-literal.""" + return '[%s]' % self.getdelimited('[', ']\r', False) + + def getatom(self, atomends=None): + """Parse an RFC 2822 atom. + + Optional atomends specifies a different set of end token delimiters + (the default is to use self.atomends). This is used e.g. in + getphraselist() since phrase endings must not include the `.' (which + is legal in phrases).""" + atomlist = [''] + if atomends is None: + atomends = self.atomends + + while self.pos < len(self.field): + if self.field[self.pos] in atomends: + break + else: + atomlist.append(self.field[self.pos]) + self.pos += 1 + + return EMPTYSTRING.join(atomlist) + + def getphraselist(self): + """Parse a sequence of RFC 2822 phrases. + + A phrase is a sequence of words, which are in turn either RFC 2822 + atoms or quoted-strings. Phrases are canonicalized by squeezing all + runs of continuous whitespace into one space. + """ + plist = [] + + while self.pos < len(self.field): + if self.field[self.pos] in self.FWS: + self.pos += 1 + elif self.field[self.pos] == '"': + plist.append(self.getquote()) + elif self.field[self.pos] == '(': + self.commentlist.append(self.getcomment()) + elif self.field[self.pos] in self.phraseends: + break + else: + plist.append(self.getatom(self.phraseends)) + + return plist + +class AddressList(AddrlistClass): + """An AddressList encapsulates a list of parsed RFC 2822 addresses.""" + def __init__(self, field): + AddrlistClass.__init__(self, field) + if field: + self.addresslist = self.getaddrlist() + else: + self.addresslist = [] + + def __len__(self): + return len(self.addresslist) + + def __add__(self, other): + # Set union + newaddr = AddressList(None) + newaddr.addresslist = self.addresslist[:] + for x in other.addresslist: + if not x in self.addresslist: + newaddr.addresslist.append(x) + return newaddr + + def __iadd__(self, other): + # Set union, in-place + for x in other.addresslist: + if not x in self.addresslist: + self.addresslist.append(x) + return self + + def __sub__(self, other): + # Set difference + newaddr = AddressList(None) + for x in self.addresslist: + if not x in other.addresslist: + newaddr.addresslist.append(x) + return newaddr + + def __isub__(self, other): + # Set difference, in-place + for x in other.addresslist: + if x in self.addresslist: + self.addresslist.remove(x) + return self + + def __getitem__(self, index): + # Make indexing, slices, and 'in' work + return self.addresslist[index] diff --git a/PythonHome/Lib/email/_parseaddr.pyc b/PythonHome/Lib/email/_parseaddr.pyc index 7918849a1afe151f4a221e13d68f8ff62510a519..a1bddd2ba2ae0d54ac76aecec356c17fe9a38d97 100644 GIT binary patch delta 1614 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 R29wz2^X$cB=nUj=0RW;PkSG8E delta 180 zcmZn`o+`LuFC)Jq0|SGzRZKu-Nk)F2k@;kMPU*><*p;vJuRd5*1r)>r@jv;|@bWXnrCrL+xVIY_&ubP2=?X^~|MAbn6uH$gmv&xk}iS$8Y(WWb$1sr%oBo;)Gi(?Vel1kB+3Z z`1&BrOjbG`-3|LV>;|bp$D_Y-ZbEcSp#b{@eZZ~Eb+NI@m?RCBDb3sjtyOLB^(d0A zi_>tZc`AoPx9T5KBW4LbF8fDe;^DA|w=kdVr})_a?)25An;8A|&x4S#EmbHQL&Cy@Yni)nV6!VBgHN;MwJZ8TA;K z_RTC2de^bB(tF6f zi!T{y40=>UR|v!#8W=4j3g+C9zq^jLh`8`ESs?(OMyKf>;?2N>;yl!4vS0D||587N z<9X>;>?JCdSgeMPB&%loXy(|23#Rc+QN6@N$o^Q^wWSg@sLyc(1|pcp4r@3d9T@kL z%r6R)I^1h)WC5ThrE?@y6j~xnVDCfiwc*)Bvrj8{D2OjrW?kM4e#Klov`8_?iZi4} zqZh^XJt~}sj{?M5T+zoU-5H`&&LR(^WtMjh|DraW)Zf0U;3PUYQg)i~Sc(Ir-^5I1 zj(JgpKY4_^ziIXE%W-DX-2i}M=A#u3DX9_yyQ3MS4+@Z@#KdoFLrJ~ySp_9^oFks# zaS3bYX6Rm^3ZKyPJ-Z2ao~2V|{n>;fni&0*;jxTB8$6L^7YdJSX)s&t0=8jYxNM_rm|WkgICQTaz+C8bV8&W*_K4SIm@ cI6veE>>p_lzK3?&+r@vUz1`XBY`4PyUnSeq5&!@I diff --git a/PythonHome/Lib/email/feedparser.py b/PythonHome/Lib/email/feedparser.py new file mode 100644 index 0000000000..15db26d22a --- /dev/null +++ b/PythonHome/Lib/email/feedparser.py @@ -0,0 +1,484 @@ +# Copyright (C) 2004-2006 Python Software Foundation +# Authors: Baxter, Wouters and Warsaw +# Contact: email-sig@python.org + +"""FeedParser - An email feed parser. + +The feed parser implements an interface for incrementally parsing an email +message, line by line. This has advantages for certain applications, such as +those reading email messages off a socket. + +FeedParser.feed() is the primary interface for pushing new data into the +parser. It returns when there's nothing more it can do with the available +data. When you have no more data to push into the parser, call .close(). +This completes the parsing and returns the root message object. + +The other advantage of this parser is that it will never raise a parsing +exception. Instead, when it finds something unexpected, it adds a 'defect' to +the current message. Defects are just instances that live on the message +object's .defects attribute. +""" + +__all__ = ['FeedParser'] + +import re + +from email import errors +from email import message + +NLCRE = re.compile('\r\n|\r|\n') +NLCRE_bol = re.compile('(\r\n|\r|\n)') +NLCRE_eol = re.compile('(\r\n|\r|\n)\Z') +NLCRE_crack = re.compile('(\r\n|\r|\n)') +# RFC 2822 $3.6.8 Optional fields. ftext is %d33-57 / %d59-126, Any character +# except controls, SP, and ":". +headerRE = re.compile(r'^(From |[\041-\071\073-\176]{1,}:|[\t ])') +EMPTYSTRING = '' +NL = '\n' + +NeedMoreData = object() + + + +class BufferedSubFile(object): + """A file-ish object that can have new data loaded into it. + + You can also push and pop line-matching predicates onto a stack. When the + current predicate matches the current line, a false EOF response + (i.e. empty string) is returned instead. This lets the parser adhere to a + simple abstraction -- it parses until EOF closes the current message. + """ + def __init__(self): + # The last partial line pushed into this object. + self._partial = '' + # The list of full, pushed lines, in reverse order + self._lines = [] + # The stack of false-EOF checking predicates. + self._eofstack = [] + # A flag indicating whether the file has been closed or not. + self._closed = False + + def push_eof_matcher(self, pred): + self._eofstack.append(pred) + + def pop_eof_matcher(self): + return self._eofstack.pop() + + def close(self): + # Don't forget any trailing partial line. + self._lines.append(self._partial) + self._partial = '' + self._closed = True + + def readline(self): + if not self._lines: + if self._closed: + return '' + return NeedMoreData + # Pop the line off the stack and see if it matches the current + # false-EOF predicate. + line = self._lines.pop() + # RFC 2046, section 5.1.2 requires us to recognize outer level + # boundaries at any level of inner nesting. Do this, but be sure it's + # in the order of most to least nested. + for ateof in self._eofstack[::-1]: + if ateof(line): + # We're at the false EOF. But push the last line back first. + self._lines.append(line) + return '' + return line + + def unreadline(self, line): + # Let the consumer push a line back into the buffer. + assert line is not NeedMoreData + self._lines.append(line) + + def push(self, data): + """Push some new data into this object.""" + # Handle any previous leftovers + data, self._partial = self._partial + data, '' + # Crack into lines, but preserve the newlines on the end of each + parts = NLCRE_crack.split(data) + # The *ahem* interesting behaviour of re.split when supplied grouping + # parentheses is that the last element of the resulting list is the + # data after the final RE. In the case of a NL/CR terminated string, + # this is the empty string. + self._partial = parts.pop() + #GAN 29Mar09 bugs 1555570, 1721862 Confusion at 8K boundary ending with \r: + # is there a \n to follow later? + if not self._partial and parts and parts[-1].endswith('\r'): + self._partial = parts.pop(-2)+parts.pop() + # parts is a list of strings, alternating between the line contents + # and the eol character(s). Gather up a list of lines after + # re-attaching the newlines. + lines = [] + for i in range(len(parts) // 2): + lines.append(parts[i*2] + parts[i*2+1]) + self.pushlines(lines) + + def pushlines(self, lines): + # Reverse and insert at the front of the lines. + self._lines[:0] = lines[::-1] + + def is_closed(self): + return self._closed + + def __iter__(self): + return self + + def next(self): + line = self.readline() + if line == '': + raise StopIteration + return line + + + +class FeedParser: + """A feed-style parser of email.""" + + def __init__(self, _factory=message.Message): + """_factory is called with no arguments to create a new message obj""" + self._factory = _factory + self._input = BufferedSubFile() + self._msgstack = [] + self._parse = self._parsegen().next + self._cur = None + self._last = None + self._headersonly = False + + # Non-public interface for supporting Parser's headersonly flag + def _set_headersonly(self): + self._headersonly = True + + def feed(self, data): + """Push more data into the parser.""" + self._input.push(data) + self._call_parse() + + def _call_parse(self): + try: + self._parse() + except StopIteration: + pass + + def close(self): + """Parse all remaining data and return the root message object.""" + self._input.close() + self._call_parse() + root = self._pop_message() + assert not self._msgstack + # Look for final set of defects + if root.get_content_maintype() == 'multipart' \ + and not root.is_multipart(): + root.defects.append(errors.MultipartInvariantViolationDefect()) + return root + + def _new_message(self): + msg = self._factory() + if self._cur and self._cur.get_content_type() == 'multipart/digest': + msg.set_default_type('message/rfc822') + if self._msgstack: + self._msgstack[-1].attach(msg) + self._msgstack.append(msg) + self._cur = msg + self._last = msg + + def _pop_message(self): + retval = self._msgstack.pop() + if self._msgstack: + self._cur = self._msgstack[-1] + else: + self._cur = None + return retval + + def _parsegen(self): + # Create a new message and start by parsing headers. + self._new_message() + headers = [] + # Collect the headers, searching for a line that doesn't match the RFC + # 2822 header or continuation pattern (including an empty line). + for line in self._input: + if line is NeedMoreData: + yield NeedMoreData + continue + if not headerRE.match(line): + # If we saw the RFC defined header/body separator + # (i.e. newline), just throw it away. Otherwise the line is + # part of the body so push it back. + if not NLCRE.match(line): + self._input.unreadline(line) + break + headers.append(line) + # Done with the headers, so parse them and figure out what we're + # supposed to see in the body of the message. + self._parse_headers(headers) + # Headers-only parsing is a backwards compatibility hack, which was + # necessary in the older parser, which could raise errors. All + # remaining lines in the input are thrown into the message body. + if self._headersonly: + lines = [] + while True: + line = self._input.readline() + if line is NeedMoreData: + yield NeedMoreData + continue + if line == '': + break + lines.append(line) + self._cur.set_payload(EMPTYSTRING.join(lines)) + return + if self._cur.get_content_type() == 'message/delivery-status': + # message/delivery-status contains blocks of headers separated by + # a blank line. We'll represent each header block as a separate + # nested message object, but the processing is a bit different + # than standard message/* types because there is no body for the + # nested messages. A blank line separates the subparts. + while True: + self._input.push_eof_matcher(NLCRE.match) + for retval in self._parsegen(): + if retval is NeedMoreData: + yield NeedMoreData + continue + break + msg = self._pop_message() + # We need to pop the EOF matcher in order to tell if we're at + # the end of the current file, not the end of the last block + # of message headers. + self._input.pop_eof_matcher() + # The input stream must be sitting at the newline or at the + # EOF. We want to see if we're at the end of this subpart, so + # first consume the blank line, then test the next line to see + # if we're at this subpart's EOF. + while True: + line = self._input.readline() + if line is NeedMoreData: + yield NeedMoreData + continue + break + while True: + line = self._input.readline() + if line is NeedMoreData: + yield NeedMoreData + continue + break + if line == '': + break + # Not at EOF so this is a line we're going to need. + self._input.unreadline(line) + return + if self._cur.get_content_maintype() == 'message': + # The message claims to be a message/* type, then what follows is + # another RFC 2822 message. + for retval in self._parsegen(): + if retval is NeedMoreData: + yield NeedMoreData + continue + break + self._pop_message() + return + if self._cur.get_content_maintype() == 'multipart': + boundary = self._cur.get_boundary() + if boundary is None: + # The message /claims/ to be a multipart but it has not + # defined a boundary. That's a problem which we'll handle by + # reading everything until the EOF and marking the message as + # defective. + self._cur.defects.append(errors.NoBoundaryInMultipartDefect()) + lines = [] + for line in self._input: + if line is NeedMoreData: + yield NeedMoreData + continue + lines.append(line) + self._cur.set_payload(EMPTYSTRING.join(lines)) + return + # Create a line match predicate which matches the inter-part + # boundary as well as the end-of-multipart boundary. Don't push + # this onto the input stream until we've scanned past the + # preamble. + separator = '--' + boundary + boundaryre = re.compile( + '(?P' + re.escape(separator) + + r')(?P--)?(?P[ \t]*)(?P\r\n|\r|\n)?$') + capturing_preamble = True + preamble = [] + linesep = False + while True: + line = self._input.readline() + if line is NeedMoreData: + yield NeedMoreData + continue + if line == '': + break + mo = boundaryre.match(line) + if mo: + # If we're looking at the end boundary, we're done with + # this multipart. If there was a newline at the end of + # the closing boundary, then we need to initialize the + # epilogue with the empty string (see below). + if mo.group('end'): + linesep = mo.group('linesep') + break + # We saw an inter-part boundary. Were we in the preamble? + if capturing_preamble: + if preamble: + # According to RFC 2046, the last newline belongs + # to the boundary. + lastline = preamble[-1] + eolmo = NLCRE_eol.search(lastline) + if eolmo: + preamble[-1] = lastline[:-len(eolmo.group(0))] + self._cur.preamble = EMPTYSTRING.join(preamble) + capturing_preamble = False + self._input.unreadline(line) + continue + # We saw a boundary separating two parts. Consume any + # multiple boundary lines that may be following. Our + # interpretation of RFC 2046 BNF grammar does not produce + # body parts within such double boundaries. + while True: + line = self._input.readline() + if line is NeedMoreData: + yield NeedMoreData + continue + mo = boundaryre.match(line) + if not mo: + self._input.unreadline(line) + break + # Recurse to parse this subpart; the input stream points + # at the subpart's first line. + self._input.push_eof_matcher(boundaryre.match) + for retval in self._parsegen(): + if retval is NeedMoreData: + yield NeedMoreData + continue + break + # Because of RFC 2046, the newline preceding the boundary + # separator actually belongs to the boundary, not the + # previous subpart's payload (or epilogue if the previous + # part is a multipart). + if self._last.get_content_maintype() == 'multipart': + epilogue = self._last.epilogue + if epilogue == '': + self._last.epilogue = None + elif epilogue is not None: + mo = NLCRE_eol.search(epilogue) + if mo: + end = len(mo.group(0)) + self._last.epilogue = epilogue[:-end] + else: + payload = self._last.get_payload() + if isinstance(payload, basestring): + mo = NLCRE_eol.search(payload) + if mo: + payload = payload[:-len(mo.group(0))] + self._last.set_payload(payload) + self._input.pop_eof_matcher() + self._pop_message() + # Set the multipart up for newline cleansing, which will + # happen if we're in a nested multipart. + self._last = self._cur + else: + # I think we must be in the preamble + assert capturing_preamble + preamble.append(line) + # We've seen either the EOF or the end boundary. If we're still + # capturing the preamble, we never saw the start boundary. Note + # that as a defect and store the captured text as the payload. + # Everything from here to the EOF is epilogue. + if capturing_preamble: + self._cur.defects.append(errors.StartBoundaryNotFoundDefect()) + self._cur.set_payload(EMPTYSTRING.join(preamble)) + epilogue = [] + for line in self._input: + if line is NeedMoreData: + yield NeedMoreData + continue + self._cur.epilogue = EMPTYSTRING.join(epilogue) + return + # If the end boundary ended in a newline, we'll need to make sure + # the epilogue isn't None + if linesep: + epilogue = [''] + else: + epilogue = [] + for line in self._input: + if line is NeedMoreData: + yield NeedMoreData + continue + epilogue.append(line) + # Any CRLF at the front of the epilogue is not technically part of + # the epilogue. Also, watch out for an empty string epilogue, + # which means a single newline. + if epilogue: + firstline = epilogue[0] + bolmo = NLCRE_bol.match(firstline) + if bolmo: + epilogue[0] = firstline[len(bolmo.group(0)):] + self._cur.epilogue = EMPTYSTRING.join(epilogue) + return + # Otherwise, it's some non-multipart type, so the entire rest of the + # file contents becomes the payload. + lines = [] + for line in self._input: + if line is NeedMoreData: + yield NeedMoreData + continue + lines.append(line) + self._cur.set_payload(EMPTYSTRING.join(lines)) + + def _parse_headers(self, lines): + # Passed a list of lines that make up the headers for the current msg + lastheader = '' + lastvalue = [] + for lineno, line in enumerate(lines): + # Check for continuation + if line[0] in ' \t': + if not lastheader: + # The first line of the headers was a continuation. This + # is illegal, so let's note the defect, store the illegal + # line, and ignore it for purposes of headers. + defect = errors.FirstHeaderLineIsContinuationDefect(line) + self._cur.defects.append(defect) + continue + lastvalue.append(line) + continue + if lastheader: + # XXX reconsider the joining of folded lines + lhdr = EMPTYSTRING.join(lastvalue)[:-1].rstrip('\r\n') + self._cur[lastheader] = lhdr + lastheader, lastvalue = '', [] + # Check for envelope header, i.e. unix-from + if line.startswith('From '): + if lineno == 0: + # Strip off the trailing newline + mo = NLCRE_eol.search(line) + if mo: + line = line[:-len(mo.group(0))] + self._cur.set_unixfrom(line) + continue + elif lineno == len(lines) - 1: + # Something looking like a unix-from at the end - it's + # probably the first line of the body, so push back the + # line and stop. + self._input.unreadline(line) + return + else: + # Weirdly placed unix-from line. Note this as a defect + # and ignore it. + defect = errors.MisplacedEnvelopeHeaderDefect(line) + self._cur.defects.append(defect) + continue + # Split the line on the colon separating field name from value. + i = line.find(':') + if i < 0: + defect = errors.MalformedHeaderDefect(line) + self._cur.defects.append(defect) + continue + lastheader = line[:i] + lastvalue = [line[i+1:].lstrip()] + # Done with all the lines, so handle the last header. + if lastheader: + # XXX reconsider the joining of folded lines + self._cur[lastheader] = EMPTYSTRING.join(lastvalue).rstrip('\r\n') diff --git a/PythonHome/Lib/email/feedparser.pyc b/PythonHome/Lib/email/feedparser.pyc deleted file mode 100644 index 4471a5038541a81f939bc1c15f66be6df5e78ea9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11027 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 XK~usPZ}|NI%1D0mloLh^M?d|4$HK;N diff --git a/PythonHome/Lib/email/generator.py b/PythonHome/Lib/email/generator.py new file mode 100644 index 0000000000..e50f912c5a --- /dev/null +++ b/PythonHome/Lib/email/generator.py @@ -0,0 +1,371 @@ +# Copyright (C) 2001-2010 Python Software Foundation +# Contact: email-sig@python.org + +"""Classes to generate plain text from a message object tree.""" + +__all__ = ['Generator', 'DecodedGenerator'] + +import re +import sys +import time +import random +import warnings + +from cStringIO import StringIO +from email.header import Header + +UNDERSCORE = '_' +NL = '\n' + +fcre = re.compile(r'^From ', re.MULTILINE) + +def _is8bitstring(s): + if isinstance(s, str): + try: + unicode(s, 'us-ascii') + except UnicodeError: + return True + return False + + + +class Generator: + """Generates output from a Message object tree. + + This basic generator writes the message to the given file object as plain + text. + """ + # + # Public interface + # + + def __init__(self, outfp, mangle_from_=True, maxheaderlen=78): + """Create the generator for message flattening. + + outfp is the output file-like object for writing the message to. It + must have a write() method. + + Optional mangle_from_ is a flag that, when True (the default), escapes + From_ lines in the body of the message by putting a `>' in front of + them. + + Optional maxheaderlen specifies the longest length for a non-continued + header. When a header line is longer (in characters, with tabs + expanded to 8 spaces) than maxheaderlen, the header will split as + defined in the Header class. Set maxheaderlen to zero to disable + header wrapping. The default is 78, as recommended (but not required) + by RFC 2822. + """ + self._fp = outfp + self._mangle_from_ = mangle_from_ + self._maxheaderlen = maxheaderlen + + def write(self, s): + # Just delegate to the file object + self._fp.write(s) + + def flatten(self, msg, unixfrom=False): + """Print the message object tree rooted at msg to the output file + specified when the Generator instance was created. + + unixfrom is a flag that forces the printing of a Unix From_ delimiter + before the first object in the message tree. If the original message + has no From_ delimiter, a `standard' one is crafted. By default, this + is False to inhibit the printing of any From_ delimiter. + + Note that for subobjects, no From_ line is printed. + """ + if unixfrom: + ufrom = msg.get_unixfrom() + if not ufrom: + ufrom = 'From nobody ' + time.ctime(time.time()) + print >> self._fp, ufrom + self._write(msg) + + def clone(self, fp): + """Clone this generator with the exact same options.""" + return self.__class__(fp, self._mangle_from_, self._maxheaderlen) + + # + # Protected interface - undocumented ;/ + # + + def _write(self, msg): + # We can't write the headers yet because of the following scenario: + # say a multipart message includes the boundary string somewhere in + # its body. We'd have to calculate the new boundary /before/ we write + # the headers so that we can write the correct Content-Type: + # parameter. + # + # The way we do this, so as to make the _handle_*() methods simpler, + # is to cache any subpart writes into a StringIO. The we write the + # headers and the StringIO contents. That way, subpart handlers can + # Do The Right Thing, and can still modify the Content-Type: header if + # necessary. + oldfp = self._fp + try: + self._fp = sfp = StringIO() + self._dispatch(msg) + finally: + self._fp = oldfp + # Write the headers. First we see if the message object wants to + # handle that itself. If not, we'll do it generically. + meth = getattr(msg, '_write_headers', None) + if meth is None: + self._write_headers(msg) + else: + meth(self) + self._fp.write(sfp.getvalue()) + + def _dispatch(self, msg): + # Get the Content-Type: for the message, then try to dispatch to + # self._handle__(). If there's no handler for the + # full MIME type, then dispatch to self._handle_(). If + # that's missing too, then dispatch to self._writeBody(). + main = msg.get_content_maintype() + sub = msg.get_content_subtype() + specific = UNDERSCORE.join((main, sub)).replace('-', '_') + meth = getattr(self, '_handle_' + specific, None) + if meth is None: + generic = main.replace('-', '_') + meth = getattr(self, '_handle_' + generic, None) + if meth is None: + meth = self._writeBody + meth(msg) + + # + # Default handlers + # + + def _write_headers(self, msg): + for h, v in msg.items(): + print >> self._fp, '%s:' % h, + if self._maxheaderlen == 0: + # Explicit no-wrapping + print >> self._fp, v + elif isinstance(v, Header): + # Header instances know what to do + print >> self._fp, v.encode() + elif _is8bitstring(v): + # If we have raw 8bit data in a byte string, we have no idea + # what the encoding is. There is no safe way to split this + # string. If it's ascii-subset, then we could do a normal + # ascii split, but if it's multibyte then we could break the + # string. There's no way to know so the least harm seems to + # be to not split the string and risk it being too long. + print >> self._fp, v + else: + # Header's got lots of smarts, so use it. Note that this is + # fundamentally broken though because we lose idempotency when + # the header string is continued with tabs. It will now be + # continued with spaces. This was reversedly broken before we + # fixed bug 1974. Either way, we lose. + print >> self._fp, Header( + v, maxlinelen=self._maxheaderlen, header_name=h).encode() + # A blank line always separates headers from body + print >> self._fp + + # + # Handlers for writing types and subtypes + # + + def _handle_text(self, msg): + payload = msg.get_payload() + if payload is None: + return + if not isinstance(payload, basestring): + raise TypeError('string payload expected: %s' % type(payload)) + if self._mangle_from_: + payload = fcre.sub('>From ', payload) + self._fp.write(payload) + + # Default body handler + _writeBody = _handle_text + + def _handle_multipart(self, msg): + # The trick here is to write out each part separately, merge them all + # together, and then make sure that the boundary we've chosen isn't + # present in the payload. + msgtexts = [] + subparts = msg.get_payload() + if subparts is None: + subparts = [] + elif isinstance(subparts, basestring): + # e.g. a non-strict parse of a message with no starting boundary. + self._fp.write(subparts) + return + elif not isinstance(subparts, list): + # Scalar payload + subparts = [subparts] + for part in subparts: + s = StringIO() + g = self.clone(s) + g.flatten(part, unixfrom=False) + msgtexts.append(s.getvalue()) + # BAW: What about boundaries that are wrapped in double-quotes? + boundary = msg.get_boundary() + if not boundary: + # Create a boundary that doesn't appear in any of the + # message texts. + alltext = NL.join(msgtexts) + boundary = _make_boundary(alltext) + msg.set_boundary(boundary) + # If there's a preamble, write it out, with a trailing CRLF + if msg.preamble is not None: + if self._mangle_from_: + preamble = fcre.sub('>From ', msg.preamble) + else: + preamble = msg.preamble + print >> self._fp, preamble + # dash-boundary transport-padding CRLF + print >> self._fp, '--' + boundary + # body-part + if msgtexts: + self._fp.write(msgtexts.pop(0)) + # *encapsulation + # --> delimiter transport-padding + # --> CRLF body-part + for body_part in msgtexts: + # delimiter transport-padding CRLF + print >> self._fp, '\n--' + boundary + # body-part + self._fp.write(body_part) + # close-delimiter transport-padding + self._fp.write('\n--' + boundary + '--' + NL) + if msg.epilogue is not None: + if self._mangle_from_: + epilogue = fcre.sub('>From ', msg.epilogue) + else: + epilogue = msg.epilogue + self._fp.write(epilogue) + + def _handle_multipart_signed(self, msg): + # The contents of signed parts has to stay unmodified in order to keep + # the signature intact per RFC1847 2.1, so we disable header wrapping. + # RDM: This isn't enough to completely preserve the part, but it helps. + old_maxheaderlen = self._maxheaderlen + try: + self._maxheaderlen = 0 + self._handle_multipart(msg) + finally: + self._maxheaderlen = old_maxheaderlen + + def _handle_message_delivery_status(self, msg): + # We can't just write the headers directly to self's file object + # because this will leave an extra newline between the last header + # block and the boundary. Sigh. + blocks = [] + for part in msg.get_payload(): + s = StringIO() + g = self.clone(s) + g.flatten(part, unixfrom=False) + text = s.getvalue() + lines = text.split('\n') + # Strip off the unnecessary trailing empty line + if lines and lines[-1] == '': + blocks.append(NL.join(lines[:-1])) + else: + blocks.append(text) + # Now join all the blocks with an empty line. This has the lovely + # effect of separating each block with an empty line, but not adding + # an extra one after the last one. + self._fp.write(NL.join(blocks)) + + def _handle_message(self, msg): + s = StringIO() + g = self.clone(s) + # The payload of a message/rfc822 part should be a multipart sequence + # of length 1. The zeroth element of the list should be the Message + # object for the subpart. Extract that object, stringify it, and + # write it out. + # Except, it turns out, when it's a string instead, which happens when + # and only when HeaderParser is used on a message of mime type + # message/rfc822. Such messages are generated by, for example, + # Groupwise when forwarding unadorned messages. (Issue 7970.) So + # in that case we just emit the string body. + payload = msg.get_payload() + if isinstance(payload, list): + g.flatten(msg.get_payload(0), unixfrom=False) + payload = s.getvalue() + self._fp.write(payload) + + + +_FMT = '[Non-text (%(type)s) part of message omitted, filename %(filename)s]' + +class DecodedGenerator(Generator): + """Generates a text representation of a message. + + Like the Generator base class, except that non-text parts are substituted + with a format string representing the part. + """ + def __init__(self, outfp, mangle_from_=True, maxheaderlen=78, fmt=None): + """Like Generator.__init__() except that an additional optional + argument is allowed. + + Walks through all subparts of a message. If the subpart is of main + type `text', then it prints the decoded payload of the subpart. + + Otherwise, fmt is a format string that is used instead of the message + payload. fmt is expanded with the following keywords (in + %(keyword)s format): + + type : Full MIME type of the non-text part + maintype : Main MIME type of the non-text part + subtype : Sub-MIME type of the non-text part + filename : Filename of the non-text part + description: Description associated with the non-text part + encoding : Content transfer encoding of the non-text part + + The default value for fmt is None, meaning + + [Non-text (%(type)s) part of message omitted, filename %(filename)s] + """ + Generator.__init__(self, outfp, mangle_from_, maxheaderlen) + if fmt is None: + self._fmt = _FMT + else: + self._fmt = fmt + + def _dispatch(self, msg): + for part in msg.walk(): + maintype = part.get_content_maintype() + if maintype == 'text': + print >> self, part.get_payload(decode=True) + elif maintype == 'multipart': + # Just skip this + pass + else: + print >> self, self._fmt % { + 'type' : part.get_content_type(), + 'maintype' : part.get_content_maintype(), + 'subtype' : part.get_content_subtype(), + 'filename' : part.get_filename('[no filename]'), + 'description': part.get('Content-Description', + '[no description]'), + 'encoding' : part.get('Content-Transfer-Encoding', + '[no encoding]'), + } + + + +# Helper +_width = len(repr(sys.maxint-1)) +_fmt = '%%0%dd' % _width + +def _make_boundary(text=None): + # Craft a random boundary. If text is given, ensure that the chosen + # boundary doesn't appear in the text. + token = random.randrange(sys.maxint) + boundary = ('=' * 15) + (_fmt % token) + '==' + if text is None: + return boundary + b = boundary + counter = 0 + while True: + cre = re.compile('^--' + re.escape(b) + '(--)?$', re.MULTILINE) + if not cre.search(text): + break + b = boundary + '.' + str(counter) + counter += 1 + return b diff --git a/PythonHome/Lib/email/generator.pyc b/PythonHome/Lib/email/generator.pyc deleted file mode 100644 index bbbc9e046368362e8e54eb1d75c6e2f714c674e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10095 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 diff --git a/PythonHome/Lib/email/header.py b/PythonHome/Lib/email/header.py new file mode 100644 index 0000000000..2cf870fd57 --- /dev/null +++ b/PythonHome/Lib/email/header.py @@ -0,0 +1,514 @@ +# Copyright (C) 2002-2006 Python Software Foundation +# Author: Ben Gertzfield, Barry Warsaw +# Contact: email-sig@python.org + +"""Header encoding and decoding functionality.""" + +__all__ = [ + 'Header', + 'decode_header', + 'make_header', + ] + +import re +import binascii + +import email.quoprimime +import email.base64mime + +from email.errors import HeaderParseError +from email.charset import Charset + +NL = '\n' +SPACE = ' ' +USPACE = u' ' +SPACE8 = ' ' * 8 +UEMPTYSTRING = u'' + +MAXLINELEN = 76 + +USASCII = Charset('us-ascii') +UTF8 = Charset('utf-8') + +# Match encoded-word strings in the form =?charset?q?Hello_World?= +ecre = re.compile(r''' + =\? # literal =? + (?P[^?]*?) # non-greedy up to the next ? is the charset + \? # literal ? + (?P[qb]) # either a "q" or a "b", case insensitive + \? # literal ? + (?P.*?) # non-greedy up to the next ?= is the encoded string + \?= # literal ?= + (?=[ \t]|$) # whitespace or the end of the string + ''', re.VERBOSE | re.IGNORECASE | re.MULTILINE) + +# Field name regexp, including trailing colon, but not separating whitespace, +# according to RFC 2822. Character range is from tilde to exclamation mark. +# For use with .match() +fcre = re.compile(r'[\041-\176]+:$') + +# Find a header embedded in a putative header value. Used to check for +# header injection attack. +_embeded_header = re.compile(r'\n[^ \t]+:') + + + +# Helpers +_max_append = email.quoprimime._max_append + + + +def decode_header(header): + """Decode a message header value without converting charset. + + Returns a list of (decoded_string, charset) pairs containing each of the + decoded parts of the header. Charset is None for non-encoded parts of the + header, otherwise a lower-case string containing the name of the character + set specified in the encoded string. + + An email.errors.HeaderParseError may be raised when certain decoding error + occurs (e.g. a base64 decoding exception). + """ + # If no encoding, just return the header + header = str(header) + if not ecre.search(header): + return [(header, None)] + decoded = [] + dec = '' + for line in header.splitlines(): + # This line might not have an encoding in it + if not ecre.search(line): + decoded.append((line, None)) + continue + parts = ecre.split(line) + while parts: + unenc = parts.pop(0).strip() + if unenc: + # Should we continue a long line? + if decoded and decoded[-1][1] is None: + decoded[-1] = (decoded[-1][0] + SPACE + unenc, None) + else: + decoded.append((unenc, None)) + if parts: + charset, encoding = [s.lower() for s in parts[0:2]] + encoded = parts[2] + dec = None + if encoding == 'q': + dec = email.quoprimime.header_decode(encoded) + elif encoding == 'b': + paderr = len(encoded) % 4 # Postel's law: add missing padding + if paderr: + encoded += '==='[:4 - paderr] + try: + dec = email.base64mime.decode(encoded) + except binascii.Error: + # Turn this into a higher level exception. BAW: Right + # now we throw the lower level exception away but + # when/if we get exception chaining, we'll preserve it. + raise HeaderParseError + if dec is None: + dec = encoded + + if decoded and decoded[-1][1] == charset: + decoded[-1] = (decoded[-1][0] + dec, decoded[-1][1]) + else: + decoded.append((dec, charset)) + del parts[0:3] + return decoded + + + +def make_header(decoded_seq, maxlinelen=None, header_name=None, + continuation_ws=' '): + """Create a Header from a sequence of pairs as returned by decode_header() + + decode_header() takes a header value string and returns a sequence of + pairs of the format (decoded_string, charset) where charset is the string + name of the character set. + + This function takes one of those sequence of pairs and returns a Header + instance. Optional maxlinelen, header_name, and continuation_ws are as in + the Header constructor. + """ + h = Header(maxlinelen=maxlinelen, header_name=header_name, + continuation_ws=continuation_ws) + for s, charset in decoded_seq: + # None means us-ascii but we can simply pass it on to h.append() + if charset is not None and not isinstance(charset, Charset): + charset = Charset(charset) + h.append(s, charset) + return h + + + +class Header: + def __init__(self, s=None, charset=None, + maxlinelen=None, header_name=None, + continuation_ws=' ', errors='strict'): + """Create a MIME-compliant header that can contain many character sets. + + Optional s is the initial header value. If None, the initial header + value is not set. You can later append to the header with .append() + method calls. s may be a byte string or a Unicode string, but see the + .append() documentation for semantics. + + Optional charset serves two purposes: it has the same meaning as the + charset argument to the .append() method. It also sets the default + character set for all subsequent .append() calls that omit the charset + argument. If charset is not provided in the constructor, the us-ascii + charset is used both as s's initial charset and as the default for + subsequent .append() calls. + + The maximum line length can be specified explicit via maxlinelen. For + splitting the first line to a shorter value (to account for the field + header which isn't included in s, e.g. `Subject') pass in the name of + the field in header_name. The default maxlinelen is 76. + + continuation_ws must be RFC 2822 compliant folding whitespace (usually + either a space or a hard tab) which will be prepended to continuation + lines. + + errors is passed through to the .append() call. + """ + if charset is None: + charset = USASCII + if not isinstance(charset, Charset): + charset = Charset(charset) + self._charset = charset + self._continuation_ws = continuation_ws + cws_expanded_len = len(continuation_ws.replace('\t', SPACE8)) + # BAW: I believe `chunks' and `maxlinelen' should be non-public. + self._chunks = [] + if s is not None: + self.append(s, charset, errors) + if maxlinelen is None: + maxlinelen = MAXLINELEN + if header_name is None: + # We don't know anything about the field header so the first line + # is the same length as subsequent lines. + self._firstlinelen = maxlinelen + else: + # The first line should be shorter to take into account the field + # header. Also subtract off 2 extra for the colon and space. + self._firstlinelen = maxlinelen - len(header_name) - 2 + # Second and subsequent lines should subtract off the length in + # columns of the continuation whitespace prefix. + self._maxlinelen = maxlinelen - cws_expanded_len + + def __str__(self): + """A synonym for self.encode().""" + return self.encode() + + def __unicode__(self): + """Helper for the built-in unicode function.""" + uchunks = [] + lastcs = None + for s, charset in self._chunks: + # We must preserve spaces between encoded and non-encoded word + # boundaries, which means for us we need to add a space when we go + # from a charset to None/us-ascii, or from None/us-ascii to a + # charset. Only do this for the second and subsequent chunks. + nextcs = charset + if uchunks: + if lastcs not in (None, 'us-ascii'): + if nextcs in (None, 'us-ascii'): + uchunks.append(USPACE) + nextcs = None + elif nextcs not in (None, 'us-ascii'): + uchunks.append(USPACE) + lastcs = nextcs + uchunks.append(unicode(s, str(charset))) + return UEMPTYSTRING.join(uchunks) + + # Rich comparison operators for equality only. BAW: does it make sense to + # have or explicitly disable <, <=, >, >= operators? + def __eq__(self, other): + # other may be a Header or a string. Both are fine so coerce + # ourselves to a string, swap the args and do another comparison. + return other == self.encode() + + def __ne__(self, other): + return not self == other + + def append(self, s, charset=None, errors='strict'): + """Append a string to the MIME header. + + Optional charset, if given, should be a Charset instance or the name + of a character set (which will be converted to a Charset instance). A + value of None (the default) means that the charset given in the + constructor is used. + + s may be a byte string or a Unicode string. If it is a byte string + (i.e. isinstance(s, str) is true), then charset is the encoding of + that byte string, and a UnicodeError will be raised if the string + cannot be decoded with that charset. If s is a Unicode string, then + charset is a hint specifying the character set of the characters in + the string. In this case, when producing an RFC 2822 compliant header + using RFC 2047 rules, the Unicode string will be encoded using the + following charsets in order: us-ascii, the charset hint, utf-8. The + first character set not to provoke a UnicodeError is used. + + Optional `errors' is passed as the third argument to any unicode() or + ustr.encode() call. + """ + if charset is None: + charset = self._charset + elif not isinstance(charset, Charset): + charset = Charset(charset) + # If the charset is our faux 8bit charset, leave the string unchanged + if charset != '8bit': + # We need to test that the string can be converted to unicode and + # back to a byte string, given the input and output codecs of the + # charset. + if isinstance(s, str): + # Possibly raise UnicodeError if the byte string can't be + # converted to a unicode with the input codec of the charset. + incodec = charset.input_codec or 'us-ascii' + ustr = unicode(s, incodec, errors) + # Now make sure that the unicode could be converted back to a + # byte string with the output codec, which may be different + # than the iput coded. Still, use the original byte string. + outcodec = charset.output_codec or 'us-ascii' + ustr.encode(outcodec, errors) + elif isinstance(s, unicode): + # Now we have to be sure the unicode string can be converted + # to a byte string with a reasonable output codec. We want to + # use the byte string in the chunk. + for charset in USASCII, charset, UTF8: + try: + outcodec = charset.output_codec or 'us-ascii' + s = s.encode(outcodec, errors) + break + except UnicodeError: + pass + else: + assert False, 'utf-8 conversion failed' + self._chunks.append((s, charset)) + + def _split(self, s, charset, maxlinelen, splitchars): + # Split up a header safely for use with encode_chunks. + splittable = charset.to_splittable(s) + encoded = charset.from_splittable(splittable, True) + elen = charset.encoded_header_len(encoded) + # If the line's encoded length first, just return it + if elen <= maxlinelen: + return [(encoded, charset)] + # If we have undetermined raw 8bit characters sitting in a byte + # string, we really don't know what the right thing to do is. We + # can't really split it because it might be multibyte data which we + # could break if we split it between pairs. The least harm seems to + # be to not split the header at all, but that means they could go out + # longer than maxlinelen. + if charset == '8bit': + return [(s, charset)] + # BAW: I'm not sure what the right test here is. What we're trying to + # do is be faithful to RFC 2822's recommendation that ($2.2.3): + # + # "Note: Though structured field bodies are defined in such a way that + # folding can take place between many of the lexical tokens (and even + # within some of the lexical tokens), folding SHOULD be limited to + # placing the CRLF at higher-level syntactic breaks." + # + # For now, I can only imagine doing this when the charset is us-ascii, + # although it's possible that other charsets may also benefit from the + # higher-level syntactic breaks. + elif charset == 'us-ascii': + return self._split_ascii(s, charset, maxlinelen, splitchars) + # BAW: should we use encoded? + elif elen == len(s): + # We can split on _maxlinelen boundaries because we know that the + # encoding won't change the size of the string + splitpnt = maxlinelen + first = charset.from_splittable(splittable[:splitpnt], False) + last = charset.from_splittable(splittable[splitpnt:], False) + else: + # Binary search for split point + first, last = _binsplit(splittable, charset, maxlinelen) + # first is of the proper length so just wrap it in the appropriate + # chrome. last must be recursively split. + fsplittable = charset.to_splittable(first) + fencoded = charset.from_splittable(fsplittable, True) + chunk = [(fencoded, charset)] + return chunk + self._split(last, charset, self._maxlinelen, splitchars) + + def _split_ascii(self, s, charset, firstlen, splitchars): + chunks = _split_ascii(s, firstlen, self._maxlinelen, + self._continuation_ws, splitchars) + return zip(chunks, [charset]*len(chunks)) + + def _encode_chunks(self, newchunks, maxlinelen): + # MIME-encode a header with many different charsets and/or encodings. + # + # Given a list of pairs (string, charset), return a MIME-encoded + # string suitable for use in a header field. Each pair may have + # different charsets and/or encodings, and the resulting header will + # accurately reflect each setting. + # + # Each encoding can be email.utils.QP (quoted-printable, for + # ASCII-like character sets like iso-8859-1), email.utils.BASE64 + # (Base64, for non-ASCII like character sets like KOI8-R and + # iso-2022-jp), or None (no encoding). + # + # Each pair will be represented on a separate line; the resulting + # string will be in the format: + # + # =?charset1?q?Mar=EDa_Gonz=E1lez_Alonso?=\n + # =?charset2?b?SvxyZ2VuIEL2aW5n?=" + chunks = [] + for header, charset in newchunks: + if not header: + continue + if charset is None or charset.header_encoding is None: + s = header + else: + s = charset.header_encode(header) + # Don't add more folding whitespace than necessary + if chunks and chunks[-1].endswith(' '): + extra = '' + else: + extra = ' ' + _max_append(chunks, s, maxlinelen, extra) + joiner = NL + self._continuation_ws + return joiner.join(chunks) + + def encode(self, splitchars=';, '): + """Encode a message header into an RFC-compliant format. + + There are many issues involved in converting a given string for use in + an email header. Only certain character sets are readable in most + email clients, and as header strings can only contain a subset of + 7-bit ASCII, care must be taken to properly convert and encode (with + Base64 or quoted-printable) header strings. In addition, there is a + 75-character length limit on any given encoded header field, so + line-wrapping must be performed, even with double-byte character sets. + + This method will do its best to convert the string to the correct + character set used in email, and encode and line wrap it safely with + the appropriate scheme for that character set. + + If the given charset is not known or an error occurs during + conversion, this function will return the header untouched. + + Optional splitchars is a string containing characters to split long + ASCII lines on, in rough support of RFC 2822's `highest level + syntactic breaks'. This doesn't affect RFC 2047 encoded lines. + """ + newchunks = [] + maxlinelen = self._firstlinelen + lastlen = 0 + for s, charset in self._chunks: + # The first bit of the next chunk should be just long enough to + # fill the next line. Don't forget the space separating the + # encoded words. + targetlen = maxlinelen - lastlen - 1 + if targetlen < charset.encoded_header_len(''): + # Stick it on the next line + targetlen = maxlinelen + newchunks += self._split(s, charset, targetlen, splitchars) + lastchunk, lastcharset = newchunks[-1] + lastlen = lastcharset.encoded_header_len(lastchunk) + value = self._encode_chunks(newchunks, maxlinelen) + if _embeded_header.search(value): + raise HeaderParseError("header value appears to contain " + "an embedded header: {!r}".format(value)) + return value + + + +def _split_ascii(s, firstlen, restlen, continuation_ws, splitchars): + lines = [] + maxlen = firstlen + for line in s.splitlines(): + # Ignore any leading whitespace (i.e. continuation whitespace) already + # on the line, since we'll be adding our own. + line = line.lstrip() + if len(line) < maxlen: + lines.append(line) + maxlen = restlen + continue + # Attempt to split the line at the highest-level syntactic break + # possible. Note that we don't have a lot of smarts about field + # syntax; we just try to break on semi-colons, then commas, then + # whitespace. + for ch in splitchars: + if ch in line: + break + else: + # There's nothing useful to split the line on, not even spaces, so + # just append this line unchanged + lines.append(line) + maxlen = restlen + continue + # Now split the line on the character plus trailing whitespace + cre = re.compile(r'%s\s*' % ch) + if ch in ';,': + eol = ch + else: + eol = '' + joiner = eol + ' ' + joinlen = len(joiner) + wslen = len(continuation_ws.replace('\t', SPACE8)) + this = [] + linelen = 0 + for part in cre.split(line): + curlen = linelen + max(0, len(this)-1) * joinlen + partlen = len(part) + onfirstline = not lines + # We don't want to split after the field name, if we're on the + # first line and the field name is present in the header string. + if ch == ' ' and onfirstline and \ + len(this) == 1 and fcre.match(this[0]): + this.append(part) + linelen += partlen + elif curlen + partlen > maxlen: + if this: + lines.append(joiner.join(this) + eol) + # If this part is longer than maxlen and we aren't already + # splitting on whitespace, try to recursively split this line + # on whitespace. + if partlen > maxlen and ch != ' ': + subl = _split_ascii(part, maxlen, restlen, + continuation_ws, ' ') + lines.extend(subl[:-1]) + this = [subl[-1]] + else: + this = [part] + linelen = wslen + len(this[-1]) + maxlen = restlen + else: + this.append(part) + linelen += partlen + # Put any left over parts on a line by themselves + if this: + lines.append(joiner.join(this)) + return lines + + + +def _binsplit(splittable, charset, maxlinelen): + i = 0 + j = len(splittable) + while i < j: + # Invariants: + # 1. splittable[:k] fits for all k <= i (note that we *assume*, + # at the start, that splittable[:0] fits). + # 2. splittable[:k] does not fit for any k > j (at the start, + # this means we shouldn't look at any k > len(splittable)). + # 3. We don't know about splittable[:k] for k in i+1..j. + # 4. We want to set i to the largest k that fits, with i <= k <= j. + # + m = (i+j+1) >> 1 # ceiling((i+j)/2); i < m <= j + chunk = charset.from_splittable(splittable[:m], True) + chunklen = charset.encoded_header_len(chunk) + if chunklen <= maxlinelen: + # m is acceptable, so is a new lower bound. + i = m + else: + # m is not acceptable, so final i must be < m. + j = m - 1 + # i == j. Invariant #1 implies that splittable[:i] fits, and + # invariant #2 implies that splittable[:i+1] does not fit, so i + # is what we're looking for. + first = charset.from_splittable(splittable[:i], False) + last = charset.from_splittable(splittable[i:], False) + return first, last diff --git a/PythonHome/Lib/email/header.pyc b/PythonHome/Lib/email/header.pyc deleted file mode 100644 index 57323cc5de5f0221c5401c882df9d96bbfda9897..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13422 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 diff --git a/PythonHome/Lib/email/iterators.py b/PythonHome/Lib/email/iterators.py new file mode 100644 index 0000000000..e99f2280da --- /dev/null +++ b/PythonHome/Lib/email/iterators.py @@ -0,0 +1,73 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""Various types of useful iterators and generators.""" + +__all__ = [ + 'body_line_iterator', + 'typed_subpart_iterator', + 'walk', + # Do not include _structure() since it's part of the debugging API. + ] + +import sys +from cStringIO import StringIO + + + +# This function will become a method of the Message class +def walk(self): + """Walk over the message tree, yielding each subpart. + + The walk is performed in depth-first order. This method is a + generator. + """ + yield self + if self.is_multipart(): + for subpart in self.get_payload(): + for subsubpart in subpart.walk(): + yield subsubpart + + + +# These two functions are imported into the Iterators.py interface module. +def body_line_iterator(msg, decode=False): + """Iterate over the parts, returning string payloads line-by-line. + + Optional decode (default False) is passed through to .get_payload(). + """ + for subpart in msg.walk(): + payload = subpart.get_payload(decode=decode) + if isinstance(payload, basestring): + for line in StringIO(payload): + yield line + + +def typed_subpart_iterator(msg, maintype='text', subtype=None): + """Iterate over the subparts with a given MIME type. + + Use `maintype' as the main MIME type to match against; this defaults to + "text". Optional `subtype' is the MIME subtype to match against; if + omitted, only the main type is matched. + """ + for subpart in msg.walk(): + if subpart.get_content_maintype() == maintype: + if subtype is None or subpart.get_content_subtype() == subtype: + yield subpart + + + +def _structure(msg, fp=None, level=0, include_default=False): + """A handy debugging aid""" + if fp is None: + fp = sys.stdout + tab = ' ' * (level * 4) + print >> fp, tab + msg.get_content_type(), + if include_default: + print >> fp, '[%s]' % msg.get_default_type() + else: + print >> fp + if msg.is_multipart(): + for subpart in msg.get_payload(): + _structure(subpart, fp, level+1, include_default) diff --git a/PythonHome/Lib/email/iterators.pyc b/PythonHome/Lib/email/iterators.pyc deleted file mode 100644 index 271a01da068d87ac1d813076d8c9c64e3ec8217c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2341 zcmbVO-ESL35T84L$Fp+KrhfK_B6;eNiWiAKsyVhmw1C- zrc>-G`AeeEqElF0=GCqC3Lkn0keCm{+PmELfKuw()OjBjODPo@&PQ{s4Lz7k0 zj=zds{anwZ)Mh3+)AQFLW+OUs)BYqb{KXRA@@1SJ+Q0DWwgc8&1ljV1&4!zg6PDDf z!Le~afE>ZO0OWw^gsAwQW}mU_AmHi!y$w1JX!b501#}RWqDyof(ou+Q&+pLo^Bc6C zNj$gOAshV}WE*a%{Dmo$9~m_^&c#Ecd|}KjHMb_!a7dXr8L8?Po#kbP&l70#6_j;q zVv0dtjEz<{Q`$`Y==Q)C&a1r8rs%LTw8qAda;PAHV&Oc59hr99d|}@Lu`U`KhEJr_UY%lsqOEY zactAwGsIkHG8gmfY=aF^vk|m{HT)%fYy*Q26-1tanLQBz1dscB52|Pb5acXiIHBOU zMjjA=*61XpVufb!ldrSnBmihY2$MP^bQcJ%5dOE3?ptz2_X`f$l*BU^AaPjSEmasl zEi#73N!q9?LQZiW-tNzD^LGW;wG$+b~!Z3Z!7tRBRvGdBgr*f~JxM@2pz zj+D<;=asm(Za;guZ-1<}|IdrQ2X z!4m{4_YoW-_Wbp+!$$fLqr|SU7F-Qhft^_NX66$A zKs*%GP(;A=aFN_SSp|G3$WT_hECGOB22bz{fS**@pRoTg{Hok^>ZSD~6|13rVKVh- z^U-(GbSlJtaz^bVKQrzjAFCK0i3=2h3snYb9D5XJJj8BdCkwaOPcYmf2rY23+z2f537^Sn z&f^}2`waxCfQJGZP`pE4S}fXa*-kk*LRw$vQVyt&a^|)yDRMpB43HhgwybER7FOz< zJlDd_hnZ}6$g&2@ieG8g5tSxS@9%v;#|^HIqXzHibLw=Rdj}r7=e}&`{Ccsc?ro5} zYJ}%$jtuBeheK`-vDI*wNLjv?WAf}Hw`W<_ZS&=OZ-Gcry1A43c3$UG@2^1qDry|< zb77TZkw73Qo%etU6+cbTos2lv6Zp6u1{2Rpsd-^izY5M~NjlXgs*H&fKJLFEr0>Dv z*BFk|jlvds_vK(cXa?8Ay7cijKPJ*_qDbdS6jgkjrcuXFoZEox|KA$P=Po~Gs-w(t0tM6*^4YQa*y6@,;:\\"/\[\]\?=]') + + +# Helper functions +def _splitparam(param): + # Split header parameters. BAW: this may be too simple. It isn't + # strictly RFC 2045 (section 5.1) compliant, but it catches most headers + # found in the wild. We may eventually need a full fledged parser + # eventually. + a, sep, b = param.partition(';') + if not sep: + return a.strip(), None + return a.strip(), b.strip() + +def _formatparam(param, value=None, quote=True): + """Convenience function to format and return a key=value pair. + + This will quote the value if needed or if quote is true. If value is a + three tuple (charset, language, value), it will be encoded according + to RFC2231 rules. + """ + if value is not None and len(value) > 0: + # A tuple is used for RFC 2231 encoded parameter values where items + # are (charset, language, value). charset is a string, not a Charset + # instance. + if isinstance(value, tuple): + # Encode as per RFC 2231 + param += '*' + value = utils.encode_rfc2231(value[2], value[0], value[1]) + # BAW: Please check this. I think that if quote is set it should + # force quoting even if not necessary. + if quote or tspecials.search(value): + return '%s="%s"' % (param, utils.quote(value)) + else: + return '%s=%s' % (param, value) + else: + return param + +def _parseparam(s): + plist = [] + while s[:1] == ';': + s = s[1:] + end = s.find(';') + while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2: + end = s.find(';', end + 1) + if end < 0: + end = len(s) + f = s[:end] + if '=' in f: + i = f.index('=') + f = f[:i].strip().lower() + '=' + f[i+1:].strip() + plist.append(f.strip()) + s = s[end:] + return plist + + +def _unquotevalue(value): + # This is different than utils.collapse_rfc2231_value() because it doesn't + # try to convert the value to a unicode. Message.get_param() and + # Message.get_params() are both currently defined to return the tuple in + # the face of RFC 2231 parameters. + if isinstance(value, tuple): + return value[0], value[1], utils.unquote(value[2]) + else: + return utils.unquote(value) + + + +class Message: + """Basic message object. + + A message object is defined as something that has a bunch of RFC 2822 + headers and a payload. It may optionally have an envelope header + (a.k.a. Unix-From or From_ header). If the message is a container (i.e. a + multipart or a message/rfc822), then the payload is a list of Message + objects, otherwise it is a string. + + Message objects implement part of the `mapping' interface, which assumes + there is exactly one occurrence of the header per message. Some headers + do in fact appear multiple times (e.g. Received) and for those headers, + you must use the explicit API to set or get all the headers. Not all of + the mapping methods are implemented. + """ + def __init__(self): + self._headers = [] + self._unixfrom = None + self._payload = None + self._charset = None + # Defaults for multipart messages + self.preamble = self.epilogue = None + self.defects = [] + # Default content type + self._default_type = 'text/plain' + + def __str__(self): + """Return the entire formatted message as a string. + This includes the headers, body, and envelope header. + """ + return self.as_string(unixfrom=True) + + def as_string(self, unixfrom=False): + """Return the entire formatted message as a string. + Optional `unixfrom' when True, means include the Unix From_ envelope + header. + + This is a convenience method and may not generate the message exactly + as you intend because by default it mangles lines that begin with + "From ". For more flexibility, use the flatten() method of a + Generator instance. + """ + from email.generator import Generator + fp = StringIO() + g = Generator(fp) + g.flatten(self, unixfrom=unixfrom) + return fp.getvalue() + + def is_multipart(self): + """Return True if the message consists of multiple parts.""" + return isinstance(self._payload, list) + + # + # Unix From_ line + # + def set_unixfrom(self, unixfrom): + self._unixfrom = unixfrom + + def get_unixfrom(self): + return self._unixfrom + + # + # Payload manipulation. + # + def attach(self, payload): + """Add the given payload to the current payload. + + The current payload will always be a list of objects after this method + is called. If you want to set the payload to a scalar object, use + set_payload() instead. + """ + if self._payload is None: + self._payload = [payload] + else: + self._payload.append(payload) + + def get_payload(self, i=None, decode=False): + """Return a reference to the payload. + + The payload will either be a list object or a string. If you mutate + the list object, you modify the message's payload in place. Optional + i returns that index into the payload. + + Optional decode is a flag indicating whether the payload should be + decoded or not, according to the Content-Transfer-Encoding header + (default is False). + + When True and the message is not a multipart, the payload will be + decoded if this header's value is `quoted-printable' or `base64'. If + some other encoding is used, or the header is missing, or if the + payload has bogus data (i.e. bogus base64 or uuencoded data), the + payload is returned as-is. + + If the message is a multipart and the decode flag is True, then None + is returned. + """ + if i is None: + payload = self._payload + elif not isinstance(self._payload, list): + raise TypeError('Expected list, got %s' % type(self._payload)) + else: + payload = self._payload[i] + if decode: + if self.is_multipart(): + return None + cte = self.get('content-transfer-encoding', '').lower() + if cte == 'quoted-printable': + return utils._qdecode(payload) + elif cte == 'base64': + try: + return utils._bdecode(payload) + except binascii.Error: + # Incorrect padding + return payload + elif cte in ('x-uuencode', 'uuencode', 'uue', 'x-uue'): + sfp = StringIO() + try: + uu.decode(StringIO(payload+'\n'), sfp, quiet=True) + payload = sfp.getvalue() + except uu.Error: + # Some decoding problem + return payload + # Everything else, including encodings with 8bit or 7bit are returned + # unchanged. + return payload + + def set_payload(self, payload, charset=None): + """Set the payload to the given value. + + Optional charset sets the message's default character set. See + set_charset() for details. + """ + self._payload = payload + if charset is not None: + self.set_charset(charset) + + def set_charset(self, charset): + """Set the charset of the payload to a given character set. + + charset can be a Charset instance, a string naming a character set, or + None. If it is a string it will be converted to a Charset instance. + If charset is None, the charset parameter will be removed from the + Content-Type field. Anything else will generate a TypeError. + + The message will be assumed to be of type text/* encoded with + charset.input_charset. It will be converted to charset.output_charset + and encoded properly, if needed, when generating the plain text + representation of the message. MIME headers (MIME-Version, + Content-Type, Content-Transfer-Encoding) will be added as needed. + + """ + if charset is None: + self.del_param('charset') + self._charset = None + return + if isinstance(charset, basestring): + charset = email.charset.Charset(charset) + if not isinstance(charset, email.charset.Charset): + raise TypeError(charset) + # BAW: should we accept strings that can serve as arguments to the + # Charset constructor? + self._charset = charset + if 'MIME-Version' not in self: + self.add_header('MIME-Version', '1.0') + if 'Content-Type' not in self: + self.add_header('Content-Type', 'text/plain', + charset=charset.get_output_charset()) + else: + self.set_param('charset', charset.get_output_charset()) + if isinstance(self._payload, unicode): + self._payload = self._payload.encode(charset.output_charset) + if str(charset) != charset.get_output_charset(): + self._payload = charset.body_encode(self._payload) + if 'Content-Transfer-Encoding' not in self: + cte = charset.get_body_encoding() + try: + cte(self) + except TypeError: + self._payload = charset.body_encode(self._payload) + self.add_header('Content-Transfer-Encoding', cte) + + def get_charset(self): + """Return the Charset instance associated with the message's payload. + """ + return self._charset + + # + # MAPPING INTERFACE (partial) + # + def __len__(self): + """Return the total number of headers, including duplicates.""" + return len(self._headers) + + def __getitem__(self, name): + """Get a header value. + + Return None if the header is missing instead of raising an exception. + + Note that if the header appeared multiple times, exactly which + occurrence gets returned is undefined. Use get_all() to get all + the values matching a header field name. + """ + return self.get(name) + + def __setitem__(self, name, val): + """Set the value of a header. + + Note: this does not overwrite an existing header with the same field + name. Use __delitem__() first to delete any existing headers. + """ + self._headers.append((name, val)) + + def __delitem__(self, name): + """Delete all occurrences of a header, if present. + + Does not raise an exception if the header is missing. + """ + name = name.lower() + newheaders = [] + for k, v in self._headers: + if k.lower() != name: + newheaders.append((k, v)) + self._headers = newheaders + + def __contains__(self, name): + return name.lower() in [k.lower() for k, v in self._headers] + + def has_key(self, name): + """Return true if the message contains the header.""" + missing = object() + return self.get(name, missing) is not missing + + def keys(self): + """Return a list of all the message's header field names. + + These will be sorted in the order they appeared in the original + message, or were added to the message, and may contain duplicates. + Any fields deleted and re-inserted are always appended to the header + list. + """ + return [k for k, v in self._headers] + + def values(self): + """Return a list of all the message's header values. + + These will be sorted in the order they appeared in the original + message, or were added to the message, and may contain duplicates. + Any fields deleted and re-inserted are always appended to the header + list. + """ + return [v for k, v in self._headers] + + def items(self): + """Get all the message's header fields and values. + + These will be sorted in the order they appeared in the original + message, or were added to the message, and may contain duplicates. + Any fields deleted and re-inserted are always appended to the header + list. + """ + return self._headers[:] + + def get(self, name, failobj=None): + """Get a header value. + + Like __getitem__() but return failobj instead of None when the field + is missing. + """ + name = name.lower() + for k, v in self._headers: + if k.lower() == name: + return v + return failobj + + # + # Additional useful stuff + # + + def get_all(self, name, failobj=None): + """Return a list of all the values for the named field. + + These will be sorted in the order they appeared in the original + message, and may contain duplicates. Any fields deleted and + re-inserted are always appended to the header list. + + If no such fields exist, failobj is returned (defaults to None). + """ + values = [] + name = name.lower() + for k, v in self._headers: + if k.lower() == name: + values.append(v) + if not values: + return failobj + return values + + def add_header(self, _name, _value, **_params): + """Extended header setting. + + name is the header field to add. keyword arguments can be used to set + additional parameters for the header field, with underscores converted + to dashes. Normally the parameter will be added as key="value" unless + value is None, in which case only the key will be added. If a + parameter value contains non-ASCII characters it must be specified as a + three-tuple of (charset, language, value), in which case it will be + encoded according to RFC2231 rules. + + Example: + + msg.add_header('content-disposition', 'attachment', filename='bud.gif') + """ + parts = [] + for k, v in _params.items(): + if v is None: + parts.append(k.replace('_', '-')) + else: + parts.append(_formatparam(k.replace('_', '-'), v)) + if _value is not None: + parts.insert(0, _value) + self._headers.append((_name, SEMISPACE.join(parts))) + + def replace_header(self, _name, _value): + """Replace a header. + + Replace the first matching header found in the message, retaining + header order and case. If no matching header was found, a KeyError is + raised. + """ + _name = _name.lower() + for i, (k, v) in zip(range(len(self._headers)), self._headers): + if k.lower() == _name: + self._headers[i] = (k, _value) + break + else: + raise KeyError(_name) + + # + # Use these three methods instead of the three above. + # + + def get_content_type(self): + """Return the message's content type. + + The returned string is coerced to lower case of the form + `maintype/subtype'. If there was no Content-Type header in the + message, the default type as given by get_default_type() will be + returned. Since according to RFC 2045, messages always have a default + type this will always return a value. + + RFC 2045 defines a message's default type to be text/plain unless it + appears inside a multipart/digest container, in which case it would be + message/rfc822. + """ + missing = object() + value = self.get('content-type', missing) + if value is missing: + # This should have no parameters + return self.get_default_type() + ctype = _splitparam(value)[0].lower() + # RFC 2045, section 5.2 says if its invalid, use text/plain + if ctype.count('/') != 1: + return 'text/plain' + return ctype + + def get_content_maintype(self): + """Return the message's main content type. + + This is the `maintype' part of the string returned by + get_content_type(). + """ + ctype = self.get_content_type() + return ctype.split('/')[0] + + def get_content_subtype(self): + """Returns the message's sub-content type. + + This is the `subtype' part of the string returned by + get_content_type(). + """ + ctype = self.get_content_type() + return ctype.split('/')[1] + + def get_default_type(self): + """Return the `default' content type. + + Most messages have a default content type of text/plain, except for + messages that are subparts of multipart/digest containers. Such + subparts have a default content type of message/rfc822. + """ + return self._default_type + + def set_default_type(self, ctype): + """Set the `default' content type. + + ctype should be either "text/plain" or "message/rfc822", although this + is not enforced. The default content type is not stored in the + Content-Type header. + """ + self._default_type = ctype + + def _get_params_preserve(self, failobj, header): + # Like get_params() but preserves the quoting of values. BAW: + # should this be part of the public interface? + missing = object() + value = self.get(header, missing) + if value is missing: + return failobj + params = [] + for p in _parseparam(';' + value): + try: + name, val = p.split('=', 1) + name = name.strip() + val = val.strip() + except ValueError: + # Must have been a bare attribute + name = p.strip() + val = '' + params.append((name, val)) + params = utils.decode_params(params) + return params + + def get_params(self, failobj=None, header='content-type', unquote=True): + """Return the message's Content-Type parameters, as a list. + + The elements of the returned list are 2-tuples of key/value pairs, as + split on the `=' sign. The left hand side of the `=' is the key, + while the right hand side is the value. If there is no `=' sign in + the parameter the value is the empty string. The value is as + described in the get_param() method. + + Optional failobj is the object to return if there is no Content-Type + header. Optional header is the header to search instead of + Content-Type. If unquote is True, the value is unquoted. + """ + missing = object() + params = self._get_params_preserve(missing, header) + if params is missing: + return failobj + if unquote: + return [(k, _unquotevalue(v)) for k, v in params] + else: + return params + + def get_param(self, param, failobj=None, header='content-type', + unquote=True): + """Return the parameter value if found in the Content-Type header. + + Optional failobj is the object to return if there is no Content-Type + header, or the Content-Type header has no such parameter. Optional + header is the header to search instead of Content-Type. + + Parameter keys are always compared case insensitively. The return + value can either be a string, or a 3-tuple if the parameter was RFC + 2231 encoded. When it's a 3-tuple, the elements of the value are of + the form (CHARSET, LANGUAGE, VALUE). Note that both CHARSET and + LANGUAGE can be None, in which case you should consider VALUE to be + encoded in the us-ascii charset. You can usually ignore LANGUAGE. + + Your application should be prepared to deal with 3-tuple return + values, and can convert the parameter to a Unicode string like so: + + param = msg.get_param('foo') + if isinstance(param, tuple): + param = unicode(param[2], param[0] or 'us-ascii') + + In any case, the parameter value (either the returned string, or the + VALUE item in the 3-tuple) is always unquoted, unless unquote is set + to False. + """ + if header not in self: + return failobj + for k, v in self._get_params_preserve(failobj, header): + if k.lower() == param.lower(): + if unquote: + return _unquotevalue(v) + else: + return v + return failobj + + def set_param(self, param, value, header='Content-Type', requote=True, + charset=None, language=''): + """Set a parameter in the Content-Type header. + + If the parameter already exists in the header, its value will be + replaced with the new value. + + If header is Content-Type and has not yet been defined for this + message, it will be set to "text/plain" and the new parameter and + value will be appended as per RFC 2045. + + An alternate header can specified in the header argument, and all + parameters will be quoted as necessary unless requote is False. + + If charset is specified, the parameter will be encoded according to RFC + 2231. Optional language specifies the RFC 2231 language, defaulting + to the empty string. Both charset and language should be strings. + """ + if not isinstance(value, tuple) and charset: + value = (charset, language, value) + + if header not in self and header.lower() == 'content-type': + ctype = 'text/plain' + else: + ctype = self.get(header) + if not self.get_param(param, header=header): + if not ctype: + ctype = _formatparam(param, value, requote) + else: + ctype = SEMISPACE.join( + [ctype, _formatparam(param, value, requote)]) + else: + ctype = '' + for old_param, old_value in self.get_params(header=header, + unquote=requote): + append_param = '' + if old_param.lower() == param.lower(): + append_param = _formatparam(param, value, requote) + else: + append_param = _formatparam(old_param, old_value, requote) + if not ctype: + ctype = append_param + else: + ctype = SEMISPACE.join([ctype, append_param]) + if ctype != self.get(header): + del self[header] + self[header] = ctype + + def del_param(self, param, header='content-type', requote=True): + """Remove the given parameter completely from the Content-Type header. + + The header will be re-written in place without the parameter or its + value. All values will be quoted as necessary unless requote is + False. Optional header specifies an alternative to the Content-Type + header. + """ + if header not in self: + return + new_ctype = '' + for p, v in self.get_params(header=header, unquote=requote): + if p.lower() != param.lower(): + if not new_ctype: + new_ctype = _formatparam(p, v, requote) + else: + new_ctype = SEMISPACE.join([new_ctype, + _formatparam(p, v, requote)]) + if new_ctype != self.get(header): + del self[header] + self[header] = new_ctype + + def set_type(self, type, header='Content-Type', requote=True): + """Set the main type and subtype for the Content-Type header. + + type must be a string in the form "maintype/subtype", otherwise a + ValueError is raised. + + This method replaces the Content-Type header, keeping all the + parameters in place. If requote is False, this leaves the existing + header's quoting as is. Otherwise, the parameters will be quoted (the + default). + + An alternative header can be specified in the header argument. When + the Content-Type header is set, we'll always also add a MIME-Version + header. + """ + # BAW: should we be strict? + if not type.count('/') == 1: + raise ValueError + # Set the Content-Type, you get a MIME-Version + if header.lower() == 'content-type': + del self['mime-version'] + self['MIME-Version'] = '1.0' + if header not in self: + self[header] = type + return + params = self.get_params(header=header, unquote=requote) + del self[header] + self[header] = type + # Skip the first param; it's the old type. + for p, v in params[1:]: + self.set_param(p, v, header, requote) + + def get_filename(self, failobj=None): + """Return the filename associated with the payload if present. + + The filename is extracted from the Content-Disposition header's + `filename' parameter, and it is unquoted. If that header is missing + the `filename' parameter, this method falls back to looking for the + `name' parameter. + """ + missing = object() + filename = self.get_param('filename', missing, 'content-disposition') + if filename is missing: + filename = self.get_param('name', missing, 'content-type') + if filename is missing: + return failobj + return utils.collapse_rfc2231_value(filename).strip() + + def get_boundary(self, failobj=None): + """Return the boundary associated with the payload if present. + + The boundary is extracted from the Content-Type header's `boundary' + parameter, and it is unquoted. + """ + missing = object() + boundary = self.get_param('boundary', missing) + if boundary is missing: + return failobj + # RFC 2046 says that boundaries may begin but not end in w/s + return utils.collapse_rfc2231_value(boundary).rstrip() + + def set_boundary(self, boundary): + """Set the boundary parameter in Content-Type to 'boundary'. + + This is subtly different than deleting the Content-Type header and + adding a new one with a new boundary parameter via add_header(). The + main difference is that using the set_boundary() method preserves the + order of the Content-Type header in the original message. + + HeaderParseError is raised if the message has no Content-Type header. + """ + missing = object() + params = self._get_params_preserve(missing, 'content-type') + if params is missing: + # There was no Content-Type header, and we don't know what type + # to set it to, so raise an exception. + raise errors.HeaderParseError('No Content-Type header found') + newparams = [] + foundp = False + for pk, pv in params: + if pk.lower() == 'boundary': + newparams.append(('boundary', '"%s"' % boundary)) + foundp = True + else: + newparams.append((pk, pv)) + if not foundp: + # The original Content-Type header had no boundary attribute. + # Tack one on the end. BAW: should we raise an exception + # instead??? + newparams.append(('boundary', '"%s"' % boundary)) + # Replace the existing Content-Type header with the new value + newheaders = [] + for h, v in self._headers: + if h.lower() == 'content-type': + parts = [] + for k, v in newparams: + if v == '': + parts.append(k) + else: + parts.append('%s=%s' % (k, v)) + newheaders.append((h, SEMISPACE.join(parts))) + + else: + newheaders.append((h, v)) + self._headers = newheaders + + def get_content_charset(self, failobj=None): + """Return the charset parameter of the Content-Type header. + + The returned string is always coerced to lower case. If there is no + Content-Type header, or if that header has no charset parameter, + failobj is returned. + """ + missing = object() + charset = self.get_param('charset', missing) + if charset is missing: + return failobj + if isinstance(charset, tuple): + # RFC 2231 encoded, so decode it, and it better end up as ascii. + pcharset = charset[0] or 'us-ascii' + try: + # LookupError will be raised if the charset isn't known to + # Python. UnicodeError will be raised if the encoded text + # contains a character not in the charset. + charset = unicode(charset[2], pcharset).encode('us-ascii') + except (LookupError, UnicodeError): + charset = charset[2] + # charset character must be in us-ascii range + try: + if isinstance(charset, str): + charset = unicode(charset, 'us-ascii') + charset = charset.encode('us-ascii') + except UnicodeError: + return failobj + # RFC 2046, $4.1.2 says charsets are not case sensitive + return charset.lower() + + def get_charsets(self, failobj=None): + """Return a list containing the charset(s) used in this message. + + The returned list of items describes the Content-Type headers' + charset parameter for this message and all the subparts in its + payload. + + Each item will either be a string (the value of the charset parameter + in the Content-Type header of that part) or the value of the + 'failobj' parameter (defaults to None), if the part does not have a + main MIME type of "text", or the charset is not defined. + + The list will contain one string for each part of the message, plus + one for the container message (i.e. self), so that a non-multipart + message will still return a list of length 1. + """ + return [part.get_content_charset(failobj) for part in self.walk()] + + # I.e. def walk(self): ... + from email.iterators import walk diff --git a/PythonHome/Lib/email/message.pyc b/PythonHome/Lib/email/message.pyc deleted file mode 100644 index 053154397ea084946f328495ba69572c555de70c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28454 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 diff --git a/PythonHome/Lib/email/mime/__init__.py b/PythonHome/Lib/email/mime/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/PythonHome/Lib/email/mime/__init__.pyc b/PythonHome/Lib/email/mime/__init__.pyc index 7779e6f6b08d4aff4c8077866af8e4e61b4b231a..a9c488f614f344b0bb4432c6dc62585b441572fd 100644 GIT binary patch delta 58 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 diff --git a/PythonHome/Lib/email/mime/message.py b/PythonHome/Lib/email/mime/message.py new file mode 100644 index 0000000000..275dbfd088 --- /dev/null +++ b/PythonHome/Lib/email/mime/message.py @@ -0,0 +1,34 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""Class representing message/* MIME documents.""" + +__all__ = ['MIMEMessage'] + +from email import message +from email.mime.nonmultipart import MIMENonMultipart + + + +class MIMEMessage(MIMENonMultipart): + """Class representing message/* MIME documents.""" + + def __init__(self, _msg, _subtype='rfc822'): + """Create a message/* type MIME document. + + _msg is a message object and must be an instance of Message, or a + derived class of Message, otherwise a TypeError is raised. + + Optional _subtype defines the subtype of the contained message. The + default is "rfc822" (this is defined by the MIME standard, even though + the term "rfc822" is technically outdated by RFC 2822). + """ + MIMENonMultipart.__init__(self, 'message', _subtype) + if not isinstance(_msg, message.Message): + raise TypeError('Argument is not an instance of Message') + # It's convenient to use this base class method. We need to do it + # this way or we'll get an exception + message.Message.attach(self, _msg) + # And be sure our default type is set correctly + self.set_default_type('message/rfc822') diff --git a/PythonHome/Lib/email/mime/message.pyc b/PythonHome/Lib/email/mime/message.pyc deleted file mode 100644 index ca2110e43d568e48a925d2de2b722cbf96d7aba5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1403 zcmb7EUuzRV5TCvLX&cd2`ylAc(g!)Eq)>eDK|~D|3Z_C*P($F{+-;H#cYEP>QVI0Q z^i%jj{9=9po!PsjEePt7o!rjO{AT7ivse3hxAo)WmwpV@Q=|XawA?9)1Ykf?z(l}6 zKoUSwgEWAw27?+1-q#_mL)L&ngZ2V+1IA?7fGdC%z~?~|k|y-SErvWK(Mgqave5HF zJ8jX}iOjTfYNC&x$?j?QL?(H>$mqzm@eVn#u3K7|U-X26l*o9MU#ZxuOwV%LU8HE{ zs=!TA0Uf@j3R+pU(Yo+xt@Y23Ag%ttdFqf|DL*}|b55t^08I#f2+G9SyT z2Zu5*q}m`Qx-b_yk+E;Z5Eh;*sJjOTiMD4TL1L!8o_&uE#Ts{1!#V8jK=r(Z;xSk9;J5FRD)A4xMk9 zN1jrJsNyN|U2z&CqJz1Lm~%h-$aCv-I`%I-C1u2_2O*t;7w$2=wTJJ`Xs9z~(qU#Y zJzRHWzU(p3eOiu_gx0=zAa-l}LCE^53ac_*RS`v5o-9({^2LrK`UXUi2f2>~h^M|s=Vk5J8U2j~U+BxS Sv{(MJZWBl|*a`N;Ui~+eomqtd diff --git a/PythonHome/Lib/email/mime/multipart.py b/PythonHome/Lib/email/mime/multipart.py new file mode 100644 index 0000000000..96618650c5 --- /dev/null +++ b/PythonHome/Lib/email/mime/multipart.py @@ -0,0 +1,47 @@ +# Copyright (C) 2002-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""Base class for MIME multipart/* type messages.""" + +__all__ = ['MIMEMultipart'] + +from email.mime.base import MIMEBase + + + +class MIMEMultipart(MIMEBase): + """Base class for MIME multipart/* type messages.""" + + def __init__(self, _subtype='mixed', boundary=None, _subparts=None, + **_params): + """Creates a multipart/* type message. + + By default, creates a multipart/mixed message, with proper + Content-Type and MIME-Version headers. + + _subtype is the subtype of the multipart content type, defaulting to + `mixed'. + + boundary is the multipart boundary string. By default it is + calculated as needed. + + _subparts is a sequence of initial subparts for the payload. It + must be an iterable object, such as a list. You can always + attach new subparts to the message by using the attach() method. + + Additional parameters for the Content-Type header are taken from the + keyword arguments (or passed into the _params argument). + """ + MIMEBase.__init__(self, 'multipart', _subtype, **_params) + + # Initialise _payload to an empty list as the Message superclass's + # implementation of is_multipart assumes that _payload is a list for + # multipart messages. + self._payload = [] + + if _subparts: + for p in _subparts: + self.attach(p) + if boundary: + self.set_boundary(boundary) diff --git a/PythonHome/Lib/email/mime/multipart.pyc b/PythonHome/Lib/email/mime/multipart.pyc deleted file mode 100644 index a8d371360e798fa214b187da3f317ec234574399..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1624 zcmbVM-EP}96h4w{w+WW5K#SgOICpc4RJ$Hf6kEFuD7N$>8Co=Oq0l02E0IK3q>viO zuG-tZ&YofKvj^C|L&lmgwc_i1e6FrV~k#qIs;G;k;DN@xnHI^z`Uw zuG-QUYt{Jg?z7*l4OhlFwKOjE2UsF8N86C%Up&(Y!~SMJCn*QMBf-Gy7>xm6ut5u^ z=p^A6(>w4T(ecStqCbb$80)IyjnTPe5OFf{D_(bo#uJ@KbQP?+LT5yO!k#6`P!`iw zLd`Gq<{Rn!^y)VKF_ww*gs#T)HlpbDA-$*(98)t3Gb8EC3`Sx4$yBQ1{*H;BG)8&j zSbfyQbbp`w=kbQMStwX}$oU5r21Q%*5Bak2D_%EtZJHs)6I**z`v<>EnN+Pq0Uta! zjVo-;E2A{J*B~?3&O=EH$9`pa`)L>9bErJ$UE)yx!!6CCUb43X_*o$M?X~oC+tyk& z8}8HZ@(nZ2H%OB*@6>bQv0zA>t1@p(*r-`Ku8q+~U&9ayvN@fAD0b#`YwFxEBouYw z3ss7$E<(1n$Xu&UX_W@*Q$OHTt@At=+d#lHYF;AA{M_Uyhimhdpers5=dtdkZ8=Az zDlgS$$5nZ+5Luhc9jLdRm))V^`G#8;oCA?AetHj8^(%W_){k0)ysbeW+!f|gxo{>$ zz%F3!S?A3*-dC}NPFb8QDW^-v9_}47k3j4$H6i%#h%3*3z_YAWD1d)Bzy>v+6 z_pqaf>OGsvaXKDOd6tROSr(2wvIKLz9J@}R|3c1#@!7WO;lAl_}In; z*rCAw2GaB-y@0Q$Xec!9YxL6DZ^e9ODpi!Ts;JCtV4SWu#{zc?ulo`W-MKs7izm@R zbSIibouH0KR>N#)*+)>8RaUp9dKq}*}%R3ZW|7pDuCQ#6TtKZRV6 uqskIEUtu7qNkvUM$3+@UKgM_`dk6mi1_XHzJ3)`6fKDnjiTC1LqyGQ^%&M~h diff --git a/PythonHome/Lib/email/mime/nonmultipart.py b/PythonHome/Lib/email/mime/nonmultipart.py new file mode 100644 index 0000000000..fc3b9eb4dc --- /dev/null +++ b/PythonHome/Lib/email/mime/nonmultipart.py @@ -0,0 +1,22 @@ +# Copyright (C) 2002-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""Base class for MIME type messages that are not multipart.""" + +__all__ = ['MIMENonMultipart'] + +from email import errors +from email.mime.base import MIMEBase + + + +class MIMENonMultipart(MIMEBase): + """Base class for MIME multipart/* type messages.""" + + def attach(self, payload): + # The public API prohibits attaching multiple subparts to MIMEBase + # derived subtypes since none of them are, by definition, of content + # type multipart/* + raise errors.MultipartConversionError( + 'Cannot attach additional subparts to non-multipart/*') diff --git a/PythonHome/Lib/email/mime/nonmultipart.pyc b/PythonHome/Lib/email/mime/nonmultipart.pyc deleted file mode 100644 index e50c707a0f72f091fe11bb5453a1c8a561ce9ffb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 841 zcmbVKO=}x55FPDTlR#649@?XhOQG9KFM(1@Ob&tChxH+3F>K|PoNSR+W+exFP4b)a z$NB@38LjO$&_k&}vl{7X-g~2sf4x3>y!o+&nFj?bM7}Q z#f@@KTr0=@jqqIbig(s?v(~;{iQX4}gtrMkwcTX5+dkpQ8J_qIgX(+RyCFZ=!ijM2 zj*w?K-8({~JJgC1eK1mtrpj3!5uhOCU$pK8efscHchS(j-5gVmw-`LYPb6V*&)_bw z4Fps78BfQeBbUN^(cEw$W$Rnp3C-PlL9VeI7W>eB{DU^=D}(3vSYqFcvF&bE@9_RP zwIRTKLOPUQdU}AB*k~(cj!Ou^aan+a diff --git a/PythonHome/Lib/email/mime/text.py b/PythonHome/Lib/email/mime/text.py new file mode 100644 index 0000000000..5747db5d67 --- /dev/null +++ b/PythonHome/Lib/email/mime/text.py @@ -0,0 +1,30 @@ +# Copyright (C) 2001-2006 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""Class representing text/* type MIME documents.""" + +__all__ = ['MIMEText'] + +from email.encoders import encode_7or8bit +from email.mime.nonmultipart import MIMENonMultipart + + + +class MIMEText(MIMENonMultipart): + """Class for generating text/* type MIME documents.""" + + def __init__(self, _text, _subtype='plain', _charset='us-ascii'): + """Create a text/* type MIME document. + + _text is the string for this message object. + + _subtype is the MIME sub content type, defaulting to "plain". + + _charset is the character set parameter added to the Content-Type + header. This defaults to "us-ascii". Note that as a side-effect, the + Content-Transfer-Encoding header will also be set. + """ + MIMENonMultipart.__init__(self, 'text', _subtype, + **{'charset': _charset}) + self.set_payload(_text, _charset) diff --git a/PythonHome/Lib/email/mime/text.pyc b/PythonHome/Lib/email/mime/text.pyc deleted file mode 100644 index 500fcdba1fd019682a37fdd8af83f0fdad913507..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1263 zcma)5&2G~`5FXn}fK-%nf(z2BrwBC$E|dd8h^U83G>5bjB8p@--f^>cQ#Y4yQ~>jEr~H8~x0*zGxqrrn~pVu2M}`Ok*C6tpr@ zSB_g>yPm$}8$vzLfl2i|&lcc#kdQKo`HE+sWxCQn%lr;06rQc*g{h?q zLkt-ln!@uB69&`-wWK#nn|VMk5QKY7U+L_tF>X35o8&yT$Y6dH^u&=BG=(vbWBJu>c!)*=@YiKnWZsQ zB`hp=oHlD~-6SmXBXSH#Qbv+ibyaTmHZVD%`v&?=Uw= 1: + if '_class' in kws: + raise TypeError("Multiple values for keyword arg '_class'") + kws['_class'] = args[0] + if len(args) == 2: + if 'strict' in kws: + raise TypeError("Multiple values for keyword arg 'strict'") + kws['strict'] = args[1] + if len(args) > 2: + raise TypeError('Too many arguments') + if '_class' in kws: + self._class = kws['_class'] + del kws['_class'] + else: + self._class = Message + if 'strict' in kws: + warnings.warn("'strict' argument is deprecated (and ignored)", + DeprecationWarning, 2) + del kws['strict'] + if kws: + raise TypeError('Unexpected keyword arguments') + + def parse(self, fp, headersonly=False): + """Create a message structure from the data in a file. + + Reads all the data from the file and returns the root of the message + structure. Optional headersonly is a flag specifying whether to stop + parsing after reading the headers or not. The default is False, + meaning it parses the entire contents of the file. + """ + feedparser = FeedParser(self._class) + if headersonly: + feedparser._set_headersonly() + while True: + data = fp.read(8192) + if not data: + break + feedparser.feed(data) + return feedparser.close() + + def parsestr(self, text, headersonly=False): + """Create a message structure from a string. + + Returns the root of the message structure. Optional headersonly is a + flag specifying whether to stop parsing after reading the headers or + not. The default is False, meaning it parses the entire contents of + the file. + """ + return self.parse(StringIO(text), headersonly=headersonly) + + + +class HeaderParser(Parser): + def parse(self, fp, headersonly=True): + return Parser.parse(self, fp, True) + + def parsestr(self, text, headersonly=True): + return Parser.parsestr(self, text, True) diff --git a/PythonHome/Lib/email/parser.pyc b/PythonHome/Lib/email/parser.pyc deleted file mode 100644 index d660d508f71d2830ea40490e201d0a607e0f2691..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3789 zcmbtX>uwx16h5=JWYdJCtw1UlVIe`bQWK&4p+cpCrY#gHZ8b@Wh$3w#Gu~vfvonkB zZL*O5A$<*AgWo&=PXiAC-#MP0O(?VhHX4t|KIiycK7V%Vzc0-Fy!~`Drt(+E`*S?@ z2Q&%M4%&c{8tvC;2c0@44a(53Nxw;1odylsX;8p(Ey|iSXwgo~f6q`hLxWk`nZ-BM z=O~$_7euE--|n>8u5MEg6YXjgA`RN?Tw*6y(0rkWk+IsSqNl?9>uT-h+M0^;L~T6S zxTo|WN;5Uk)<*lEM1%`b`QqJDk^;m*!3b&m%nc z5=I=+NkFGC6HvcN<~Hk{)TrMgvqBEzb)Nk(pj;%8ookqe&@Bv1wVTwhkvZWSl-hmK zo;j}_c{E@h8gntL5W@gC6-svozQChAM{aLX>4=g|x)LJ|fy1!}QZ9d3wCk zGsR%JG_!k~+RZg2hnoD+cihvB;;lMOpDPt_7L56sZ%G6#K<$c92or%61 zXOXpvEyIZaK$_Fsx(I<_AAgLT&*z4Uo7xQBotWoR%P-adZrOJ zk_0D5u~hLOa!L>o^`~)vuMLWA_D2JN$imWH-HS$Se?A9^;2OSCMF-2?V!5> zt#p`a^(@Lpz$}N;*W;tY0AOZcEqmGJ6ta{u=?JxP5@UBU3to2FUV-vfQ80#)_=)qv zt;?lMHOzq|yh~y!W{07a?&pQk$#wfK3_Z#9@emsdP&wnS&&R_K6DIh8C_{eQyzY3Y z?-^5=u!*mbiBGuqC^9)Vp#@J6@rPqC@0KeAmfK!HcvFO|&U(^81XkAQA4wjF(@FMy zH0z)4J|4S+B47JtH%s?+<#5;?%5ktd9LvhxZkngA+vWAV{?e6TK3EJc2h;Z=Mizp( zS{v_nFo(ZZ5OZ7{1s7wTwYzATe~Au-z@LK&L2Vzo_^ppypKyY!g(5aLb##zgSlhqTQDE!N-c@M3ls2=e5nq6+XHsw0D~fQ>2}C5c>w zO#-1_nw{NGA(#QYkY!V`N{K~xP8FW3g@OM^C5MzWVT&AW0t~@} zEZSEVP)U1Zrd#YwAqH$?>xyAzjjO}+Q4b^ndW@0@IZx<}H+tbb0|A`XhPxkSR^O-$ z4Kz3!hEnG*3_cJhd!&f@kGJe3CZC_l!I6?867Ys~M)8X86{ybGom58(DR2uirETmWuSc{-gT?NCm=f5Z^^3bG3$Erc3f z#$$QaR?z-v{z}Ya{9}La;IRsgmiw^AO%GRMT!ZVx{mGRW*I<@@8IxBr3L*uI0-2ym z>>Jz|H{}xk&?gcSM2#lN$cTskeFTKRCs< z@E_O2DbFN)?1t}g!>jziO7d0Y8$6aV*$U?C9u7=Ujt}o{Hz{I($@g(!07-m~%V8dG zmj5vcz=a^?gk7C-neeAufQFwb&ki~G1x6uz@E-~\t]') + + + +# Helpers +def header_quopri_check(c): + """Return True if the character should be escaped with header quopri.""" + return bool(hqre.match(c)) + + +def body_quopri_check(c): + """Return True if the character should be escaped with body quopri.""" + return bool(bqre.match(c)) + + +def header_quopri_len(s): + """Return the length of str when it is encoded with header quopri.""" + count = 0 + for c in s: + if hqre.match(c): + count += 3 + else: + count += 1 + return count + + +def body_quopri_len(str): + """Return the length of str when it is encoded with body quopri.""" + count = 0 + for c in str: + if bqre.match(c): + count += 3 + else: + count += 1 + return count + + +def _max_append(L, s, maxlen, extra=''): + if not L: + L.append(s.lstrip()) + elif len(L[-1]) + len(s) <= maxlen: + L[-1] += extra + s + else: + L.append(s.lstrip()) + + +def unquote(s): + """Turn a string in the form =AB to the ASCII character with value 0xab""" + return chr(int(s[1:3], 16)) + + +def quote(c): + return "=%02X" % ord(c) + + + +def header_encode(header, charset="iso-8859-1", keep_eols=False, + maxlinelen=76, eol=NL): + """Encode a single header line with quoted-printable (like) encoding. + + Defined in RFC 2045, this `Q' encoding is similar to quoted-printable, but + used specifically for email header fields to allow charsets with mostly 7 + bit characters (and some 8 bit) to remain more or less readable in non-RFC + 2045 aware mail clients. + + charset names the character set to use to encode the header. It defaults + to iso-8859-1. + + The resulting string will be in the form: + + "=?charset?q?I_f=E2rt_in_your_g=E8n=E8ral_dire=E7tion?\\n + =?charset?q?Silly_=C8nglish_Kn=EEghts?=" + + with each line wrapped safely at, at most, maxlinelen characters (defaults + to 76 characters). If maxlinelen is None, the entire string is encoded in + one chunk with no splitting. + + End-of-line characters (\\r, \\n, \\r\\n) will be automatically converted + to the canonical email line separator \\r\\n unless the keep_eols + parameter is True (the default is False). + + Each line of the header will be terminated in the value of eol, which + defaults to "\\n". Set this to "\\r\\n" if you are using the result of + this function directly in email. + """ + # Return empty headers unchanged + if not header: + return header + + if not keep_eols: + header = fix_eols(header) + + # Quopri encode each line, in encoded chunks no greater than maxlinelen in + # length, after the RFC chrome is added in. + quoted = [] + if maxlinelen is None: + # An obnoxiously large number that's good enough + max_encoded = 100000 + else: + max_encoded = maxlinelen - len(charset) - MISC_LEN - 1 + + for c in header: + # Space may be represented as _ instead of =20 for readability + if c == ' ': + _max_append(quoted, '_', max_encoded) + # These characters can be included verbatim + elif not hqre.match(c): + _max_append(quoted, c, max_encoded) + # Otherwise, replace with hex value like =E2 + else: + _max_append(quoted, "=%02X" % ord(c), max_encoded) + + # Now add the RFC chrome to each encoded chunk and glue the chunks + # together. BAW: should we be able to specify the leading whitespace in + # the joiner? + joiner = eol + ' ' + return joiner.join(['=?%s?q?%s?=' % (charset, line) for line in quoted]) + + + +def encode(body, binary=False, maxlinelen=76, eol=NL): + """Encode with quoted-printable, wrapping at maxlinelen characters. + + If binary is False (the default), end-of-line characters will be converted + to the canonical email end-of-line sequence \\r\\n. Otherwise they will + be left verbatim. + + Each line of encoded text will end with eol, which defaults to "\\n". Set + this to "\\r\\n" if you will be using the result of this function directly + in an email. + + Each line will be wrapped at, at most, maxlinelen characters (defaults to + 76 characters). Long lines will have the `soft linefeed' quoted-printable + character "=" appended to them, so the decoded text will be identical to + the original text. + """ + if not body: + return body + + if not binary: + body = fix_eols(body) + + # BAW: We're accumulating the body text by string concatenation. That + # can't be very efficient, but I don't have time now to rewrite it. It + # just feels like this algorithm could be more efficient. + encoded_body = '' + lineno = -1 + # Preserve line endings here so we can check later to see an eol needs to + # be added to the output later. + lines = body.splitlines(1) + for line in lines: + # But strip off line-endings for processing this line. + if line.endswith(CRLF): + line = line[:-2] + elif line[-1] in CRLF: + line = line[:-1] + + lineno += 1 + encoded_line = '' + prev = None + linelen = len(line) + # Now we need to examine every character to see if it needs to be + # quopri encoded. BAW: again, string concatenation is inefficient. + for j in range(linelen): + c = line[j] + prev = c + if bqre.match(c): + c = quote(c) + elif j+1 == linelen: + # Check for whitespace at end of line; special case + if c not in ' \t': + encoded_line += c + prev = c + continue + # Check to see to see if the line has reached its maximum length + if len(encoded_line) + len(c) >= maxlinelen: + encoded_body += encoded_line + '=' + eol + encoded_line = '' + encoded_line += c + # Now at end of line.. + if prev and prev in ' \t': + # Special case for whitespace at end of file + if lineno + 1 == len(lines): + prev = quote(prev) + if len(encoded_line) + len(prev) > maxlinelen: + encoded_body += encoded_line + '=' + eol + prev + else: + encoded_body += encoded_line + prev + # Just normal whitespace at end of line + else: + encoded_body += encoded_line + prev + '=' + eol + encoded_line = '' + # Now look at the line we just finished and it has a line ending, we + # need to add eol to the end of the line. + if lines[lineno].endswith(CRLF) or lines[lineno][-1] in CRLF: + encoded_body += encoded_line + eol + else: + encoded_body += encoded_line + encoded_line = '' + return encoded_body + + +# For convenience and backwards compatibility w/ standard base64 module +body_encode = encode +encodestring = encode + + + +# BAW: I'm not sure if the intent was for the signature of this function to be +# the same as base64MIME.decode() or not... +def decode(encoded, eol=NL): + """Decode a quoted-printable string. + + Lines are separated with eol, which defaults to \\n. + """ + if not encoded: + return encoded + # BAW: see comment in encode() above. Again, we're building up the + # decoded string with string concatenation, which could be done much more + # efficiently. + decoded = '' + + for line in encoded.splitlines(): + line = line.rstrip() + if not line: + decoded += eol + continue + + i = 0 + n = len(line) + while i < n: + c = line[i] + if c != '=': + decoded += c + i += 1 + # Otherwise, c == "=". Are we at the end of the line? If so, add + # a soft line break. + elif i+1 == n: + i += 1 + continue + # Decode if in form =AB + elif i+2 < n and line[i+1] in hexdigits and line[i+2] in hexdigits: + decoded += unquote(line[i:i+3]) + i += 3 + # Otherwise, not in form =AB, pass literally + else: + decoded += c + i += 1 + + if i == n: + decoded += eol + # Special case if original string did not end with eol + if not encoded.endswith(eol) and decoded.endswith(eol): + decoded = decoded[:-1] + return decoded + + +# For convenience and backwards compatibility w/ standard base64 module +body_decode = decode +decodestring = decode + + + +def _unquote_match(match): + """Turn a match in the form =AB to the ASCII character with value 0xab""" + s = match.group(0) + return unquote(s) + + +# Header decoding is done a bit differently +def header_decode(s): + """Decode a string encoded with RFC 2045 MIME header `Q' encoding. + + This function does not parse a full MIME header value encoded with + quoted-printable (like =?iso-8895-1?q?Hello_World?=) -- please use + the high level email.header class for that functionality. + """ + s = s.replace('_', ' ') + return re.sub(r'=[a-fA-F0-9]{2}', _unquote_match, s) diff --git a/PythonHome/Lib/email/quoprimime.pyc b/PythonHome/Lib/email/quoprimime.pyc deleted file mode 100644 index edccc0cd878127a7bf2b14203400596f19c78bc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8785 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 T4*_-Q@)~Aqqc_nGjhy)(!1Q}G diff --git a/PythonHome/Lib/email/utils.py b/PythonHome/Lib/email/utils.py new file mode 100644 index 0000000000..c976021e0e --- /dev/null +++ b/PythonHome/Lib/email/utils.py @@ -0,0 +1,324 @@ +# Copyright (C) 2001-2010 Python Software Foundation +# Author: Barry Warsaw +# Contact: email-sig@python.org + +"""Miscellaneous utilities.""" + +__all__ = [ + 'collapse_rfc2231_value', + 'decode_params', + 'decode_rfc2231', + 'encode_rfc2231', + 'formataddr', + 'formatdate', + 'getaddresses', + 'make_msgid', + 'mktime_tz', + 'parseaddr', + 'parsedate', + 'parsedate_tz', + 'unquote', + ] + +import os +import re +import time +import base64 +import random +import socket +import urllib +import warnings + +from email._parseaddr import quote +from email._parseaddr import AddressList as _AddressList +from email._parseaddr import mktime_tz + +# We need wormarounds for bugs in these methods in older Pythons (see below) +from email._parseaddr import parsedate as _parsedate +from email._parseaddr import parsedate_tz as _parsedate_tz + +from quopri import decodestring as _qdecode + +# Intrapackage imports +from email.encoders import _bencode, _qencode + +COMMASPACE = ', ' +EMPTYSTRING = '' +UEMPTYSTRING = u'' +CRLF = '\r\n' +TICK = "'" + +specialsre = re.compile(r'[][\\()<>@,:;".]') +escapesre = re.compile(r'[][\\()"]') + + + +# Helpers + +def _identity(s): + return s + + +def _bdecode(s): + """Decodes a base64 string. + + This function is equivalent to base64.decodestring and it's retained only + for backward compatibility. It used to remove the last \\n of the decoded + string, if it had any (see issue 7143). + """ + if not s: + return s + return base64.decodestring(s) + + + +def fix_eols(s): + """Replace all line-ending characters with \\r\\n.""" + # Fix newlines with no preceding carriage return + s = re.sub(r'(?', name) + return '%s%s%s <%s>' % (quotes, name, quotes, address) + return address + + + +def getaddresses(fieldvalues): + """Return a list of (REALNAME, EMAIL) for each fieldvalue.""" + all = COMMASPACE.join(fieldvalues) + a = _AddressList(all) + return a.addresslist + + + +ecre = re.compile(r''' + =\? # literal =? + (?P[^?]*?) # non-greedy up to the next ? is the charset + \? # literal ? + (?P[qb]) # either a "q" or a "b", case insensitive + \? # literal ? + (?P.*?) # non-greedy up to the next ?= is the atom + \?= # literal ?= + ''', re.VERBOSE | re.IGNORECASE) + + + +def formatdate(timeval=None, localtime=False, usegmt=False): + """Returns a date string as specified by RFC 2822, e.g.: + + Fri, 09 Nov 2001 01:08:47 -0000 + + Optional timeval if given is a floating point time value as accepted by + gmtime() and localtime(), otherwise the current time is used. + + Optional localtime is a flag that when True, interprets timeval, and + returns a date relative to the local timezone instead of UTC, properly + taking daylight savings time into account. + + Optional argument usegmt means that the timezone is written out as + an ascii string, not numeric one (so "GMT" instead of "+0000"). This + is needed for HTTP, and is only used when localtime==False. + """ + # Note: we cannot use strftime() because that honors the locale and RFC + # 2822 requires that day and month names be the English abbreviations. + if timeval is None: + timeval = time.time() + if localtime: + now = time.localtime(timeval) + # Calculate timezone offset, based on whether the local zone has + # daylight savings time, and whether DST is in effect. + if time.daylight and now[-1]: + offset = time.altzone + else: + offset = time.timezone + hours, minutes = divmod(abs(offset), 3600) + # Remember offset is in seconds west of UTC, but the timezone is in + # minutes east of UTC, so the signs differ. + if offset > 0: + sign = '-' + else: + sign = '+' + zone = '%s%02d%02d' % (sign, hours, minutes // 60) + else: + now = time.gmtime(timeval) + # Timezone offset is always -0000 + if usegmt: + zone = 'GMT' + else: + zone = '-0000' + return '%s, %02d %s %04d %02d:%02d:%02d %s' % ( + ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'][now[6]], + now[2], + ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][now[1] - 1], + now[0], now[3], now[4], now[5], + zone) + + + +def make_msgid(idstring=None): + """Returns a string suitable for RFC 2822 compliant Message-ID, e.g: + + <20020201195627.33539.96671@nightshade.la.mastaler.com> + + Optional idstring if given is a string used to strengthen the + uniqueness of the message id. + """ + timeval = time.time() + utcdate = time.strftime('%Y%m%d%H%M%S', time.gmtime(timeval)) + pid = os.getpid() + randint = random.randrange(100000) + if idstring is None: + idstring = '' + else: + idstring = '.' + idstring + idhost = socket.getfqdn() + msgid = '<%s.%s.%s%s@%s>' % (utcdate, pid, randint, idstring, idhost) + return msgid + + + +# These functions are in the standalone mimelib version only because they've +# subsequently been fixed in the latest Python versions. We use this to worm +# around broken older Pythons. +def parsedate(data): + if not data: + return None + return _parsedate(data) + + +def parsedate_tz(data): + if not data: + return None + return _parsedate_tz(data) + + +def parseaddr(addr): + addrs = _AddressList(addr).addresslist + if not addrs: + return '', '' + return addrs[0] + + +# rfc822.unquote() doesn't properly de-backslash-ify in Python pre-2.3. +def unquote(str): + """Remove quotes from a string.""" + if len(str) > 1: + if str.startswith('"') and str.endswith('"'): + return str[1:-1].replace('\\\\', '\\').replace('\\"', '"') + if str.startswith('<') and str.endswith('>'): + return str[1:-1] + return str + + + +# RFC2231-related functions - parameter encoding and decoding +def decode_rfc2231(s): + """Decode string according to RFC 2231""" + parts = s.split(TICK, 2) + if len(parts) <= 2: + return None, None, s + return parts + + +def encode_rfc2231(s, charset=None, language=None): + """Encode string according to RFC 2231. + + If neither charset nor language is given, then s is returned as-is. If + charset is given but not language, the string is encoded using the empty + string for language. + """ + import urllib + s = urllib.quote(s, safe='') + if charset is None and language is None: + return s + if language is None: + language = '' + return "%s'%s'%s" % (charset, language, s) + + +rfc2231_continuation = re.compile(r'^(?P\w+)\*((?P[0-9]+)\*?)?$') + +def decode_params(params): + """Decode parameters list according to RFC 2231. + + params is a sequence of 2-tuples containing (param name, string value). + """ + # Copy params so we don't mess with the original + params = params[:] + new_params = [] + # Map parameter's name to a list of continuations. The values are a + # 3-tuple of the continuation number, the string value, and a flag + # specifying whether a particular segment is %-encoded. + rfc2231_params = {} + name, value = params.pop(0) + new_params.append((name, value)) + while params: + name, value = params.pop(0) + if name.endswith('*'): + encoded = True + else: + encoded = False + value = unquote(value) + mo = rfc2231_continuation.match(name) + if mo: + name, num = mo.group('name', 'num') + if num is not None: + num = int(num) + rfc2231_params.setdefault(name, []).append((num, value, encoded)) + else: + new_params.append((name, '"%s"' % quote(value))) + if rfc2231_params: + for name, continuations in rfc2231_params.items(): + value = [] + extended = False + # Sort by number + continuations.sort() + # And now append all values in numerical order, converting + # %-encodings for the encoded segments. If any of the + # continuation names ends in a *, then the entire string, after + # decoding segments and concatenating, must have the charset and + # language specifiers at the beginning of the string. + for num, s, encoded in continuations: + if encoded: + s = urllib.unquote(s) + extended = True + value.append(s) + value = quote(EMPTYSTRING.join(value)) + if extended: + charset, language, value = decode_rfc2231(value) + new_params.append((name, (charset, language, '"%s"' % value))) + else: + new_params.append((name, '"%s"' % value)) + return new_params + +def collapse_rfc2231_value(value, errors='replace', + fallback_charset='us-ascii'): + if isinstance(value, tuple): + rawval = unquote(value[2]) + charset = value[0] or 'us-ascii' + try: + return unicode(rawval, charset, errors) + except LookupError: + # XXX charset is unknown to Python. + return unicode(rawval, fallback_charset, errors) + else: + return unquote(value) diff --git a/PythonHome/Lib/email/utils.pyc b/PythonHome/Lib/email/utils.pyc index 15fbd0b03073655426dd75835509a51c541dbeb7..da9d3ebe0b066ee43c0a0d1e323963e6f090d4d9 100644 GIT binary patch delta 966 zcmezEHrsoH3X7ow0|P^On82Uo>#EHUr>N^jDKlKL1{^hOKMVSdQ3oN zNk)F2M}BVV codecs.CodecInfo object + The getregentry() API must a CodecInfo object with encoder, decoder, + incrementalencoder, incrementaldecoder, streamwriter and streamreader + atttributes which adhere to the Python Codec Interface Standard. + + In addition, a module may optionally also define the following + APIs which are then used by the package's codec search function: + + * getaliases() -> sequence of encoding name strings to use as aliases + + Alias names returned by getaliases() must be normalized encoding + names as defined by normalize_encoding(). + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +"""#" + +import codecs +from encodings import aliases +import __builtin__ + +_cache = {} +_unknown = '--unknown--' +_import_tail = ['*'] +_norm_encoding_map = (' . ' + '0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ ' + ' abcdefghijklmnopqrstuvwxyz ' + ' ' + ' ' + ' ') +_aliases = aliases.aliases + +class CodecRegistryError(LookupError, SystemError): + pass + +def normalize_encoding(encoding): + + """ Normalize an encoding name. + + Normalization works as follows: all non-alphanumeric + characters except the dot used for Python package names are + collapsed and replaced with a single underscore, e.g. ' -;#' + becomes '_'. Leading and trailing underscores are removed. + + Note that encoding names should be ASCII only; if they do use + non-ASCII characters, these must be Latin-1 compatible. + + """ + # Make sure we have an 8-bit string, because .translate() works + # differently for Unicode strings. + if hasattr(__builtin__, "unicode") and isinstance(encoding, unicode): + # Note that .encode('latin-1') does *not* use the codec + # registry, so this call doesn't recurse. (See unicodeobject.c + # PyUnicode_AsEncodedString() for details) + encoding = encoding.encode('latin-1') + return '_'.join(encoding.translate(_norm_encoding_map).split()) + +def search_function(encoding): + + # Cache lookup + entry = _cache.get(encoding, _unknown) + if entry is not _unknown: + return entry + + # Import the module: + # + # First try to find an alias for the normalized encoding + # name and lookup the module using the aliased name, then try to + # lookup the module using the standard import scheme, i.e. first + # try in the encodings package, then at top-level. + # + norm_encoding = normalize_encoding(encoding) + aliased_encoding = _aliases.get(norm_encoding) or \ + _aliases.get(norm_encoding.replace('.', '_')) + if aliased_encoding is not None: + modnames = [aliased_encoding, + norm_encoding] + else: + modnames = [norm_encoding] + for modname in modnames: + if not modname or '.' in modname: + continue + try: + # Import is absolute to prevent the possibly malicious import of a + # module with side-effects that is not in the 'encodings' package. + mod = __import__('encodings.' + modname, fromlist=_import_tail, + level=0) + except ImportError: + pass + else: + break + else: + mod = None + + try: + getregentry = mod.getregentry + except AttributeError: + # Not a codec module + mod = None + + if mod is None: + # Cache misses + _cache[encoding] = None + return None + + # Now ask the module for the registry entry + entry = getregentry() + if not isinstance(entry, codecs.CodecInfo): + if not 4 <= len(entry) <= 7: + raise CodecRegistryError,\ + 'module "%s" (%s) failed to register' % \ + (mod.__name__, mod.__file__) + if not hasattr(entry[0], '__call__') or \ + not hasattr(entry[1], '__call__') or \ + (entry[2] is not None and not hasattr(entry[2], '__call__')) or \ + (entry[3] is not None and not hasattr(entry[3], '__call__')) or \ + (len(entry) > 4 and entry[4] is not None and not hasattr(entry[4], '__call__')) or \ + (len(entry) > 5 and entry[5] is not None and not hasattr(entry[5], '__call__')): + raise CodecRegistryError,\ + 'incompatible codecs in module "%s" (%s)' % \ + (mod.__name__, mod.__file__) + if len(entry)<7 or entry[6] is None: + entry += (None,)*(6-len(entry)) + (mod.__name__.split(".", 1)[1],) + entry = codecs.CodecInfo(*entry) + + # Cache the codec registry entry + _cache[encoding] = entry + + # Register its aliases (without overwriting previously registered + # aliases) + try: + codecaliases = mod.getaliases() + except AttributeError: + pass + else: + for alias in codecaliases: + if alias not in _aliases: + _aliases[alias] = modname + + # Return the registry entry + return entry + +# Register the search_function in the Python codec registry +codecs.register(search_function) diff --git a/PythonHome/Lib/encodings/__init__.pyc b/PythonHome/Lib/encodings/__init__.pyc index 9d5e1017e792a759c9c9371b187b7dad4c7ae083..b7380f5f9a2138f90e73e704ac7b41bbe7da2659 100644 GIT binary patch delta 246 zcmZou>QmlO&t~Y(z`)>Y6_cJ>l2Muz6P{n8=N0Vl7Zl(e<6l}*P+Ah>lA2VS9urVm zl98Y1k)NA7xsT15k!ABCwv$X`Xx=9vJ$Wmq9;5K)C!B4pa6%$Zdl98WhWIlNVn=vEv<|k|?nXpJnP5!~D&&a-6gR6}d SoAla>Hz>*)*!_I diff --git a/PythonHome/Lib/encodings/aliases.py b/PythonHome/Lib/encodings/aliases.py new file mode 100644 index 0000000000..a54cf774b7 --- /dev/null +++ b/PythonHome/Lib/encodings/aliases.py @@ -0,0 +1,527 @@ +""" Encoding Aliases Support + + This module is used by the encodings package search function to + map encodings names to module names. + + Note that the search function normalizes the encoding names before + doing the lookup, so the mapping will have to map normalized + encoding names to module names. + + Contents: + + The following aliases dictionary contains mappings of all IANA + character set names for which the Python core library provides + codecs. In addition to these, a few Python specific codec + aliases have also been added. + +""" +aliases = { + + # Please keep this list sorted alphabetically by value ! + + # ascii codec + '646' : 'ascii', + 'ansi_x3.4_1968' : 'ascii', + 'ansi_x3_4_1968' : 'ascii', # some email headers use this non-standard name + 'ansi_x3.4_1986' : 'ascii', + 'cp367' : 'ascii', + 'csascii' : 'ascii', + 'ibm367' : 'ascii', + 'iso646_us' : 'ascii', + 'iso_646.irv_1991' : 'ascii', + 'iso_ir_6' : 'ascii', + 'us' : 'ascii', + 'us_ascii' : 'ascii', + + # base64_codec codec + 'base64' : 'base64_codec', + 'base_64' : 'base64_codec', + + # big5 codec + 'big5_tw' : 'big5', + 'csbig5' : 'big5', + + # big5hkscs codec + 'big5_hkscs' : 'big5hkscs', + 'hkscs' : 'big5hkscs', + + # bz2_codec codec + 'bz2' : 'bz2_codec', + + # cp037 codec + '037' : 'cp037', + 'csibm037' : 'cp037', + 'ebcdic_cp_ca' : 'cp037', + 'ebcdic_cp_nl' : 'cp037', + 'ebcdic_cp_us' : 'cp037', + 'ebcdic_cp_wt' : 'cp037', + 'ibm037' : 'cp037', + 'ibm039' : 'cp037', + + # cp1026 codec + '1026' : 'cp1026', + 'csibm1026' : 'cp1026', + 'ibm1026' : 'cp1026', + + # cp1140 codec + '1140' : 'cp1140', + 'ibm1140' : 'cp1140', + + # cp1250 codec + '1250' : 'cp1250', + 'windows_1250' : 'cp1250', + + # cp1251 codec + '1251' : 'cp1251', + 'windows_1251' : 'cp1251', + + # cp1252 codec + '1252' : 'cp1252', + 'windows_1252' : 'cp1252', + + # cp1253 codec + '1253' : 'cp1253', + 'windows_1253' : 'cp1253', + + # cp1254 codec + '1254' : 'cp1254', + 'windows_1254' : 'cp1254', + + # cp1255 codec + '1255' : 'cp1255', + 'windows_1255' : 'cp1255', + + # cp1256 codec + '1256' : 'cp1256', + 'windows_1256' : 'cp1256', + + # cp1257 codec + '1257' : 'cp1257', + 'windows_1257' : 'cp1257', + + # cp1258 codec + '1258' : 'cp1258', + 'windows_1258' : 'cp1258', + + # cp424 codec + '424' : 'cp424', + 'csibm424' : 'cp424', + 'ebcdic_cp_he' : 'cp424', + 'ibm424' : 'cp424', + + # cp437 codec + '437' : 'cp437', + 'cspc8codepage437' : 'cp437', + 'ibm437' : 'cp437', + + # cp500 codec + '500' : 'cp500', + 'csibm500' : 'cp500', + 'ebcdic_cp_be' : 'cp500', + 'ebcdic_cp_ch' : 'cp500', + 'ibm500' : 'cp500', + + # cp775 codec + '775' : 'cp775', + 'cspc775baltic' : 'cp775', + 'ibm775' : 'cp775', + + # cp850 codec + '850' : 'cp850', + 'cspc850multilingual' : 'cp850', + 'ibm850' : 'cp850', + + # cp852 codec + '852' : 'cp852', + 'cspcp852' : 'cp852', + 'ibm852' : 'cp852', + + # cp855 codec + '855' : 'cp855', + 'csibm855' : 'cp855', + 'ibm855' : 'cp855', + + # cp857 codec + '857' : 'cp857', + 'csibm857' : 'cp857', + 'ibm857' : 'cp857', + + # cp858 codec + '858' : 'cp858', + 'csibm858' : 'cp858', + 'ibm858' : 'cp858', + + # cp860 codec + '860' : 'cp860', + 'csibm860' : 'cp860', + 'ibm860' : 'cp860', + + # cp861 codec + '861' : 'cp861', + 'cp_is' : 'cp861', + 'csibm861' : 'cp861', + 'ibm861' : 'cp861', + + # cp862 codec + '862' : 'cp862', + 'cspc862latinhebrew' : 'cp862', + 'ibm862' : 'cp862', + + # cp863 codec + '863' : 'cp863', + 'csibm863' : 'cp863', + 'ibm863' : 'cp863', + + # cp864 codec + '864' : 'cp864', + 'csibm864' : 'cp864', + 'ibm864' : 'cp864', + + # cp865 codec + '865' : 'cp865', + 'csibm865' : 'cp865', + 'ibm865' : 'cp865', + + # cp866 codec + '866' : 'cp866', + 'csibm866' : 'cp866', + 'ibm866' : 'cp866', + + # cp869 codec + '869' : 'cp869', + 'cp_gr' : 'cp869', + 'csibm869' : 'cp869', + 'ibm869' : 'cp869', + + # cp932 codec + '932' : 'cp932', + 'ms932' : 'cp932', + 'mskanji' : 'cp932', + 'ms_kanji' : 'cp932', + + # cp949 codec + '949' : 'cp949', + 'ms949' : 'cp949', + 'uhc' : 'cp949', + + # cp950 codec + '950' : 'cp950', + 'ms950' : 'cp950', + + # euc_jis_2004 codec + 'jisx0213' : 'euc_jis_2004', + 'eucjis2004' : 'euc_jis_2004', + 'euc_jis2004' : 'euc_jis_2004', + + # euc_jisx0213 codec + 'eucjisx0213' : 'euc_jisx0213', + + # euc_jp codec + 'eucjp' : 'euc_jp', + 'ujis' : 'euc_jp', + 'u_jis' : 'euc_jp', + + # euc_kr codec + 'euckr' : 'euc_kr', + 'korean' : 'euc_kr', + 'ksc5601' : 'euc_kr', + 'ks_c_5601' : 'euc_kr', + 'ks_c_5601_1987' : 'euc_kr', + 'ksx1001' : 'euc_kr', + 'ks_x_1001' : 'euc_kr', + + # gb18030 codec + 'gb18030_2000' : 'gb18030', + + # gb2312 codec + 'chinese' : 'gb2312', + 'csiso58gb231280' : 'gb2312', + 'euc_cn' : 'gb2312', + 'euccn' : 'gb2312', + 'eucgb2312_cn' : 'gb2312', + 'gb2312_1980' : 'gb2312', + 'gb2312_80' : 'gb2312', + 'iso_ir_58' : 'gb2312', + + # gbk codec + '936' : 'gbk', + 'cp936' : 'gbk', + 'ms936' : 'gbk', + + # hex_codec codec + 'hex' : 'hex_codec', + + # hp_roman8 codec + 'roman8' : 'hp_roman8', + 'r8' : 'hp_roman8', + 'csHPRoman8' : 'hp_roman8', + + # hz codec + 'hzgb' : 'hz', + 'hz_gb' : 'hz', + 'hz_gb_2312' : 'hz', + + # iso2022_jp codec + 'csiso2022jp' : 'iso2022_jp', + 'iso2022jp' : 'iso2022_jp', + 'iso_2022_jp' : 'iso2022_jp', + + # iso2022_jp_1 codec + 'iso2022jp_1' : 'iso2022_jp_1', + 'iso_2022_jp_1' : 'iso2022_jp_1', + + # iso2022_jp_2 codec + 'iso2022jp_2' : 'iso2022_jp_2', + 'iso_2022_jp_2' : 'iso2022_jp_2', + + # iso2022_jp_2004 codec + 'iso_2022_jp_2004' : 'iso2022_jp_2004', + 'iso2022jp_2004' : 'iso2022_jp_2004', + + # iso2022_jp_3 codec + 'iso2022jp_3' : 'iso2022_jp_3', + 'iso_2022_jp_3' : 'iso2022_jp_3', + + # iso2022_jp_ext codec + 'iso2022jp_ext' : 'iso2022_jp_ext', + 'iso_2022_jp_ext' : 'iso2022_jp_ext', + + # iso2022_kr codec + 'csiso2022kr' : 'iso2022_kr', + 'iso2022kr' : 'iso2022_kr', + 'iso_2022_kr' : 'iso2022_kr', + + # iso8859_10 codec + 'csisolatin6' : 'iso8859_10', + 'iso_8859_10' : 'iso8859_10', + 'iso_8859_10_1992' : 'iso8859_10', + 'iso_ir_157' : 'iso8859_10', + 'l6' : 'iso8859_10', + 'latin6' : 'iso8859_10', + + # iso8859_11 codec + 'thai' : 'iso8859_11', + 'iso_8859_11' : 'iso8859_11', + 'iso_8859_11_2001' : 'iso8859_11', + + # iso8859_13 codec + 'iso_8859_13' : 'iso8859_13', + 'l7' : 'iso8859_13', + 'latin7' : 'iso8859_13', + + # iso8859_14 codec + 'iso_8859_14' : 'iso8859_14', + 'iso_8859_14_1998' : 'iso8859_14', + 'iso_celtic' : 'iso8859_14', + 'iso_ir_199' : 'iso8859_14', + 'l8' : 'iso8859_14', + 'latin8' : 'iso8859_14', + + # iso8859_15 codec + 'iso_8859_15' : 'iso8859_15', + 'l9' : 'iso8859_15', + 'latin9' : 'iso8859_15', + + # iso8859_16 codec + 'iso_8859_16' : 'iso8859_16', + 'iso_8859_16_2001' : 'iso8859_16', + 'iso_ir_226' : 'iso8859_16', + 'l10' : 'iso8859_16', + 'latin10' : 'iso8859_16', + + # iso8859_2 codec + 'csisolatin2' : 'iso8859_2', + 'iso_8859_2' : 'iso8859_2', + 'iso_8859_2_1987' : 'iso8859_2', + 'iso_ir_101' : 'iso8859_2', + 'l2' : 'iso8859_2', + 'latin2' : 'iso8859_2', + + # iso8859_3 codec + 'csisolatin3' : 'iso8859_3', + 'iso_8859_3' : 'iso8859_3', + 'iso_8859_3_1988' : 'iso8859_3', + 'iso_ir_109' : 'iso8859_3', + 'l3' : 'iso8859_3', + 'latin3' : 'iso8859_3', + + # iso8859_4 codec + 'csisolatin4' : 'iso8859_4', + 'iso_8859_4' : 'iso8859_4', + 'iso_8859_4_1988' : 'iso8859_4', + 'iso_ir_110' : 'iso8859_4', + 'l4' : 'iso8859_4', + 'latin4' : 'iso8859_4', + + # iso8859_5 codec + 'csisolatincyrillic' : 'iso8859_5', + 'cyrillic' : 'iso8859_5', + 'iso_8859_5' : 'iso8859_5', + 'iso_8859_5_1988' : 'iso8859_5', + 'iso_ir_144' : 'iso8859_5', + + # iso8859_6 codec + 'arabic' : 'iso8859_6', + 'asmo_708' : 'iso8859_6', + 'csisolatinarabic' : 'iso8859_6', + 'ecma_114' : 'iso8859_6', + 'iso_8859_6' : 'iso8859_6', + 'iso_8859_6_1987' : 'iso8859_6', + 'iso_ir_127' : 'iso8859_6', + + # iso8859_7 codec + 'csisolatingreek' : 'iso8859_7', + 'ecma_118' : 'iso8859_7', + 'elot_928' : 'iso8859_7', + 'greek' : 'iso8859_7', + 'greek8' : 'iso8859_7', + 'iso_8859_7' : 'iso8859_7', + 'iso_8859_7_1987' : 'iso8859_7', + 'iso_ir_126' : 'iso8859_7', + + # iso8859_8 codec + 'csisolatinhebrew' : 'iso8859_8', + 'hebrew' : 'iso8859_8', + 'iso_8859_8' : 'iso8859_8', + 'iso_8859_8_1988' : 'iso8859_8', + 'iso_ir_138' : 'iso8859_8', + + # iso8859_9 codec + 'csisolatin5' : 'iso8859_9', + 'iso_8859_9' : 'iso8859_9', + 'iso_8859_9_1989' : 'iso8859_9', + 'iso_ir_148' : 'iso8859_9', + 'l5' : 'iso8859_9', + 'latin5' : 'iso8859_9', + + # johab codec + 'cp1361' : 'johab', + 'ms1361' : 'johab', + + # koi8_r codec + 'cskoi8r' : 'koi8_r', + + # latin_1 codec + # + # Note that the latin_1 codec is implemented internally in C and a + # lot faster than the charmap codec iso8859_1 which uses the same + # encoding. This is why we discourage the use of the iso8859_1 + # codec and alias it to latin_1 instead. + # + '8859' : 'latin_1', + 'cp819' : 'latin_1', + 'csisolatin1' : 'latin_1', + 'ibm819' : 'latin_1', + 'iso8859' : 'latin_1', + 'iso8859_1' : 'latin_1', + 'iso_8859_1' : 'latin_1', + 'iso_8859_1_1987' : 'latin_1', + 'iso_ir_100' : 'latin_1', + 'l1' : 'latin_1', + 'latin' : 'latin_1', + 'latin1' : 'latin_1', + + # mac_cyrillic codec + 'maccyrillic' : 'mac_cyrillic', + + # mac_greek codec + 'macgreek' : 'mac_greek', + + # mac_iceland codec + 'maciceland' : 'mac_iceland', + + # mac_latin2 codec + 'maccentraleurope' : 'mac_latin2', + 'maclatin2' : 'mac_latin2', + + # mac_roman codec + 'macroman' : 'mac_roman', + + # mac_turkish codec + 'macturkish' : 'mac_turkish', + + # mbcs codec + 'dbcs' : 'mbcs', + + # ptcp154 codec + 'csptcp154' : 'ptcp154', + 'pt154' : 'ptcp154', + 'cp154' : 'ptcp154', + 'cyrillic_asian' : 'ptcp154', + + # quopri_codec codec + 'quopri' : 'quopri_codec', + 'quoted_printable' : 'quopri_codec', + 'quotedprintable' : 'quopri_codec', + + # rot_13 codec + 'rot13' : 'rot_13', + + # shift_jis codec + 'csshiftjis' : 'shift_jis', + 'shiftjis' : 'shift_jis', + 'sjis' : 'shift_jis', + 's_jis' : 'shift_jis', + + # shift_jis_2004 codec + 'shiftjis2004' : 'shift_jis_2004', + 'sjis_2004' : 'shift_jis_2004', + 's_jis_2004' : 'shift_jis_2004', + + # shift_jisx0213 codec + 'shiftjisx0213' : 'shift_jisx0213', + 'sjisx0213' : 'shift_jisx0213', + 's_jisx0213' : 'shift_jisx0213', + + # tactis codec + 'tis260' : 'tactis', + + # tis_620 codec + 'tis620' : 'tis_620', + 'tis_620_0' : 'tis_620', + 'tis_620_2529_0' : 'tis_620', + 'tis_620_2529_1' : 'tis_620', + 'iso_ir_166' : 'tis_620', + + # utf_16 codec + 'u16' : 'utf_16', + 'utf16' : 'utf_16', + + # utf_16_be codec + 'unicodebigunmarked' : 'utf_16_be', + 'utf_16be' : 'utf_16_be', + + # utf_16_le codec + 'unicodelittleunmarked' : 'utf_16_le', + 'utf_16le' : 'utf_16_le', + + # utf_32 codec + 'u32' : 'utf_32', + 'utf32' : 'utf_32', + + # utf_32_be codec + 'utf_32be' : 'utf_32_be', + + # utf_32_le codec + 'utf_32le' : 'utf_32_le', + + # utf_7 codec + 'u7' : 'utf_7', + 'utf7' : 'utf_7', + 'unicode_1_1_utf_7' : 'utf_7', + + # utf_8 codec + 'u8' : 'utf_8', + 'utf' : 'utf_8', + 'utf8' : 'utf_8', + 'utf8_ucs2' : 'utf_8', + 'utf8_ucs4' : 'utf_8', + + # uu_codec codec + 'uu' : 'uu_codec', + + # zlib_codec codec + 'zip' : 'zlib_codec', + 'zlib' : 'zlib_codec', + +} diff --git a/PythonHome/Lib/encodings/aliases.pyc b/PythonHome/Lib/encodings/aliases.pyc index 8157ed7af0a5e14c1ad7a54053bbcc2bbf162bc3..31661a3de39cdf641aab9a41bc2a9bc7504a331e 100644 GIT binary patch delta 62 zcmdn%a^Gdcba_KJ1_lOKtC;l6l8n-%nDG1xJ+EMYzn}o;82{3eg3^*0m(--v^q7Fk Sl8pR3kNn)!&CBGcGXVg=Ru=C7 delta 28 kcmccbve#w9ba{Ri1_lOatC)bwl8pR3BlFECmsdFNS8USjZ%q9Q; delta 240 zcmeAc*)F(2mWf}9fq}up9;5|dk*ZLx}TvmC%GF2ZVoReUOI i5>{~sHtgcB*(P99zxfEeJR^q0IZlbmI-G@A#BBi+EI{)B diff --git a/PythonHome/Lib/encodings/base64_codec.py b/PythonHome/Lib/encodings/base64_codec.py new file mode 100644 index 0000000000..f84e7808e9 --- /dev/null +++ b/PythonHome/Lib/encodings/base64_codec.py @@ -0,0 +1,79 @@ +""" Python 'base64_codec' Codec - base64 content transfer encoding + + Unlike most of the other codecs which target Unicode, this codec + will return Python string objects for both encode and decode. + + Written by Marc-Andre Lemburg (mal@lemburg.com). + +""" +import codecs, base64 + +### Codec APIs + +def base64_encode(input,errors='strict'): + + """ Encodes the object input and returns a tuple (output + object, length consumed). + + errors defines the error handling to apply. It defaults to + 'strict' handling which is the only currently supported + error handling for this codec. + + """ + assert errors == 'strict' + output = base64.encodestring(input) + return (output, len(input)) + +def base64_decode(input,errors='strict'): + + """ Decodes the object input and returns a tuple (output + object, length consumed). + + input must be an object which provides the bf_getreadbuf + buffer slot. Python strings, buffer objects and memory + mapped files are examples of objects providing this slot. + + errors defines the error handling to apply. It defaults to + 'strict' handling which is the only currently supported + error handling for this codec. + + """ + assert errors == 'strict' + output = base64.decodestring(input) + return (output, len(input)) + +class Codec(codecs.Codec): + + def encode(self, input,errors='strict'): + return base64_encode(input,errors) + def decode(self, input,errors='strict'): + return base64_decode(input,errors) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + assert self.errors == 'strict' + return base64.encodestring(input) + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + assert self.errors == 'strict' + return base64.decodestring(input) + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='base64', + encode=base64_encode, + decode=base64_decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/PythonHome/Lib/encodings/base64_codec.pyc b/PythonHome/Lib/encodings/base64_codec.pyc deleted file mode 100644 index 8c080b6109f9d5486ca47e934f900b15d4f05b3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3633 zcmdT{>uwuG6rOcrJ8{#r1d51=V8ovosSQFZNFY=-O5Biwl}08rQssjWX5Ob%;j9ZbI$D2ua|p2J^J<_RkLRazqirc z&*(Cx4$(&{YpEhqhadvoQim;-Eval-y}&pK{I`W(R#``xNS(CR2$Q?&g;LLz`sT2$ zvK3);gt59{bX3+8Mpqb@7L2aS)|6=rZ$*u8;^hTzMP=)A-m37fEO@IbyULft9tA(> zzd?OoqSIeZ{c&CC?P21~r#A;_otbo7@9{_9&|y@kb>&UvwYN#-M#gGWVPak#^?Dl5 z*Hw`}F}kds*Y!yIW20+y7VEH$(@&4{^jQ1E9vP3xIft)fTJFLO+2mC`cOl*2%x5}*14^26o*dyI9 zlj3#}UUt&D{1B`1mw5JlhvvXxsZU!V>2bC_4u6d9nYj5$OSui@mHIJK9`0#EbYrU#Ao8C*#8Cem(Kvi9u-Dp!#)P znCb|M!w+s!nv9~8&Bs_3|?o8Ae22uTGbbcM(u5-rvysqw1 zd~ra)nqLD~;AMjQVOOP~f1kg;jZVxbOM>n~2E+BiR?@lmLG3(#m=7P%!Rj8L2Kml- z>Mvu?Y%Cnf0Y@~b-bQpK`diWP3(;^_@cPf8Awa8~AQFd+kQstzAvm`6cljKQ!_ffo zXibt0C!>WgK{LQzQTv_W$DzBfXUus(G5||c)^@sBUIJ+*)1$lq7869D`93LuY{$ef zUl+s>Xfg-LS^r}|$8fBQ8Sw(%kdgv;V**}~8xy%Pp%r&IhITQahV9?Q@&MFz0#)K- zkJ&cm#(XHx9WJXJ-GIC?R=K;lZFv zN;4RE9yb`2bv7yR8q-oSvsi-lVuEg~Yz< z;I}X@IM|3^!~FwJrJoiCq&>x-AAmsNIuS6ird?w-V@+$R6BMzCH7!)I{U&P%=q`{R z6C!6UEg(b{N{UARbE!_deS#*ctLR!JrjD;*D87nLHol(}&WMSd-Oq1bUU+Wu2%4c2 zowe;!Gq#NhhDPyonUzTV9PQ7{8ovqVh4D(%ea78q7G=O4u$+{q*#O~5iBuB=y}AP z+#`{9@o|7?%a(a-#8-lsPXxdm9|yS2;H$uQ@rlqq=o1S2U@OIxBSof3GlJs0$q*rX z+OxwUlUXTFC`<6rQ}NKL0p0?P?bAbYo8pxn}obzeO6Cf98&Nme +# + +import _codecs_tw, codecs +import _multibytecodec as mbc + +codec = _codecs_tw.getcodec('big5') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='big5', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/big5.pyc b/PythonHome/Lib/encodings/big5.pyc deleted file mode 100644 index 0ec9db0f37fdebe03c33b8133035689e2b72beb2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1665 zcmcgs&2G~`5FY=;`Kgm2#7_Z<1E-vNe-R<06{v0KAfBATyW0b!zX*>=siK1F|C~~%X zmm-f0(ZVO~(gvmmX=of;1T=%2Pq#!Hq90K}xT)>He8MPSV?wG(-ng{zBy$KpMLwy~09G3C=eC6@j`K-o;@Ea%k*)Ogl9%j| zaC{p;GC9j4LItsk0t<;$zJzo({+dq5;+p33a?Ci-uGWfyg%~A+51h7RpF+6Elfq;s zx0B@;iC#R;gcGkbiQF2!2fcE65{cs;0;mc9Cm1D%2;7HoK1+tjgTu%0Y!43CYGeyD z$&{IBb37nzY(4P+uo=X~1AcmBL2GD0HGeCE z>kUFDgS}{7(AG9dx47>&)Eo^s-HK660fiMQZhOTYFHMo|dbDCd@lai{p^#FQa%MO; zoY|h@MrtR!34w%FrRCj+Ot6c5wi1r)HdoxCiu*#bo8o#L(BSq2{&NF3bMUKJzs0iT zh9{6Oa6;UH+yhot%&$8af>h&Q=BhuXPKtjnhZKv;{Gs~qedM~A%*9hDbo=frzwNy6 Ic)Y{?7vmK(bpQYW diff --git a/PythonHome/Lib/encodings/big5hkscs.py b/PythonHome/Lib/encodings/big5hkscs.py new file mode 100644 index 0000000000..350df37baa --- /dev/null +++ b/PythonHome/Lib/encodings/big5hkscs.py @@ -0,0 +1,39 @@ +# +# big5hkscs.py: Python Unicode Codec for BIG5HKSCS +# +# Written by Hye-Shik Chang +# + +import _codecs_hk, codecs +import _multibytecodec as mbc + +codec = _codecs_hk.getcodec('big5hkscs') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='big5hkscs', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/big5hkscs.pyc b/PythonHome/Lib/encodings/big5hkscs.pyc deleted file mode 100644 index 579c76595cd09a381148e5f0f1d9650ede56ef72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1705 zcmcgs&2G~`5FY=;`Ki+&1gQLo1E-vN<5r=Hz@ZZKusKv%kxb%sQm3(lyj!81!!z+R zJO&Q{-;5h4YT=Meyx#Tf%oGPXuJ+Bh@x6{C~`J> zmm-f+qPb7nr8P_q($F|G4`>QEpMDUniM~Vu=?0}9&6{Fw(bOd!)aDjx7+`LTxg+LQ zZSIhUArOxv@d#<^k?zzUA!!&YkFIzei$_>{9Fy+yB`Jj_!Rl1hJ9G6&&zEKLmU_5JdI=9kx9PP zw+o)KL&E#p08(18EFx48t6g9rk<2Sdr=w5VWF)RxF*BnY?CH0aVss(8;iC(jwqqYd zxG0h`&C|k;7a!#p<->3|1$8))TZiC5uUsBP;(hl<)x@Gl=!W+R-20e5NUR6O#HaFP z2NP#)Xv=h*t8}c>1Eb-pJE_q)c8lh!%;qN$6e2i<`6=NK%w4qD>{dp)us zJv1PqzmahhGzcXQZlk6_YTG2;VnVE`IqY-HmzE2PxuNhS#e7gq1*ws2TelT8%KPey zCZ*)d$m!t(ae6z7?~*|In=ni0W`yShX5K|HT?%iuKUZ9^iYr7hNX7Zsx9IH=7R^#% znt^!b>NTc@NkCv_;Dl&_v_31Vd!d3BU*9Ovak}IDc44#0$_hsk%OuPviCik!T~;X0 zp@d-h)IM)kJfyt@_Ftzv9!lW$>F!Ru#E_Ky%Uo5eBunwFvvND&Fh5V6 Q(CxX;{kHSWbs{@!7fUxqRm`^PMA5-;ubw4dP?-wL4%T2nP|$y z+I*r(Nn0jbGI3@;(W0b7x*>C`G{P6x=X0x+Y|Q4?WNvdlw?@fXemQ6}U6Wn{`+JqYUW>hP{jp&GyN6MzH71u!D{T{8b}5S zw>=(y58V?%#={!fEpkLZ1mu8#8a;vS1Nt6BjaVNHwe>m`J*c!8 zPn-zvwPjVL++>_-)h#Cub0P)X#VhWj%5-rEwZ&y&C%I0Tb)M!&8&et!HICAv`iu;z zBWO2c?YmM%<8e0asoRd%MUxD+aOM1nT`&9YVvDyotSd+;vZ;zE#^}OaL)38|bcCtBnH?Z!-JP9T5=fR`EMSsSHB!E>F4!I?)q8L!9X^<0+&-8)1VH23Sil1^tvB&z835GY3O0j(6#zdo0B#7t|2qJ9 zH02Yx?vP!o0!`%`V^e;c&hR%J4dB2=N6Bz9nwt;w2<~OG()Ir6xb~u|CTAYZ9-HgD zG}HO^9N>b>j?xV9i{NnjyC?^kEk}~sKF@}rk%NYO>m|l;2*XmyPA+KT80JH3$Osq2 zhK$&dffcrR3~gC}`q20mHhO?=FhIo<_BbrZd?Y{2$8|KT&}k$Fge%EwoV<`$K-a27 z7WO@JSV%ED)~xM;w(IB+-w^H)(4KM}V>$Pw57{@pFS3kQXQPFP%Sgv6@vg_A)iU!G zEXfPIuot8Q>c#o+8h#&VRDAdd#i9-dMU?BoKny$>0LC-`fJuYHMa%gb`cw$BeX`DPZj2QyI#P$=k2Odlz6+MD5*$F?kC$*Ov5fW0 zO$^)v@q994dqZGkwHh7Qxt!rw97Uw zNrj=9iFYlucB;Z88w>_%k-EX)Bkc8F5Nri&9xp8DT(pnz0@Rud%=|I_Aygpg8HrhP zGYV&3C8UoP*^Zvdh0NE|yz#kLd@1w^>%eki X0K$XLN@t_9wcXl2yS=$n-)Z~?wPuy9 diff --git a/PythonHome/Lib/encodings/charmap.py b/PythonHome/Lib/encodings/charmap.py new file mode 100644 index 0000000000..81189b161a --- /dev/null +++ b/PythonHome/Lib/encodings/charmap.py @@ -0,0 +1,69 @@ +""" Generic Python Character Mapping Codec. + + Use this codec directly rather than through the automatic + conversion mechanisms supplied by unicode() and .encode(). + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + # Note: Binding these as C functions will result in the class not + # converting them to methods. This is intended. + encode = codecs.charmap_encode + decode = codecs.charmap_decode + +class IncrementalEncoder(codecs.IncrementalEncoder): + def __init__(self, errors='strict', mapping=None): + codecs.IncrementalEncoder.__init__(self, errors) + self.mapping = mapping + + def encode(self, input, final=False): + return codecs.charmap_encode(input, self.errors, self.mapping)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def __init__(self, errors='strict', mapping=None): + codecs.IncrementalDecoder.__init__(self, errors) + self.mapping = mapping + + def decode(self, input, final=False): + return codecs.charmap_decode(input, self.errors, self.mapping)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + + def __init__(self,stream,errors='strict',mapping=None): + codecs.StreamWriter.__init__(self,stream,errors) + self.mapping = mapping + + def encode(self,input,errors='strict'): + return Codec.encode(input,errors,self.mapping) + +class StreamReader(Codec,codecs.StreamReader): + + def __init__(self,stream,errors='strict',mapping=None): + codecs.StreamReader.__init__(self,stream,errors) + self.mapping = mapping + + def decode(self,input,errors='strict'): + return Codec.decode(input,errors,self.mapping) + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='charmap', + encode=Codec.encode, + decode=Codec.decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/PythonHome/Lib/encodings/charmap.pyc b/PythonHome/Lib/encodings/charmap.pyc deleted file mode 100644 index 55d7208b98da265db2c1bb3c8f70275b4f2b895b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3278 zcmd5;>uMxL6h7T^%_MPkR~I8Ilq^C=b_c{Cf-JHzUI^@tQlo?&0%NDUGSi_iLv_u{ zK>j69;zRgiK7gL@bmqbk&Bgq%hpMTnQ{Gw>;Hh@d8d=0Z@TxFv$R2-*ulo#G8LzQ`JM z!W(oJvIfPQb6HblTMJo};%#&WEhyCw-hr+UJtFmk$&F1S_0!Cai(KuGLmNiUSoJ!b zOp<)0_KVm=-A+gG_e*J%8z-fTFsS0hn#iRyWkWaSC2kz%T-jne8uPzV;nWpb=#ofQ zM@9bD*fQZ`G86IKq|8cHPA8KzF|j(HscD{I=U`Wbd91o7uX=oX=g=n3nH;lThcI)k)TJ#NY`-m&USb9MFv_^xvG#WH$lI{mArJ%)? zYjZUm=3!=rL)Vc`R>ad3-6nSh#nQnT42R9a$*{VzNH3eKQU;yj5oy(|4&(JCEm5s| z^eQ<%lGSX#^5}Bw?qsGh@jWhOovUVj!*dV0agayWWF~iE`kf$d7k37)<<3vJQQeu@ z&2(mVU-&d&UNa?qx?q|&aCvMj`jw7ZJ9L?gM<7I%eYNj{l6X`Li_ znBH7pFcb=vIFr0y07_{p##;q9xUdzSTAYU;9&$yY_0KZST+&?kIVpkAD!|C;dxq>&c z5j^5kXn8dq^t;#+SJ8+78q;sd0${4RELi{&_nkFihVX1|WB-`LNEJ8g^SDvjAI>r_ zV*jT+ux5Xb7VL4}S?%9~#v@+0LIH6?@j9T+;fb}rD;qw;4%m>q$5(`j$1GTei7G~j z#`DMqZfh(TXI!VK7$2-y+UGh4g->_6ER2tVWh_`R{vEs@Kth$u?mm0}((c-X@&C;3 zAK>ajbcwbLyX*HMSb7`xZtnkI@Z|fkI2`XDERJoygi>>N|3{18!P5cZ=hz(JHQC}3 z|I3G%BwqOyH!6--i7w{^PO_o6E)7l#8hCZ$Ch`GJXZgvF+jzy#snrh<>U;7;Aw81k z{4!6eTmnkVBa%&zhWQCNKTmL4(Xk~zXomnb}NZvlrYg5r4_s@S0pu;}_s4x%_Y#7twH7r8}4@ mInSCF8qfVLRlx}_s;u*Cs8u4mH2tmmPHU&V(|)q?Wb NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x9c' # 0x04 -> CONTROL + u'\t' # 0x05 -> HORIZONTAL TABULATION + u'\x86' # 0x06 -> CONTROL + u'\x7f' # 0x07 -> DELETE + u'\x97' # 0x08 -> CONTROL + u'\x8d' # 0x09 -> CONTROL + u'\x8e' # 0x0A -> CONTROL + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x9d' # 0x14 -> CONTROL + u'\x85' # 0x15 -> CONTROL + u'\x08' # 0x16 -> BACKSPACE + u'\x87' # 0x17 -> CONTROL + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x92' # 0x1A -> CONTROL + u'\x8f' # 0x1B -> CONTROL + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u'\x80' # 0x20 -> CONTROL + u'\x81' # 0x21 -> CONTROL + u'\x82' # 0x22 -> CONTROL + u'\x83' # 0x23 -> CONTROL + u'\x84' # 0x24 -> CONTROL + u'\n' # 0x25 -> LINE FEED + u'\x17' # 0x26 -> END OF TRANSMISSION BLOCK + u'\x1b' # 0x27 -> ESCAPE + u'\x88' # 0x28 -> CONTROL + u'\x89' # 0x29 -> CONTROL + u'\x8a' # 0x2A -> CONTROL + u'\x8b' # 0x2B -> CONTROL + u'\x8c' # 0x2C -> CONTROL + u'\x05' # 0x2D -> ENQUIRY + u'\x06' # 0x2E -> ACKNOWLEDGE + u'\x07' # 0x2F -> BELL + u'\x90' # 0x30 -> CONTROL + u'\x91' # 0x31 -> CONTROL + u'\x16' # 0x32 -> SYNCHRONOUS IDLE + u'\x93' # 0x33 -> CONTROL + u'\x94' # 0x34 -> CONTROL + u'\x95' # 0x35 -> CONTROL + u'\x96' # 0x36 -> CONTROL + u'\x04' # 0x37 -> END OF TRANSMISSION + u'\x98' # 0x38 -> CONTROL + u'\x99' # 0x39 -> CONTROL + u'\x9a' # 0x3A -> CONTROL + u'\x9b' # 0x3B -> CONTROL + u'\x14' # 0x3C -> DEVICE CONTROL FOUR + u'\x15' # 0x3D -> NEGATIVE ACKNOWLEDGE + u'\x9e' # 0x3E -> CONTROL + u'\x1a' # 0x3F -> SUBSTITUTE + u' ' # 0x40 -> SPACE + u'\xa0' # 0x41 -> NO-BREAK SPACE + u'\xe2' # 0x42 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x43 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe0' # 0x44 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe1' # 0x45 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe3' # 0x46 -> LATIN SMALL LETTER A WITH TILDE + u'\xe5' # 0x47 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe7' # 0x48 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xf1' # 0x49 -> LATIN SMALL LETTER N WITH TILDE + u'\xa2' # 0x4A -> CENT SIGN + u'.' # 0x4B -> FULL STOP + u'<' # 0x4C -> LESS-THAN SIGN + u'(' # 0x4D -> LEFT PARENTHESIS + u'+' # 0x4E -> PLUS SIGN + u'|' # 0x4F -> VERTICAL LINE + u'&' # 0x50 -> AMPERSAND + u'\xe9' # 0x51 -> LATIN SMALL LETTER E WITH ACUTE + u'\xea' # 0x52 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x53 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xe8' # 0x54 -> LATIN SMALL LETTER E WITH GRAVE + u'\xed' # 0x55 -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0x56 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0x57 -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xec' # 0x58 -> LATIN SMALL LETTER I WITH GRAVE + u'\xdf' # 0x59 -> LATIN SMALL LETTER SHARP S (GERMAN) + u'!' # 0x5A -> EXCLAMATION MARK + u'$' # 0x5B -> DOLLAR SIGN + u'*' # 0x5C -> ASTERISK + u')' # 0x5D -> RIGHT PARENTHESIS + u';' # 0x5E -> SEMICOLON + u'\xac' # 0x5F -> NOT SIGN + u'-' # 0x60 -> HYPHEN-MINUS + u'/' # 0x61 -> SOLIDUS + u'\xc2' # 0x62 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xc4' # 0x63 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc0' # 0x64 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc1' # 0x65 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc3' # 0x66 -> LATIN CAPITAL LETTER A WITH TILDE + u'\xc5' # 0x67 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc7' # 0x68 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xd1' # 0x69 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xa6' # 0x6A -> BROKEN BAR + u',' # 0x6B -> COMMA + u'%' # 0x6C -> PERCENT SIGN + u'_' # 0x6D -> LOW LINE + u'>' # 0x6E -> GREATER-THAN SIGN + u'?' # 0x6F -> QUESTION MARK + u'\xf8' # 0x70 -> LATIN SMALL LETTER O WITH STROKE + u'\xc9' # 0x71 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xca' # 0x72 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xcb' # 0x73 -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xc8' # 0x74 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xcd' # 0x75 -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0x76 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0x77 -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\xcc' # 0x78 -> LATIN CAPITAL LETTER I WITH GRAVE + u'`' # 0x79 -> GRAVE ACCENT + u':' # 0x7A -> COLON + u'#' # 0x7B -> NUMBER SIGN + u'@' # 0x7C -> COMMERCIAL AT + u"'" # 0x7D -> APOSTROPHE + u'=' # 0x7E -> EQUALS SIGN + u'"' # 0x7F -> QUOTATION MARK + u'\xd8' # 0x80 -> LATIN CAPITAL LETTER O WITH STROKE + u'a' # 0x81 -> LATIN SMALL LETTER A + u'b' # 0x82 -> LATIN SMALL LETTER B + u'c' # 0x83 -> LATIN SMALL LETTER C + u'd' # 0x84 -> LATIN SMALL LETTER D + u'e' # 0x85 -> LATIN SMALL LETTER E + u'f' # 0x86 -> LATIN SMALL LETTER F + u'g' # 0x87 -> LATIN SMALL LETTER G + u'h' # 0x88 -> LATIN SMALL LETTER H + u'i' # 0x89 -> LATIN SMALL LETTER I + u'\xab' # 0x8A -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x8B -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xf0' # 0x8C -> LATIN SMALL LETTER ETH (ICELANDIC) + u'\xfd' # 0x8D -> LATIN SMALL LETTER Y WITH ACUTE + u'\xfe' # 0x8E -> LATIN SMALL LETTER THORN (ICELANDIC) + u'\xb1' # 0x8F -> PLUS-MINUS SIGN + u'\xb0' # 0x90 -> DEGREE SIGN + u'j' # 0x91 -> LATIN SMALL LETTER J + u'k' # 0x92 -> LATIN SMALL LETTER K + u'l' # 0x93 -> LATIN SMALL LETTER L + u'm' # 0x94 -> LATIN SMALL LETTER M + u'n' # 0x95 -> LATIN SMALL LETTER N + u'o' # 0x96 -> LATIN SMALL LETTER O + u'p' # 0x97 -> LATIN SMALL LETTER P + u'q' # 0x98 -> LATIN SMALL LETTER Q + u'r' # 0x99 -> LATIN SMALL LETTER R + u'\xaa' # 0x9A -> FEMININE ORDINAL INDICATOR + u'\xba' # 0x9B -> MASCULINE ORDINAL INDICATOR + u'\xe6' # 0x9C -> LATIN SMALL LIGATURE AE + u'\xb8' # 0x9D -> CEDILLA + u'\xc6' # 0x9E -> LATIN CAPITAL LIGATURE AE + u'\xa4' # 0x9F -> CURRENCY SIGN + u'\xb5' # 0xA0 -> MICRO SIGN + u'~' # 0xA1 -> TILDE + u's' # 0xA2 -> LATIN SMALL LETTER S + u't' # 0xA3 -> LATIN SMALL LETTER T + u'u' # 0xA4 -> LATIN SMALL LETTER U + u'v' # 0xA5 -> LATIN SMALL LETTER V + u'w' # 0xA6 -> LATIN SMALL LETTER W + u'x' # 0xA7 -> LATIN SMALL LETTER X + u'y' # 0xA8 -> LATIN SMALL LETTER Y + u'z' # 0xA9 -> LATIN SMALL LETTER Z + u'\xa1' # 0xAA -> INVERTED EXCLAMATION MARK + u'\xbf' # 0xAB -> INVERTED QUESTION MARK + u'\xd0' # 0xAC -> LATIN CAPITAL LETTER ETH (ICELANDIC) + u'\xdd' # 0xAD -> LATIN CAPITAL LETTER Y WITH ACUTE + u'\xde' # 0xAE -> LATIN CAPITAL LETTER THORN (ICELANDIC) + u'\xae' # 0xAF -> REGISTERED SIGN + u'^' # 0xB0 -> CIRCUMFLEX ACCENT + u'\xa3' # 0xB1 -> POUND SIGN + u'\xa5' # 0xB2 -> YEN SIGN + u'\xb7' # 0xB3 -> MIDDLE DOT + u'\xa9' # 0xB4 -> COPYRIGHT SIGN + u'\xa7' # 0xB5 -> SECTION SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xbc' # 0xB7 -> VULGAR FRACTION ONE QUARTER + u'\xbd' # 0xB8 -> VULGAR FRACTION ONE HALF + u'\xbe' # 0xB9 -> VULGAR FRACTION THREE QUARTERS + u'[' # 0xBA -> LEFT SQUARE BRACKET + u']' # 0xBB -> RIGHT SQUARE BRACKET + u'\xaf' # 0xBC -> MACRON + u'\xa8' # 0xBD -> DIAERESIS + u'\xb4' # 0xBE -> ACUTE ACCENT + u'\xd7' # 0xBF -> MULTIPLICATION SIGN + u'{' # 0xC0 -> LEFT CURLY BRACKET + u'A' # 0xC1 -> LATIN CAPITAL LETTER A + u'B' # 0xC2 -> LATIN CAPITAL LETTER B + u'C' # 0xC3 -> LATIN CAPITAL LETTER C + u'D' # 0xC4 -> LATIN CAPITAL LETTER D + u'E' # 0xC5 -> LATIN CAPITAL LETTER E + u'F' # 0xC6 -> LATIN CAPITAL LETTER F + u'G' # 0xC7 -> LATIN CAPITAL LETTER G + u'H' # 0xC8 -> LATIN CAPITAL LETTER H + u'I' # 0xC9 -> LATIN CAPITAL LETTER I + u'\xad' # 0xCA -> SOFT HYPHEN + u'\xf4' # 0xCB -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0xCC -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf2' # 0xCD -> LATIN SMALL LETTER O WITH GRAVE + u'\xf3' # 0xCE -> LATIN SMALL LETTER O WITH ACUTE + u'\xf5' # 0xCF -> LATIN SMALL LETTER O WITH TILDE + u'}' # 0xD0 -> RIGHT CURLY BRACKET + u'J' # 0xD1 -> LATIN CAPITAL LETTER J + u'K' # 0xD2 -> LATIN CAPITAL LETTER K + u'L' # 0xD3 -> LATIN CAPITAL LETTER L + u'M' # 0xD4 -> LATIN CAPITAL LETTER M + u'N' # 0xD5 -> LATIN CAPITAL LETTER N + u'O' # 0xD6 -> LATIN CAPITAL LETTER O + u'P' # 0xD7 -> LATIN CAPITAL LETTER P + u'Q' # 0xD8 -> LATIN CAPITAL LETTER Q + u'R' # 0xD9 -> LATIN CAPITAL LETTER R + u'\xb9' # 0xDA -> SUPERSCRIPT ONE + u'\xfb' # 0xDB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0xDC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xf9' # 0xDD -> LATIN SMALL LETTER U WITH GRAVE + u'\xfa' # 0xDE -> LATIN SMALL LETTER U WITH ACUTE + u'\xff' # 0xDF -> LATIN SMALL LETTER Y WITH DIAERESIS + u'\\' # 0xE0 -> REVERSE SOLIDUS + u'\xf7' # 0xE1 -> DIVISION SIGN + u'S' # 0xE2 -> LATIN CAPITAL LETTER S + u'T' # 0xE3 -> LATIN CAPITAL LETTER T + u'U' # 0xE4 -> LATIN CAPITAL LETTER U + u'V' # 0xE5 -> LATIN CAPITAL LETTER V + u'W' # 0xE6 -> LATIN CAPITAL LETTER W + u'X' # 0xE7 -> LATIN CAPITAL LETTER X + u'Y' # 0xE8 -> LATIN CAPITAL LETTER Y + u'Z' # 0xE9 -> LATIN CAPITAL LETTER Z + u'\xb2' # 0xEA -> SUPERSCRIPT TWO + u'\xd4' # 0xEB -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\xd6' # 0xEC -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xd2' # 0xED -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd5' # 0xEF -> LATIN CAPITAL LETTER O WITH TILDE + u'0' # 0xF0 -> DIGIT ZERO + u'1' # 0xF1 -> DIGIT ONE + u'2' # 0xF2 -> DIGIT TWO + u'3' # 0xF3 -> DIGIT THREE + u'4' # 0xF4 -> DIGIT FOUR + u'5' # 0xF5 -> DIGIT FIVE + u'6' # 0xF6 -> DIGIT SIX + u'7' # 0xF7 -> DIGIT SEVEN + u'8' # 0xF8 -> DIGIT EIGHT + u'9' # 0xF9 -> DIGIT NINE + u'\xb3' # 0xFA -> SUPERSCRIPT THREE + u'\xdb' # 0xFB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xdc' # 0xFC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xd9' # 0xFD -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xda' # 0xFE -> LATIN CAPITAL LETTER U WITH ACUTE + u'\x9f' # 0xFF -> CONTROL +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp037.pyc b/PythonHome/Lib/encodings/cp037.pyc deleted file mode 100644 index 6c14032d11add558185ecbb1d42723c38f7116e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2694 zcmc&$30E9N5bix$76`cw3F^j+^@3>Bc*ICpAfjP|vltRYH^a^>Ebis(Afi!8AoqRW z_kG`xJMUHfB!57x>Ipj}`gr1dK6mM+rfa&o>Z`A-*7Zk;f3Rg)BqpAGT=c)1MsA2E zO^8;S9YS-8q(iil;1aq+bU8(wWVaX)qF;!mtxlnNq{1Z?-n_ykv;wJcONB45a0{(a z=uWBgh&UPW=XD;T6%FgWQdgYUd4*QO53L148z)+Q(g0cViGFg>&z?qtr5r$xra)7# z*_lZPLY=Ci#!TG^G^*KbBHa-PWi&k&h-GKZo)hTM)4HLWx)z8VnN*;naeh-%LwG@? zYH?k-c99aPYHSEa>YJ&`93sj_WhqP=a{O0G@fNjO+LBrHX2j$;>&e-nhlTc2{DkS4U{ zk`$kIUt!=C22LrUX)OL)h8d|R{stKe(??S@npRVKG-~?gLn@qO00}emob>a{Ksvu$-0 z)a6X-NIotX{h}ZeWD0~$zCv6%B+q4Wv`dC0Y{I_uR#`TlUAC%{A(KSCfRaRmP#Uq& zBeN!tw8|wPE}Kt7I-Zf`#y(czd!sM~6h=bfY>Xv+CR4IQCr_yFnMUtSddx8og`?2n zbrjRrE5F@+Odp5S1qTaZ_3y9;Ho@ki;*xQt<0nj<1czXi57ta8gYB@T{P`DNgg#gS zE1@3-{LjsRwXhD>!v@&s@fN^V*fte*z)si&yWOxC_Q8HQFnJ0bo*sascpOjSQ9Onx z@D!fGYjC`BZt%_Jui-g7j~DPPUc$?G1ux=}nXkO@`X_Ml?J8V}1K5Wvupd|98r%k_ z-+DDV?=!rO>u^18z_qvuH{%xExa{MXt1CWz3HPe)F-?zmbSB^e+{3H*03X6NxZ3r7 zGL_C`e=y)Y+{M#y8&|_gxb<7k?EbOmr{1687(BwQcnA-}#Tj4tH#ND_Zci^sB@4P$vz4t$u^WjHu0}tRq+=u(&NRYEd%;XlPWn$E_ zxaeDyu!+DNu-GtzB`#Vfm*?SM4DH>Cq-OO4S{*@`Q7^jeoO7*SInPD=a@@YC-?__t SW$rR}xvSh$Sn7Q&+ NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\u06f0' # 0xA1 -> EXTENDED ARABIC-INDIC DIGIT ZERO + u'\u06f1' # 0xA2 -> EXTENDED ARABIC-INDIC DIGIT ONE + u'\u06f2' # 0xA3 -> EXTENDED ARABIC-INDIC DIGIT TWO + u'\u06f3' # 0xA4 -> EXTENDED ARABIC-INDIC DIGIT THREE + u'\u06f4' # 0xA5 -> EXTENDED ARABIC-INDIC DIGIT FOUR + u'\u06f5' # 0xA6 -> EXTENDED ARABIC-INDIC DIGIT FIVE + u'\u06f6' # 0xA7 -> EXTENDED ARABIC-INDIC DIGIT SIX + u'\u06f7' # 0xA8 -> EXTENDED ARABIC-INDIC DIGIT SEVEN + u'\u06f8' # 0xA9 -> EXTENDED ARABIC-INDIC DIGIT EIGHT + u'\u06f9' # 0xAA -> EXTENDED ARABIC-INDIC DIGIT NINE + u'\u060c' # 0xAB -> ARABIC COMMA + u'\u061b' # 0xAC -> ARABIC SEMICOLON + u'\xad' # 0xAD -> SOFT HYPHEN + u'\u061f' # 0xAE -> ARABIC QUESTION MARK + u'\ufe81' # 0xAF -> ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM + u'\ufe8d' # 0xB0 -> ARABIC LETTER ALEF ISOLATED FORM + u'\ufe8e' # 0xB1 -> ARABIC LETTER ALEF FINAL FORM + u'\ufe8e' # 0xB2 -> ARABIC LETTER ALEF FINAL FORM + u'\ufe8f' # 0xB3 -> ARABIC LETTER BEH ISOLATED FORM + u'\ufe91' # 0xB4 -> ARABIC LETTER BEH INITIAL FORM + u'\ufb56' # 0xB5 -> ARABIC LETTER PEH ISOLATED FORM + u'\ufb58' # 0xB6 -> ARABIC LETTER PEH INITIAL FORM + u'\ufe93' # 0xB7 -> ARABIC LETTER TEH MARBUTA ISOLATED FORM + u'\ufe95' # 0xB8 -> ARABIC LETTER TEH ISOLATED FORM + u'\ufe97' # 0xB9 -> ARABIC LETTER TEH INITIAL FORM + u'\ufb66' # 0xBA -> ARABIC LETTER TTEH ISOLATED FORM + u'\ufb68' # 0xBB -> ARABIC LETTER TTEH INITIAL FORM + u'\ufe99' # 0xBC -> ARABIC LETTER THEH ISOLATED FORM + u'\ufe9b' # 0xBD -> ARABIC LETTER THEH INITIAL FORM + u'\ufe9d' # 0xBE -> ARABIC LETTER JEEM ISOLATED FORM + u'\ufe9f' # 0xBF -> ARABIC LETTER JEEM INITIAL FORM + u'\ufb7a' # 0xC0 -> ARABIC LETTER TCHEH ISOLATED FORM + u'\ufb7c' # 0xC1 -> ARABIC LETTER TCHEH INITIAL FORM + u'\ufea1' # 0xC2 -> ARABIC LETTER HAH ISOLATED FORM + u'\ufea3' # 0xC3 -> ARABIC LETTER HAH INITIAL FORM + u'\ufea5' # 0xC4 -> ARABIC LETTER KHAH ISOLATED FORM + u'\ufea7' # 0xC5 -> ARABIC LETTER KHAH INITIAL FORM + u'\ufea9' # 0xC6 -> ARABIC LETTER DAL ISOLATED FORM + u'\ufb84' # 0xC7 -> ARABIC LETTER DAHAL ISOLATED FORMN + u'\ufeab' # 0xC8 -> ARABIC LETTER THAL ISOLATED FORM + u'\ufead' # 0xC9 -> ARABIC LETTER REH ISOLATED FORM + u'\ufb8c' # 0xCA -> ARABIC LETTER RREH ISOLATED FORM + u'\ufeaf' # 0xCB -> ARABIC LETTER ZAIN ISOLATED FORM + u'\ufb8a' # 0xCC -> ARABIC LETTER JEH ISOLATED FORM + u'\ufeb1' # 0xCD -> ARABIC LETTER SEEN ISOLATED FORM + u'\ufeb3' # 0xCE -> ARABIC LETTER SEEN INITIAL FORM + u'\ufeb5' # 0xCF -> ARABIC LETTER SHEEN ISOLATED FORM + u'\ufeb7' # 0xD0 -> ARABIC LETTER SHEEN INITIAL FORM + u'\ufeb9' # 0xD1 -> ARABIC LETTER SAD ISOLATED FORM + u'\ufebb' # 0xD2 -> ARABIC LETTER SAD INITIAL FORM + u'\ufebd' # 0xD3 -> ARABIC LETTER DAD ISOLATED FORM + u'\ufebf' # 0xD4 -> ARABIC LETTER DAD INITIAL FORM + u'\ufec1' # 0xD5 -> ARABIC LETTER TAH ISOLATED FORM + u'\ufec5' # 0xD6 -> ARABIC LETTER ZAH ISOLATED FORM + u'\ufec9' # 0xD7 -> ARABIC LETTER AIN ISOLATED FORM + u'\ufeca' # 0xD8 -> ARABIC LETTER AIN FINAL FORM + u'\ufecb' # 0xD9 -> ARABIC LETTER AIN INITIAL FORM + u'\ufecc' # 0xDA -> ARABIC LETTER AIN MEDIAL FORM + u'\ufecd' # 0xDB -> ARABIC LETTER GHAIN ISOLATED FORM + u'\ufece' # 0xDC -> ARABIC LETTER GHAIN FINAL FORM + u'\ufecf' # 0xDD -> ARABIC LETTER GHAIN INITIAL FORM + u'\ufed0' # 0xDE -> ARABIC LETTER GHAIN MEDIAL FORM + u'\ufed1' # 0xDF -> ARABIC LETTER FEH ISOLATED FORM + u'\ufed3' # 0xE0 -> ARABIC LETTER FEH INITIAL FORM + u'\ufed5' # 0xE1 -> ARABIC LETTER QAF ISOLATED FORM + u'\ufed7' # 0xE2 -> ARABIC LETTER QAF INITIAL FORM + u'\ufed9' # 0xE3 -> ARABIC LETTER KAF ISOLATED FORM + u'\ufedb' # 0xE4 -> ARABIC LETTER KAF INITIAL FORM + u'\ufb92' # 0xE5 -> ARABIC LETTER GAF ISOLATED FORM + u'\ufb94' # 0xE6 -> ARABIC LETTER GAF INITIAL FORM + u'\ufedd' # 0xE7 -> ARABIC LETTER LAM ISOLATED FORM + u'\ufedf' # 0xE8 -> ARABIC LETTER LAM INITIAL FORM + u'\ufee0' # 0xE9 -> ARABIC LETTER LAM MEDIAL FORM + u'\ufee1' # 0xEA -> ARABIC LETTER MEEM ISOLATED FORM + u'\ufee3' # 0xEB -> ARABIC LETTER MEEM INITIAL FORM + u'\ufb9e' # 0xEC -> ARABIC LETTER NOON GHUNNA ISOLATED FORM + u'\ufee5' # 0xED -> ARABIC LETTER NOON ISOLATED FORM + u'\ufee7' # 0xEE -> ARABIC LETTER NOON INITIAL FORM + u'\ufe85' # 0xEF -> ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM + u'\ufeed' # 0xF0 -> ARABIC LETTER WAW ISOLATED FORM + u'\ufba6' # 0xF1 -> ARABIC LETTER HEH GOAL ISOLATED FORM + u'\ufba8' # 0xF2 -> ARABIC LETTER HEH GOAL INITIAL FORM + u'\ufba9' # 0xF3 -> ARABIC LETTER HEH GOAL MEDIAL FORM + u'\ufbaa' # 0xF4 -> ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM + u'\ufe80' # 0xF5 -> ARABIC LETTER HAMZA ISOLATED FORM + u'\ufe89' # 0xF6 -> ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM + u'\ufe8a' # 0xF7 -> ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM + u'\ufe8b' # 0xF8 -> ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM + u'\ufef1' # 0xF9 -> ARABIC LETTER YEH ISOLATED FORM + u'\ufef2' # 0xFA -> ARABIC LETTER YEH FINAL FORM + u'\ufef3' # 0xFB -> ARABIC LETTER YEH INITIAL FORM + u'\ufbb0' # 0xFC -> ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM + u'\ufbae' # 0xFD -> ARABIC LETTER YEH BARREE ISOLATED FORM + u'\ufe7c' # 0xFE -> ARABIC SHADDA ISOLATED FORM + u'\ufe7d' # 0xFF -> ARABIC SHADDA MEDIAL FORM +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp1006.pyc b/PythonHome/Lib/encodings/cp1006.pyc deleted file mode 100644 index 956d036ff885349a44f67d7ffd32e35cdfefd655..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2780 zcmc&$d2>@$6u()UhL#<)P&K#_w-#J*Lj*#>Dh>4oS!y+;c`t1+n=h|o6$NZjftG!> zLSYyXbrM+w?7c9~+;8B2%;ZCyKl}iA&V4iw&;en_G0D5V_nvpp@;kqKPCb9t2QRH& z7fZ4m9}oUrh)?k{4mx8UIJ%hbW*Hajz=?+$F1FsyQaJar0mk|nTifAgx=#r_O5m>w zJWQ`q0uJ$Z!}Rg2BcK$ZrU2_l z2ZQ8kEIfe%$lwra@3VUHxlp7hVJ4E6VTRfgg+e;l9g5_2BN<8-=FXWjFVt=13^QRF zdMIV)v!U5-i`v^;qswB=t6HKiR0!!@q1RG=7^aywi(wQpH540g*3`K?-PJj!rPyf$i9py#6fWaP9|g}`_Y;Li zM{n^Tp+>mXmYUw`zedPwgq&7`!#z1{YbLC2I2tMM|%YB2nfx6g8?% zPN;VQkoYwnpMM5Wn~0+O;2_~PZA>d-M;VD(rjf|5Hq%%ntK1`IEv6SKkv8|RLgAb# z{y3?00#dWPL`9UKBBG+Y#lB`F^#9&IRnSJqel=W5O@#Ir;$Yt$yZ2$&qbiG+2(OQK zY>q9=MUF zPuLYOPxv5CH*IWCiBmT1x=Gem8*0s^@~Y}MW;MDz8nHklC^X8)J!Q}$UUnPk3bsJY z?3;zlB9W1~YF&O;9e(}l+xrJm$mRBUeg2w2ZE##&{rCwJCrzF*b=vd?9&DH~v+<#a z9|_HR^s&dEcyf05si&WL_PM6!Idh+X;l-Ecz5L3nuf0D1jRkKmT(mf{q-E){w_4wR zXL(z6Mfh4Le|0t8qRnAu~RDP{otX!&GuKZRRy*7AlSeCAh0N(<92>4F*+XZ|Nlnz4a zFz|iA4*)*|rPEM41N;c^Vc;_JG(2;sA(4AdY|- zhVou0?+0-d#0ZGvAWncd3FTuTPJuwvs0xjqhVmIGqZ>Z~-wb>kaC88bp966o#04my zg>o52ufXWlFr^>KPR&uzC$Sk)H?c|PP>Wb)^J^x}s1{mO_Q(Dk>FP~qbi2{u?o9-| lbM;V7dA{9-7kKbsks2d*Qg1_`!Q0?%^fdZvC-|>3?_YsetQP

NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x9c' # 0x04 -> CONTROL + u'\t' # 0x05 -> HORIZONTAL TABULATION + u'\x86' # 0x06 -> CONTROL + u'\x7f' # 0x07 -> DELETE + u'\x97' # 0x08 -> CONTROL + u'\x8d' # 0x09 -> CONTROL + u'\x8e' # 0x0A -> CONTROL + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x9d' # 0x14 -> CONTROL + u'\x85' # 0x15 -> CONTROL + u'\x08' # 0x16 -> BACKSPACE + u'\x87' # 0x17 -> CONTROL + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x92' # 0x1A -> CONTROL + u'\x8f' # 0x1B -> CONTROL + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u'\x80' # 0x20 -> CONTROL + u'\x81' # 0x21 -> CONTROL + u'\x82' # 0x22 -> CONTROL + u'\x83' # 0x23 -> CONTROL + u'\x84' # 0x24 -> CONTROL + u'\n' # 0x25 -> LINE FEED + u'\x17' # 0x26 -> END OF TRANSMISSION BLOCK + u'\x1b' # 0x27 -> ESCAPE + u'\x88' # 0x28 -> CONTROL + u'\x89' # 0x29 -> CONTROL + u'\x8a' # 0x2A -> CONTROL + u'\x8b' # 0x2B -> CONTROL + u'\x8c' # 0x2C -> CONTROL + u'\x05' # 0x2D -> ENQUIRY + u'\x06' # 0x2E -> ACKNOWLEDGE + u'\x07' # 0x2F -> BELL + u'\x90' # 0x30 -> CONTROL + u'\x91' # 0x31 -> CONTROL + u'\x16' # 0x32 -> SYNCHRONOUS IDLE + u'\x93' # 0x33 -> CONTROL + u'\x94' # 0x34 -> CONTROL + u'\x95' # 0x35 -> CONTROL + u'\x96' # 0x36 -> CONTROL + u'\x04' # 0x37 -> END OF TRANSMISSION + u'\x98' # 0x38 -> CONTROL + u'\x99' # 0x39 -> CONTROL + u'\x9a' # 0x3A -> CONTROL + u'\x9b' # 0x3B -> CONTROL + u'\x14' # 0x3C -> DEVICE CONTROL FOUR + u'\x15' # 0x3D -> NEGATIVE ACKNOWLEDGE + u'\x9e' # 0x3E -> CONTROL + u'\x1a' # 0x3F -> SUBSTITUTE + u' ' # 0x40 -> SPACE + u'\xa0' # 0x41 -> NO-BREAK SPACE + u'\xe2' # 0x42 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x43 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe0' # 0x44 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe1' # 0x45 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe3' # 0x46 -> LATIN SMALL LETTER A WITH TILDE + u'\xe5' # 0x47 -> LATIN SMALL LETTER A WITH RING ABOVE + u'{' # 0x48 -> LEFT CURLY BRACKET + u'\xf1' # 0x49 -> LATIN SMALL LETTER N WITH TILDE + u'\xc7' # 0x4A -> LATIN CAPITAL LETTER C WITH CEDILLA + u'.' # 0x4B -> FULL STOP + u'<' # 0x4C -> LESS-THAN SIGN + u'(' # 0x4D -> LEFT PARENTHESIS + u'+' # 0x4E -> PLUS SIGN + u'!' # 0x4F -> EXCLAMATION MARK + u'&' # 0x50 -> AMPERSAND + u'\xe9' # 0x51 -> LATIN SMALL LETTER E WITH ACUTE + u'\xea' # 0x52 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x53 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xe8' # 0x54 -> LATIN SMALL LETTER E WITH GRAVE + u'\xed' # 0x55 -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0x56 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0x57 -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xec' # 0x58 -> LATIN SMALL LETTER I WITH GRAVE + u'\xdf' # 0x59 -> LATIN SMALL LETTER SHARP S (GERMAN) + u'\u011e' # 0x5A -> LATIN CAPITAL LETTER G WITH BREVE + u'\u0130' # 0x5B -> LATIN CAPITAL LETTER I WITH DOT ABOVE + u'*' # 0x5C -> ASTERISK + u')' # 0x5D -> RIGHT PARENTHESIS + u';' # 0x5E -> SEMICOLON + u'^' # 0x5F -> CIRCUMFLEX ACCENT + u'-' # 0x60 -> HYPHEN-MINUS + u'/' # 0x61 -> SOLIDUS + u'\xc2' # 0x62 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xc4' # 0x63 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc0' # 0x64 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc1' # 0x65 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc3' # 0x66 -> LATIN CAPITAL LETTER A WITH TILDE + u'\xc5' # 0x67 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'[' # 0x68 -> LEFT SQUARE BRACKET + u'\xd1' # 0x69 -> LATIN CAPITAL LETTER N WITH TILDE + u'\u015f' # 0x6A -> LATIN SMALL LETTER S WITH CEDILLA + u',' # 0x6B -> COMMA + u'%' # 0x6C -> PERCENT SIGN + u'_' # 0x6D -> LOW LINE + u'>' # 0x6E -> GREATER-THAN SIGN + u'?' # 0x6F -> QUESTION MARK + u'\xf8' # 0x70 -> LATIN SMALL LETTER O WITH STROKE + u'\xc9' # 0x71 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xca' # 0x72 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xcb' # 0x73 -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xc8' # 0x74 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xcd' # 0x75 -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0x76 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0x77 -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\xcc' # 0x78 -> LATIN CAPITAL LETTER I WITH GRAVE + u'\u0131' # 0x79 -> LATIN SMALL LETTER DOTLESS I + u':' # 0x7A -> COLON + u'\xd6' # 0x7B -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\u015e' # 0x7C -> LATIN CAPITAL LETTER S WITH CEDILLA + u"'" # 0x7D -> APOSTROPHE + u'=' # 0x7E -> EQUALS SIGN + u'\xdc' # 0x7F -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xd8' # 0x80 -> LATIN CAPITAL LETTER O WITH STROKE + u'a' # 0x81 -> LATIN SMALL LETTER A + u'b' # 0x82 -> LATIN SMALL LETTER B + u'c' # 0x83 -> LATIN SMALL LETTER C + u'd' # 0x84 -> LATIN SMALL LETTER D + u'e' # 0x85 -> LATIN SMALL LETTER E + u'f' # 0x86 -> LATIN SMALL LETTER F + u'g' # 0x87 -> LATIN SMALL LETTER G + u'h' # 0x88 -> LATIN SMALL LETTER H + u'i' # 0x89 -> LATIN SMALL LETTER I + u'\xab' # 0x8A -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x8B -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'}' # 0x8C -> RIGHT CURLY BRACKET + u'`' # 0x8D -> GRAVE ACCENT + u'\xa6' # 0x8E -> BROKEN BAR + u'\xb1' # 0x8F -> PLUS-MINUS SIGN + u'\xb0' # 0x90 -> DEGREE SIGN + u'j' # 0x91 -> LATIN SMALL LETTER J + u'k' # 0x92 -> LATIN SMALL LETTER K + u'l' # 0x93 -> LATIN SMALL LETTER L + u'm' # 0x94 -> LATIN SMALL LETTER M + u'n' # 0x95 -> LATIN SMALL LETTER N + u'o' # 0x96 -> LATIN SMALL LETTER O + u'p' # 0x97 -> LATIN SMALL LETTER P + u'q' # 0x98 -> LATIN SMALL LETTER Q + u'r' # 0x99 -> LATIN SMALL LETTER R + u'\xaa' # 0x9A -> FEMININE ORDINAL INDICATOR + u'\xba' # 0x9B -> MASCULINE ORDINAL INDICATOR + u'\xe6' # 0x9C -> LATIN SMALL LIGATURE AE + u'\xb8' # 0x9D -> CEDILLA + u'\xc6' # 0x9E -> LATIN CAPITAL LIGATURE AE + u'\xa4' # 0x9F -> CURRENCY SIGN + u'\xb5' # 0xA0 -> MICRO SIGN + u'\xf6' # 0xA1 -> LATIN SMALL LETTER O WITH DIAERESIS + u's' # 0xA2 -> LATIN SMALL LETTER S + u't' # 0xA3 -> LATIN SMALL LETTER T + u'u' # 0xA4 -> LATIN SMALL LETTER U + u'v' # 0xA5 -> LATIN SMALL LETTER V + u'w' # 0xA6 -> LATIN SMALL LETTER W + u'x' # 0xA7 -> LATIN SMALL LETTER X + u'y' # 0xA8 -> LATIN SMALL LETTER Y + u'z' # 0xA9 -> LATIN SMALL LETTER Z + u'\xa1' # 0xAA -> INVERTED EXCLAMATION MARK + u'\xbf' # 0xAB -> INVERTED QUESTION MARK + u']' # 0xAC -> RIGHT SQUARE BRACKET + u'$' # 0xAD -> DOLLAR SIGN + u'@' # 0xAE -> COMMERCIAL AT + u'\xae' # 0xAF -> REGISTERED SIGN + u'\xa2' # 0xB0 -> CENT SIGN + u'\xa3' # 0xB1 -> POUND SIGN + u'\xa5' # 0xB2 -> YEN SIGN + u'\xb7' # 0xB3 -> MIDDLE DOT + u'\xa9' # 0xB4 -> COPYRIGHT SIGN + u'\xa7' # 0xB5 -> SECTION SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xbc' # 0xB7 -> VULGAR FRACTION ONE QUARTER + u'\xbd' # 0xB8 -> VULGAR FRACTION ONE HALF + u'\xbe' # 0xB9 -> VULGAR FRACTION THREE QUARTERS + u'\xac' # 0xBA -> NOT SIGN + u'|' # 0xBB -> VERTICAL LINE + u'\xaf' # 0xBC -> MACRON + u'\xa8' # 0xBD -> DIAERESIS + u'\xb4' # 0xBE -> ACUTE ACCENT + u'\xd7' # 0xBF -> MULTIPLICATION SIGN + u'\xe7' # 0xC0 -> LATIN SMALL LETTER C WITH CEDILLA + u'A' # 0xC1 -> LATIN CAPITAL LETTER A + u'B' # 0xC2 -> LATIN CAPITAL LETTER B + u'C' # 0xC3 -> LATIN CAPITAL LETTER C + u'D' # 0xC4 -> LATIN CAPITAL LETTER D + u'E' # 0xC5 -> LATIN CAPITAL LETTER E + u'F' # 0xC6 -> LATIN CAPITAL LETTER F + u'G' # 0xC7 -> LATIN CAPITAL LETTER G + u'H' # 0xC8 -> LATIN CAPITAL LETTER H + u'I' # 0xC9 -> LATIN CAPITAL LETTER I + u'\xad' # 0xCA -> SOFT HYPHEN + u'\xf4' # 0xCB -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'~' # 0xCC -> TILDE + u'\xf2' # 0xCD -> LATIN SMALL LETTER O WITH GRAVE + u'\xf3' # 0xCE -> LATIN SMALL LETTER O WITH ACUTE + u'\xf5' # 0xCF -> LATIN SMALL LETTER O WITH TILDE + u'\u011f' # 0xD0 -> LATIN SMALL LETTER G WITH BREVE + u'J' # 0xD1 -> LATIN CAPITAL LETTER J + u'K' # 0xD2 -> LATIN CAPITAL LETTER K + u'L' # 0xD3 -> LATIN CAPITAL LETTER L + u'M' # 0xD4 -> LATIN CAPITAL LETTER M + u'N' # 0xD5 -> LATIN CAPITAL LETTER N + u'O' # 0xD6 -> LATIN CAPITAL LETTER O + u'P' # 0xD7 -> LATIN CAPITAL LETTER P + u'Q' # 0xD8 -> LATIN CAPITAL LETTER Q + u'R' # 0xD9 -> LATIN CAPITAL LETTER R + u'\xb9' # 0xDA -> SUPERSCRIPT ONE + u'\xfb' # 0xDB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\\' # 0xDC -> REVERSE SOLIDUS + u'\xf9' # 0xDD -> LATIN SMALL LETTER U WITH GRAVE + u'\xfa' # 0xDE -> LATIN SMALL LETTER U WITH ACUTE + u'\xff' # 0xDF -> LATIN SMALL LETTER Y WITH DIAERESIS + u'\xfc' # 0xE0 -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xf7' # 0xE1 -> DIVISION SIGN + u'S' # 0xE2 -> LATIN CAPITAL LETTER S + u'T' # 0xE3 -> LATIN CAPITAL LETTER T + u'U' # 0xE4 -> LATIN CAPITAL LETTER U + u'V' # 0xE5 -> LATIN CAPITAL LETTER V + u'W' # 0xE6 -> LATIN CAPITAL LETTER W + u'X' # 0xE7 -> LATIN CAPITAL LETTER X + u'Y' # 0xE8 -> LATIN CAPITAL LETTER Y + u'Z' # 0xE9 -> LATIN CAPITAL LETTER Z + u'\xb2' # 0xEA -> SUPERSCRIPT TWO + u'\xd4' # 0xEB -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'#' # 0xEC -> NUMBER SIGN + u'\xd2' # 0xED -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd5' # 0xEF -> LATIN CAPITAL LETTER O WITH TILDE + u'0' # 0xF0 -> DIGIT ZERO + u'1' # 0xF1 -> DIGIT ONE + u'2' # 0xF2 -> DIGIT TWO + u'3' # 0xF3 -> DIGIT THREE + u'4' # 0xF4 -> DIGIT FOUR + u'5' # 0xF5 -> DIGIT FIVE + u'6' # 0xF6 -> DIGIT SIX + u'7' # 0xF7 -> DIGIT SEVEN + u'8' # 0xF8 -> DIGIT EIGHT + u'9' # 0xF9 -> DIGIT NINE + u'\xb3' # 0xFA -> SUPERSCRIPT THREE + u'\xdb' # 0xFB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'"' # 0xFC -> QUOTATION MARK + u'\xd9' # 0xFD -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xda' # 0xFE -> LATIN CAPITAL LETTER U WITH ACUTE + u'\x9f' # 0xFF -> CONTROL +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp1026.pyc b/PythonHome/Lib/encodings/cp1026.pyc deleted file mode 100644 index 38f110b8734cc8ebe0196cc91c84523d36c3e41c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2708 zcmc&$33n7l5biy*SrWpnfvAgD)++&2ybwb+2}a2hXCr|aT_!uT$>LtlPQ)lmAmP5` zJ|*1u6^?K!?^T6g#gG4bGW(f=xX zbJuCmglM7BAvC8*Iz$TzE}=Wb5~qlh>=wO3^a!!2#VIt8G`OU}n>VT~F(VYU)}bZe&t{@`gE$ zjrHNVk;(ftgQ~!)Q2iVjl8O&X<<`&U}?ha;Po-yuOi!3;rA!* z(-Ss5biO<#kFAq5)$Ce;2AyIc3?;n1`XgA(lAAGWv50((%DW^`k@;}#>fT9DCCeUC8?ryUZSmaXqQ~8g(v}GEs?m4;{7;y;dq)T6ka;a ze}bCemMSR@_g`V;6-G`epy7!ewsvN$9ylCiFial}(P&yt>Cvd^my=XR>rB#AVVlAs z+6PJL(eNm=KoruO;{&|TB9}Rig!**M&{KNaRFkz5J0nI~`Q+I%fuBNJW(+6( z?*LCGtxXf+3o*sTOrd*S8VT~Y;RFprhAP2Um}e3^g}sxkuu+w?h$qr&(vJ8s!7@f1 z-ov0OMSMsx4RXUeHJQ^TnD(y!21m}-*rBbxj*%$VNUHolC~|r&6qzz3P*k``*`YoL zK<3vZdjAtD`=U0em-1IO^EeXG+1}XYJ$}MxXRKcqU+-xlBt(@ zn8ccw3pO=8lbVx{t45C~hyBVPM&GiO+H<=q55<@Bdd;mtiqQ^VHPM1g~IuGq70hM%XXbyp%!QwT~leA zV=@Xyp~LGaqK{X8I=h)d4yOwa6vFD|up2hP=21n(qf5q&9XB3+gH=9Q^K2<>gDqvx zJ^uo9!wOglJ<#iaW(ur@b+8^bz($X^0Dgt7lVCgSfSs_*4SQfO?1TLiCc?qV0XT$5 z@E9J#!*~>r|AhUxreap`jj6BVX*`2x@f4oN3wROFVc+1v!Aq~d_R%+QRpLtQ#co`I zJ-F&C+A4qXTJCT2XF=VzleKrAM^z| zTf|N7Wm+aiy^D*##R;1UOahAzQ&{5CWpb4s`ti`#nMi6@Um)#6e0lU`mpycr)ir0k bXkm`~7&Sh3sjt*s>MnDYc?wIs_l5f}Y1w9+ diff --git a/PythonHome/Lib/encodings/cp1140.py b/PythonHome/Lib/encodings/cp1140.py new file mode 100644 index 0000000000..7e507fd853 --- /dev/null +++ b/PythonHome/Lib/encodings/cp1140.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1140 generated from 'python-mappings/CP1140.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1140', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x9c' # 0x04 -> CONTROL + u'\t' # 0x05 -> HORIZONTAL TABULATION + u'\x86' # 0x06 -> CONTROL + u'\x7f' # 0x07 -> DELETE + u'\x97' # 0x08 -> CONTROL + u'\x8d' # 0x09 -> CONTROL + u'\x8e' # 0x0A -> CONTROL + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x9d' # 0x14 -> CONTROL + u'\x85' # 0x15 -> CONTROL + u'\x08' # 0x16 -> BACKSPACE + u'\x87' # 0x17 -> CONTROL + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x92' # 0x1A -> CONTROL + u'\x8f' # 0x1B -> CONTROL + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u'\x80' # 0x20 -> CONTROL + u'\x81' # 0x21 -> CONTROL + u'\x82' # 0x22 -> CONTROL + u'\x83' # 0x23 -> CONTROL + u'\x84' # 0x24 -> CONTROL + u'\n' # 0x25 -> LINE FEED + u'\x17' # 0x26 -> END OF TRANSMISSION BLOCK + u'\x1b' # 0x27 -> ESCAPE + u'\x88' # 0x28 -> CONTROL + u'\x89' # 0x29 -> CONTROL + u'\x8a' # 0x2A -> CONTROL + u'\x8b' # 0x2B -> CONTROL + u'\x8c' # 0x2C -> CONTROL + u'\x05' # 0x2D -> ENQUIRY + u'\x06' # 0x2E -> ACKNOWLEDGE + u'\x07' # 0x2F -> BELL + u'\x90' # 0x30 -> CONTROL + u'\x91' # 0x31 -> CONTROL + u'\x16' # 0x32 -> SYNCHRONOUS IDLE + u'\x93' # 0x33 -> CONTROL + u'\x94' # 0x34 -> CONTROL + u'\x95' # 0x35 -> CONTROL + u'\x96' # 0x36 -> CONTROL + u'\x04' # 0x37 -> END OF TRANSMISSION + u'\x98' # 0x38 -> CONTROL + u'\x99' # 0x39 -> CONTROL + u'\x9a' # 0x3A -> CONTROL + u'\x9b' # 0x3B -> CONTROL + u'\x14' # 0x3C -> DEVICE CONTROL FOUR + u'\x15' # 0x3D -> NEGATIVE ACKNOWLEDGE + u'\x9e' # 0x3E -> CONTROL + u'\x1a' # 0x3F -> SUBSTITUTE + u' ' # 0x40 -> SPACE + u'\xa0' # 0x41 -> NO-BREAK SPACE + u'\xe2' # 0x42 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x43 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe0' # 0x44 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe1' # 0x45 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe3' # 0x46 -> LATIN SMALL LETTER A WITH TILDE + u'\xe5' # 0x47 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe7' # 0x48 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xf1' # 0x49 -> LATIN SMALL LETTER N WITH TILDE + u'\xa2' # 0x4A -> CENT SIGN + u'.' # 0x4B -> FULL STOP + u'<' # 0x4C -> LESS-THAN SIGN + u'(' # 0x4D -> LEFT PARENTHESIS + u'+' # 0x4E -> PLUS SIGN + u'|' # 0x4F -> VERTICAL LINE + u'&' # 0x50 -> AMPERSAND + u'\xe9' # 0x51 -> LATIN SMALL LETTER E WITH ACUTE + u'\xea' # 0x52 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x53 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xe8' # 0x54 -> LATIN SMALL LETTER E WITH GRAVE + u'\xed' # 0x55 -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0x56 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0x57 -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xec' # 0x58 -> LATIN SMALL LETTER I WITH GRAVE + u'\xdf' # 0x59 -> LATIN SMALL LETTER SHARP S (GERMAN) + u'!' # 0x5A -> EXCLAMATION MARK + u'$' # 0x5B -> DOLLAR SIGN + u'*' # 0x5C -> ASTERISK + u')' # 0x5D -> RIGHT PARENTHESIS + u';' # 0x5E -> SEMICOLON + u'\xac' # 0x5F -> NOT SIGN + u'-' # 0x60 -> HYPHEN-MINUS + u'/' # 0x61 -> SOLIDUS + u'\xc2' # 0x62 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xc4' # 0x63 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc0' # 0x64 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc1' # 0x65 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc3' # 0x66 -> LATIN CAPITAL LETTER A WITH TILDE + u'\xc5' # 0x67 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc7' # 0x68 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xd1' # 0x69 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xa6' # 0x6A -> BROKEN BAR + u',' # 0x6B -> COMMA + u'%' # 0x6C -> PERCENT SIGN + u'_' # 0x6D -> LOW LINE + u'>' # 0x6E -> GREATER-THAN SIGN + u'?' # 0x6F -> QUESTION MARK + u'\xf8' # 0x70 -> LATIN SMALL LETTER O WITH STROKE + u'\xc9' # 0x71 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xca' # 0x72 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xcb' # 0x73 -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xc8' # 0x74 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xcd' # 0x75 -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0x76 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0x77 -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\xcc' # 0x78 -> LATIN CAPITAL LETTER I WITH GRAVE + u'`' # 0x79 -> GRAVE ACCENT + u':' # 0x7A -> COLON + u'#' # 0x7B -> NUMBER SIGN + u'@' # 0x7C -> COMMERCIAL AT + u"'" # 0x7D -> APOSTROPHE + u'=' # 0x7E -> EQUALS SIGN + u'"' # 0x7F -> QUOTATION MARK + u'\xd8' # 0x80 -> LATIN CAPITAL LETTER O WITH STROKE + u'a' # 0x81 -> LATIN SMALL LETTER A + u'b' # 0x82 -> LATIN SMALL LETTER B + u'c' # 0x83 -> LATIN SMALL LETTER C + u'd' # 0x84 -> LATIN SMALL LETTER D + u'e' # 0x85 -> LATIN SMALL LETTER E + u'f' # 0x86 -> LATIN SMALL LETTER F + u'g' # 0x87 -> LATIN SMALL LETTER G + u'h' # 0x88 -> LATIN SMALL LETTER H + u'i' # 0x89 -> LATIN SMALL LETTER I + u'\xab' # 0x8A -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x8B -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xf0' # 0x8C -> LATIN SMALL LETTER ETH (ICELANDIC) + u'\xfd' # 0x8D -> LATIN SMALL LETTER Y WITH ACUTE + u'\xfe' # 0x8E -> LATIN SMALL LETTER THORN (ICELANDIC) + u'\xb1' # 0x8F -> PLUS-MINUS SIGN + u'\xb0' # 0x90 -> DEGREE SIGN + u'j' # 0x91 -> LATIN SMALL LETTER J + u'k' # 0x92 -> LATIN SMALL LETTER K + u'l' # 0x93 -> LATIN SMALL LETTER L + u'm' # 0x94 -> LATIN SMALL LETTER M + u'n' # 0x95 -> LATIN SMALL LETTER N + u'o' # 0x96 -> LATIN SMALL LETTER O + u'p' # 0x97 -> LATIN SMALL LETTER P + u'q' # 0x98 -> LATIN SMALL LETTER Q + u'r' # 0x99 -> LATIN SMALL LETTER R + u'\xaa' # 0x9A -> FEMININE ORDINAL INDICATOR + u'\xba' # 0x9B -> MASCULINE ORDINAL INDICATOR + u'\xe6' # 0x9C -> LATIN SMALL LIGATURE AE + u'\xb8' # 0x9D -> CEDILLA + u'\xc6' # 0x9E -> LATIN CAPITAL LIGATURE AE + u'\u20ac' # 0x9F -> EURO SIGN + u'\xb5' # 0xA0 -> MICRO SIGN + u'~' # 0xA1 -> TILDE + u's' # 0xA2 -> LATIN SMALL LETTER S + u't' # 0xA3 -> LATIN SMALL LETTER T + u'u' # 0xA4 -> LATIN SMALL LETTER U + u'v' # 0xA5 -> LATIN SMALL LETTER V + u'w' # 0xA6 -> LATIN SMALL LETTER W + u'x' # 0xA7 -> LATIN SMALL LETTER X + u'y' # 0xA8 -> LATIN SMALL LETTER Y + u'z' # 0xA9 -> LATIN SMALL LETTER Z + u'\xa1' # 0xAA -> INVERTED EXCLAMATION MARK + u'\xbf' # 0xAB -> INVERTED QUESTION MARK + u'\xd0' # 0xAC -> LATIN CAPITAL LETTER ETH (ICELANDIC) + u'\xdd' # 0xAD -> LATIN CAPITAL LETTER Y WITH ACUTE + u'\xde' # 0xAE -> LATIN CAPITAL LETTER THORN (ICELANDIC) + u'\xae' # 0xAF -> REGISTERED SIGN + u'^' # 0xB0 -> CIRCUMFLEX ACCENT + u'\xa3' # 0xB1 -> POUND SIGN + u'\xa5' # 0xB2 -> YEN SIGN + u'\xb7' # 0xB3 -> MIDDLE DOT + u'\xa9' # 0xB4 -> COPYRIGHT SIGN + u'\xa7' # 0xB5 -> SECTION SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xbc' # 0xB7 -> VULGAR FRACTION ONE QUARTER + u'\xbd' # 0xB8 -> VULGAR FRACTION ONE HALF + u'\xbe' # 0xB9 -> VULGAR FRACTION THREE QUARTERS + u'[' # 0xBA -> LEFT SQUARE BRACKET + u']' # 0xBB -> RIGHT SQUARE BRACKET + u'\xaf' # 0xBC -> MACRON + u'\xa8' # 0xBD -> DIAERESIS + u'\xb4' # 0xBE -> ACUTE ACCENT + u'\xd7' # 0xBF -> MULTIPLICATION SIGN + u'{' # 0xC0 -> LEFT CURLY BRACKET + u'A' # 0xC1 -> LATIN CAPITAL LETTER A + u'B' # 0xC2 -> LATIN CAPITAL LETTER B + u'C' # 0xC3 -> LATIN CAPITAL LETTER C + u'D' # 0xC4 -> LATIN CAPITAL LETTER D + u'E' # 0xC5 -> LATIN CAPITAL LETTER E + u'F' # 0xC6 -> LATIN CAPITAL LETTER F + u'G' # 0xC7 -> LATIN CAPITAL LETTER G + u'H' # 0xC8 -> LATIN CAPITAL LETTER H + u'I' # 0xC9 -> LATIN CAPITAL LETTER I + u'\xad' # 0xCA -> SOFT HYPHEN + u'\xf4' # 0xCB -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0xCC -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf2' # 0xCD -> LATIN SMALL LETTER O WITH GRAVE + u'\xf3' # 0xCE -> LATIN SMALL LETTER O WITH ACUTE + u'\xf5' # 0xCF -> LATIN SMALL LETTER O WITH TILDE + u'}' # 0xD0 -> RIGHT CURLY BRACKET + u'J' # 0xD1 -> LATIN CAPITAL LETTER J + u'K' # 0xD2 -> LATIN CAPITAL LETTER K + u'L' # 0xD3 -> LATIN CAPITAL LETTER L + u'M' # 0xD4 -> LATIN CAPITAL LETTER M + u'N' # 0xD5 -> LATIN CAPITAL LETTER N + u'O' # 0xD6 -> LATIN CAPITAL LETTER O + u'P' # 0xD7 -> LATIN CAPITAL LETTER P + u'Q' # 0xD8 -> LATIN CAPITAL LETTER Q + u'R' # 0xD9 -> LATIN CAPITAL LETTER R + u'\xb9' # 0xDA -> SUPERSCRIPT ONE + u'\xfb' # 0xDB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0xDC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xf9' # 0xDD -> LATIN SMALL LETTER U WITH GRAVE + u'\xfa' # 0xDE -> LATIN SMALL LETTER U WITH ACUTE + u'\xff' # 0xDF -> LATIN SMALL LETTER Y WITH DIAERESIS + u'\\' # 0xE0 -> REVERSE SOLIDUS + u'\xf7' # 0xE1 -> DIVISION SIGN + u'S' # 0xE2 -> LATIN CAPITAL LETTER S + u'T' # 0xE3 -> LATIN CAPITAL LETTER T + u'U' # 0xE4 -> LATIN CAPITAL LETTER U + u'V' # 0xE5 -> LATIN CAPITAL LETTER V + u'W' # 0xE6 -> LATIN CAPITAL LETTER W + u'X' # 0xE7 -> LATIN CAPITAL LETTER X + u'Y' # 0xE8 -> LATIN CAPITAL LETTER Y + u'Z' # 0xE9 -> LATIN CAPITAL LETTER Z + u'\xb2' # 0xEA -> SUPERSCRIPT TWO + u'\xd4' # 0xEB -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\xd6' # 0xEC -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xd2' # 0xED -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd5' # 0xEF -> LATIN CAPITAL LETTER O WITH TILDE + u'0' # 0xF0 -> DIGIT ZERO + u'1' # 0xF1 -> DIGIT ONE + u'2' # 0xF2 -> DIGIT TWO + u'3' # 0xF3 -> DIGIT THREE + u'4' # 0xF4 -> DIGIT FOUR + u'5' # 0xF5 -> DIGIT FIVE + u'6' # 0xF6 -> DIGIT SIX + u'7' # 0xF7 -> DIGIT SEVEN + u'8' # 0xF8 -> DIGIT EIGHT + u'9' # 0xF9 -> DIGIT NINE + u'\xb3' # 0xFA -> SUPERSCRIPT THREE + u'\xdb' # 0xFB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xdc' # 0xFC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xd9' # 0xFD -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xda' # 0xFE -> LATIN CAPITAL LETTER U WITH ACUTE + u'\x9f' # 0xFF -> CONTROL +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp1140.pyc b/PythonHome/Lib/encodings/cp1140.pyc deleted file mode 100644 index fafaf2cd8ab10c93d89ba79cae836c71b42e0583..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2694 zcmc&$30GTH5WZOnVe786sHq!qDJ@#}T9LF>v_*VDX(O73ycY;&^W`C;)fPhcecyMx z)4hf6J!j^h_!s;Eb>_Y%571L=&+(Y>E_3g^J9p-r@6N>WXPI}fWoa-f9)2A3zmA^l z5DlsjAsTH$wTpyJgh+4*%_chSB1W=P^b3&_VoAs@RF_mZq{3ZLID}dx6;7$}6ckRO z77NWTbuJMj1KxtpCDf9<&MkGN1)W={WjqNL3AJ2=JkkJJ@`xNc=w(lX{t6BtMuV@Z z$LL6>e1VRL9*G*7?pqYeWa6oIUm&e&QC~DuTRVG}uU$)Ndc@FFUrbLYebpJcYev$1 zH#;-X#IMyfFK({(b;pek-VkL2HJP3ouQ&dHK8=Qp4wPmKVA^S=o_+DrppnxAn#8l8 ze5H^{whNXWLJ9gAdc)1H8+tryM0w7Slb!%CPo%*RqSGdp(Vtxyc9C;XxHejEw6;sn zvPLlOe=YnJz>6q3L>B&-zIz9)&iDVtTTCfZJZ`FeZ@Dkc#SB zQcD?;#C(aJ9;H?JDX?b}O-=UDg;9mY7*71(0iH^$7EOpR#1scJg)VYs(9dQY<1`2v zssvkMo=NZ&_D-_GLRHct7EeVIR>Wfj%NTKZ!$DO_`H(Uiq`?J|L{^hvT2}uJj-0FU zdDCv&XcXs3s{B7Fa(Yb^nKGkLRJbZxp^gC{^J@w{{|ulqj#N*;LB?%z-YQ|o83`J? z7D=|~aVn1m?lH6K`9)5o$vvu2Bn!zOE0tD2QW_&FrUVxe8P$mM6)mFv_vdp3t+LK9 zgv+T3@Om8$=G`&79`!q}vUG{)`Z)74H7^&FSaoy3rVeLNH}Y`R$cdt$pJ~u&@I~SR zBI}}AC9TpSSsSc)v=CM z`0^;s0)?SaI3JIdL4$eOu8}L$0u8-qI!&`oMqw+qxoxHNb<1y8FH^{7cff&SShXB> z!$#OtQd(ACF>d^XiEt2BdSLa_m9PyqS3UFWbFcz>p$~GJq{98cgWybQ-`=J;P*_A;Kqvv>|q z<9WP*7jXa&Pk-^%S3ZD&88fjD`*8*KVh&g0YTODZUwG>Z(6{9`{7rqN)~a?})=WxQ&R-2Cn*}Zvd|U zmNmM5?Eb0eXE+M?aSI;ALvZ0cI1VRZ2+qJM7=$};7w&!YEnI}ta1D3=@^O7&-uwlh zeA)o#@fr@|6}*bqfBo$9g^L=$X!=rtn|K@V;7z=R_gir&*!s^ax+uYQEFaX{Y_F>RA3gEe3-@(*Diz0 zbpF>vTUR`xnvH>0hY{w{w_P^TIcD3O>!6KUZe-N?oRywRXQi{sQROPGa6b^vzW|<> BWa0n- diff --git a/PythonHome/Lib/encodings/cp1250.py b/PythonHome/Lib/encodings/cp1250.py new file mode 100644 index 0000000000..d620b89335 --- /dev/null +++ b/PythonHome/Lib/encodings/cp1250.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1250 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1250.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1250', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\u20ac' # 0x80 -> EURO SIGN + u'\ufffe' # 0x81 -> UNDEFINED + u'\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + u'\ufffe' # 0x83 -> UNDEFINED + u'\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + u'\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + u'\u2020' # 0x86 -> DAGGER + u'\u2021' # 0x87 -> DOUBLE DAGGER + u'\ufffe' # 0x88 -> UNDEFINED + u'\u2030' # 0x89 -> PER MILLE SIGN + u'\u0160' # 0x8A -> LATIN CAPITAL LETTER S WITH CARON + u'\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + u'\u015a' # 0x8C -> LATIN CAPITAL LETTER S WITH ACUTE + u'\u0164' # 0x8D -> LATIN CAPITAL LETTER T WITH CARON + u'\u017d' # 0x8E -> LATIN CAPITAL LETTER Z WITH CARON + u'\u0179' # 0x8F -> LATIN CAPITAL LETTER Z WITH ACUTE + u'\ufffe' # 0x90 -> UNDEFINED + u'\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + u'\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + u'\u2022' # 0x95 -> BULLET + u'\u2013' # 0x96 -> EN DASH + u'\u2014' # 0x97 -> EM DASH + u'\ufffe' # 0x98 -> UNDEFINED + u'\u2122' # 0x99 -> TRADE MARK SIGN + u'\u0161' # 0x9A -> LATIN SMALL LETTER S WITH CARON + u'\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + u'\u015b' # 0x9C -> LATIN SMALL LETTER S WITH ACUTE + u'\u0165' # 0x9D -> LATIN SMALL LETTER T WITH CARON + u'\u017e' # 0x9E -> LATIN SMALL LETTER Z WITH CARON + u'\u017a' # 0x9F -> LATIN SMALL LETTER Z WITH ACUTE + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\u02c7' # 0xA1 -> CARON + u'\u02d8' # 0xA2 -> BREVE + u'\u0141' # 0xA3 -> LATIN CAPITAL LETTER L WITH STROKE + u'\xa4' # 0xA4 -> CURRENCY SIGN + u'\u0104' # 0xA5 -> LATIN CAPITAL LETTER A WITH OGONEK + u'\xa6' # 0xA6 -> BROKEN BAR + u'\xa7' # 0xA7 -> SECTION SIGN + u'\xa8' # 0xA8 -> DIAERESIS + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\u015e' # 0xAA -> LATIN CAPITAL LETTER S WITH CEDILLA + u'\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xac' # 0xAC -> NOT SIGN + u'\xad' # 0xAD -> SOFT HYPHEN + u'\xae' # 0xAE -> REGISTERED SIGN + u'\u017b' # 0xAF -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\u02db' # 0xB2 -> OGONEK + u'\u0142' # 0xB3 -> LATIN SMALL LETTER L WITH STROKE + u'\xb4' # 0xB4 -> ACUTE ACCENT + u'\xb5' # 0xB5 -> MICRO SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\xb8' # 0xB8 -> CEDILLA + u'\u0105' # 0xB9 -> LATIN SMALL LETTER A WITH OGONEK + u'\u015f' # 0xBA -> LATIN SMALL LETTER S WITH CEDILLA + u'\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u013d' # 0xBC -> LATIN CAPITAL LETTER L WITH CARON + u'\u02dd' # 0xBD -> DOUBLE ACUTE ACCENT + u'\u013e' # 0xBE -> LATIN SMALL LETTER L WITH CARON + u'\u017c' # 0xBF -> LATIN SMALL LETTER Z WITH DOT ABOVE + u'\u0154' # 0xC0 -> LATIN CAPITAL LETTER R WITH ACUTE + u'\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\u0102' # 0xC3 -> LATIN CAPITAL LETTER A WITH BREVE + u'\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\u0139' # 0xC5 -> LATIN CAPITAL LETTER L WITH ACUTE + u'\u0106' # 0xC6 -> LATIN CAPITAL LETTER C WITH ACUTE + u'\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\u010c' # 0xC8 -> LATIN CAPITAL LETTER C WITH CARON + u'\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\u0118' # 0xCA -> LATIN CAPITAL LETTER E WITH OGONEK + u'\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\u011a' # 0xCC -> LATIN CAPITAL LETTER E WITH CARON + u'\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\u010e' # 0xCF -> LATIN CAPITAL LETTER D WITH CARON + u'\u0110' # 0xD0 -> LATIN CAPITAL LETTER D WITH STROKE + u'\u0143' # 0xD1 -> LATIN CAPITAL LETTER N WITH ACUTE + u'\u0147' # 0xD2 -> LATIN CAPITAL LETTER N WITH CARON + u'\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\u0150' # 0xD5 -> LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + u'\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xd7' # 0xD7 -> MULTIPLICATION SIGN + u'\u0158' # 0xD8 -> LATIN CAPITAL LETTER R WITH CARON + u'\u016e' # 0xD9 -> LATIN CAPITAL LETTER U WITH RING ABOVE + u'\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + u'\u0170' # 0xDB -> LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + u'\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xdd' # 0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE + u'\u0162' # 0xDE -> LATIN CAPITAL LETTER T WITH CEDILLA + u'\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + u'\u0155' # 0xE0 -> LATIN SMALL LETTER R WITH ACUTE + u'\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\u0103' # 0xE3 -> LATIN SMALL LETTER A WITH BREVE + u'\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\u013a' # 0xE5 -> LATIN SMALL LETTER L WITH ACUTE + u'\u0107' # 0xE6 -> LATIN SMALL LETTER C WITH ACUTE + u'\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + u'\u010d' # 0xE8 -> LATIN SMALL LETTER C WITH CARON + u'\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + u'\u0119' # 0xEA -> LATIN SMALL LETTER E WITH OGONEK + u'\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + u'\u011b' # 0xEC -> LATIN SMALL LETTER E WITH CARON + u'\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\u010f' # 0xEF -> LATIN SMALL LETTER D WITH CARON + u'\u0111' # 0xF0 -> LATIN SMALL LETTER D WITH STROKE + u'\u0144' # 0xF1 -> LATIN SMALL LETTER N WITH ACUTE + u'\u0148' # 0xF2 -> LATIN SMALL LETTER N WITH CARON + u'\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\u0151' # 0xF5 -> LATIN SMALL LETTER O WITH DOUBLE ACUTE + u'\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf7' # 0xF7 -> DIVISION SIGN + u'\u0159' # 0xF8 -> LATIN SMALL LETTER R WITH CARON + u'\u016f' # 0xF9 -> LATIN SMALL LETTER U WITH RING ABOVE + u'\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + u'\u0171' # 0xFB -> LATIN SMALL LETTER U WITH DOUBLE ACUTE + u'\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xfd' # 0xFD -> LATIN SMALL LETTER Y WITH ACUTE + u'\u0163' # 0xFE -> LATIN SMALL LETTER T WITH CEDILLA + u'\u02d9' # 0xFF -> DOT ABOVE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp1250.pyc b/PythonHome/Lib/encodings/cp1250.pyc deleted file mode 100644 index d0cb7437de6aba9f1170dfc859ca5c78314f7c12..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2731 zcmc&$dskFd6hHH17(jd%N;URkdVyN@G(!e3N=CXvqC}0Cxp!b_UfsD!l+_3nwMx?^ z84pn*(p)Ox${;D0&1sVNvFLKe?WBj0ZbA+=T8ZS~1{*gx zvj!WHa=5|H4X&)gPNZBSTe;0a!mxomYjY4OZ^7o|w*0KkNu&atH0BU#6=`(w4PYl1 z=>`Yg=xM-Phyfgi!Bf|%wkF~pU#qByAyrm9wPG?EiMM!s2}urlLdk90cWm{v$Z=T_ zRax?cl|;-_QoFmZuExJ7P`1CyU%5{Rl-1Vw0@d|p4K*-r2$cEia9L^nf%+0pM?`JK z4MMnKX|l7_?T*}n$FDlT0e(ytTq|fQ&^HeZG6Vr2a(sKhcYpw7D?!;tgn$=Qp*r#F zsuBsQA)MoDhu4Sdbug%ev{}dz__Gq#O1fP2ylpr$)MpbS8)*# z394dqR5n)O2`M=m<{?Dl$##|dAuCEkNqNCY_>d|BskCWtq`7HfmsFDhDF9(C;ke}C zei%Hl+)ES!E?we3Kn-wn6&IKKFCg*)A}8d)a90i+J0n)N9rhv^stbl-FfPXAU{H1Q zNh~3?M`0?UO~4S%gSd2Ocm!BLa^X$k0ZwbaOo#sB&6_ zBXKcmM!Z6>h!KXj7*ru24=I3wZ&)oxQ!)qB-1Xn!h`Cy`u(i{&9K}jbmH!7tOs|0= zQf3*70#+$A)D-|ker<&Jp8*tBgXtbPh`4Q7*cGtDj099g7Gn)c1j=QWd&sN`{30gO z;2u;ckO}9HnMyMtF0Bw1QUZ$zk7~*Jf-Fk^{rOlyi_P=1;bLlhs4s`XxI0D{g#L$B z7A_H7ANzs~&CG!$mYi6yq2sC0om^Nox=BvJi!|`7c#*Jx@VaPJNwait)<(>`Zxm={ zx!R~s3eOXC1;`V;fYTyH2TvS7)2N$xI&VWY@o<7y9rIWLFOPsM5D*Fh^Kn-hRFRi0 zGPnXQP*pm&z%+$qB$ix@(~=J#C;zmcMhaQ1HoL=_gi`n%eHRY{_Jx*o`2!RmtKBl=c~J3E8kt=tE{Tt z^Lou2Z|<%2@2h)D2-Ls5zu~~a#&??DeJ^-OYz|3sxTQ7H_I@-LPb5E3Qfm9*jt@IO z`uNBvpMI9UC=ISKWUfPS?#iRMZ2nvvm4rk zc5Qx$b!peNU$seXO8ZU!oSoBd=(F>~`W(B-`sh*GrFYRDeOmv5_Uhlzuk?QUwLVCX z(c}7Y{RHb~z4R3AV<+fo`aSDs<8+Ws&@*(HjnZ@MJ32x~^=>+*&*;7MqJE5C(g)~e zeTZJA?EC}Q*40!OlR0NdXvtwALa+Vm_uMJb~q^!f{unQ!C;EX z52S`clFcY#K~u4IFZ`rvZjVGIqg#M>5sU6z0(fWLY4p-vHdvU#?gs79UgRpW7ukz# M#g5!U=PhFY3#txy3jhEB diff --git a/PythonHome/Lib/encodings/cp1251.py b/PythonHome/Lib/encodings/cp1251.py new file mode 100644 index 0000000000..216771fa4c --- /dev/null +++ b/PythonHome/Lib/encodings/cp1251.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1251 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1251', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\u0402' # 0x80 -> CYRILLIC CAPITAL LETTER DJE + u'\u0403' # 0x81 -> CYRILLIC CAPITAL LETTER GJE + u'\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + u'\u0453' # 0x83 -> CYRILLIC SMALL LETTER GJE + u'\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + u'\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + u'\u2020' # 0x86 -> DAGGER + u'\u2021' # 0x87 -> DOUBLE DAGGER + u'\u20ac' # 0x88 -> EURO SIGN + u'\u2030' # 0x89 -> PER MILLE SIGN + u'\u0409' # 0x8A -> CYRILLIC CAPITAL LETTER LJE + u'\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + u'\u040a' # 0x8C -> CYRILLIC CAPITAL LETTER NJE + u'\u040c' # 0x8D -> CYRILLIC CAPITAL LETTER KJE + u'\u040b' # 0x8E -> CYRILLIC CAPITAL LETTER TSHE + u'\u040f' # 0x8F -> CYRILLIC CAPITAL LETTER DZHE + u'\u0452' # 0x90 -> CYRILLIC SMALL LETTER DJE + u'\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + u'\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + u'\u2022' # 0x95 -> BULLET + u'\u2013' # 0x96 -> EN DASH + u'\u2014' # 0x97 -> EM DASH + u'\ufffe' # 0x98 -> UNDEFINED + u'\u2122' # 0x99 -> TRADE MARK SIGN + u'\u0459' # 0x9A -> CYRILLIC SMALL LETTER LJE + u'\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + u'\u045a' # 0x9C -> CYRILLIC SMALL LETTER NJE + u'\u045c' # 0x9D -> CYRILLIC SMALL LETTER KJE + u'\u045b' # 0x9E -> CYRILLIC SMALL LETTER TSHE + u'\u045f' # 0x9F -> CYRILLIC SMALL LETTER DZHE + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\u040e' # 0xA1 -> CYRILLIC CAPITAL LETTER SHORT U + u'\u045e' # 0xA2 -> CYRILLIC SMALL LETTER SHORT U + u'\u0408' # 0xA3 -> CYRILLIC CAPITAL LETTER JE + u'\xa4' # 0xA4 -> CURRENCY SIGN + u'\u0490' # 0xA5 -> CYRILLIC CAPITAL LETTER GHE WITH UPTURN + u'\xa6' # 0xA6 -> BROKEN BAR + u'\xa7' # 0xA7 -> SECTION SIGN + u'\u0401' # 0xA8 -> CYRILLIC CAPITAL LETTER IO + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\u0404' # 0xAA -> CYRILLIC CAPITAL LETTER UKRAINIAN IE + u'\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xac' # 0xAC -> NOT SIGN + u'\xad' # 0xAD -> SOFT HYPHEN + u'\xae' # 0xAE -> REGISTERED SIGN + u'\u0407' # 0xAF -> CYRILLIC CAPITAL LETTER YI + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\u0406' # 0xB2 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + u'\u0456' # 0xB3 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + u'\u0491' # 0xB4 -> CYRILLIC SMALL LETTER GHE WITH UPTURN + u'\xb5' # 0xB5 -> MICRO SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\u0451' # 0xB8 -> CYRILLIC SMALL LETTER IO + u'\u2116' # 0xB9 -> NUMERO SIGN + u'\u0454' # 0xBA -> CYRILLIC SMALL LETTER UKRAINIAN IE + u'\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u0458' # 0xBC -> CYRILLIC SMALL LETTER JE + u'\u0405' # 0xBD -> CYRILLIC CAPITAL LETTER DZE + u'\u0455' # 0xBE -> CYRILLIC SMALL LETTER DZE + u'\u0457' # 0xBF -> CYRILLIC SMALL LETTER YI + u'\u0410' # 0xC0 -> CYRILLIC CAPITAL LETTER A + u'\u0411' # 0xC1 -> CYRILLIC CAPITAL LETTER BE + u'\u0412' # 0xC2 -> CYRILLIC CAPITAL LETTER VE + u'\u0413' # 0xC3 -> CYRILLIC CAPITAL LETTER GHE + u'\u0414' # 0xC4 -> CYRILLIC CAPITAL LETTER DE + u'\u0415' # 0xC5 -> CYRILLIC CAPITAL LETTER IE + u'\u0416' # 0xC6 -> CYRILLIC CAPITAL LETTER ZHE + u'\u0417' # 0xC7 -> CYRILLIC CAPITAL LETTER ZE + u'\u0418' # 0xC8 -> CYRILLIC CAPITAL LETTER I + u'\u0419' # 0xC9 -> CYRILLIC CAPITAL LETTER SHORT I + u'\u041a' # 0xCA -> CYRILLIC CAPITAL LETTER KA + u'\u041b' # 0xCB -> CYRILLIC CAPITAL LETTER EL + u'\u041c' # 0xCC -> CYRILLIC CAPITAL LETTER EM + u'\u041d' # 0xCD -> CYRILLIC CAPITAL LETTER EN + u'\u041e' # 0xCE -> CYRILLIC CAPITAL LETTER O + u'\u041f' # 0xCF -> CYRILLIC CAPITAL LETTER PE + u'\u0420' # 0xD0 -> CYRILLIC CAPITAL LETTER ER + u'\u0421' # 0xD1 -> CYRILLIC CAPITAL LETTER ES + u'\u0422' # 0xD2 -> CYRILLIC CAPITAL LETTER TE + u'\u0423' # 0xD3 -> CYRILLIC CAPITAL LETTER U + u'\u0424' # 0xD4 -> CYRILLIC CAPITAL LETTER EF + u'\u0425' # 0xD5 -> CYRILLIC CAPITAL LETTER HA + u'\u0426' # 0xD6 -> CYRILLIC CAPITAL LETTER TSE + u'\u0427' # 0xD7 -> CYRILLIC CAPITAL LETTER CHE + u'\u0428' # 0xD8 -> CYRILLIC CAPITAL LETTER SHA + u'\u0429' # 0xD9 -> CYRILLIC CAPITAL LETTER SHCHA + u'\u042a' # 0xDA -> CYRILLIC CAPITAL LETTER HARD SIGN + u'\u042b' # 0xDB -> CYRILLIC CAPITAL LETTER YERU + u'\u042c' # 0xDC -> CYRILLIC CAPITAL LETTER SOFT SIGN + u'\u042d' # 0xDD -> CYRILLIC CAPITAL LETTER E + u'\u042e' # 0xDE -> CYRILLIC CAPITAL LETTER YU + u'\u042f' # 0xDF -> CYRILLIC CAPITAL LETTER YA + u'\u0430' # 0xE0 -> CYRILLIC SMALL LETTER A + u'\u0431' # 0xE1 -> CYRILLIC SMALL LETTER BE + u'\u0432' # 0xE2 -> CYRILLIC SMALL LETTER VE + u'\u0433' # 0xE3 -> CYRILLIC SMALL LETTER GHE + u'\u0434' # 0xE4 -> CYRILLIC SMALL LETTER DE + u'\u0435' # 0xE5 -> CYRILLIC SMALL LETTER IE + u'\u0436' # 0xE6 -> CYRILLIC SMALL LETTER ZHE + u'\u0437' # 0xE7 -> CYRILLIC SMALL LETTER ZE + u'\u0438' # 0xE8 -> CYRILLIC SMALL LETTER I + u'\u0439' # 0xE9 -> CYRILLIC SMALL LETTER SHORT I + u'\u043a' # 0xEA -> CYRILLIC SMALL LETTER KA + u'\u043b' # 0xEB -> CYRILLIC SMALL LETTER EL + u'\u043c' # 0xEC -> CYRILLIC SMALL LETTER EM + u'\u043d' # 0xED -> CYRILLIC SMALL LETTER EN + u'\u043e' # 0xEE -> CYRILLIC SMALL LETTER O + u'\u043f' # 0xEF -> CYRILLIC SMALL LETTER PE + u'\u0440' # 0xF0 -> CYRILLIC SMALL LETTER ER + u'\u0441' # 0xF1 -> CYRILLIC SMALL LETTER ES + u'\u0442' # 0xF2 -> CYRILLIC SMALL LETTER TE + u'\u0443' # 0xF3 -> CYRILLIC SMALL LETTER U + u'\u0444' # 0xF4 -> CYRILLIC SMALL LETTER EF + u'\u0445' # 0xF5 -> CYRILLIC SMALL LETTER HA + u'\u0446' # 0xF6 -> CYRILLIC SMALL LETTER TSE + u'\u0447' # 0xF7 -> CYRILLIC SMALL LETTER CHE + u'\u0448' # 0xF8 -> CYRILLIC SMALL LETTER SHA + u'\u0449' # 0xF9 -> CYRILLIC SMALL LETTER SHCHA + u'\u044a' # 0xFA -> CYRILLIC SMALL LETTER HARD SIGN + u'\u044b' # 0xFB -> CYRILLIC SMALL LETTER YERU + u'\u044c' # 0xFC -> CYRILLIC SMALL LETTER SOFT SIGN + u'\u044d' # 0xFD -> CYRILLIC SMALL LETTER E + u'\u044e' # 0xFE -> CYRILLIC SMALL LETTER YU + u'\u044f' # 0xFF -> CYRILLIC SMALL LETTER YA +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp1251.pyc b/PythonHome/Lib/encodings/cp1251.pyc deleted file mode 100644 index c51e6e08bf0b079ee7a68ab3912bc935d9cf91b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2728 zcmc&$d3O{=5br&+SrTs0K-9&H^-2WA6A`iyjFKhJMglRqOm=3I#l4)JfKk*T2{!^E z93g}dB7(?aPyqpj_vRB+^AY9?_=g_=t9r-|pbv!ie9mS%-BsJwRloXm)q4Ic4_;_m z9ZRsAj|cxR#J6w}2Zga_99>Ltv$Tsfti>VJ(5biQvY|-3tjP&o)k5`hKA+0Ag(5jcO@tEpIdkXD3AL$NRg-m9 z2_>~$CN#T#QA0yrbZM-5#ggdaFs17 zK?bYxomIhL>IObh-G>f{V~XIqQBp&`g>X5K`HEhc5h3H7%zV!l-0oC{*CAs%2TKwPnmop~Z$2fv~p-T*i?- z3ZA(hBnpYP-sV3-jc^N*nBMNcM952ooK%9teK~AfCai8c940XI01okZR?evLxE>UX zOit-Y<5D7>L?Jo{iP_!Zk#GYm#kW8Q_}yh5eKJn!vI$Mis99Z3FA>;j36zSb$eyXV zwAq6fNMR0RDDi&>cm_%xnjl}0DIQ`9UhIlkn9N2~I4}{a09zuS3GgKHPO!p3RnQ`t z%F1ac;(G*37*Tk)f-05KA>}v-gSB$Hpb9V@tN#W^%GIPX(|*^TC@vOM`F~KP^x7yA zW$r*xqAKNtdJh1JU(@mZX8@&%sCobn5^mGRtRi-lk(jQja;8a3VYw`FkC;_MU!+9Z z+`|fmb0+xXq|ymU%Crq3)dCJsj(;s@c zV#dtMM;?7FH0$vvo_y-*+2LoNeeU@es;Xa{Gxw#J=e_dkYp=iY=KQx7yuENyO=R(s z+NJN*z5Cv>`snh8_oZ0l2P>LZu4?|U<)e?|tL4^&q9)tgQ)@m+XR^8cr&>YpSiA1C z&d#2kj5dFct339`}hIa4ZW}j`d}~YgZ*#-`r#l9z#$lf z!!QI#U>J_V2z(32;5#@DC*XTH2|vIoI1OjuEc^(ga1MTgpWzoc4;SDf{0f)gGF*Y* z;CHwR*SNtq@GjoXd-z7aiErjx_*TA+Z|6JsH+(1G6{Z9tU8%h(xdgT|>IXJW9C8pZ zY=+FF8C5f#3isIWiPnx(TCrONN^hai-S59>tMlzfy1;`Q3)I@M7kVoK72XPOrKi$Y KI>CQ~dH(_hS9iz& diff --git a/PythonHome/Lib/encodings/cp1252.py b/PythonHome/Lib/encodings/cp1252.py new file mode 100644 index 0000000000..e60a328db4 --- /dev/null +++ b/PythonHome/Lib/encodings/cp1252.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1252 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1252', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\u20ac' # 0x80 -> EURO SIGN + u'\ufffe' # 0x81 -> UNDEFINED + u'\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + u'\u0192' # 0x83 -> LATIN SMALL LETTER F WITH HOOK + u'\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + u'\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + u'\u2020' # 0x86 -> DAGGER + u'\u2021' # 0x87 -> DOUBLE DAGGER + u'\u02c6' # 0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT + u'\u2030' # 0x89 -> PER MILLE SIGN + u'\u0160' # 0x8A -> LATIN CAPITAL LETTER S WITH CARON + u'\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + u'\u0152' # 0x8C -> LATIN CAPITAL LIGATURE OE + u'\ufffe' # 0x8D -> UNDEFINED + u'\u017d' # 0x8E -> LATIN CAPITAL LETTER Z WITH CARON + u'\ufffe' # 0x8F -> UNDEFINED + u'\ufffe' # 0x90 -> UNDEFINED + u'\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + u'\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + u'\u2022' # 0x95 -> BULLET + u'\u2013' # 0x96 -> EN DASH + u'\u2014' # 0x97 -> EM DASH + u'\u02dc' # 0x98 -> SMALL TILDE + u'\u2122' # 0x99 -> TRADE MARK SIGN + u'\u0161' # 0x9A -> LATIN SMALL LETTER S WITH CARON + u'\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + u'\u0153' # 0x9C -> LATIN SMALL LIGATURE OE + u'\ufffe' # 0x9D -> UNDEFINED + u'\u017e' # 0x9E -> LATIN SMALL LETTER Z WITH CARON + u'\u0178' # 0x9F -> LATIN CAPITAL LETTER Y WITH DIAERESIS + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\xa1' # 0xA1 -> INVERTED EXCLAMATION MARK + u'\xa2' # 0xA2 -> CENT SIGN + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa4' # 0xA4 -> CURRENCY SIGN + u'\xa5' # 0xA5 -> YEN SIGN + u'\xa6' # 0xA6 -> BROKEN BAR + u'\xa7' # 0xA7 -> SECTION SIGN + u'\xa8' # 0xA8 -> DIAERESIS + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\xaa' # 0xAA -> FEMININE ORDINAL INDICATOR + u'\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xac' # 0xAC -> NOT SIGN + u'\xad' # 0xAD -> SOFT HYPHEN + u'\xae' # 0xAE -> REGISTERED SIGN + u'\xaf' # 0xAF -> MACRON + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\xb2' # 0xB2 -> SUPERSCRIPT TWO + u'\xb3' # 0xB3 -> SUPERSCRIPT THREE + u'\xb4' # 0xB4 -> ACUTE ACCENT + u'\xb5' # 0xB5 -> MICRO SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\xb8' # 0xB8 -> CEDILLA + u'\xb9' # 0xB9 -> SUPERSCRIPT ONE + u'\xba' # 0xBA -> MASCULINE ORDINAL INDICATOR + u'\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + u'\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + u'\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + u'\xbf' # 0xBF -> INVERTED QUESTION MARK + u'\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + u'\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + u'\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + u'\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\xd0' # 0xD0 -> LATIN CAPITAL LETTER ETH + u'\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + u'\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xd7' # 0xD7 -> MULTIPLICATION SIGN + u'\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + u'\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xdd' # 0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE + u'\xde' # 0xDE -> LATIN CAPITAL LETTER THORN + u'\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + u'\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + u'\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe6' # 0xE6 -> LATIN SMALL LETTER AE + u'\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + u'\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + u'\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + u'\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xf0' # 0xF0 -> LATIN SMALL LETTER ETH + u'\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + u'\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + u'\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + u'\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf7' # 0xF7 -> DIVISION SIGN + u'\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + u'\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + u'\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + u'\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xfd' # 0xFD -> LATIN SMALL LETTER Y WITH ACUTE + u'\xfe' # 0xFE -> LATIN SMALL LETTER THORN + u'\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp1252.pyc b/PythonHome/Lib/encodings/cp1252.pyc deleted file mode 100644 index 3eac5e525436d11e740c432348fb3715c24aa85a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2731 zcmc&$dskFd6hHH17(jd%N;URkdO=$DG(*Nml#FzTM2Q+NbML^|yt;FdD65;0yj$P>2~C;`m@ zfw-1Q1uE)R)YsRB*F>t;uL`eRCq=62YD1CL4ONY`IBkqnh3aWrWy6Msia2+O8 z#Pk@=>2c!|qUAX_=!|W4u&wy#WV(}exiEYOu7~aI!n2${16N~+LrTs@EqBF|5D}56 zF1I9AYZsl6QHQAo7)CjSv?gj*~L@n-)eLS7=|qyil7$YIMeVRhZ%Ac3L#aEM0Ja!QRxb-$RT zGD>?ArxNKT3ei4DNVkVa!VRntpBx?Fbr!qy*(lVeW15;$)4H5oC9uK_DZxP)TrDSassPir`fqTgT+Ny??RDIW;z~i4{|7}%uZ1E} z<`xtss#12S(*Q{Pnvc&v11QZz)m?CqaGN(}6|tj?M08D+Q;k{z%VnN>#H<>6krHWf z4=WVPOz_7}r5%uvriqFuK}AGFb<_EhDl7l}`BXv6?ep{DQffl9UX6owcdRam{g0|F zULw3c?kO3YnTJTMc&T7x$J4Pp`KW4iv4TjDXb{%vB2fVmbRRU_oaTs(%u(p@I*Re@72ozZ~9^KNvL+!9mNcxzi?^LxouI+J~0%jxY~IzH(9 z@T09CfAXohZRn3H6Q;5E_Z_CO-!ukIqt7(@uWmPu;YpOnCU>BI@-hzMz1^m<$259P zW1ndZm`0Cj?7Z4*b`MPUo5uKL54}4vIm-KZKOf)+_(6V%5AwtO2tUe?@#B1mpWr9? zDL%|k^E3P`KgZAW5q^P>@-aTnFY-(LGN0gAz<|$S8+1W8d=A^;3-}Vgg0JBl_!ho{ z@8Jjd5q^Rl&;vW+XV?Y5z;4(Bd*N5;g?+FeeuF;fhXFVM2jLJ5!eKZ9N8uP8haort zC*c$f!)Z7JXW<;2hY`2{qc8^Ja1k!SWte~~LCPUAmO7l0iD5^hmS8c(<_A&3BFRFM zsG#XoyQh9qw6rIZiq$P}^#&H*z66NQy3FdO%U!rJN8JtEp}Wji<}P!WyUIO NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\u20ac' # 0x80 -> EURO SIGN + u'\ufffe' # 0x81 -> UNDEFINED + u'\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + u'\u0192' # 0x83 -> LATIN SMALL LETTER F WITH HOOK + u'\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + u'\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + u'\u2020' # 0x86 -> DAGGER + u'\u2021' # 0x87 -> DOUBLE DAGGER + u'\ufffe' # 0x88 -> UNDEFINED + u'\u2030' # 0x89 -> PER MILLE SIGN + u'\ufffe' # 0x8A -> UNDEFINED + u'\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + u'\ufffe' # 0x8C -> UNDEFINED + u'\ufffe' # 0x8D -> UNDEFINED + u'\ufffe' # 0x8E -> UNDEFINED + u'\ufffe' # 0x8F -> UNDEFINED + u'\ufffe' # 0x90 -> UNDEFINED + u'\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + u'\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + u'\u2022' # 0x95 -> BULLET + u'\u2013' # 0x96 -> EN DASH + u'\u2014' # 0x97 -> EM DASH + u'\ufffe' # 0x98 -> UNDEFINED + u'\u2122' # 0x99 -> TRADE MARK SIGN + u'\ufffe' # 0x9A -> UNDEFINED + u'\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + u'\ufffe' # 0x9C -> UNDEFINED + u'\ufffe' # 0x9D -> UNDEFINED + u'\ufffe' # 0x9E -> UNDEFINED + u'\ufffe' # 0x9F -> UNDEFINED + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\u0385' # 0xA1 -> GREEK DIALYTIKA TONOS + u'\u0386' # 0xA2 -> GREEK CAPITAL LETTER ALPHA WITH TONOS + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa4' # 0xA4 -> CURRENCY SIGN + u'\xa5' # 0xA5 -> YEN SIGN + u'\xa6' # 0xA6 -> BROKEN BAR + u'\xa7' # 0xA7 -> SECTION SIGN + u'\xa8' # 0xA8 -> DIAERESIS + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\ufffe' # 0xAA -> UNDEFINED + u'\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xac' # 0xAC -> NOT SIGN + u'\xad' # 0xAD -> SOFT HYPHEN + u'\xae' # 0xAE -> REGISTERED SIGN + u'\u2015' # 0xAF -> HORIZONTAL BAR + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\xb2' # 0xB2 -> SUPERSCRIPT TWO + u'\xb3' # 0xB3 -> SUPERSCRIPT THREE + u'\u0384' # 0xB4 -> GREEK TONOS + u'\xb5' # 0xB5 -> MICRO SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\u0388' # 0xB8 -> GREEK CAPITAL LETTER EPSILON WITH TONOS + u'\u0389' # 0xB9 -> GREEK CAPITAL LETTER ETA WITH TONOS + u'\u038a' # 0xBA -> GREEK CAPITAL LETTER IOTA WITH TONOS + u'\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u038c' # 0xBC -> GREEK CAPITAL LETTER OMICRON WITH TONOS + u'\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + u'\u038e' # 0xBE -> GREEK CAPITAL LETTER UPSILON WITH TONOS + u'\u038f' # 0xBF -> GREEK CAPITAL LETTER OMEGA WITH TONOS + u'\u0390' # 0xC0 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + u'\u0391' # 0xC1 -> GREEK CAPITAL LETTER ALPHA + u'\u0392' # 0xC2 -> GREEK CAPITAL LETTER BETA + u'\u0393' # 0xC3 -> GREEK CAPITAL LETTER GAMMA + u'\u0394' # 0xC4 -> GREEK CAPITAL LETTER DELTA + u'\u0395' # 0xC5 -> GREEK CAPITAL LETTER EPSILON + u'\u0396' # 0xC6 -> GREEK CAPITAL LETTER ZETA + u'\u0397' # 0xC7 -> GREEK CAPITAL LETTER ETA + u'\u0398' # 0xC8 -> GREEK CAPITAL LETTER THETA + u'\u0399' # 0xC9 -> GREEK CAPITAL LETTER IOTA + u'\u039a' # 0xCA -> GREEK CAPITAL LETTER KAPPA + u'\u039b' # 0xCB -> GREEK CAPITAL LETTER LAMDA + u'\u039c' # 0xCC -> GREEK CAPITAL LETTER MU + u'\u039d' # 0xCD -> GREEK CAPITAL LETTER NU + u'\u039e' # 0xCE -> GREEK CAPITAL LETTER XI + u'\u039f' # 0xCF -> GREEK CAPITAL LETTER OMICRON + u'\u03a0' # 0xD0 -> GREEK CAPITAL LETTER PI + u'\u03a1' # 0xD1 -> GREEK CAPITAL LETTER RHO + u'\ufffe' # 0xD2 -> UNDEFINED + u'\u03a3' # 0xD3 -> GREEK CAPITAL LETTER SIGMA + u'\u03a4' # 0xD4 -> GREEK CAPITAL LETTER TAU + u'\u03a5' # 0xD5 -> GREEK CAPITAL LETTER UPSILON + u'\u03a6' # 0xD6 -> GREEK CAPITAL LETTER PHI + u'\u03a7' # 0xD7 -> GREEK CAPITAL LETTER CHI + u'\u03a8' # 0xD8 -> GREEK CAPITAL LETTER PSI + u'\u03a9' # 0xD9 -> GREEK CAPITAL LETTER OMEGA + u'\u03aa' # 0xDA -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + u'\u03ab' # 0xDB -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + u'\u03ac' # 0xDC -> GREEK SMALL LETTER ALPHA WITH TONOS + u'\u03ad' # 0xDD -> GREEK SMALL LETTER EPSILON WITH TONOS + u'\u03ae' # 0xDE -> GREEK SMALL LETTER ETA WITH TONOS + u'\u03af' # 0xDF -> GREEK SMALL LETTER IOTA WITH TONOS + u'\u03b0' # 0xE0 -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + u'\u03b1' # 0xE1 -> GREEK SMALL LETTER ALPHA + u'\u03b2' # 0xE2 -> GREEK SMALL LETTER BETA + u'\u03b3' # 0xE3 -> GREEK SMALL LETTER GAMMA + u'\u03b4' # 0xE4 -> GREEK SMALL LETTER DELTA + u'\u03b5' # 0xE5 -> GREEK SMALL LETTER EPSILON + u'\u03b6' # 0xE6 -> GREEK SMALL LETTER ZETA + u'\u03b7' # 0xE7 -> GREEK SMALL LETTER ETA + u'\u03b8' # 0xE8 -> GREEK SMALL LETTER THETA + u'\u03b9' # 0xE9 -> GREEK SMALL LETTER IOTA + u'\u03ba' # 0xEA -> GREEK SMALL LETTER KAPPA + u'\u03bb' # 0xEB -> GREEK SMALL LETTER LAMDA + u'\u03bc' # 0xEC -> GREEK SMALL LETTER MU + u'\u03bd' # 0xED -> GREEK SMALL LETTER NU + u'\u03be' # 0xEE -> GREEK SMALL LETTER XI + u'\u03bf' # 0xEF -> GREEK SMALL LETTER OMICRON + u'\u03c0' # 0xF0 -> GREEK SMALL LETTER PI + u'\u03c1' # 0xF1 -> GREEK SMALL LETTER RHO + u'\u03c2' # 0xF2 -> GREEK SMALL LETTER FINAL SIGMA + u'\u03c3' # 0xF3 -> GREEK SMALL LETTER SIGMA + u'\u03c4' # 0xF4 -> GREEK SMALL LETTER TAU + u'\u03c5' # 0xF5 -> GREEK SMALL LETTER UPSILON + u'\u03c6' # 0xF6 -> GREEK SMALL LETTER PHI + u'\u03c7' # 0xF7 -> GREEK SMALL LETTER CHI + u'\u03c8' # 0xF8 -> GREEK SMALL LETTER PSI + u'\u03c9' # 0xF9 -> GREEK SMALL LETTER OMEGA + u'\u03ca' # 0xFA -> GREEK SMALL LETTER IOTA WITH DIALYTIKA + u'\u03cb' # 0xFB -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA + u'\u03cc' # 0xFC -> GREEK SMALL LETTER OMICRON WITH TONOS + u'\u03cd' # 0xFD -> GREEK SMALL LETTER UPSILON WITH TONOS + u'\u03ce' # 0xFE -> GREEK SMALL LETTER OMEGA WITH TONOS + u'\ufffe' # 0xFF -> UNDEFINED +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp1253.pyc b/PythonHome/Lib/encodings/cp1253.pyc deleted file mode 100644 index 3657cfea9c455d05a789a893a3dee49f66a5c055..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2744 zcmc&$>vt1X5WjggO<%mVP&N2!e6<4N6R|XHu}VYTR0_2kw%JXanwOg`wTiORf`Ew1 zLjeIRg#uErfV2Vv=j;bR&i)Vk5BR}90B7#fY+F54ILBj>y}fs4@7$T+{O(L$f0p>i zS~o^w?Dofne{1l`jpHCO)`p{lNlun@ur{2ynCxKPP8P?xn+-75&)9}GCzCu};o=H! zUg2U=0av)W!k1ULnN-MRC)asc91ZyMIuDbICUjn|E6(e@OeTLF_wS(}d=KubQ> zj}H3D(@3z40@#E@pt(=&%A^CKE>RI#B4T^?hJ%7k{k=fvP+gOUl!<;)3PF} zvJ{9bnN*;%X;pJ`V|aC>dR=|EZmkfhZfXog8d|Db8*$khsSY*MwyKu(EtP@ZgxW<0 zVq~x?+gIiHCvM>ZR9J zB@t6&w5G?6Pl&{GaZnlScCgL(b28P*`dt{l1La|RJNGQ7mZCIcClugtR}Nd239H)<2MG+-heI@)7E^LGs`~jN zm63XqxD-eyP>A+He0FDe1l+(1@yXEvUT3jOor9CcbWD*`a#|IW^&C4ThEo2?vu7SI zE%x9Al9BZ~lV&?k``s zsN#VK9||mf_>o5+d%QCE#FI}w{Y+K$vrCpPdv5vjFTD8D%df0>b>(X{t7=1a^$n|E zZ+zp;HBI5Q&2I^jmbcfnuHVr1PW!v>MK_8aF-eYhb|t#sPo~nD><3Ct?b+1(Vc$m| zZ~o-dE#}sdKW^SIwZp&fHML`=Hf(BxruHM3jq>pdj+1|;cF@!gnc5LkJ8EjjO>Lj4 z?WZ>fj`R1gPJUS*gl({0AJR|gC-q_dlzv)2gL?g}KBAw~&zsr-eN?}oU(_$bfPPsY z)5l>4?1WwVHQ23RhduBWd=1~gUf2iw;Q)LK-@!pR1c%{!I08rE82kW(K;FU-oPd)s z45#2UoPnR^8nM_Mqt?B^2pP?M}+Xu)R@#uxMkGg?M5yW)aP(x~WviC;q?a w=t(3ct977s5~c234|tnhVKvs3F5H--R)@XOUG6J)m%A%m6`sN}?=9y33$;mz9{>OV diff --git a/PythonHome/Lib/encodings/cp1254.py b/PythonHome/Lib/encodings/cp1254.py new file mode 100644 index 0000000000..65530ab546 --- /dev/null +++ b/PythonHome/Lib/encodings/cp1254.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1254 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1254.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1254', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\u20ac' # 0x80 -> EURO SIGN + u'\ufffe' # 0x81 -> UNDEFINED + u'\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + u'\u0192' # 0x83 -> LATIN SMALL LETTER F WITH HOOK + u'\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + u'\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + u'\u2020' # 0x86 -> DAGGER + u'\u2021' # 0x87 -> DOUBLE DAGGER + u'\u02c6' # 0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT + u'\u2030' # 0x89 -> PER MILLE SIGN + u'\u0160' # 0x8A -> LATIN CAPITAL LETTER S WITH CARON + u'\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + u'\u0152' # 0x8C -> LATIN CAPITAL LIGATURE OE + u'\ufffe' # 0x8D -> UNDEFINED + u'\ufffe' # 0x8E -> UNDEFINED + u'\ufffe' # 0x8F -> UNDEFINED + u'\ufffe' # 0x90 -> UNDEFINED + u'\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + u'\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + u'\u2022' # 0x95 -> BULLET + u'\u2013' # 0x96 -> EN DASH + u'\u2014' # 0x97 -> EM DASH + u'\u02dc' # 0x98 -> SMALL TILDE + u'\u2122' # 0x99 -> TRADE MARK SIGN + u'\u0161' # 0x9A -> LATIN SMALL LETTER S WITH CARON + u'\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + u'\u0153' # 0x9C -> LATIN SMALL LIGATURE OE + u'\ufffe' # 0x9D -> UNDEFINED + u'\ufffe' # 0x9E -> UNDEFINED + u'\u0178' # 0x9F -> LATIN CAPITAL LETTER Y WITH DIAERESIS + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\xa1' # 0xA1 -> INVERTED EXCLAMATION MARK + u'\xa2' # 0xA2 -> CENT SIGN + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa4' # 0xA4 -> CURRENCY SIGN + u'\xa5' # 0xA5 -> YEN SIGN + u'\xa6' # 0xA6 -> BROKEN BAR + u'\xa7' # 0xA7 -> SECTION SIGN + u'\xa8' # 0xA8 -> DIAERESIS + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\xaa' # 0xAA -> FEMININE ORDINAL INDICATOR + u'\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xac' # 0xAC -> NOT SIGN + u'\xad' # 0xAD -> SOFT HYPHEN + u'\xae' # 0xAE -> REGISTERED SIGN + u'\xaf' # 0xAF -> MACRON + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\xb2' # 0xB2 -> SUPERSCRIPT TWO + u'\xb3' # 0xB3 -> SUPERSCRIPT THREE + u'\xb4' # 0xB4 -> ACUTE ACCENT + u'\xb5' # 0xB5 -> MICRO SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\xb8' # 0xB8 -> CEDILLA + u'\xb9' # 0xB9 -> SUPERSCRIPT ONE + u'\xba' # 0xBA -> MASCULINE ORDINAL INDICATOR + u'\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + u'\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + u'\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + u'\xbf' # 0xBF -> INVERTED QUESTION MARK + u'\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + u'\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + u'\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + u'\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\u011e' # 0xD0 -> LATIN CAPITAL LETTER G WITH BREVE + u'\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + u'\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xd7' # 0xD7 -> MULTIPLICATION SIGN + u'\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + u'\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\u0130' # 0xDD -> LATIN CAPITAL LETTER I WITH DOT ABOVE + u'\u015e' # 0xDE -> LATIN CAPITAL LETTER S WITH CEDILLA + u'\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + u'\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + u'\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe6' # 0xE6 -> LATIN SMALL LETTER AE + u'\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + u'\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + u'\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + u'\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + u'\u011f' # 0xF0 -> LATIN SMALL LETTER G WITH BREVE + u'\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + u'\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + u'\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + u'\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf7' # 0xF7 -> DIVISION SIGN + u'\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + u'\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + u'\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + u'\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\u0131' # 0xFD -> LATIN SMALL LETTER DOTLESS I + u'\u015f' # 0xFE -> LATIN SMALL LETTER S WITH CEDILLA + u'\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp1254.pyc b/PythonHome/Lib/encodings/cp1254.pyc deleted file mode 100644 index d174941e8194e72b15957916b301d7a26825f11f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2733 zcmc&$d3O{=5br&+*(BVcfvAfY>y-$CCt_feV3aIzHWG-@WwJAyY~0J)2^d8kNyJ;9 z32MNYkO1Kd_k9TOb!GjBZ!urMKl}h#)kAh5`apQk=k89Yx@)?+>Q}$6itEoZ|C#2E zkr=!FapB);d~#=TP#9~$(ZLiaOFCE!3NEHPSf`W4QFgOl#(Egr(Bfo@M<`rE;Vmd! zOeqoyw@~;B3O7@Vnd%fe4~wG#e?jMAO39?oD|Dp=otG(PG-)Yf$~4yE69&+dkM*E~ ze)2RDoK693!XePut#@S7fl!C6$uV8k0u6FDn@G0@LK#Jk1!CF7OO`DSw5w@VlXX=I z#I;N+u&7~WV`F`Ib);%tZMbHw6sc;c4@K&ls+#L@+8n70HPW`qru9vW0-FG{70w}Zm}f9oBfvvd5Msdig36ihb_y5)pdu11cvUzAsS7~DK#3^{bG{J zC|yaMN~Du0MEf8i-5MSVH?U%Sa&&;#S?bbfp-`WWX=+MM>vFPIV5h}!ReTEUnS)b{ zJ$Qi>W;2Eo|961rC~}CPEcpOT;q)ozImSjiAc^gCeEZLXjvl z1x1OflpX4A03?3R!{?s?lxCpnE;vZI&7HK0*il9zx~9shW-Wo`vcNrJ)+&0D5@~S{ zD-_C1@W)Q29gvW26BSW{iin8nrt>9LR{s0*se)G6=NH1I)P!ig8VBp{SX~hNA5~er zM0kDNlQK3l50O~$Qo+WKr(<{WQPt>SMUf!UAgt3xq5>l7qE#jB(ji!zuL#5o+E9Huo)J~YK31a3BM}QEf|> zLB)OdKM+{>;6o2T^5~-AV~;=a0om{>PQerm^$)KGPU7jWN^MWf~(_x0%MVJWA*DeW)+|Ok=<_c9_PXY5Zy$ zqo&bs8r!c9n!Tg>5!1Mk@3-E}pX0mu2p{FU`5wNPkMVtcKR>_^@ NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\u20ac' # 0x80 -> EURO SIGN + u'\ufffe' # 0x81 -> UNDEFINED + u'\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + u'\u0192' # 0x83 -> LATIN SMALL LETTER F WITH HOOK + u'\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + u'\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + u'\u2020' # 0x86 -> DAGGER + u'\u2021' # 0x87 -> DOUBLE DAGGER + u'\u02c6' # 0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT + u'\u2030' # 0x89 -> PER MILLE SIGN + u'\ufffe' # 0x8A -> UNDEFINED + u'\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + u'\ufffe' # 0x8C -> UNDEFINED + u'\ufffe' # 0x8D -> UNDEFINED + u'\ufffe' # 0x8E -> UNDEFINED + u'\ufffe' # 0x8F -> UNDEFINED + u'\ufffe' # 0x90 -> UNDEFINED + u'\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + u'\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + u'\u2022' # 0x95 -> BULLET + u'\u2013' # 0x96 -> EN DASH + u'\u2014' # 0x97 -> EM DASH + u'\u02dc' # 0x98 -> SMALL TILDE + u'\u2122' # 0x99 -> TRADE MARK SIGN + u'\ufffe' # 0x9A -> UNDEFINED + u'\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + u'\ufffe' # 0x9C -> UNDEFINED + u'\ufffe' # 0x9D -> UNDEFINED + u'\ufffe' # 0x9E -> UNDEFINED + u'\ufffe' # 0x9F -> UNDEFINED + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\xa1' # 0xA1 -> INVERTED EXCLAMATION MARK + u'\xa2' # 0xA2 -> CENT SIGN + u'\xa3' # 0xA3 -> POUND SIGN + u'\u20aa' # 0xA4 -> NEW SHEQEL SIGN + u'\xa5' # 0xA5 -> YEN SIGN + u'\xa6' # 0xA6 -> BROKEN BAR + u'\xa7' # 0xA7 -> SECTION SIGN + u'\xa8' # 0xA8 -> DIAERESIS + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\xd7' # 0xAA -> MULTIPLICATION SIGN + u'\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xac' # 0xAC -> NOT SIGN + u'\xad' # 0xAD -> SOFT HYPHEN + u'\xae' # 0xAE -> REGISTERED SIGN + u'\xaf' # 0xAF -> MACRON + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\xb2' # 0xB2 -> SUPERSCRIPT TWO + u'\xb3' # 0xB3 -> SUPERSCRIPT THREE + u'\xb4' # 0xB4 -> ACUTE ACCENT + u'\xb5' # 0xB5 -> MICRO SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\xb8' # 0xB8 -> CEDILLA + u'\xb9' # 0xB9 -> SUPERSCRIPT ONE + u'\xf7' # 0xBA -> DIVISION SIGN + u'\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + u'\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + u'\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + u'\xbf' # 0xBF -> INVERTED QUESTION MARK + u'\u05b0' # 0xC0 -> HEBREW POINT SHEVA + u'\u05b1' # 0xC1 -> HEBREW POINT HATAF SEGOL + u'\u05b2' # 0xC2 -> HEBREW POINT HATAF PATAH + u'\u05b3' # 0xC3 -> HEBREW POINT HATAF QAMATS + u'\u05b4' # 0xC4 -> HEBREW POINT HIRIQ + u'\u05b5' # 0xC5 -> HEBREW POINT TSERE + u'\u05b6' # 0xC6 -> HEBREW POINT SEGOL + u'\u05b7' # 0xC7 -> HEBREW POINT PATAH + u'\u05b8' # 0xC8 -> HEBREW POINT QAMATS + u'\u05b9' # 0xC9 -> HEBREW POINT HOLAM + u'\ufffe' # 0xCA -> UNDEFINED + u'\u05bb' # 0xCB -> HEBREW POINT QUBUTS + u'\u05bc' # 0xCC -> HEBREW POINT DAGESH OR MAPIQ + u'\u05bd' # 0xCD -> HEBREW POINT METEG + u'\u05be' # 0xCE -> HEBREW PUNCTUATION MAQAF + u'\u05bf' # 0xCF -> HEBREW POINT RAFE + u'\u05c0' # 0xD0 -> HEBREW PUNCTUATION PASEQ + u'\u05c1' # 0xD1 -> HEBREW POINT SHIN DOT + u'\u05c2' # 0xD2 -> HEBREW POINT SIN DOT + u'\u05c3' # 0xD3 -> HEBREW PUNCTUATION SOF PASUQ + u'\u05f0' # 0xD4 -> HEBREW LIGATURE YIDDISH DOUBLE VAV + u'\u05f1' # 0xD5 -> HEBREW LIGATURE YIDDISH VAV YOD + u'\u05f2' # 0xD6 -> HEBREW LIGATURE YIDDISH DOUBLE YOD + u'\u05f3' # 0xD7 -> HEBREW PUNCTUATION GERESH + u'\u05f4' # 0xD8 -> HEBREW PUNCTUATION GERSHAYIM + u'\ufffe' # 0xD9 -> UNDEFINED + u'\ufffe' # 0xDA -> UNDEFINED + u'\ufffe' # 0xDB -> UNDEFINED + u'\ufffe' # 0xDC -> UNDEFINED + u'\ufffe' # 0xDD -> UNDEFINED + u'\ufffe' # 0xDE -> UNDEFINED + u'\ufffe' # 0xDF -> UNDEFINED + u'\u05d0' # 0xE0 -> HEBREW LETTER ALEF + u'\u05d1' # 0xE1 -> HEBREW LETTER BET + u'\u05d2' # 0xE2 -> HEBREW LETTER GIMEL + u'\u05d3' # 0xE3 -> HEBREW LETTER DALET + u'\u05d4' # 0xE4 -> HEBREW LETTER HE + u'\u05d5' # 0xE5 -> HEBREW LETTER VAV + u'\u05d6' # 0xE6 -> HEBREW LETTER ZAYIN + u'\u05d7' # 0xE7 -> HEBREW LETTER HET + u'\u05d8' # 0xE8 -> HEBREW LETTER TET + u'\u05d9' # 0xE9 -> HEBREW LETTER YOD + u'\u05da' # 0xEA -> HEBREW LETTER FINAL KAF + u'\u05db' # 0xEB -> HEBREW LETTER KAF + u'\u05dc' # 0xEC -> HEBREW LETTER LAMED + u'\u05dd' # 0xED -> HEBREW LETTER FINAL MEM + u'\u05de' # 0xEE -> HEBREW LETTER MEM + u'\u05df' # 0xEF -> HEBREW LETTER FINAL NUN + u'\u05e0' # 0xF0 -> HEBREW LETTER NUN + u'\u05e1' # 0xF1 -> HEBREW LETTER SAMEKH + u'\u05e2' # 0xF2 -> HEBREW LETTER AYIN + u'\u05e3' # 0xF3 -> HEBREW LETTER FINAL PE + u'\u05e4' # 0xF4 -> HEBREW LETTER PE + u'\u05e5' # 0xF5 -> HEBREW LETTER FINAL TSADI + u'\u05e6' # 0xF6 -> HEBREW LETTER TSADI + u'\u05e7' # 0xF7 -> HEBREW LETTER QOF + u'\u05e8' # 0xF8 -> HEBREW LETTER RESH + u'\u05e9' # 0xF9 -> HEBREW LETTER SHIN + u'\u05ea' # 0xFA -> HEBREW LETTER TAV + u'\ufffe' # 0xFB -> UNDEFINED + u'\ufffe' # 0xFC -> UNDEFINED + u'\u200e' # 0xFD -> LEFT-TO-RIGHT MARK + u'\u200f' # 0xFE -> RIGHT-TO-LEFT MARK + u'\ufffe' # 0xFF -> UNDEFINED +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp1255.pyc b/PythonHome/Lib/encodings/cp1255.pyc deleted file mode 100644 index ba580edeb979573bc91d46567c0eb35d14c1bda3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2752 zcmc&$=~o+76n|L>Ve786sHq!q16#$lR!V@1mJ}yg+K8q@W&)|%oD4;@>IfV^y0q0U z(hAhlRb?x*wuN(E&+$vY&-*_AfFJw=>b-B8Oh8YuJ;!5`dEEEzy!-C`-QT+x$Dd{1 z*^a%TD7pP{z~6d!vU4yWMO@+J3Qu0)BvLVv?Of*~F)-lG>s&-C$?4o&SDM$kiByJ@a1oKpN!Y^;fF%zZ z1P8t7X~U`aDN>)Tw zmV7ZKo%B_=Zfk3632qP7?rI7)?i50`tu292b9-$^3rssgwShL=R@1(_z1r6oS9{Pv z6b;s7`fI%2_$~MZRTntGkI92;hm{8O%?E=FK>&yx-y!fFAOP7;P<9X@_oMbK?j6ygY}@boqLv5%V9MNI3&eP#B`T0aS;%S zsA5+_Hh19(Sve8oA;eReUX}YHD@t0)`awzfkgWu%rgKNUt21XM+i5}yK$u%NE+uFW zgD19oi9*1wi~I+u0dBs;#l`*$h`fNv2}Lm6mBXfG#Ok)gegs4Hzz~U~#H1XFs9ruv zrlsBlOa;^l7@~C$m+lOY02@d#JXt)zZ7+4Gt3YT;MHM+Ir&KY~#IaMNu*yGq_N;-a z$sV{s60sPAiT^vm>tWTR3GfA&;y|Xr#jXtb(QGgd1L2`^um$892TwrnI4dkvIW1!G zl$fw0UM5(?2*WD`RVc+n%3$CIo5e&{=3rV@{|%0qtCcy^Zrf568#z_}9~3dYCW=Uz zB`6A5rL0hw0TB7M4xWDoP*?$~d*C4Awl-%Ku)~amR7Dn(9ZDR^WuAM;tOk4$6KQe} zDip|s^T$f16%dz}i3%x!MTAGS=zKvIrT_kXte{oa`T1}$H33|&hrzr%W*3D1hgB9X z5nLZP1Xa99SU`APG^?alIyh_N*4;M?w6b*B ztWFBg6Lba06Fh)Z!9pKT96!^nn|L~JLoKOTnpYj`SOG7OfGiLY3IX$RR~b~1m)$bB z0xeKg`ZvNfi)19WVw>Am3ST$>_Fg~=+3XId%U$Ft_Lh{El~=4-xoY*Awd?M?zjFPC zss|o?$hYy~M;?9b@oN7QPd@eZGc~o(Zrc3Z^K~!0_|nU-yt?JJt*_T_YX~$pHE(~T z<;}Ntv<7#!y)A^=-`Ul%dr$b?&iCGr>=nDBk{s*qiSPR$kxZpCA1Yb3cYohU{U3jF z;M31OHwG^Lu`q9F$A3R)XeSMA+|Wi0ZS>}shBmuU)Iqd{i=RVzpl^g3ru5QumLv6 zCfFpKV$*D<@cg{YzG2_8gX|DH%)Vpavm@*%JI0Q)AJ{NE!A`Ot*$5kDW9$_BiJfNS z>Eh(7p!QkBJ2uW80I`QD}46CrtWSq(Q!z%-MhvRyh?5dhY*>uHJY; tGFu3&7EtTXb%D3rEoOt=>VS<|Y NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\u20ac' # 0x80 -> EURO SIGN + u'\u067e' # 0x81 -> ARABIC LETTER PEH + u'\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + u'\u0192' # 0x83 -> LATIN SMALL LETTER F WITH HOOK + u'\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + u'\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + u'\u2020' # 0x86 -> DAGGER + u'\u2021' # 0x87 -> DOUBLE DAGGER + u'\u02c6' # 0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT + u'\u2030' # 0x89 -> PER MILLE SIGN + u'\u0679' # 0x8A -> ARABIC LETTER TTEH + u'\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + u'\u0152' # 0x8C -> LATIN CAPITAL LIGATURE OE + u'\u0686' # 0x8D -> ARABIC LETTER TCHEH + u'\u0698' # 0x8E -> ARABIC LETTER JEH + u'\u0688' # 0x8F -> ARABIC LETTER DDAL + u'\u06af' # 0x90 -> ARABIC LETTER GAF + u'\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + u'\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + u'\u2022' # 0x95 -> BULLET + u'\u2013' # 0x96 -> EN DASH + u'\u2014' # 0x97 -> EM DASH + u'\u06a9' # 0x98 -> ARABIC LETTER KEHEH + u'\u2122' # 0x99 -> TRADE MARK SIGN + u'\u0691' # 0x9A -> ARABIC LETTER RREH + u'\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + u'\u0153' # 0x9C -> LATIN SMALL LIGATURE OE + u'\u200c' # 0x9D -> ZERO WIDTH NON-JOINER + u'\u200d' # 0x9E -> ZERO WIDTH JOINER + u'\u06ba' # 0x9F -> ARABIC LETTER NOON GHUNNA + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\u060c' # 0xA1 -> ARABIC COMMA + u'\xa2' # 0xA2 -> CENT SIGN + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa4' # 0xA4 -> CURRENCY SIGN + u'\xa5' # 0xA5 -> YEN SIGN + u'\xa6' # 0xA6 -> BROKEN BAR + u'\xa7' # 0xA7 -> SECTION SIGN + u'\xa8' # 0xA8 -> DIAERESIS + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\u06be' # 0xAA -> ARABIC LETTER HEH DOACHASHMEE + u'\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xac' # 0xAC -> NOT SIGN + u'\xad' # 0xAD -> SOFT HYPHEN + u'\xae' # 0xAE -> REGISTERED SIGN + u'\xaf' # 0xAF -> MACRON + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\xb2' # 0xB2 -> SUPERSCRIPT TWO + u'\xb3' # 0xB3 -> SUPERSCRIPT THREE + u'\xb4' # 0xB4 -> ACUTE ACCENT + u'\xb5' # 0xB5 -> MICRO SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\xb8' # 0xB8 -> CEDILLA + u'\xb9' # 0xB9 -> SUPERSCRIPT ONE + u'\u061b' # 0xBA -> ARABIC SEMICOLON + u'\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + u'\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + u'\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + u'\u061f' # 0xBF -> ARABIC QUESTION MARK + u'\u06c1' # 0xC0 -> ARABIC LETTER HEH GOAL + u'\u0621' # 0xC1 -> ARABIC LETTER HAMZA + u'\u0622' # 0xC2 -> ARABIC LETTER ALEF WITH MADDA ABOVE + u'\u0623' # 0xC3 -> ARABIC LETTER ALEF WITH HAMZA ABOVE + u'\u0624' # 0xC4 -> ARABIC LETTER WAW WITH HAMZA ABOVE + u'\u0625' # 0xC5 -> ARABIC LETTER ALEF WITH HAMZA BELOW + u'\u0626' # 0xC6 -> ARABIC LETTER YEH WITH HAMZA ABOVE + u'\u0627' # 0xC7 -> ARABIC LETTER ALEF + u'\u0628' # 0xC8 -> ARABIC LETTER BEH + u'\u0629' # 0xC9 -> ARABIC LETTER TEH MARBUTA + u'\u062a' # 0xCA -> ARABIC LETTER TEH + u'\u062b' # 0xCB -> ARABIC LETTER THEH + u'\u062c' # 0xCC -> ARABIC LETTER JEEM + u'\u062d' # 0xCD -> ARABIC LETTER HAH + u'\u062e' # 0xCE -> ARABIC LETTER KHAH + u'\u062f' # 0xCF -> ARABIC LETTER DAL + u'\u0630' # 0xD0 -> ARABIC LETTER THAL + u'\u0631' # 0xD1 -> ARABIC LETTER REH + u'\u0632' # 0xD2 -> ARABIC LETTER ZAIN + u'\u0633' # 0xD3 -> ARABIC LETTER SEEN + u'\u0634' # 0xD4 -> ARABIC LETTER SHEEN + u'\u0635' # 0xD5 -> ARABIC LETTER SAD + u'\u0636' # 0xD6 -> ARABIC LETTER DAD + u'\xd7' # 0xD7 -> MULTIPLICATION SIGN + u'\u0637' # 0xD8 -> ARABIC LETTER TAH + u'\u0638' # 0xD9 -> ARABIC LETTER ZAH + u'\u0639' # 0xDA -> ARABIC LETTER AIN + u'\u063a' # 0xDB -> ARABIC LETTER GHAIN + u'\u0640' # 0xDC -> ARABIC TATWEEL + u'\u0641' # 0xDD -> ARABIC LETTER FEH + u'\u0642' # 0xDE -> ARABIC LETTER QAF + u'\u0643' # 0xDF -> ARABIC LETTER KAF + u'\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + u'\u0644' # 0xE1 -> ARABIC LETTER LAM + u'\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\u0645' # 0xE3 -> ARABIC LETTER MEEM + u'\u0646' # 0xE4 -> ARABIC LETTER NOON + u'\u0647' # 0xE5 -> ARABIC LETTER HEH + u'\u0648' # 0xE6 -> ARABIC LETTER WAW + u'\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + u'\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + u'\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + u'\u0649' # 0xEC -> ARABIC LETTER ALEF MAKSURA + u'\u064a' # 0xED -> ARABIC LETTER YEH + u'\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + u'\u064b' # 0xF0 -> ARABIC FATHATAN + u'\u064c' # 0xF1 -> ARABIC DAMMATAN + u'\u064d' # 0xF2 -> ARABIC KASRATAN + u'\u064e' # 0xF3 -> ARABIC FATHA + u'\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\u064f' # 0xF5 -> ARABIC DAMMA + u'\u0650' # 0xF6 -> ARABIC KASRA + u'\xf7' # 0xF7 -> DIVISION SIGN + u'\u0651' # 0xF8 -> ARABIC SHADDA + u'\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + u'\u0652' # 0xFA -> ARABIC SUKUN + u'\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\u200e' # 0xFD -> LEFT-TO-RIGHT MARK + u'\u200f' # 0xFE -> RIGHT-TO-LEFT MARK + u'\u06d2' # 0xFF -> ARABIC LETTER YEH BARREE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp1256.pyc b/PythonHome/Lib/encodings/cp1256.pyc deleted file mode 100644 index 1d473405414a82561ef05f1118b8a324d31a1754..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2730 zcmc&$>30-G5br&+*(BVcfvAfY>y-!!UWkF^FiMs<8wtedGTE6;Htyx@1dO5%BqAz@ zM1A57;YvtI0)&JF%!i(bU;GDpmT&Vf_y=HB57{B;1K~ZNvzbnH*LHQ)uYO&%u0PBC zqYc|4F>?KJ!T)M_b7L?_gfznFAd-_L9i$Ni7m*#L%}L@QyGa)zorG*{bP~zK6)vvu z78EWb6>)`|D|`ion@Gh(c54dy3&HqOQbTKG!_wQ25Izh17OKV zI>A9ddKwAN!~nL#5UA@=TQliEs8v+Nm?|rQS}~hVq+0@^j3mbbvFy@i%U1+iHHhubRax705Q>`17s zXds3LE3+Myet+T`JYm%X4)9|N;5uPt4f+;G4_zn<&>?A0=h!6>4DpW6i zT~!h>HHLG1-SCERc`ghpA#Dz_6aJh;b&^gOgztd$u)UpomQ!cIY7B5liP@;-E??pz zAQDx@=A>-x!V_|GGR{Ltq_gcR_d`~cjFJn2lJFr{4pL>)#zb?|l$BhQ1t|bwZQ;0- zpgjzpIPNA20k=-`AD{-f`4ShW`!68!0wO0A!Ei?oTb2>4>kbDI4AloiG@2Guax|*? z`6QK*+LJI9P$yuB_CZ{_H9P`rAjRVBEqAZcD^8s(tm$GR?rIj{6e^xnh>s6!(iPVs|!N^ z!zv4x2(FKNN`_|UK@v+|EZETTROn7VtQwu9C=x^(gjKvqSU`APw5p_CIyh?+_T9G% zv~u&ZRh<-`C+G^0CwKv;8y0r(#PKt&x{0UrHdK?2XL!}Ij}`Fp2*?5fp%5@1ca%XD zdD$X^E6@T}rDHKnb4W(wD0X-qrSS3cPy4q>A&1lD_IQhY#r~4gvKcdH&7L!N-uwmk z+*`hIQN?}tKM+{_;6o2T^5~M_V~;=ac zyKeo4S8HB-ePeBSQ{5Xvr2fs#4O_N0zSZ>hJJD@ob4-%sEv<>Rcay1fCi|X}Q`@)i zc)#O=4|jg_@h9f)0b|nCe)zrH)P6CwlcsjW)QleQj#rt_S(3>#!aY?z&8=h%5R!Y;5;{W~_sF0yepVQ9uKW4F<%A2GW09^+GEkMWtY zS3jlq>V5iYz2ErU_(C7lhm0?cea3#{fIeazG``Zuj6?dk(XC(7FPqu{Q#*LIJBTR+ z!eWDyGBIdq*bywE*z`bVSR7e|64o;nOZU_-istr2QnH!_tlmJPTUP+ySXWxDbd?J> a=CHXzH*}Z#%H8Ge3Ri`vc&7InasLHj27A~5 diff --git a/PythonHome/Lib/encodings/cp1257.py b/PythonHome/Lib/encodings/cp1257.py new file mode 100644 index 0000000000..53a6b29d5b --- /dev/null +++ b/PythonHome/Lib/encodings/cp1257.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1257 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1257.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1257', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\u20ac' # 0x80 -> EURO SIGN + u'\ufffe' # 0x81 -> UNDEFINED + u'\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + u'\ufffe' # 0x83 -> UNDEFINED + u'\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + u'\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + u'\u2020' # 0x86 -> DAGGER + u'\u2021' # 0x87 -> DOUBLE DAGGER + u'\ufffe' # 0x88 -> UNDEFINED + u'\u2030' # 0x89 -> PER MILLE SIGN + u'\ufffe' # 0x8A -> UNDEFINED + u'\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + u'\ufffe' # 0x8C -> UNDEFINED + u'\xa8' # 0x8D -> DIAERESIS + u'\u02c7' # 0x8E -> CARON + u'\xb8' # 0x8F -> CEDILLA + u'\ufffe' # 0x90 -> UNDEFINED + u'\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + u'\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + u'\u2022' # 0x95 -> BULLET + u'\u2013' # 0x96 -> EN DASH + u'\u2014' # 0x97 -> EM DASH + u'\ufffe' # 0x98 -> UNDEFINED + u'\u2122' # 0x99 -> TRADE MARK SIGN + u'\ufffe' # 0x9A -> UNDEFINED + u'\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + u'\ufffe' # 0x9C -> UNDEFINED + u'\xaf' # 0x9D -> MACRON + u'\u02db' # 0x9E -> OGONEK + u'\ufffe' # 0x9F -> UNDEFINED + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\ufffe' # 0xA1 -> UNDEFINED + u'\xa2' # 0xA2 -> CENT SIGN + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa4' # 0xA4 -> CURRENCY SIGN + u'\ufffe' # 0xA5 -> UNDEFINED + u'\xa6' # 0xA6 -> BROKEN BAR + u'\xa7' # 0xA7 -> SECTION SIGN + u'\xd8' # 0xA8 -> LATIN CAPITAL LETTER O WITH STROKE + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\u0156' # 0xAA -> LATIN CAPITAL LETTER R WITH CEDILLA + u'\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xac' # 0xAC -> NOT SIGN + u'\xad' # 0xAD -> SOFT HYPHEN + u'\xae' # 0xAE -> REGISTERED SIGN + u'\xc6' # 0xAF -> LATIN CAPITAL LETTER AE + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\xb2' # 0xB2 -> SUPERSCRIPT TWO + u'\xb3' # 0xB3 -> SUPERSCRIPT THREE + u'\xb4' # 0xB4 -> ACUTE ACCENT + u'\xb5' # 0xB5 -> MICRO SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\xf8' # 0xB8 -> LATIN SMALL LETTER O WITH STROKE + u'\xb9' # 0xB9 -> SUPERSCRIPT ONE + u'\u0157' # 0xBA -> LATIN SMALL LETTER R WITH CEDILLA + u'\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + u'\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + u'\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + u'\xe6' # 0xBF -> LATIN SMALL LETTER AE + u'\u0104' # 0xC0 -> LATIN CAPITAL LETTER A WITH OGONEK + u'\u012e' # 0xC1 -> LATIN CAPITAL LETTER I WITH OGONEK + u'\u0100' # 0xC2 -> LATIN CAPITAL LETTER A WITH MACRON + u'\u0106' # 0xC3 -> LATIN CAPITAL LETTER C WITH ACUTE + u'\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\u0118' # 0xC6 -> LATIN CAPITAL LETTER E WITH OGONEK + u'\u0112' # 0xC7 -> LATIN CAPITAL LETTER E WITH MACRON + u'\u010c' # 0xC8 -> LATIN CAPITAL LETTER C WITH CARON + u'\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\u0179' # 0xCA -> LATIN CAPITAL LETTER Z WITH ACUTE + u'\u0116' # 0xCB -> LATIN CAPITAL LETTER E WITH DOT ABOVE + u'\u0122' # 0xCC -> LATIN CAPITAL LETTER G WITH CEDILLA + u'\u0136' # 0xCD -> LATIN CAPITAL LETTER K WITH CEDILLA + u'\u012a' # 0xCE -> LATIN CAPITAL LETTER I WITH MACRON + u'\u013b' # 0xCF -> LATIN CAPITAL LETTER L WITH CEDILLA + u'\u0160' # 0xD0 -> LATIN CAPITAL LETTER S WITH CARON + u'\u0143' # 0xD1 -> LATIN CAPITAL LETTER N WITH ACUTE + u'\u0145' # 0xD2 -> LATIN CAPITAL LETTER N WITH CEDILLA + u'\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\u014c' # 0xD4 -> LATIN CAPITAL LETTER O WITH MACRON + u'\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + u'\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xd7' # 0xD7 -> MULTIPLICATION SIGN + u'\u0172' # 0xD8 -> LATIN CAPITAL LETTER U WITH OGONEK + u'\u0141' # 0xD9 -> LATIN CAPITAL LETTER L WITH STROKE + u'\u015a' # 0xDA -> LATIN CAPITAL LETTER S WITH ACUTE + u'\u016a' # 0xDB -> LATIN CAPITAL LETTER U WITH MACRON + u'\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\u017b' # 0xDD -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + u'\u017d' # 0xDE -> LATIN CAPITAL LETTER Z WITH CARON + u'\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + u'\u0105' # 0xE0 -> LATIN SMALL LETTER A WITH OGONEK + u'\u012f' # 0xE1 -> LATIN SMALL LETTER I WITH OGONEK + u'\u0101' # 0xE2 -> LATIN SMALL LETTER A WITH MACRON + u'\u0107' # 0xE3 -> LATIN SMALL LETTER C WITH ACUTE + u'\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\u0119' # 0xE6 -> LATIN SMALL LETTER E WITH OGONEK + u'\u0113' # 0xE7 -> LATIN SMALL LETTER E WITH MACRON + u'\u010d' # 0xE8 -> LATIN SMALL LETTER C WITH CARON + u'\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + u'\u017a' # 0xEA -> LATIN SMALL LETTER Z WITH ACUTE + u'\u0117' # 0xEB -> LATIN SMALL LETTER E WITH DOT ABOVE + u'\u0123' # 0xEC -> LATIN SMALL LETTER G WITH CEDILLA + u'\u0137' # 0xED -> LATIN SMALL LETTER K WITH CEDILLA + u'\u012b' # 0xEE -> LATIN SMALL LETTER I WITH MACRON + u'\u013c' # 0xEF -> LATIN SMALL LETTER L WITH CEDILLA + u'\u0161' # 0xF0 -> LATIN SMALL LETTER S WITH CARON + u'\u0144' # 0xF1 -> LATIN SMALL LETTER N WITH ACUTE + u'\u0146' # 0xF2 -> LATIN SMALL LETTER N WITH CEDILLA + u'\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + u'\u014d' # 0xF4 -> LATIN SMALL LETTER O WITH MACRON + u'\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + u'\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf7' # 0xF7 -> DIVISION SIGN + u'\u0173' # 0xF8 -> LATIN SMALL LETTER U WITH OGONEK + u'\u0142' # 0xF9 -> LATIN SMALL LETTER L WITH STROKE + u'\u015b' # 0xFA -> LATIN SMALL LETTER S WITH ACUTE + u'\u016b' # 0xFB -> LATIN SMALL LETTER U WITH MACRON + u'\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\u017c' # 0xFD -> LATIN SMALL LETTER Z WITH DOT ABOVE + u'\u017e' # 0xFE -> LATIN SMALL LETTER Z WITH CARON + u'\u02d9' # 0xFF -> DOT ABOVE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp1257.pyc b/PythonHome/Lib/encodings/cp1257.pyc deleted file mode 100644 index 830e5139251975e55aefab9a69eedb0d2a8a198c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2738 zcmc&$>vt1X5WmSLX_~%xYoKcI)%a=!MSLKZrY%NksGCY5R>O98(+2Z$v!zy115L~E z9Qb0j4<1?yR-p(;rKPmgbN2D6|3&@*KllgW%w3XgtA`5bcucyJxp(&7JM)|0ohkEY znQN-`V2~$wKMefV!jql`ArKM*X(57@#4IEP3PVH-Ib-Q}=xNYffdL!_;c4!XJCg~IualEFUKS-!6PHRw6CEC3QV@9$pW3o@+jdWfm=GmS z76ng4O2$1^O}m<#{ej)Vntcs{`n_zhrpfOMHn!BX`eE1_tnoGDvg(%oEmfZGsN9Jg z@VH@hs;AoJir#@wK(>Pe^q2y;R+y%9r(H| zMR}RWF+MhUd^o)pgiOdG3poORRw7$TF9YFQU_M|jr=F$da+u`-hd7rC8}8C6ssbWm znQM=U#wt7^Eyf}=glHnwB~w2{NlHp-FBl0GX*X!qZF{2aZTVf&Z3d(Ogt3I;QiA(o z@Wk>UQLwmliT?mKz)h#9y3~Ibk!KM(wg|+1Ic)5VSlxBli(tr35aDowi;Ll~?4pBs zQs|1okVPAdA({tK?cVUPuz(c9lg0xa)>1}Z1BySvOJZD1$Xu*}Vkhx1OFsqntb?J! z9=JdPF&Tr2|2x1NVb-Jx@CBH{AXDICyMtcbHV_3tXs8ry7I{X&W6?Xx3KLaIi%2xV z#mtCT2o^EI@D_v0mf|60An1mTTr4e8FwI^64UU+r)%mR*mgOkcQ>y$wC}MgI6p=E^ zP-L-6nW3%#Ao6PiJpT+Jy9!JXz(K@qeSTNK4l@#zC6SA_N>M161@0lU>hMKOq`^I? zP@ogaA2XF^KvY{HDx?G!5gOH!^I4G-{`>Q>f>xU67sAEV_;9`!gmHI_E(rY(t1Mh1 zxIVVL4$aJtBo-W4u%YA0(4CxEHF`-=(2Fz($as;kfY7>VR7taRP}WAxyKfX|Y5BBK zog|tk=n9Z0cmStG6Wug%^h~2};_0*v`4f>OtvcqhEM6WKS->I`Eav0BGAJW2J4A2= zTA(cTY=&VP$w(~47Kf!2z7G2BI*SytSQ(q$QRFOkm6Vp1SFBpSX6?H58yV0J zBac4j+5GquPd@c@mG_xvpL_m=>Y5j~Y<=nFZLe&9^|jaE*zxAhw`zCQ`RW@Qcfaj_ z=iNO`fxXS|vB8%2_qFan5c;6)!;iuTxprO%DJ^#$?*6prv(Jxw z@#R;!W0(K+EqwXv!fE^&MKPwFS1zD3uKc79D;M=aWkR{E{Gwb@`;}|TugZ00Qu$4} zp-d^$>P=-vA5vzOIpwx8ua0Y3?TVJs`qix3rwwc0XeZRK^%-qY8`Gw=OWLeHs`u)B z>VSSi{Z1WJhxF_EQT>#DNj;;_>bKP&v_9>sc2qmAUQmD3MzjI#q68N+2#aIw8qJW5dp15XPhlGQ{A@ zCe*O5$ymbk|5>zmMPq`|G+=fSneJT)XoKBhwA7spEKFmQgRW?EJKZ+7t&*v<7gsp$ G5Zhn={(zhS diff --git a/PythonHome/Lib/encodings/cp1258.py b/PythonHome/Lib/encodings/cp1258.py new file mode 100644 index 0000000000..4b25d8e7e8 --- /dev/null +++ b/PythonHome/Lib/encodings/cp1258.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1258 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1258.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1258', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\u20ac' # 0x80 -> EURO SIGN + u'\ufffe' # 0x81 -> UNDEFINED + u'\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + u'\u0192' # 0x83 -> LATIN SMALL LETTER F WITH HOOK + u'\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + u'\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + u'\u2020' # 0x86 -> DAGGER + u'\u2021' # 0x87 -> DOUBLE DAGGER + u'\u02c6' # 0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT + u'\u2030' # 0x89 -> PER MILLE SIGN + u'\ufffe' # 0x8A -> UNDEFINED + u'\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + u'\u0152' # 0x8C -> LATIN CAPITAL LIGATURE OE + u'\ufffe' # 0x8D -> UNDEFINED + u'\ufffe' # 0x8E -> UNDEFINED + u'\ufffe' # 0x8F -> UNDEFINED + u'\ufffe' # 0x90 -> UNDEFINED + u'\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + u'\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + u'\u2022' # 0x95 -> BULLET + u'\u2013' # 0x96 -> EN DASH + u'\u2014' # 0x97 -> EM DASH + u'\u02dc' # 0x98 -> SMALL TILDE + u'\u2122' # 0x99 -> TRADE MARK SIGN + u'\ufffe' # 0x9A -> UNDEFINED + u'\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + u'\u0153' # 0x9C -> LATIN SMALL LIGATURE OE + u'\ufffe' # 0x9D -> UNDEFINED + u'\ufffe' # 0x9E -> UNDEFINED + u'\u0178' # 0x9F -> LATIN CAPITAL LETTER Y WITH DIAERESIS + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\xa1' # 0xA1 -> INVERTED EXCLAMATION MARK + u'\xa2' # 0xA2 -> CENT SIGN + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa4' # 0xA4 -> CURRENCY SIGN + u'\xa5' # 0xA5 -> YEN SIGN + u'\xa6' # 0xA6 -> BROKEN BAR + u'\xa7' # 0xA7 -> SECTION SIGN + u'\xa8' # 0xA8 -> DIAERESIS + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\xaa' # 0xAA -> FEMININE ORDINAL INDICATOR + u'\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xac' # 0xAC -> NOT SIGN + u'\xad' # 0xAD -> SOFT HYPHEN + u'\xae' # 0xAE -> REGISTERED SIGN + u'\xaf' # 0xAF -> MACRON + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\xb2' # 0xB2 -> SUPERSCRIPT TWO + u'\xb3' # 0xB3 -> SUPERSCRIPT THREE + u'\xb4' # 0xB4 -> ACUTE ACCENT + u'\xb5' # 0xB5 -> MICRO SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\xb8' # 0xB8 -> CEDILLA + u'\xb9' # 0xB9 -> SUPERSCRIPT ONE + u'\xba' # 0xBA -> MASCULINE ORDINAL INDICATOR + u'\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + u'\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + u'\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + u'\xbf' # 0xBF -> INVERTED QUESTION MARK + u'\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\u0102' # 0xC3 -> LATIN CAPITAL LETTER A WITH BREVE + u'\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + u'\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\u0300' # 0xCC -> COMBINING GRAVE ACCENT + u'\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\u0110' # 0xD0 -> LATIN CAPITAL LETTER D WITH STROKE + u'\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + u'\u0309' # 0xD2 -> COMBINING HOOK ABOVE + u'\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\u01a0' # 0xD5 -> LATIN CAPITAL LETTER O WITH HORN + u'\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xd7' # 0xD7 -> MULTIPLICATION SIGN + u'\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + u'\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\u01af' # 0xDD -> LATIN CAPITAL LETTER U WITH HORN + u'\u0303' # 0xDE -> COMBINING TILDE + u'\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + u'\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\u0103' # 0xE3 -> LATIN SMALL LETTER A WITH BREVE + u'\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe6' # 0xE6 -> LATIN SMALL LETTER AE + u'\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + u'\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + u'\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + u'\u0301' # 0xEC -> COMBINING ACUTE ACCENT + u'\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + u'\u0111' # 0xF0 -> LATIN SMALL LETTER D WITH STROKE + u'\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + u'\u0323' # 0xF2 -> COMBINING DOT BELOW + u'\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\u01a1' # 0xF5 -> LATIN SMALL LETTER O WITH HORN + u'\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf7' # 0xF7 -> DIVISION SIGN + u'\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + u'\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + u'\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + u'\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\u01b0' # 0xFD -> LATIN SMALL LETTER U WITH HORN + u'\u20ab' # 0xFE -> DONG SIGN + u'\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp1258.pyc b/PythonHome/Lib/encodings/cp1258.pyc deleted file mode 100644 index f5a90b175120562f60f18536efa0dc25391494c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2736 zcmc&$d3O{=5br&+*(BVcfvAfY>y-$Kq9O)10i$GzvyniIE|Z8t?Krv5k#Rrg((HB^2Jg z!o`#Vp>PX@FRySjrI4vkq4Tgf8t~_J9;Osc>byc%oY#4oQbLo)0;Wu3jXq%jE%{g% zI_M`)Bf;quz-Al*bsc(ZCLIX1%9ntC)=80y+L};gb$vxc4Ne;(6`?xXR$jlMeo=n zQSi)hFHuOeb&CH8HNq{HggDiIiIA5FIjI1LyK>mFOjzA;I7ndVJ{+Raw473-QQa>l zsf^N|#HmC&i9)mw64LGAk#GYm#3x4wc%8*AeHIEe>6oUb)U+-qs|9vi3|GY`&z?Cr zwb+9fNMSZ(DDi&>cs{P$G(o-~Q(VLpyx66YAejv(a9|=-0k%Xu6W~eYonVEHs-Q(Y zk(QHo#CHgmFrx5o230DiLrQQE23O0;oGQSyt^OMvDOWQmO?w@;qF5!U^8cVn>9tTK z%G`pYL{-WT^$q|Mzvkid&j3m@P<0O+B;4jsT1D(ABN1IweC_zO;L^b7nNtKoV{(P#SW%l{`a49t*TCc>xx;s`E#QsNB z7B3NAANQn;&CEk2R=iZOvE%93oqSX^x>!LZNHhrRbdjilh`MN1NxO6i)+X$`Zxv|m z)@7?YX(CV96);cuAWklNSj14JQ*)8+Pf3w(wCqT-Ti(`U?_HG9t7dH3C4 zI)6dg0}nnFSorWGk3RPJqTmxxKK1l7@YOJ8_#*-J0Kvi#K*uT`#G6{@OU zz2^0rH{M)Z8(vrUmK3Rfdws)(jg9X#z58BtliVCr)Obs4qV4@;DxJxGpyl-T&09X~ z_~_%UpM3h6*?H=Z(JQ90e|(o|{A?OWOrzH{`mSv^jRBz;zPby4^M9tX*EIH-MvrOy zWE%aZvD-BETlULE4SypQ+ugZvOb%#ZM+{1`vZPwY$u$XI0)zA!gwECgh3dBVHkl+aCv;d>^uphK}sajmfD<>iD6r#zF^VCCJFJw zV#)%NsH*8yz$gE&Xl_p=6{}_7>P=L-eH{?(b-C40SGaIvj#?b{M0csL)LrT>bCr1t Jr+cq6_g|Upef|Id diff --git a/PythonHome/Lib/encodings/cp424.py b/PythonHome/Lib/encodings/cp424.py new file mode 100644 index 0000000000..d3ade22776 --- /dev/null +++ b/PythonHome/Lib/encodings/cp424.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp424 generated from 'MAPPINGS/VENDORS/MISC/CP424.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp424', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x9c' # 0x04 -> SELECT + u'\t' # 0x05 -> HORIZONTAL TABULATION + u'\x86' # 0x06 -> REQUIRED NEW LINE + u'\x7f' # 0x07 -> DELETE + u'\x97' # 0x08 -> GRAPHIC ESCAPE + u'\x8d' # 0x09 -> SUPERSCRIPT + u'\x8e' # 0x0A -> REPEAT + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x9d' # 0x14 -> RESTORE/ENABLE PRESENTATION + u'\x85' # 0x15 -> NEW LINE + u'\x08' # 0x16 -> BACKSPACE + u'\x87' # 0x17 -> PROGRAM OPERATOR COMMUNICATION + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x92' # 0x1A -> UNIT BACK SPACE + u'\x8f' # 0x1B -> CUSTOMER USE ONE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u'\x80' # 0x20 -> DIGIT SELECT + u'\x81' # 0x21 -> START OF SIGNIFICANCE + u'\x82' # 0x22 -> FIELD SEPARATOR + u'\x83' # 0x23 -> WORD UNDERSCORE + u'\x84' # 0x24 -> BYPASS OR INHIBIT PRESENTATION + u'\n' # 0x25 -> LINE FEED + u'\x17' # 0x26 -> END OF TRANSMISSION BLOCK + u'\x1b' # 0x27 -> ESCAPE + u'\x88' # 0x28 -> SET ATTRIBUTE + u'\x89' # 0x29 -> START FIELD EXTENDED + u'\x8a' # 0x2A -> SET MODE OR SWITCH + u'\x8b' # 0x2B -> CONTROL SEQUENCE PREFIX + u'\x8c' # 0x2C -> MODIFY FIELD ATTRIBUTE + u'\x05' # 0x2D -> ENQUIRY + u'\x06' # 0x2E -> ACKNOWLEDGE + u'\x07' # 0x2F -> BELL + u'\x90' # 0x30 -> + u'\x91' # 0x31 -> + u'\x16' # 0x32 -> SYNCHRONOUS IDLE + u'\x93' # 0x33 -> INDEX RETURN + u'\x94' # 0x34 -> PRESENTATION POSITION + u'\x95' # 0x35 -> TRANSPARENT + u'\x96' # 0x36 -> NUMERIC BACKSPACE + u'\x04' # 0x37 -> END OF TRANSMISSION + u'\x98' # 0x38 -> SUBSCRIPT + u'\x99' # 0x39 -> INDENT TABULATION + u'\x9a' # 0x3A -> REVERSE FORM FEED + u'\x9b' # 0x3B -> CUSTOMER USE THREE + u'\x14' # 0x3C -> DEVICE CONTROL FOUR + u'\x15' # 0x3D -> NEGATIVE ACKNOWLEDGE + u'\x9e' # 0x3E -> + u'\x1a' # 0x3F -> SUBSTITUTE + u' ' # 0x40 -> SPACE + u'\u05d0' # 0x41 -> HEBREW LETTER ALEF + u'\u05d1' # 0x42 -> HEBREW LETTER BET + u'\u05d2' # 0x43 -> HEBREW LETTER GIMEL + u'\u05d3' # 0x44 -> HEBREW LETTER DALET + u'\u05d4' # 0x45 -> HEBREW LETTER HE + u'\u05d5' # 0x46 -> HEBREW LETTER VAV + u'\u05d6' # 0x47 -> HEBREW LETTER ZAYIN + u'\u05d7' # 0x48 -> HEBREW LETTER HET + u'\u05d8' # 0x49 -> HEBREW LETTER TET + u'\xa2' # 0x4A -> CENT SIGN + u'.' # 0x4B -> FULL STOP + u'<' # 0x4C -> LESS-THAN SIGN + u'(' # 0x4D -> LEFT PARENTHESIS + u'+' # 0x4E -> PLUS SIGN + u'|' # 0x4F -> VERTICAL LINE + u'&' # 0x50 -> AMPERSAND + u'\u05d9' # 0x51 -> HEBREW LETTER YOD + u'\u05da' # 0x52 -> HEBREW LETTER FINAL KAF + u'\u05db' # 0x53 -> HEBREW LETTER KAF + u'\u05dc' # 0x54 -> HEBREW LETTER LAMED + u'\u05dd' # 0x55 -> HEBREW LETTER FINAL MEM + u'\u05de' # 0x56 -> HEBREW LETTER MEM + u'\u05df' # 0x57 -> HEBREW LETTER FINAL NUN + u'\u05e0' # 0x58 -> HEBREW LETTER NUN + u'\u05e1' # 0x59 -> HEBREW LETTER SAMEKH + u'!' # 0x5A -> EXCLAMATION MARK + u'$' # 0x5B -> DOLLAR SIGN + u'*' # 0x5C -> ASTERISK + u')' # 0x5D -> RIGHT PARENTHESIS + u';' # 0x5E -> SEMICOLON + u'\xac' # 0x5F -> NOT SIGN + u'-' # 0x60 -> HYPHEN-MINUS + u'/' # 0x61 -> SOLIDUS + u'\u05e2' # 0x62 -> HEBREW LETTER AYIN + u'\u05e3' # 0x63 -> HEBREW LETTER FINAL PE + u'\u05e4' # 0x64 -> HEBREW LETTER PE + u'\u05e5' # 0x65 -> HEBREW LETTER FINAL TSADI + u'\u05e6' # 0x66 -> HEBREW LETTER TSADI + u'\u05e7' # 0x67 -> HEBREW LETTER QOF + u'\u05e8' # 0x68 -> HEBREW LETTER RESH + u'\u05e9' # 0x69 -> HEBREW LETTER SHIN + u'\xa6' # 0x6A -> BROKEN BAR + u',' # 0x6B -> COMMA + u'%' # 0x6C -> PERCENT SIGN + u'_' # 0x6D -> LOW LINE + u'>' # 0x6E -> GREATER-THAN SIGN + u'?' # 0x6F -> QUESTION MARK + u'\ufffe' # 0x70 -> UNDEFINED + u'\u05ea' # 0x71 -> HEBREW LETTER TAV + u'\ufffe' # 0x72 -> UNDEFINED + u'\ufffe' # 0x73 -> UNDEFINED + u'\xa0' # 0x74 -> NO-BREAK SPACE + u'\ufffe' # 0x75 -> UNDEFINED + u'\ufffe' # 0x76 -> UNDEFINED + u'\ufffe' # 0x77 -> UNDEFINED + u'\u2017' # 0x78 -> DOUBLE LOW LINE + u'`' # 0x79 -> GRAVE ACCENT + u':' # 0x7A -> COLON + u'#' # 0x7B -> NUMBER SIGN + u'@' # 0x7C -> COMMERCIAL AT + u"'" # 0x7D -> APOSTROPHE + u'=' # 0x7E -> EQUALS SIGN + u'"' # 0x7F -> QUOTATION MARK + u'\ufffe' # 0x80 -> UNDEFINED + u'a' # 0x81 -> LATIN SMALL LETTER A + u'b' # 0x82 -> LATIN SMALL LETTER B + u'c' # 0x83 -> LATIN SMALL LETTER C + u'd' # 0x84 -> LATIN SMALL LETTER D + u'e' # 0x85 -> LATIN SMALL LETTER E + u'f' # 0x86 -> LATIN SMALL LETTER F + u'g' # 0x87 -> LATIN SMALL LETTER G + u'h' # 0x88 -> LATIN SMALL LETTER H + u'i' # 0x89 -> LATIN SMALL LETTER I + u'\xab' # 0x8A -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x8B -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\ufffe' # 0x8C -> UNDEFINED + u'\ufffe' # 0x8D -> UNDEFINED + u'\ufffe' # 0x8E -> UNDEFINED + u'\xb1' # 0x8F -> PLUS-MINUS SIGN + u'\xb0' # 0x90 -> DEGREE SIGN + u'j' # 0x91 -> LATIN SMALL LETTER J + u'k' # 0x92 -> LATIN SMALL LETTER K + u'l' # 0x93 -> LATIN SMALL LETTER L + u'm' # 0x94 -> LATIN SMALL LETTER M + u'n' # 0x95 -> LATIN SMALL LETTER N + u'o' # 0x96 -> LATIN SMALL LETTER O + u'p' # 0x97 -> LATIN SMALL LETTER P + u'q' # 0x98 -> LATIN SMALL LETTER Q + u'r' # 0x99 -> LATIN SMALL LETTER R + u'\ufffe' # 0x9A -> UNDEFINED + u'\ufffe' # 0x9B -> UNDEFINED + u'\ufffe' # 0x9C -> UNDEFINED + u'\xb8' # 0x9D -> CEDILLA + u'\ufffe' # 0x9E -> UNDEFINED + u'\xa4' # 0x9F -> CURRENCY SIGN + u'\xb5' # 0xA0 -> MICRO SIGN + u'~' # 0xA1 -> TILDE + u's' # 0xA2 -> LATIN SMALL LETTER S + u't' # 0xA3 -> LATIN SMALL LETTER T + u'u' # 0xA4 -> LATIN SMALL LETTER U + u'v' # 0xA5 -> LATIN SMALL LETTER V + u'w' # 0xA6 -> LATIN SMALL LETTER W + u'x' # 0xA7 -> LATIN SMALL LETTER X + u'y' # 0xA8 -> LATIN SMALL LETTER Y + u'z' # 0xA9 -> LATIN SMALL LETTER Z + u'\ufffe' # 0xAA -> UNDEFINED + u'\ufffe' # 0xAB -> UNDEFINED + u'\ufffe' # 0xAC -> UNDEFINED + u'\ufffe' # 0xAD -> UNDEFINED + u'\ufffe' # 0xAE -> UNDEFINED + u'\xae' # 0xAF -> REGISTERED SIGN + u'^' # 0xB0 -> CIRCUMFLEX ACCENT + u'\xa3' # 0xB1 -> POUND SIGN + u'\xa5' # 0xB2 -> YEN SIGN + u'\xb7' # 0xB3 -> MIDDLE DOT + u'\xa9' # 0xB4 -> COPYRIGHT SIGN + u'\xa7' # 0xB5 -> SECTION SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xbc' # 0xB7 -> VULGAR FRACTION ONE QUARTER + u'\xbd' # 0xB8 -> VULGAR FRACTION ONE HALF + u'\xbe' # 0xB9 -> VULGAR FRACTION THREE QUARTERS + u'[' # 0xBA -> LEFT SQUARE BRACKET + u']' # 0xBB -> RIGHT SQUARE BRACKET + u'\xaf' # 0xBC -> MACRON + u'\xa8' # 0xBD -> DIAERESIS + u'\xb4' # 0xBE -> ACUTE ACCENT + u'\xd7' # 0xBF -> MULTIPLICATION SIGN + u'{' # 0xC0 -> LEFT CURLY BRACKET + u'A' # 0xC1 -> LATIN CAPITAL LETTER A + u'B' # 0xC2 -> LATIN CAPITAL LETTER B + u'C' # 0xC3 -> LATIN CAPITAL LETTER C + u'D' # 0xC4 -> LATIN CAPITAL LETTER D + u'E' # 0xC5 -> LATIN CAPITAL LETTER E + u'F' # 0xC6 -> LATIN CAPITAL LETTER F + u'G' # 0xC7 -> LATIN CAPITAL LETTER G + u'H' # 0xC8 -> LATIN CAPITAL LETTER H + u'I' # 0xC9 -> LATIN CAPITAL LETTER I + u'\xad' # 0xCA -> SOFT HYPHEN + u'\ufffe' # 0xCB -> UNDEFINED + u'\ufffe' # 0xCC -> UNDEFINED + u'\ufffe' # 0xCD -> UNDEFINED + u'\ufffe' # 0xCE -> UNDEFINED + u'\ufffe' # 0xCF -> UNDEFINED + u'}' # 0xD0 -> RIGHT CURLY BRACKET + u'J' # 0xD1 -> LATIN CAPITAL LETTER J + u'K' # 0xD2 -> LATIN CAPITAL LETTER K + u'L' # 0xD3 -> LATIN CAPITAL LETTER L + u'M' # 0xD4 -> LATIN CAPITAL LETTER M + u'N' # 0xD5 -> LATIN CAPITAL LETTER N + u'O' # 0xD6 -> LATIN CAPITAL LETTER O + u'P' # 0xD7 -> LATIN CAPITAL LETTER P + u'Q' # 0xD8 -> LATIN CAPITAL LETTER Q + u'R' # 0xD9 -> LATIN CAPITAL LETTER R + u'\xb9' # 0xDA -> SUPERSCRIPT ONE + u'\ufffe' # 0xDB -> UNDEFINED + u'\ufffe' # 0xDC -> UNDEFINED + u'\ufffe' # 0xDD -> UNDEFINED + u'\ufffe' # 0xDE -> UNDEFINED + u'\ufffe' # 0xDF -> UNDEFINED + u'\\' # 0xE0 -> REVERSE SOLIDUS + u'\xf7' # 0xE1 -> DIVISION SIGN + u'S' # 0xE2 -> LATIN CAPITAL LETTER S + u'T' # 0xE3 -> LATIN CAPITAL LETTER T + u'U' # 0xE4 -> LATIN CAPITAL LETTER U + u'V' # 0xE5 -> LATIN CAPITAL LETTER V + u'W' # 0xE6 -> LATIN CAPITAL LETTER W + u'X' # 0xE7 -> LATIN CAPITAL LETTER X + u'Y' # 0xE8 -> LATIN CAPITAL LETTER Y + u'Z' # 0xE9 -> LATIN CAPITAL LETTER Z + u'\xb2' # 0xEA -> SUPERSCRIPT TWO + u'\ufffe' # 0xEB -> UNDEFINED + u'\ufffe' # 0xEC -> UNDEFINED + u'\ufffe' # 0xED -> UNDEFINED + u'\ufffe' # 0xEE -> UNDEFINED + u'\ufffe' # 0xEF -> UNDEFINED + u'0' # 0xF0 -> DIGIT ZERO + u'1' # 0xF1 -> DIGIT ONE + u'2' # 0xF2 -> DIGIT TWO + u'3' # 0xF3 -> DIGIT THREE + u'4' # 0xF4 -> DIGIT FOUR + u'5' # 0xF5 -> DIGIT FIVE + u'6' # 0xF6 -> DIGIT SIX + u'7' # 0xF7 -> DIGIT SEVEN + u'8' # 0xF8 -> DIGIT EIGHT + u'9' # 0xF9 -> DIGIT NINE + u'\xb3' # 0xFA -> SUPERSCRIPT THREE + u'\ufffe' # 0xFB -> UNDEFINED + u'\ufffe' # 0xFC -> UNDEFINED + u'\ufffe' # 0xFD -> UNDEFINED + u'\ufffe' # 0xFE -> UNDEFINED + u'\x9f' # 0xFF -> EIGHT ONES +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp424.pyc b/PythonHome/Lib/encodings/cp424.pyc deleted file mode 100644 index 67ec0c44e32e230119c0d6ce997f1a43ce69c92f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2724 zcmc&$>2e!I5FTkIS(dNdM2P`~%i^*jm^%c=vJ(ukVpb+jgh5&FuIx3sSdB4;Kms=R zmD{-!ayj8XV<;e0bsl2=^8)wqYwyV`ngy#NNXUFUxpX5(R~s9yaV{X_S3zg0XSNwkEyI@Jodv6@jusVMdiy z_@p9OR`{4v%}lS<`B@qbgvvTUGipk@fYjBNbpdA7(I8pHjCz&~N&{#q$i~sZ5P6!2 zHc$Y=*hPBA_)tC@@ePTV&7JX%O=_a0yDJfEiS^*S&AnTCn;n3R4qNf}aQIb#7Za*J(`6hb>0ai?QR34SU#j z{CXMpvT+4N_TYTnT`oN<@_L-rG4`xhNICAxDJdcfDXtAsNt6EvLpodsL*h#XhAJf`H`2M`BW^9j_V@6q3s5zG z{t;?ROGXhnI*tUlO)cAJTbLWmydze%(~ES94(~8Eq0A(A+;eopk<#2T5go$VWK6TR zS53|M&$p+<+30Rx4wjB3M)PghIk(0scv$Kvx#IP~i{mTFShxJdUn4+y8jBmpLKLKQ zG0v(IQKCSc(-or3A$cy7qnk1$VJ-L4J89XjoOZI3Ee{E60Ui=IL}|vvs5~{frIRjc zb6I@4a_PKGH}1A7-5ZrCpb`=)oyL5Qj}s*aP4ooo9=FF<;jl%0>akL3nF<81}$Njn`gxJ?w>iO@AG z;ca*a-i7zzeSe?|cERptuow2hemLNRgK!8A!;vLR;rNP(*d=z0Jz}reC-#d2Vp1H0 zQ_X9lw{O2i91@4c5ph%;6UW5~aZ-G|>ZaRneHcEwvqhW|r^Oj@R-6-4;=H&3=kB;U zwf529f4w9=!4AK0()q>yx1E#Q9=fru>5&_7pbhATnI0Un;8Xai{0e*xUkyK($>#Ef z=WTcP2NdB9eE({ZkGwGY;@C@Nl_S6x&%$Xq3)64`rr;v{48Opor=Ni@;XHhIdGh6T z?Xix|^&1}Rg3l{fzVi4J8@uD1dY)9_#|l;d<>^H4Q=9v?Y)!&96}r3bUVTsNz4zV! zz=QDZOck7n(xD=OsnQvF9V;8v28TH=Ux+FWX;zX%xs6j6Fa5C?7_l;jQ#NpR2CL@G j2eQDfaZ2i11=kg+%3)dbg@a*V*w?5u`l}lPSD5cl NULL + u'\x01' # 0x0001 -> START OF HEADING + u'\x02' # 0x0002 -> START OF TEXT + u'\x03' # 0x0003 -> END OF TEXT + u'\x04' # 0x0004 -> END OF TRANSMISSION + u'\x05' # 0x0005 -> ENQUIRY + u'\x06' # 0x0006 -> ACKNOWLEDGE + u'\x07' # 0x0007 -> BELL + u'\x08' # 0x0008 -> BACKSPACE + u'\t' # 0x0009 -> HORIZONTAL TABULATION + u'\n' # 0x000a -> LINE FEED + u'\x0b' # 0x000b -> VERTICAL TABULATION + u'\x0c' # 0x000c -> FORM FEED + u'\r' # 0x000d -> CARRIAGE RETURN + u'\x0e' # 0x000e -> SHIFT OUT + u'\x0f' # 0x000f -> SHIFT IN + u'\x10' # 0x0010 -> DATA LINK ESCAPE + u'\x11' # 0x0011 -> DEVICE CONTROL ONE + u'\x12' # 0x0012 -> DEVICE CONTROL TWO + u'\x13' # 0x0013 -> DEVICE CONTROL THREE + u'\x14' # 0x0014 -> DEVICE CONTROL FOUR + u'\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x0016 -> SYNCHRONOUS IDLE + u'\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x0018 -> CANCEL + u'\x19' # 0x0019 -> END OF MEDIUM + u'\x1a' # 0x001a -> SUBSTITUTE + u'\x1b' # 0x001b -> ESCAPE + u'\x1c' # 0x001c -> FILE SEPARATOR + u'\x1d' # 0x001d -> GROUP SEPARATOR + u'\x1e' # 0x001e -> RECORD SEPARATOR + u'\x1f' # 0x001f -> UNIT SEPARATOR + u' ' # 0x0020 -> SPACE + u'!' # 0x0021 -> EXCLAMATION MARK + u'"' # 0x0022 -> QUOTATION MARK + u'#' # 0x0023 -> NUMBER SIGN + u'$' # 0x0024 -> DOLLAR SIGN + u'%' # 0x0025 -> PERCENT SIGN + u'&' # 0x0026 -> AMPERSAND + u"'" # 0x0027 -> APOSTROPHE + u'(' # 0x0028 -> LEFT PARENTHESIS + u')' # 0x0029 -> RIGHT PARENTHESIS + u'*' # 0x002a -> ASTERISK + u'+' # 0x002b -> PLUS SIGN + u',' # 0x002c -> COMMA + u'-' # 0x002d -> HYPHEN-MINUS + u'.' # 0x002e -> FULL STOP + u'/' # 0x002f -> SOLIDUS + u'0' # 0x0030 -> DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE + u':' # 0x003a -> COLON + u';' # 0x003b -> SEMICOLON + u'<' # 0x003c -> LESS-THAN SIGN + u'=' # 0x003d -> EQUALS SIGN + u'>' # 0x003e -> GREATER-THAN SIGN + u'?' # 0x003f -> QUESTION MARK + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET + u'\\' # 0x005c -> REVERSE SOLIDUS + u']' # 0x005d -> RIGHT SQUARE BRACKET + u'^' # 0x005e -> CIRCUMFLEX ACCENT + u'_' # 0x005f -> LOW LINE + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET + u'|' # 0x007c -> VERTICAL LINE + u'}' # 0x007d -> RIGHT CURLY BRACKET + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> DELETE + u'\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + u'\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe0' # 0x0085 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe5' # 0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xea' # 0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xe8' # 0x008a -> LATIN SMALL LETTER E WITH GRAVE + u'\xef' # 0x008b -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xee' # 0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xec' # 0x008d -> LATIN SMALL LETTER I WITH GRAVE + u'\xc4' # 0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xe6' # 0x0091 -> LATIN SMALL LIGATURE AE + u'\xc6' # 0x0092 -> LATIN CAPITAL LIGATURE AE + u'\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf2' # 0x0095 -> LATIN SMALL LETTER O WITH GRAVE + u'\xfb' # 0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xf9' # 0x0097 -> LATIN SMALL LETTER U WITH GRAVE + u'\xff' # 0x0098 -> LATIN SMALL LETTER Y WITH DIAERESIS + u'\xd6' # 0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xa2' # 0x009b -> CENT SIGN + u'\xa3' # 0x009c -> POUND SIGN + u'\xa5' # 0x009d -> YEN SIGN + u'\u20a7' # 0x009e -> PESETA SIGN + u'\u0192' # 0x009f -> LATIN SMALL LETTER F WITH HOOK + u'\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + u'\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + u'\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + u'\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + u'\xf1' # 0x00a4 -> LATIN SMALL LETTER N WITH TILDE + u'\xd1' # 0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xaa' # 0x00a6 -> FEMININE ORDINAL INDICATOR + u'\xba' # 0x00a7 -> MASCULINE ORDINAL INDICATOR + u'\xbf' # 0x00a8 -> INVERTED QUESTION MARK + u'\u2310' # 0x00a9 -> REVERSED NOT SIGN + u'\xac' # 0x00aa -> NOT SIGN + u'\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + u'\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + u'\xa1' # 0x00ad -> INVERTED EXCLAMATION MARK + u'\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2591' # 0x00b0 -> LIGHT SHADE + u'\u2592' # 0x00b1 -> MEDIUM SHADE + u'\u2593' # 0x00b2 -> DARK SHADE + u'\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + u'\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + u'\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + u'\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + u'\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + u'\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + u'\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + u'\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + u'\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + u'\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + u'\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + u'\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + u'\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + u'\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + u'\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + u'\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + u'\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + u'\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + u'\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0x00db -> FULL BLOCK + u'\u2584' # 0x00dc -> LOWER HALF BLOCK + u'\u258c' # 0x00dd -> LEFT HALF BLOCK + u'\u2590' # 0x00de -> RIGHT HALF BLOCK + u'\u2580' # 0x00df -> UPPER HALF BLOCK + u'\u03b1' # 0x00e0 -> GREEK SMALL LETTER ALPHA + u'\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + u'\u0393' # 0x00e2 -> GREEK CAPITAL LETTER GAMMA + u'\u03c0' # 0x00e3 -> GREEK SMALL LETTER PI + u'\u03a3' # 0x00e4 -> GREEK CAPITAL LETTER SIGMA + u'\u03c3' # 0x00e5 -> GREEK SMALL LETTER SIGMA + u'\xb5' # 0x00e6 -> MICRO SIGN + u'\u03c4' # 0x00e7 -> GREEK SMALL LETTER TAU + u'\u03a6' # 0x00e8 -> GREEK CAPITAL LETTER PHI + u'\u0398' # 0x00e9 -> GREEK CAPITAL LETTER THETA + u'\u03a9' # 0x00ea -> GREEK CAPITAL LETTER OMEGA + u'\u03b4' # 0x00eb -> GREEK SMALL LETTER DELTA + u'\u221e' # 0x00ec -> INFINITY + u'\u03c6' # 0x00ed -> GREEK SMALL LETTER PHI + u'\u03b5' # 0x00ee -> GREEK SMALL LETTER EPSILON + u'\u2229' # 0x00ef -> INTERSECTION + u'\u2261' # 0x00f0 -> IDENTICAL TO + u'\xb1' # 0x00f1 -> PLUS-MINUS SIGN + u'\u2265' # 0x00f2 -> GREATER-THAN OR EQUAL TO + u'\u2264' # 0x00f3 -> LESS-THAN OR EQUAL TO + u'\u2320' # 0x00f4 -> TOP HALF INTEGRAL + u'\u2321' # 0x00f5 -> BOTTOM HALF INTEGRAL + u'\xf7' # 0x00f6 -> DIVISION SIGN + u'\u2248' # 0x00f7 -> ALMOST EQUAL TO + u'\xb0' # 0x00f8 -> DEGREE SIGN + u'\u2219' # 0x00f9 -> BULLET OPERATOR + u'\xb7' # 0x00fa -> MIDDLE DOT + u'\u221a' # 0x00fb -> SQUARE ROOT + u'\u207f' # 0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N + u'\xb2' # 0x00fd -> SUPERSCRIPT TWO + u'\u25a0' # 0x00fe -> BLACK SQUARE + u'\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a1: 0x00ad, # INVERTED EXCLAMATION MARK + 0x00a2: 0x009b, # CENT SIGN + 0x00a3: 0x009c, # POUND SIGN + 0x00a5: 0x009d, # YEN SIGN + 0x00aa: 0x00a6, # FEMININE ORDINAL INDICATOR + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00ba: 0x00a7, # MASCULINE ORDINAL INDICATOR + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00bf: 0x00a8, # INVERTED QUESTION MARK + 0x00c4: 0x008e, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5: 0x008f, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c6: 0x0092, # LATIN CAPITAL LIGATURE AE + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00d1: 0x00a5, # LATIN CAPITAL LETTER N WITH TILDE + 0x00d6: 0x0099, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e0: 0x0085, # LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e4: 0x0084, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e5: 0x0086, # LATIN SMALL LETTER A WITH RING ABOVE + 0x00e6: 0x0091, # LATIN SMALL LIGATURE AE + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008a, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0088, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x0089, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ec: 0x008d, # LATIN SMALL LETTER I WITH GRAVE + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00ee: 0x008c, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ef: 0x008b, # LATIN SMALL LETTER I WITH DIAERESIS + 0x00f1: 0x00a4, # LATIN SMALL LETTER N WITH TILDE + 0x00f2: 0x0095, # LATIN SMALL LETTER O WITH GRAVE + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f6: 0x0094, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f9: 0x0097, # LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x0096, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00ff: 0x0098, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x0192: 0x009f, # LATIN SMALL LETTER F WITH HOOK + 0x0393: 0x00e2, # GREEK CAPITAL LETTER GAMMA + 0x0398: 0x00e9, # GREEK CAPITAL LETTER THETA + 0x03a3: 0x00e4, # GREEK CAPITAL LETTER SIGMA + 0x03a6: 0x00e8, # GREEK CAPITAL LETTER PHI + 0x03a9: 0x00ea, # GREEK CAPITAL LETTER OMEGA + 0x03b1: 0x00e0, # GREEK SMALL LETTER ALPHA + 0x03b4: 0x00eb, # GREEK SMALL LETTER DELTA + 0x03b5: 0x00ee, # GREEK SMALL LETTER EPSILON + 0x03c0: 0x00e3, # GREEK SMALL LETTER PI + 0x03c3: 0x00e5, # GREEK SMALL LETTER SIGMA + 0x03c4: 0x00e7, # GREEK SMALL LETTER TAU + 0x03c6: 0x00ed, # GREEK SMALL LETTER PHI + 0x207f: 0x00fc, # SUPERSCRIPT LATIN SMALL LETTER N + 0x20a7: 0x009e, # PESETA SIGN + 0x2219: 0x00f9, # BULLET OPERATOR + 0x221a: 0x00fb, # SQUARE ROOT + 0x221e: 0x00ec, # INFINITY + 0x2229: 0x00ef, # INTERSECTION + 0x2248: 0x00f7, # ALMOST EQUAL TO + 0x2261: 0x00f0, # IDENTICAL TO + 0x2264: 0x00f3, # LESS-THAN OR EQUAL TO + 0x2265: 0x00f2, # GREATER-THAN OR EQUAL TO + 0x2310: 0x00a9, # REVERSED NOT SIGN + 0x2320: 0x00f4, # TOP HALF INTEGRAL + 0x2321: 0x00f5, # BOTTOM HALF INTEGRAL + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/PythonHome/Lib/encodings/cp437.pyc b/PythonHome/Lib/encodings/cp437.pyc deleted file mode 100644 index b344da6d6638043fc4e313c6bef697700ce6dcd2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7929 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 hX7+5+x@}j?MlC NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x9c' # 0x04 -> CONTROL + u'\t' # 0x05 -> HORIZONTAL TABULATION + u'\x86' # 0x06 -> CONTROL + u'\x7f' # 0x07 -> DELETE + u'\x97' # 0x08 -> CONTROL + u'\x8d' # 0x09 -> CONTROL + u'\x8e' # 0x0A -> CONTROL + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x9d' # 0x14 -> CONTROL + u'\x85' # 0x15 -> CONTROL + u'\x08' # 0x16 -> BACKSPACE + u'\x87' # 0x17 -> CONTROL + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x92' # 0x1A -> CONTROL + u'\x8f' # 0x1B -> CONTROL + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u'\x80' # 0x20 -> CONTROL + u'\x81' # 0x21 -> CONTROL + u'\x82' # 0x22 -> CONTROL + u'\x83' # 0x23 -> CONTROL + u'\x84' # 0x24 -> CONTROL + u'\n' # 0x25 -> LINE FEED + u'\x17' # 0x26 -> END OF TRANSMISSION BLOCK + u'\x1b' # 0x27 -> ESCAPE + u'\x88' # 0x28 -> CONTROL + u'\x89' # 0x29 -> CONTROL + u'\x8a' # 0x2A -> CONTROL + u'\x8b' # 0x2B -> CONTROL + u'\x8c' # 0x2C -> CONTROL + u'\x05' # 0x2D -> ENQUIRY + u'\x06' # 0x2E -> ACKNOWLEDGE + u'\x07' # 0x2F -> BELL + u'\x90' # 0x30 -> CONTROL + u'\x91' # 0x31 -> CONTROL + u'\x16' # 0x32 -> SYNCHRONOUS IDLE + u'\x93' # 0x33 -> CONTROL + u'\x94' # 0x34 -> CONTROL + u'\x95' # 0x35 -> CONTROL + u'\x96' # 0x36 -> CONTROL + u'\x04' # 0x37 -> END OF TRANSMISSION + u'\x98' # 0x38 -> CONTROL + u'\x99' # 0x39 -> CONTROL + u'\x9a' # 0x3A -> CONTROL + u'\x9b' # 0x3B -> CONTROL + u'\x14' # 0x3C -> DEVICE CONTROL FOUR + u'\x15' # 0x3D -> NEGATIVE ACKNOWLEDGE + u'\x9e' # 0x3E -> CONTROL + u'\x1a' # 0x3F -> SUBSTITUTE + u' ' # 0x40 -> SPACE + u'\xa0' # 0x41 -> NO-BREAK SPACE + u'\xe2' # 0x42 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x43 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe0' # 0x44 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe1' # 0x45 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe3' # 0x46 -> LATIN SMALL LETTER A WITH TILDE + u'\xe5' # 0x47 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe7' # 0x48 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xf1' # 0x49 -> LATIN SMALL LETTER N WITH TILDE + u'[' # 0x4A -> LEFT SQUARE BRACKET + u'.' # 0x4B -> FULL STOP + u'<' # 0x4C -> LESS-THAN SIGN + u'(' # 0x4D -> LEFT PARENTHESIS + u'+' # 0x4E -> PLUS SIGN + u'!' # 0x4F -> EXCLAMATION MARK + u'&' # 0x50 -> AMPERSAND + u'\xe9' # 0x51 -> LATIN SMALL LETTER E WITH ACUTE + u'\xea' # 0x52 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x53 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xe8' # 0x54 -> LATIN SMALL LETTER E WITH GRAVE + u'\xed' # 0x55 -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0x56 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0x57 -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xec' # 0x58 -> LATIN SMALL LETTER I WITH GRAVE + u'\xdf' # 0x59 -> LATIN SMALL LETTER SHARP S (GERMAN) + u']' # 0x5A -> RIGHT SQUARE BRACKET + u'$' # 0x5B -> DOLLAR SIGN + u'*' # 0x5C -> ASTERISK + u')' # 0x5D -> RIGHT PARENTHESIS + u';' # 0x5E -> SEMICOLON + u'^' # 0x5F -> CIRCUMFLEX ACCENT + u'-' # 0x60 -> HYPHEN-MINUS + u'/' # 0x61 -> SOLIDUS + u'\xc2' # 0x62 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xc4' # 0x63 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc0' # 0x64 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc1' # 0x65 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc3' # 0x66 -> LATIN CAPITAL LETTER A WITH TILDE + u'\xc5' # 0x67 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc7' # 0x68 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xd1' # 0x69 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xa6' # 0x6A -> BROKEN BAR + u',' # 0x6B -> COMMA + u'%' # 0x6C -> PERCENT SIGN + u'_' # 0x6D -> LOW LINE + u'>' # 0x6E -> GREATER-THAN SIGN + u'?' # 0x6F -> QUESTION MARK + u'\xf8' # 0x70 -> LATIN SMALL LETTER O WITH STROKE + u'\xc9' # 0x71 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xca' # 0x72 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xcb' # 0x73 -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xc8' # 0x74 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xcd' # 0x75 -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0x76 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0x77 -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\xcc' # 0x78 -> LATIN CAPITAL LETTER I WITH GRAVE + u'`' # 0x79 -> GRAVE ACCENT + u':' # 0x7A -> COLON + u'#' # 0x7B -> NUMBER SIGN + u'@' # 0x7C -> COMMERCIAL AT + u"'" # 0x7D -> APOSTROPHE + u'=' # 0x7E -> EQUALS SIGN + u'"' # 0x7F -> QUOTATION MARK + u'\xd8' # 0x80 -> LATIN CAPITAL LETTER O WITH STROKE + u'a' # 0x81 -> LATIN SMALL LETTER A + u'b' # 0x82 -> LATIN SMALL LETTER B + u'c' # 0x83 -> LATIN SMALL LETTER C + u'd' # 0x84 -> LATIN SMALL LETTER D + u'e' # 0x85 -> LATIN SMALL LETTER E + u'f' # 0x86 -> LATIN SMALL LETTER F + u'g' # 0x87 -> LATIN SMALL LETTER G + u'h' # 0x88 -> LATIN SMALL LETTER H + u'i' # 0x89 -> LATIN SMALL LETTER I + u'\xab' # 0x8A -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x8B -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xf0' # 0x8C -> LATIN SMALL LETTER ETH (ICELANDIC) + u'\xfd' # 0x8D -> LATIN SMALL LETTER Y WITH ACUTE + u'\xfe' # 0x8E -> LATIN SMALL LETTER THORN (ICELANDIC) + u'\xb1' # 0x8F -> PLUS-MINUS SIGN + u'\xb0' # 0x90 -> DEGREE SIGN + u'j' # 0x91 -> LATIN SMALL LETTER J + u'k' # 0x92 -> LATIN SMALL LETTER K + u'l' # 0x93 -> LATIN SMALL LETTER L + u'm' # 0x94 -> LATIN SMALL LETTER M + u'n' # 0x95 -> LATIN SMALL LETTER N + u'o' # 0x96 -> LATIN SMALL LETTER O + u'p' # 0x97 -> LATIN SMALL LETTER P + u'q' # 0x98 -> LATIN SMALL LETTER Q + u'r' # 0x99 -> LATIN SMALL LETTER R + u'\xaa' # 0x9A -> FEMININE ORDINAL INDICATOR + u'\xba' # 0x9B -> MASCULINE ORDINAL INDICATOR + u'\xe6' # 0x9C -> LATIN SMALL LIGATURE AE + u'\xb8' # 0x9D -> CEDILLA + u'\xc6' # 0x9E -> LATIN CAPITAL LIGATURE AE + u'\xa4' # 0x9F -> CURRENCY SIGN + u'\xb5' # 0xA0 -> MICRO SIGN + u'~' # 0xA1 -> TILDE + u's' # 0xA2 -> LATIN SMALL LETTER S + u't' # 0xA3 -> LATIN SMALL LETTER T + u'u' # 0xA4 -> LATIN SMALL LETTER U + u'v' # 0xA5 -> LATIN SMALL LETTER V + u'w' # 0xA6 -> LATIN SMALL LETTER W + u'x' # 0xA7 -> LATIN SMALL LETTER X + u'y' # 0xA8 -> LATIN SMALL LETTER Y + u'z' # 0xA9 -> LATIN SMALL LETTER Z + u'\xa1' # 0xAA -> INVERTED EXCLAMATION MARK + u'\xbf' # 0xAB -> INVERTED QUESTION MARK + u'\xd0' # 0xAC -> LATIN CAPITAL LETTER ETH (ICELANDIC) + u'\xdd' # 0xAD -> LATIN CAPITAL LETTER Y WITH ACUTE + u'\xde' # 0xAE -> LATIN CAPITAL LETTER THORN (ICELANDIC) + u'\xae' # 0xAF -> REGISTERED SIGN + u'\xa2' # 0xB0 -> CENT SIGN + u'\xa3' # 0xB1 -> POUND SIGN + u'\xa5' # 0xB2 -> YEN SIGN + u'\xb7' # 0xB3 -> MIDDLE DOT + u'\xa9' # 0xB4 -> COPYRIGHT SIGN + u'\xa7' # 0xB5 -> SECTION SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xbc' # 0xB7 -> VULGAR FRACTION ONE QUARTER + u'\xbd' # 0xB8 -> VULGAR FRACTION ONE HALF + u'\xbe' # 0xB9 -> VULGAR FRACTION THREE QUARTERS + u'\xac' # 0xBA -> NOT SIGN + u'|' # 0xBB -> VERTICAL LINE + u'\xaf' # 0xBC -> MACRON + u'\xa8' # 0xBD -> DIAERESIS + u'\xb4' # 0xBE -> ACUTE ACCENT + u'\xd7' # 0xBF -> MULTIPLICATION SIGN + u'{' # 0xC0 -> LEFT CURLY BRACKET + u'A' # 0xC1 -> LATIN CAPITAL LETTER A + u'B' # 0xC2 -> LATIN CAPITAL LETTER B + u'C' # 0xC3 -> LATIN CAPITAL LETTER C + u'D' # 0xC4 -> LATIN CAPITAL LETTER D + u'E' # 0xC5 -> LATIN CAPITAL LETTER E + u'F' # 0xC6 -> LATIN CAPITAL LETTER F + u'G' # 0xC7 -> LATIN CAPITAL LETTER G + u'H' # 0xC8 -> LATIN CAPITAL LETTER H + u'I' # 0xC9 -> LATIN CAPITAL LETTER I + u'\xad' # 0xCA -> SOFT HYPHEN + u'\xf4' # 0xCB -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0xCC -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf2' # 0xCD -> LATIN SMALL LETTER O WITH GRAVE + u'\xf3' # 0xCE -> LATIN SMALL LETTER O WITH ACUTE + u'\xf5' # 0xCF -> LATIN SMALL LETTER O WITH TILDE + u'}' # 0xD0 -> RIGHT CURLY BRACKET + u'J' # 0xD1 -> LATIN CAPITAL LETTER J + u'K' # 0xD2 -> LATIN CAPITAL LETTER K + u'L' # 0xD3 -> LATIN CAPITAL LETTER L + u'M' # 0xD4 -> LATIN CAPITAL LETTER M + u'N' # 0xD5 -> LATIN CAPITAL LETTER N + u'O' # 0xD6 -> LATIN CAPITAL LETTER O + u'P' # 0xD7 -> LATIN CAPITAL LETTER P + u'Q' # 0xD8 -> LATIN CAPITAL LETTER Q + u'R' # 0xD9 -> LATIN CAPITAL LETTER R + u'\xb9' # 0xDA -> SUPERSCRIPT ONE + u'\xfb' # 0xDB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0xDC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xf9' # 0xDD -> LATIN SMALL LETTER U WITH GRAVE + u'\xfa' # 0xDE -> LATIN SMALL LETTER U WITH ACUTE + u'\xff' # 0xDF -> LATIN SMALL LETTER Y WITH DIAERESIS + u'\\' # 0xE0 -> REVERSE SOLIDUS + u'\xf7' # 0xE1 -> DIVISION SIGN + u'S' # 0xE2 -> LATIN CAPITAL LETTER S + u'T' # 0xE3 -> LATIN CAPITAL LETTER T + u'U' # 0xE4 -> LATIN CAPITAL LETTER U + u'V' # 0xE5 -> LATIN CAPITAL LETTER V + u'W' # 0xE6 -> LATIN CAPITAL LETTER W + u'X' # 0xE7 -> LATIN CAPITAL LETTER X + u'Y' # 0xE8 -> LATIN CAPITAL LETTER Y + u'Z' # 0xE9 -> LATIN CAPITAL LETTER Z + u'\xb2' # 0xEA -> SUPERSCRIPT TWO + u'\xd4' # 0xEB -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\xd6' # 0xEC -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xd2' # 0xED -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd5' # 0xEF -> LATIN CAPITAL LETTER O WITH TILDE + u'0' # 0xF0 -> DIGIT ZERO + u'1' # 0xF1 -> DIGIT ONE + u'2' # 0xF2 -> DIGIT TWO + u'3' # 0xF3 -> DIGIT THREE + u'4' # 0xF4 -> DIGIT FOUR + u'5' # 0xF5 -> DIGIT FIVE + u'6' # 0xF6 -> DIGIT SIX + u'7' # 0xF7 -> DIGIT SEVEN + u'8' # 0xF8 -> DIGIT EIGHT + u'9' # 0xF9 -> DIGIT NINE + u'\xb3' # 0xFA -> SUPERSCRIPT THREE + u'\xdb' # 0xFB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xdc' # 0xFC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xd9' # 0xFD -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xda' # 0xFE -> LATIN CAPITAL LETTER U WITH ACUTE + u'\x9f' # 0xFF -> CONTROL +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp500.pyc b/PythonHome/Lib/encodings/cp500.pyc deleted file mode 100644 index 8f4731c87aef7a6079d58258fe09ef7f407f01c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2694 zcmc&$2X`Aq5MEWwic30CVnCr;G&__~LvW%v!4NCvWa7jal(X(+%cyZW6AXbkvD16+ zz4vaX=e?Pq#19BFdy&pDJU_yFJS6XWZs&G(=9_P4>>R;SQBQsI&cZ&BeAT8UJ+rNUQKxP?|K zbf?sLM1lPoYmCS5SbUP zU05HPvp|W~Ha3K#bDL}HXNTuBglof1w5g_fQFC>0Y0~WE?QynNlk2JR`;(996EQt> zx;&$Ztdmw|vtvP;bc%owl;HN0;}k#1PQkKEDA5q-!SwR$rjd-Baen6ErV-}laWt7i zbUDN_`g01?Df(O#yMxvv_IBx6-mIY2IDwE>b1}|P1Q@}j5w{zPmwy~>CvJNT^&u>bm6T372e6T zYIB6hLNswPP3TGoq9HaLNzx=_q!Ma{NhYCF*gHuH8&k=NL^7kM?0`p(l@a3ThC-^8 z@fqbbNqckER9=@*+D88Yikzr11dIRJc0Xk&X->b88}v zzlTp5O{!<-AEP#*V3d&KbVN-8!E#!{yk19>b!)87M?H^=D_tMDIPQW>4a~#*)x2D% zsmqzvk$hY(`b0@I#1x2_e1*7jNS@2$XqOC0*ra{wt+H$kU$&}}A(KSCfRaRmP#UtZ zRAx;cX_ZSpTsEJEOd>1GjeV@b_eNm~D2#-{*?5-pnM}zJojjqwXBs_I=`qhd6pm7d z*HK1aul#oRGJPCQ7aS~w)yrWIY=X_B%E~J$M~@jh4i3R8AFP=afbFoQ>iHL5gkD$y zE1?hi{m)H-wXhD>!v@&s@s_|=*ftS%z)si&yWOxC_Q8HQFn$6Yo*aaucpOjSQ9Onx z@D!fGYv0z)2)#M=H9Uvs@dBR3OL!Tt;6*(0-79ar{^|E`*Wya-$6j24eYgtO;5In@ z)~m6ZpW|&@hwE_zuEkBb8MolZC7--pSN+*bxL0kDYkH!iGYJ>q9$v)<_z z=}b2FqXFmPE}n+lxEfBvt>5!z_fJcI?)e3d!6V#?hww05hU0JoPQf6YgEKGy_u&CN zgp14I3Y>+TxaZed^wXk#?z}G=;1b@%0lbbk@YZi%el@=_vY_c}1@7QIypMPAEEOF5?xjYwsF|>ClQ<~KeXmto(M!e{Fa diff --git a/PythonHome/Lib/encodings/cp720.py b/PythonHome/Lib/encodings/cp720.py new file mode 100644 index 0000000000..5c96d9813c --- /dev/null +++ b/PythonHome/Lib/encodings/cp720.py @@ -0,0 +1,309 @@ +"""Python Character Mapping Codec cp720 generated on Windows: +Vista 6.0.6002 SP2 Multiprocessor Free with the command: + python Tools/unicode/genwincodec.py 720 +"""#" + + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp720', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> CONTROL CHARACTER + u'\x01' # 0x01 -> CONTROL CHARACTER + u'\x02' # 0x02 -> CONTROL CHARACTER + u'\x03' # 0x03 -> CONTROL CHARACTER + u'\x04' # 0x04 -> CONTROL CHARACTER + u'\x05' # 0x05 -> CONTROL CHARACTER + u'\x06' # 0x06 -> CONTROL CHARACTER + u'\x07' # 0x07 -> CONTROL CHARACTER + u'\x08' # 0x08 -> CONTROL CHARACTER + u'\t' # 0x09 -> CONTROL CHARACTER + u'\n' # 0x0A -> CONTROL CHARACTER + u'\x0b' # 0x0B -> CONTROL CHARACTER + u'\x0c' # 0x0C -> CONTROL CHARACTER + u'\r' # 0x0D -> CONTROL CHARACTER + u'\x0e' # 0x0E -> CONTROL CHARACTER + u'\x0f' # 0x0F -> CONTROL CHARACTER + u'\x10' # 0x10 -> CONTROL CHARACTER + u'\x11' # 0x11 -> CONTROL CHARACTER + u'\x12' # 0x12 -> CONTROL CHARACTER + u'\x13' # 0x13 -> CONTROL CHARACTER + u'\x14' # 0x14 -> CONTROL CHARACTER + u'\x15' # 0x15 -> CONTROL CHARACTER + u'\x16' # 0x16 -> CONTROL CHARACTER + u'\x17' # 0x17 -> CONTROL CHARACTER + u'\x18' # 0x18 -> CONTROL CHARACTER + u'\x19' # 0x19 -> CONTROL CHARACTER + u'\x1a' # 0x1A -> CONTROL CHARACTER + u'\x1b' # 0x1B -> CONTROL CHARACTER + u'\x1c' # 0x1C -> CONTROL CHARACTER + u'\x1d' # 0x1D -> CONTROL CHARACTER + u'\x1e' # 0x1E -> CONTROL CHARACTER + u'\x1f' # 0x1F -> CONTROL CHARACTER + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> CONTROL CHARACTER + u'\x80' + u'\x81' + u'\xe9' # 0x82 -> LATIN SMALL LETTER E WITH ACUTE + u'\xe2' # 0x83 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\x84' + u'\xe0' # 0x85 -> LATIN SMALL LETTER A WITH GRAVE + u'\x86' + u'\xe7' # 0x87 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xea' # 0x88 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x89 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xe8' # 0x8A -> LATIN SMALL LETTER E WITH GRAVE + u'\xef' # 0x8B -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xee' # 0x8C -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\x8d' + u'\x8e' + u'\x8f' + u'\x90' + u'\u0651' # 0x91 -> ARABIC SHADDA + u'\u0652' # 0x92 -> ARABIC SUKUN + u'\xf4' # 0x93 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xa4' # 0x94 -> CURRENCY SIGN + u'\u0640' # 0x95 -> ARABIC TATWEEL + u'\xfb' # 0x96 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xf9' # 0x97 -> LATIN SMALL LETTER U WITH GRAVE + u'\u0621' # 0x98 -> ARABIC LETTER HAMZA + u'\u0622' # 0x99 -> ARABIC LETTER ALEF WITH MADDA ABOVE + u'\u0623' # 0x9A -> ARABIC LETTER ALEF WITH HAMZA ABOVE + u'\u0624' # 0x9B -> ARABIC LETTER WAW WITH HAMZA ABOVE + u'\xa3' # 0x9C -> POUND SIGN + u'\u0625' # 0x9D -> ARABIC LETTER ALEF WITH HAMZA BELOW + u'\u0626' # 0x9E -> ARABIC LETTER YEH WITH HAMZA ABOVE + u'\u0627' # 0x9F -> ARABIC LETTER ALEF + u'\u0628' # 0xA0 -> ARABIC LETTER BEH + u'\u0629' # 0xA1 -> ARABIC LETTER TEH MARBUTA + u'\u062a' # 0xA2 -> ARABIC LETTER TEH + u'\u062b' # 0xA3 -> ARABIC LETTER THEH + u'\u062c' # 0xA4 -> ARABIC LETTER JEEM + u'\u062d' # 0xA5 -> ARABIC LETTER HAH + u'\u062e' # 0xA6 -> ARABIC LETTER KHAH + u'\u062f' # 0xA7 -> ARABIC LETTER DAL + u'\u0630' # 0xA8 -> ARABIC LETTER THAL + u'\u0631' # 0xA9 -> ARABIC LETTER REH + u'\u0632' # 0xAA -> ARABIC LETTER ZAIN + u'\u0633' # 0xAB -> ARABIC LETTER SEEN + u'\u0634' # 0xAC -> ARABIC LETTER SHEEN + u'\u0635' # 0xAD -> ARABIC LETTER SAD + u'\xab' # 0xAE -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0xAF -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2591' # 0xB0 -> LIGHT SHADE + u'\u2592' # 0xB1 -> MEDIUM SHADE + u'\u2593' # 0xB2 -> DARK SHADE + u'\u2502' # 0xB3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0xB4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\u2561' # 0xB5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + u'\u2562' # 0xB6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + u'\u2556' # 0xB7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + u'\u2555' # 0xB8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + u'\u2563' # 0xB9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0xBA -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0xBB -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0xBC -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\u255c' # 0xBD -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + u'\u255b' # 0xBE -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + u'\u2510' # 0xBF -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0xC0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0xC1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0xC2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0xC3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0xC4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0xC5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\u255e' # 0xC6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + u'\u255f' # 0xC7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + u'\u255a' # 0xC8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0xC9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0xCA -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0xCB -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0xCC -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0xCD -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0xCE -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\u2567' # 0xCF -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + u'\u2568' # 0xD0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + u'\u2564' # 0xD1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + u'\u2565' # 0xD2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + u'\u2559' # 0xD3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + u'\u2558' # 0xD4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + u'\u2552' # 0xD5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + u'\u2553' # 0xD6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + u'\u256b' # 0xD7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + u'\u256a' # 0xD8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + u'\u2518' # 0xD9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0xDA -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0xDB -> FULL BLOCK + u'\u2584' # 0xDC -> LOWER HALF BLOCK + u'\u258c' # 0xDD -> LEFT HALF BLOCK + u'\u2590' # 0xDE -> RIGHT HALF BLOCK + u'\u2580' # 0xDF -> UPPER HALF BLOCK + u'\u0636' # 0xE0 -> ARABIC LETTER DAD + u'\u0637' # 0xE1 -> ARABIC LETTER TAH + u'\u0638' # 0xE2 -> ARABIC LETTER ZAH + u'\u0639' # 0xE3 -> ARABIC LETTER AIN + u'\u063a' # 0xE4 -> ARABIC LETTER GHAIN + u'\u0641' # 0xE5 -> ARABIC LETTER FEH + u'\xb5' # 0xE6 -> MICRO SIGN + u'\u0642' # 0xE7 -> ARABIC LETTER QAF + u'\u0643' # 0xE8 -> ARABIC LETTER KAF + u'\u0644' # 0xE9 -> ARABIC LETTER LAM + u'\u0645' # 0xEA -> ARABIC LETTER MEEM + u'\u0646' # 0xEB -> ARABIC LETTER NOON + u'\u0647' # 0xEC -> ARABIC LETTER HEH + u'\u0648' # 0xED -> ARABIC LETTER WAW + u'\u0649' # 0xEE -> ARABIC LETTER ALEF MAKSURA + u'\u064a' # 0xEF -> ARABIC LETTER YEH + u'\u2261' # 0xF0 -> IDENTICAL TO + u'\u064b' # 0xF1 -> ARABIC FATHATAN + u'\u064c' # 0xF2 -> ARABIC DAMMATAN + u'\u064d' # 0xF3 -> ARABIC KASRATAN + u'\u064e' # 0xF4 -> ARABIC FATHA + u'\u064f' # 0xF5 -> ARABIC DAMMA + u'\u0650' # 0xF6 -> ARABIC KASRA + u'\u2248' # 0xF7 -> ALMOST EQUAL TO + u'\xb0' # 0xF8 -> DEGREE SIGN + u'\u2219' # 0xF9 -> BULLET OPERATOR + u'\xb7' # 0xFA -> MIDDLE DOT + u'\u221a' # 0xFB -> SQUARE ROOT + u'\u207f' # 0xFC -> SUPERSCRIPT LATIN SMALL LETTER N + u'\xb2' # 0xFD -> SUPERSCRIPT TWO + u'\u25a0' # 0xFE -> BLACK SQUARE + u'\xa0' # 0xFF -> NO-BREAK SPACE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp720.pyc b/PythonHome/Lib/encodings/cp720.pyc deleted file mode 100644 index b1a08b17377aad51467ab5764764833958d749cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2791 zcmc&$dvg>;5TASIawNPJ0*I^lIA0+~1w}+8fT9p_4~fL+vDw`ui+6kH?w&D<8c4*T zJOb>TfQTWy2?8Py5v#1)`x3kV&R6gQVD~I{3uvXpD$BdAuJx^~o!3 z8`Cnm`H8^)rSOj=Q1_>D;WJ7zHC^4>xa7DbT zh!CZQE23PHs4AjFsU>Qd>tdt}4oFsYF``VU=;B;gSJlOdQje4N8lp@j?FoJWoRlB~ z;9wFxO{XSd0Eb~%+h_IUb)lt4G9=kj4PlK`C}?`O(2`eFS&$10o127gRaXtkQWXJS zZPRom-)k;PuGdUU5*9QzH7;msY8KLKn}s#Stfdur`3vqquifr62h>u3}X;r zP$5_Vo9AH=Vg#r_4il6kL`$mvMEG1!(W(KVKNW_ zm_o4L8f@pjnbt&Dl>xAvRLH2@VZOvgfG%T6omti2g%(UT+r>lB^g_|%eyE0#H_Q|$ z2_MXvAT@TZ);c>Xr}Oh&pis41pakjSG$l?-Sf);`#A# zUBsFS!YW-h)SRkYQg#JL&X8f1f2!1(4pW~xaLW`D&;_&pS9oW^YQPa73(zEjG=baS zkWS&Ttr`r3N6MiVkz^b?5xwJ-2r%WG=+bm48w5OltcVbLeJiA59oj%*@bgwmSySau z28aFw6p_++3HZtJ(481A=QR0$Fs#M+kbWZaUojUN+|eKtIm#0BO> zRZ{+Q^T?UGf%$5%n3fh?UkZbNYy2h&?GcMBTpzeN(TWVcE{6P7;#jAlAzIM95?C$< zNKHD06lk^Z3Ss5oJmflv&^#)a-Y?6>oy&ezGI)}p7eJEW0hDf8=;c}CCjD}W z#(DEurFZ3dxe3gQcyC0cfQU$ln2ozhpM{j{R>2c!ewNWU52hyakc4VO@lYLn3(&Q;qr%k`--Wf9+X3d^+-`x9!2OgaF(8G^BntJTV{w1<`UveG_gZ)Nr|MvpK$%4msE%IHx>_b~b` zqu(=nh|%wuJ~Tg9FuI@7y^QW-bd1q6%-+xJ9jr9ON`tHf!Z0iKyI0(+?l0~&_g8O=bJ^SK4S0jz zm) NULL + u'\x01' # 0x0001 -> START OF HEADING + u'\x02' # 0x0002 -> START OF TEXT + u'\x03' # 0x0003 -> END OF TEXT + u'\x04' # 0x0004 -> END OF TRANSMISSION + u'\x05' # 0x0005 -> ENQUIRY + u'\x06' # 0x0006 -> ACKNOWLEDGE + u'\x07' # 0x0007 -> BELL + u'\x08' # 0x0008 -> BACKSPACE + u'\t' # 0x0009 -> HORIZONTAL TABULATION + u'\n' # 0x000a -> LINE FEED + u'\x0b' # 0x000b -> VERTICAL TABULATION + u'\x0c' # 0x000c -> FORM FEED + u'\r' # 0x000d -> CARRIAGE RETURN + u'\x0e' # 0x000e -> SHIFT OUT + u'\x0f' # 0x000f -> SHIFT IN + u'\x10' # 0x0010 -> DATA LINK ESCAPE + u'\x11' # 0x0011 -> DEVICE CONTROL ONE + u'\x12' # 0x0012 -> DEVICE CONTROL TWO + u'\x13' # 0x0013 -> DEVICE CONTROL THREE + u'\x14' # 0x0014 -> DEVICE CONTROL FOUR + u'\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x0016 -> SYNCHRONOUS IDLE + u'\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x0018 -> CANCEL + u'\x19' # 0x0019 -> END OF MEDIUM + u'\x1a' # 0x001a -> SUBSTITUTE + u'\x1b' # 0x001b -> ESCAPE + u'\x1c' # 0x001c -> FILE SEPARATOR + u'\x1d' # 0x001d -> GROUP SEPARATOR + u'\x1e' # 0x001e -> RECORD SEPARATOR + u'\x1f' # 0x001f -> UNIT SEPARATOR + u' ' # 0x0020 -> SPACE + u'!' # 0x0021 -> EXCLAMATION MARK + u'"' # 0x0022 -> QUOTATION MARK + u'#' # 0x0023 -> NUMBER SIGN + u'$' # 0x0024 -> DOLLAR SIGN + u'%' # 0x0025 -> PERCENT SIGN + u'&' # 0x0026 -> AMPERSAND + u"'" # 0x0027 -> APOSTROPHE + u'(' # 0x0028 -> LEFT PARENTHESIS + u')' # 0x0029 -> RIGHT PARENTHESIS + u'*' # 0x002a -> ASTERISK + u'+' # 0x002b -> PLUS SIGN + u',' # 0x002c -> COMMA + u'-' # 0x002d -> HYPHEN-MINUS + u'.' # 0x002e -> FULL STOP + u'/' # 0x002f -> SOLIDUS + u'0' # 0x0030 -> DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE + u':' # 0x003a -> COLON + u';' # 0x003b -> SEMICOLON + u'<' # 0x003c -> LESS-THAN SIGN + u'=' # 0x003d -> EQUALS SIGN + u'>' # 0x003e -> GREATER-THAN SIGN + u'?' # 0x003f -> QUESTION MARK + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET + u'\\' # 0x005c -> REVERSE SOLIDUS + u']' # 0x005d -> RIGHT SQUARE BRACKET + u'^' # 0x005e -> CIRCUMFLEX ACCENT + u'_' # 0x005f -> LOW LINE + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET + u'|' # 0x007c -> VERTICAL LINE + u'}' # 0x007d -> RIGHT CURLY BRACKET + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> DELETE + u'\u0391' # 0x0080 -> GREEK CAPITAL LETTER ALPHA + u'\u0392' # 0x0081 -> GREEK CAPITAL LETTER BETA + u'\u0393' # 0x0082 -> GREEK CAPITAL LETTER GAMMA + u'\u0394' # 0x0083 -> GREEK CAPITAL LETTER DELTA + u'\u0395' # 0x0084 -> GREEK CAPITAL LETTER EPSILON + u'\u0396' # 0x0085 -> GREEK CAPITAL LETTER ZETA + u'\u0397' # 0x0086 -> GREEK CAPITAL LETTER ETA + u'\u0398' # 0x0087 -> GREEK CAPITAL LETTER THETA + u'\u0399' # 0x0088 -> GREEK CAPITAL LETTER IOTA + u'\u039a' # 0x0089 -> GREEK CAPITAL LETTER KAPPA + u'\u039b' # 0x008a -> GREEK CAPITAL LETTER LAMDA + u'\u039c' # 0x008b -> GREEK CAPITAL LETTER MU + u'\u039d' # 0x008c -> GREEK CAPITAL LETTER NU + u'\u039e' # 0x008d -> GREEK CAPITAL LETTER XI + u'\u039f' # 0x008e -> GREEK CAPITAL LETTER OMICRON + u'\u03a0' # 0x008f -> GREEK CAPITAL LETTER PI + u'\u03a1' # 0x0090 -> GREEK CAPITAL LETTER RHO + u'\u03a3' # 0x0091 -> GREEK CAPITAL LETTER SIGMA + u'\u03a4' # 0x0092 -> GREEK CAPITAL LETTER TAU + u'\u03a5' # 0x0093 -> GREEK CAPITAL LETTER UPSILON + u'\u03a6' # 0x0094 -> GREEK CAPITAL LETTER PHI + u'\u03a7' # 0x0095 -> GREEK CAPITAL LETTER CHI + u'\u03a8' # 0x0096 -> GREEK CAPITAL LETTER PSI + u'\u03a9' # 0x0097 -> GREEK CAPITAL LETTER OMEGA + u'\u03b1' # 0x0098 -> GREEK SMALL LETTER ALPHA + u'\u03b2' # 0x0099 -> GREEK SMALL LETTER BETA + u'\u03b3' # 0x009a -> GREEK SMALL LETTER GAMMA + u'\u03b4' # 0x009b -> GREEK SMALL LETTER DELTA + u'\u03b5' # 0x009c -> GREEK SMALL LETTER EPSILON + u'\u03b6' # 0x009d -> GREEK SMALL LETTER ZETA + u'\u03b7' # 0x009e -> GREEK SMALL LETTER ETA + u'\u03b8' # 0x009f -> GREEK SMALL LETTER THETA + u'\u03b9' # 0x00a0 -> GREEK SMALL LETTER IOTA + u'\u03ba' # 0x00a1 -> GREEK SMALL LETTER KAPPA + u'\u03bb' # 0x00a2 -> GREEK SMALL LETTER LAMDA + u'\u03bc' # 0x00a3 -> GREEK SMALL LETTER MU + u'\u03bd' # 0x00a4 -> GREEK SMALL LETTER NU + u'\u03be' # 0x00a5 -> GREEK SMALL LETTER XI + u'\u03bf' # 0x00a6 -> GREEK SMALL LETTER OMICRON + u'\u03c0' # 0x00a7 -> GREEK SMALL LETTER PI + u'\u03c1' # 0x00a8 -> GREEK SMALL LETTER RHO + u'\u03c3' # 0x00a9 -> GREEK SMALL LETTER SIGMA + u'\u03c2' # 0x00aa -> GREEK SMALL LETTER FINAL SIGMA + u'\u03c4' # 0x00ab -> GREEK SMALL LETTER TAU + u'\u03c5' # 0x00ac -> GREEK SMALL LETTER UPSILON + u'\u03c6' # 0x00ad -> GREEK SMALL LETTER PHI + u'\u03c7' # 0x00ae -> GREEK SMALL LETTER CHI + u'\u03c8' # 0x00af -> GREEK SMALL LETTER PSI + u'\u2591' # 0x00b0 -> LIGHT SHADE + u'\u2592' # 0x00b1 -> MEDIUM SHADE + u'\u2593' # 0x00b2 -> DARK SHADE + u'\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + u'\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + u'\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + u'\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + u'\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + u'\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + u'\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + u'\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + u'\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + u'\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + u'\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + u'\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + u'\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + u'\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + u'\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + u'\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + u'\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + u'\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + u'\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0x00db -> FULL BLOCK + u'\u2584' # 0x00dc -> LOWER HALF BLOCK + u'\u258c' # 0x00dd -> LEFT HALF BLOCK + u'\u2590' # 0x00de -> RIGHT HALF BLOCK + u'\u2580' # 0x00df -> UPPER HALF BLOCK + u'\u03c9' # 0x00e0 -> GREEK SMALL LETTER OMEGA + u'\u03ac' # 0x00e1 -> GREEK SMALL LETTER ALPHA WITH TONOS + u'\u03ad' # 0x00e2 -> GREEK SMALL LETTER EPSILON WITH TONOS + u'\u03ae' # 0x00e3 -> GREEK SMALL LETTER ETA WITH TONOS + u'\u03ca' # 0x00e4 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA + u'\u03af' # 0x00e5 -> GREEK SMALL LETTER IOTA WITH TONOS + u'\u03cc' # 0x00e6 -> GREEK SMALL LETTER OMICRON WITH TONOS + u'\u03cd' # 0x00e7 -> GREEK SMALL LETTER UPSILON WITH TONOS + u'\u03cb' # 0x00e8 -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA + u'\u03ce' # 0x00e9 -> GREEK SMALL LETTER OMEGA WITH TONOS + u'\u0386' # 0x00ea -> GREEK CAPITAL LETTER ALPHA WITH TONOS + u'\u0388' # 0x00eb -> GREEK CAPITAL LETTER EPSILON WITH TONOS + u'\u0389' # 0x00ec -> GREEK CAPITAL LETTER ETA WITH TONOS + u'\u038a' # 0x00ed -> GREEK CAPITAL LETTER IOTA WITH TONOS + u'\u038c' # 0x00ee -> GREEK CAPITAL LETTER OMICRON WITH TONOS + u'\u038e' # 0x00ef -> GREEK CAPITAL LETTER UPSILON WITH TONOS + u'\u038f' # 0x00f0 -> GREEK CAPITAL LETTER OMEGA WITH TONOS + u'\xb1' # 0x00f1 -> PLUS-MINUS SIGN + u'\u2265' # 0x00f2 -> GREATER-THAN OR EQUAL TO + u'\u2264' # 0x00f3 -> LESS-THAN OR EQUAL TO + u'\u03aa' # 0x00f4 -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + u'\u03ab' # 0x00f5 -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + u'\xf7' # 0x00f6 -> DIVISION SIGN + u'\u2248' # 0x00f7 -> ALMOST EQUAL TO + u'\xb0' # 0x00f8 -> DEGREE SIGN + u'\u2219' # 0x00f9 -> BULLET OPERATOR + u'\xb7' # 0x00fa -> MIDDLE DOT + u'\u221a' # 0x00fb -> SQUARE ROOT + u'\u207f' # 0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N + u'\xb2' # 0x00fd -> SUPERSCRIPT TWO + u'\u25a0' # 0x00fe -> BLACK SQUARE + u'\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00f7: 0x00f6, # DIVISION SIGN + 0x0386: 0x00ea, # GREEK CAPITAL LETTER ALPHA WITH TONOS + 0x0388: 0x00eb, # GREEK CAPITAL LETTER EPSILON WITH TONOS + 0x0389: 0x00ec, # GREEK CAPITAL LETTER ETA WITH TONOS + 0x038a: 0x00ed, # GREEK CAPITAL LETTER IOTA WITH TONOS + 0x038c: 0x00ee, # GREEK CAPITAL LETTER OMICRON WITH TONOS + 0x038e: 0x00ef, # GREEK CAPITAL LETTER UPSILON WITH TONOS + 0x038f: 0x00f0, # GREEK CAPITAL LETTER OMEGA WITH TONOS + 0x0391: 0x0080, # GREEK CAPITAL LETTER ALPHA + 0x0392: 0x0081, # GREEK CAPITAL LETTER BETA + 0x0393: 0x0082, # GREEK CAPITAL LETTER GAMMA + 0x0394: 0x0083, # GREEK CAPITAL LETTER DELTA + 0x0395: 0x0084, # GREEK CAPITAL LETTER EPSILON + 0x0396: 0x0085, # GREEK CAPITAL LETTER ZETA + 0x0397: 0x0086, # GREEK CAPITAL LETTER ETA + 0x0398: 0x0087, # GREEK CAPITAL LETTER THETA + 0x0399: 0x0088, # GREEK CAPITAL LETTER IOTA + 0x039a: 0x0089, # GREEK CAPITAL LETTER KAPPA + 0x039b: 0x008a, # GREEK CAPITAL LETTER LAMDA + 0x039c: 0x008b, # GREEK CAPITAL LETTER MU + 0x039d: 0x008c, # GREEK CAPITAL LETTER NU + 0x039e: 0x008d, # GREEK CAPITAL LETTER XI + 0x039f: 0x008e, # GREEK CAPITAL LETTER OMICRON + 0x03a0: 0x008f, # GREEK CAPITAL LETTER PI + 0x03a1: 0x0090, # GREEK CAPITAL LETTER RHO + 0x03a3: 0x0091, # GREEK CAPITAL LETTER SIGMA + 0x03a4: 0x0092, # GREEK CAPITAL LETTER TAU + 0x03a5: 0x0093, # GREEK CAPITAL LETTER UPSILON + 0x03a6: 0x0094, # GREEK CAPITAL LETTER PHI + 0x03a7: 0x0095, # GREEK CAPITAL LETTER CHI + 0x03a8: 0x0096, # GREEK CAPITAL LETTER PSI + 0x03a9: 0x0097, # GREEK CAPITAL LETTER OMEGA + 0x03aa: 0x00f4, # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + 0x03ab: 0x00f5, # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + 0x03ac: 0x00e1, # GREEK SMALL LETTER ALPHA WITH TONOS + 0x03ad: 0x00e2, # GREEK SMALL LETTER EPSILON WITH TONOS + 0x03ae: 0x00e3, # GREEK SMALL LETTER ETA WITH TONOS + 0x03af: 0x00e5, # GREEK SMALL LETTER IOTA WITH TONOS + 0x03b1: 0x0098, # GREEK SMALL LETTER ALPHA + 0x03b2: 0x0099, # GREEK SMALL LETTER BETA + 0x03b3: 0x009a, # GREEK SMALL LETTER GAMMA + 0x03b4: 0x009b, # GREEK SMALL LETTER DELTA + 0x03b5: 0x009c, # GREEK SMALL LETTER EPSILON + 0x03b6: 0x009d, # GREEK SMALL LETTER ZETA + 0x03b7: 0x009e, # GREEK SMALL LETTER ETA + 0x03b8: 0x009f, # GREEK SMALL LETTER THETA + 0x03b9: 0x00a0, # GREEK SMALL LETTER IOTA + 0x03ba: 0x00a1, # GREEK SMALL LETTER KAPPA + 0x03bb: 0x00a2, # GREEK SMALL LETTER LAMDA + 0x03bc: 0x00a3, # GREEK SMALL LETTER MU + 0x03bd: 0x00a4, # GREEK SMALL LETTER NU + 0x03be: 0x00a5, # GREEK SMALL LETTER XI + 0x03bf: 0x00a6, # GREEK SMALL LETTER OMICRON + 0x03c0: 0x00a7, # GREEK SMALL LETTER PI + 0x03c1: 0x00a8, # GREEK SMALL LETTER RHO + 0x03c2: 0x00aa, # GREEK SMALL LETTER FINAL SIGMA + 0x03c3: 0x00a9, # GREEK SMALL LETTER SIGMA + 0x03c4: 0x00ab, # GREEK SMALL LETTER TAU + 0x03c5: 0x00ac, # GREEK SMALL LETTER UPSILON + 0x03c6: 0x00ad, # GREEK SMALL LETTER PHI + 0x03c7: 0x00ae, # GREEK SMALL LETTER CHI + 0x03c8: 0x00af, # GREEK SMALL LETTER PSI + 0x03c9: 0x00e0, # GREEK SMALL LETTER OMEGA + 0x03ca: 0x00e4, # GREEK SMALL LETTER IOTA WITH DIALYTIKA + 0x03cb: 0x00e8, # GREEK SMALL LETTER UPSILON WITH DIALYTIKA + 0x03cc: 0x00e6, # GREEK SMALL LETTER OMICRON WITH TONOS + 0x03cd: 0x00e7, # GREEK SMALL LETTER UPSILON WITH TONOS + 0x03ce: 0x00e9, # GREEK SMALL LETTER OMEGA WITH TONOS + 0x207f: 0x00fc, # SUPERSCRIPT LATIN SMALL LETTER N + 0x2219: 0x00f9, # BULLET OPERATOR + 0x221a: 0x00fb, # SQUARE ROOT + 0x2248: 0x00f7, # ALMOST EQUAL TO + 0x2264: 0x00f3, # LESS-THAN OR EQUAL TO + 0x2265: 0x00f2, # GREATER-THAN OR EQUAL TO + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/PythonHome/Lib/encodings/cp737.pyc b/PythonHome/Lib/encodings/cp737.pyc deleted file mode 100644 index a04c4d97ca10d36f91b92a57819886b156cbb183..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8157 zcmd^@cX*U#y2hV3385<@Dj;g?*ueVQP!SNtf;d6Ih=!17fWZ(j8C0w&h=8b+Oaw$l z1uOP~y|?$!v7h-MVzBxC!~y095(k+dOdMh!i9^i~ zBMvt|f;iHA2yvA8(Zn(4Ly2R}hY`cgM-a!Ek0g#aKYBKqa z4a5xdMq;M{MbAteq#O(@l*4k5kEKo z1@TMsUlG4H{|)h5^WPD_H~$0CWd1JkNAvfHKbgNz{Mr03#9z(-M*Q9U1L8x2A|JZ{ zgZQWUN5rKJg%CXiFC)r>R}e+EKT#RHGcm@zONea8;9Wya4=VuOr0CrPiryoj=sg39 zzC}RMw+twHuYlOL0Y&c}5W6>^=zRiW69*K1+kn{10Y&c{5L-H+==}p?X9pC0KtOEp zfTHgh5c@o!=v4u+-2;lgOF-=UfTHgf5Su@s=z9dj3;xz0*bzWK#Yliq8}I#(;}eg2M5H^2q=0Ch}jWP^uq#Tgaj1*h=7{TnQ-p(0~{(0Yx7c5K|_g=pzDR*aQ@PWI)WEfTEue5Thrc=qCom1PUnn z$pJBl0*XF5Am&j(eEI<~mI8{N3yA3yQ1r0@F{A>DJ}w|;RY1`v1jNV+D0)pmOs;^U zPYj3w7EtuF17eN^6n#=ajI)5EPY#Hw7Ep8#h~XAc^eF)`;{u94Eg(i+K+&fM#Ka3I zdP6`AzJQ`P2E_aei0u#%V=y3gQ$S3^fY=8CF%$!eeqKP##(<(<5D+6Wpy(F{#H0); z`o#e;Fau(X1;pG8DEi!h7@q+}zak)}Xh6~D2gEQ9DEfkcn5h9pUlX~Im2OcQ2GWSTHj*s!Wv zcB)aeY*C|X*_%eyvMG(KWj7jC%QiHsmi=c`EgR3MT6UaKwQMz`YT08()v~#as%2Lh zRm*lVs+N6ZR4p6Gs9JW8QMGItqiWeJM%A)OjH+dK7*)%*FshdQU{q~nz%k|`1CB8l znYm2f$joK(MrJOPH!^G)xojDul-VmrDYHq8Qf7A;rOdW4N}2s&lrkH^C}nnlQOeoi zJC(>8rOaYCN|{w|lrqcPC}q~QQOYc6qm)_6Mk%v|jZ$W{8g0xHHoBSBYLqg|)F@@v zr%}o*Orw-pkwz&;>Vp!AGzEPTDFvz_(iHSXq$%i&NJUT-ks-~fjtp?dcw}-jzq2v_ zA=lnFS|HK}bV8(7DOc96QSFf`qtGICOesg|m{N|^9Ay{jVcM8=ZM1)+oT=zYRa4lJ zR;HUHB}>(^OpV%)R3`-*sZI(sQqEK~%iB0X$ZF*hVu5jH5b0VPH`2WHZ=}uX^vJ0J zCkT-f1x^=O-p0v8r1xq6Nbl4Bk#48q*<8k%2)oKS6Jg63=N^$#r`jW>PPIo)1~?^% z^git$>3!Nia-zWLLZr><^hmeU@R2hF&J!YyO>alqoKBB)I}INxb*ep5>QsAHlrxDY z;~XjL#Ac#%pcZ3IPn|+n4_q8Lv!24~b=8$)x#T!!oBt+Arn^k5gGGAowZymH26n)^b7CZ1fFJn`elXr7oIK#oHDZ)69BFErMycW&W-^A>XY)qi{O9A}Poc2kCW z@x{8y4f*Wl=XBU}I&8Vl*ynk@?GLQu^sm=DP=}(}1*@%XtecUqtu1!TuFRO}vm3aY z(|tL;!;a_4=ra#aj-R)#T$=Uxm1RB3i@kwSjrC3W8TrOyUBhwNk!z~w*6iQrh0}+t z?F)x5ac&)pMW6Y9KfL|9wPS^_R9GbCS|qHwe$@l@u%io@W$!dQ)HyA&?9k=(>OOT$ zvo$fL&{)^d@rFP9z3K?*-F@ezW>mhU@mBSo^MN{~HW{ebH!T`>=5;KIRJj@rCv4m73E0y`|WhZ(tf1 z^Q?3AKrMmMMQtHXj%=N0!?9yzWDB;?vFY1~a?_`8Zl6j`*@r|E@F8*GD1G9F^RrJa zd&>54sVC2>XH?^qnc2AMc-oxyO-@T7rz4Tmr}23{zM{t6)I6_*)+;v6*_o@&T89?8 zhRV=`|CQN)zJQt)mX%|3xwo)fbh&7S=n7GbXr8DfnlEY-R&<@{7SU4CZK7qOb)w~>^`aG`+eIy+J47YX zouXFJU83tn4~kZb9uln*JuF%+dPH=C=uy!c(PN?;MH@voi5?f-EP6t;R`jIk7SU6p zTSZTcZWBEtS|@r|v|jX_=yuWbqB}${i0%}imqi;yuZZpyy(+p- z^qS~?(X!pK2Sm$74~kZZ9uk#_9v1B;dPGzwdQ>!7^q6RzXrt(K(c_|e(G#N6L{Eyw zi=GmlC3;#kQS^-HOwqHVUZUqjeMHZT4i>#2+E=tmG(hyC$V4xRhKODkoh^DrR4aN_ zR3my#G*_wn?$Whe_Z~gB*s|AFy|?bO z&9>Y1?bm<%0XyutQ`OG9?7G|Td+a%Iuf6x#cfUb{_dnpkgAP6<9(vf}M;tlisH2Y= zdhD>_BaRz+{0XB@Jn7_9MxQ$7v|RPr)5ndUa7N9U6VE!kc2eEsde2XpI;}AMoQ4^V zGiROK)Lfi>-uV~Ix$vTkFS+!xWLdI2S&_6PrKB~vK3SQpN>(Q~Bx{lzlbe#8leNh$ z$!*EHWPNgbaz}D!a#!+T@=)?{@<{S%@>sGlc|3U{c`|t_c{+I}c{X{jZEoA;ZS&f$ zXq(@5W!r+btJ)T(t;^EZ(kPWX=zPb zx*=^@nzpp0Esvxv8`73FY0KQS<>|C^Q(C$?Ev-&VEotelv~+t~TAP-Zrlk#O>5jB? zXIkQ6*QcdbX=!CzTAr3xq@{b((%osx%Cu!k+RAH~pSA)^)7H6di;@k=y~%xTis6PS#h}Pu5?yy=;JN2icCYon%$AonU}HL^2h6J=+~ z&X(26Cduk#lV$ZXm*r(sWK(6+WLgb{>9TWV4YC=sM%hf+EZMoTCRwwrD4Q)iPjp4Td858y`pkO1P-+?Kt=lI~(|YTwmQqgZBs)KxQFl(h zw&0wA6^e6eoj(s`XP8ZOjhvZjVQ&6r%-8zt%lPbB&Yv`L-SjY8;aV}Du+KbW&%Oc= zY5&rDwDw4IUz{(l75%#OtLRrTpnO25u06Nm{IByD`hWMz%8#s5`4{>ae6d%6-u-_8 DKhV{$ diff --git a/PythonHome/Lib/encodings/cp775.py b/PythonHome/Lib/encodings/cp775.py new file mode 100644 index 0000000000..6a456a5825 --- /dev/null +++ b/PythonHome/Lib/encodings/cp775.py @@ -0,0 +1,697 @@ +""" Python Character Mapping Codec cp775 generated from 'VENDORS/MICSFT/PC/CP775.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp775', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x0106, # LATIN CAPITAL LETTER C WITH ACUTE + 0x0081: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0082: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x0083: 0x0101, # LATIN SMALL LETTER A WITH MACRON + 0x0084: 0x00e4, # LATIN SMALL LETTER A WITH DIAERESIS + 0x0085: 0x0123, # LATIN SMALL LETTER G WITH CEDILLA + 0x0086: 0x00e5, # LATIN SMALL LETTER A WITH RING ABOVE + 0x0087: 0x0107, # LATIN SMALL LETTER C WITH ACUTE + 0x0088: 0x0142, # LATIN SMALL LETTER L WITH STROKE + 0x0089: 0x0113, # LATIN SMALL LETTER E WITH MACRON + 0x008a: 0x0156, # LATIN CAPITAL LETTER R WITH CEDILLA + 0x008b: 0x0157, # LATIN SMALL LETTER R WITH CEDILLA + 0x008c: 0x012b, # LATIN SMALL LETTER I WITH MACRON + 0x008d: 0x0179, # LATIN CAPITAL LETTER Z WITH ACUTE + 0x008e: 0x00c4, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x008f: 0x00c5, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x0090: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0091: 0x00e6, # LATIN SMALL LIGATURE AE + 0x0092: 0x00c6, # LATIN CAPITAL LIGATURE AE + 0x0093: 0x014d, # LATIN SMALL LETTER O WITH MACRON + 0x0094: 0x00f6, # LATIN SMALL LETTER O WITH DIAERESIS + 0x0095: 0x0122, # LATIN CAPITAL LETTER G WITH CEDILLA + 0x0096: 0x00a2, # CENT SIGN + 0x0097: 0x015a, # LATIN CAPITAL LETTER S WITH ACUTE + 0x0098: 0x015b, # LATIN SMALL LETTER S WITH ACUTE + 0x0099: 0x00d6, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x009a: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x009b: 0x00f8, # LATIN SMALL LETTER O WITH STROKE + 0x009c: 0x00a3, # POUND SIGN + 0x009d: 0x00d8, # LATIN CAPITAL LETTER O WITH STROKE + 0x009e: 0x00d7, # MULTIPLICATION SIGN + 0x009f: 0x00a4, # CURRENCY SIGN + 0x00a0: 0x0100, # LATIN CAPITAL LETTER A WITH MACRON + 0x00a1: 0x012a, # LATIN CAPITAL LETTER I WITH MACRON + 0x00a2: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00a3: 0x017b, # LATIN CAPITAL LETTER Z WITH DOT ABOVE + 0x00a4: 0x017c, # LATIN SMALL LETTER Z WITH DOT ABOVE + 0x00a5: 0x017a, # LATIN SMALL LETTER Z WITH ACUTE + 0x00a6: 0x201d, # RIGHT DOUBLE QUOTATION MARK + 0x00a7: 0x00a6, # BROKEN BAR + 0x00a8: 0x00a9, # COPYRIGHT SIGN + 0x00a9: 0x00ae, # REGISTERED SIGN + 0x00aa: 0x00ac, # NOT SIGN + 0x00ab: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00ac: 0x00bc, # VULGAR FRACTION ONE QUARTER + 0x00ad: 0x0141, # LATIN CAPITAL LETTER L WITH STROKE + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x0104, # LATIN CAPITAL LETTER A WITH OGONEK + 0x00b6: 0x010c, # LATIN CAPITAL LETTER C WITH CARON + 0x00b7: 0x0118, # LATIN CAPITAL LETTER E WITH OGONEK + 0x00b8: 0x0116, # LATIN CAPITAL LETTER E WITH DOT ABOVE + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x012e, # LATIN CAPITAL LETTER I WITH OGONEK + 0x00be: 0x0160, # LATIN CAPITAL LETTER S WITH CARON + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x0172, # LATIN CAPITAL LETTER U WITH OGONEK + 0x00c7: 0x016a, # LATIN CAPITAL LETTER U WITH MACRON + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x017d, # LATIN CAPITAL LETTER Z WITH CARON + 0x00d0: 0x0105, # LATIN SMALL LETTER A WITH OGONEK + 0x00d1: 0x010d, # LATIN SMALL LETTER C WITH CARON + 0x00d2: 0x0119, # LATIN SMALL LETTER E WITH OGONEK + 0x00d3: 0x0117, # LATIN SMALL LETTER E WITH DOT ABOVE + 0x00d4: 0x012f, # LATIN SMALL LETTER I WITH OGONEK + 0x00d5: 0x0161, # LATIN SMALL LETTER S WITH CARON + 0x00d6: 0x0173, # LATIN SMALL LETTER U WITH OGONEK + 0x00d7: 0x016b, # LATIN SMALL LETTER U WITH MACRON + 0x00d8: 0x017e, # LATIN SMALL LETTER Z WITH CARON + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x258c, # LEFT HALF BLOCK + 0x00de: 0x2590, # RIGHT HALF BLOCK + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x00d3, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00e1: 0x00df, # LATIN SMALL LETTER SHARP S (GERMAN) + 0x00e2: 0x014c, # LATIN CAPITAL LETTER O WITH MACRON + 0x00e3: 0x0143, # LATIN CAPITAL LETTER N WITH ACUTE + 0x00e4: 0x00f5, # LATIN SMALL LETTER O WITH TILDE + 0x00e5: 0x00d5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00e6: 0x00b5, # MICRO SIGN + 0x00e7: 0x0144, # LATIN SMALL LETTER N WITH ACUTE + 0x00e8: 0x0136, # LATIN CAPITAL LETTER K WITH CEDILLA + 0x00e9: 0x0137, # LATIN SMALL LETTER K WITH CEDILLA + 0x00ea: 0x013b, # LATIN CAPITAL LETTER L WITH CEDILLA + 0x00eb: 0x013c, # LATIN SMALL LETTER L WITH CEDILLA + 0x00ec: 0x0146, # LATIN SMALL LETTER N WITH CEDILLA + 0x00ed: 0x0112, # LATIN CAPITAL LETTER E WITH MACRON + 0x00ee: 0x0145, # LATIN CAPITAL LETTER N WITH CEDILLA + 0x00ef: 0x2019, # RIGHT SINGLE QUOTATION MARK + 0x00f0: 0x00ad, # SOFT HYPHEN + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: 0x201c, # LEFT DOUBLE QUOTATION MARK + 0x00f3: 0x00be, # VULGAR FRACTION THREE QUARTERS + 0x00f4: 0x00b6, # PILCROW SIGN + 0x00f5: 0x00a7, # SECTION SIGN + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x201e, # DOUBLE LOW-9 QUOTATION MARK + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x2219, # BULLET OPERATOR + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x00b9, # SUPERSCRIPT ONE + 0x00fc: 0x00b3, # SUPERSCRIPT THREE + 0x00fd: 0x00b2, # SUPERSCRIPT TWO + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x0000 -> NULL + u'\x01' # 0x0001 -> START OF HEADING + u'\x02' # 0x0002 -> START OF TEXT + u'\x03' # 0x0003 -> END OF TEXT + u'\x04' # 0x0004 -> END OF TRANSMISSION + u'\x05' # 0x0005 -> ENQUIRY + u'\x06' # 0x0006 -> ACKNOWLEDGE + u'\x07' # 0x0007 -> BELL + u'\x08' # 0x0008 -> BACKSPACE + u'\t' # 0x0009 -> HORIZONTAL TABULATION + u'\n' # 0x000a -> LINE FEED + u'\x0b' # 0x000b -> VERTICAL TABULATION + u'\x0c' # 0x000c -> FORM FEED + u'\r' # 0x000d -> CARRIAGE RETURN + u'\x0e' # 0x000e -> SHIFT OUT + u'\x0f' # 0x000f -> SHIFT IN + u'\x10' # 0x0010 -> DATA LINK ESCAPE + u'\x11' # 0x0011 -> DEVICE CONTROL ONE + u'\x12' # 0x0012 -> DEVICE CONTROL TWO + u'\x13' # 0x0013 -> DEVICE CONTROL THREE + u'\x14' # 0x0014 -> DEVICE CONTROL FOUR + u'\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x0016 -> SYNCHRONOUS IDLE + u'\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x0018 -> CANCEL + u'\x19' # 0x0019 -> END OF MEDIUM + u'\x1a' # 0x001a -> SUBSTITUTE + u'\x1b' # 0x001b -> ESCAPE + u'\x1c' # 0x001c -> FILE SEPARATOR + u'\x1d' # 0x001d -> GROUP SEPARATOR + u'\x1e' # 0x001e -> RECORD SEPARATOR + u'\x1f' # 0x001f -> UNIT SEPARATOR + u' ' # 0x0020 -> SPACE + u'!' # 0x0021 -> EXCLAMATION MARK + u'"' # 0x0022 -> QUOTATION MARK + u'#' # 0x0023 -> NUMBER SIGN + u'$' # 0x0024 -> DOLLAR SIGN + u'%' # 0x0025 -> PERCENT SIGN + u'&' # 0x0026 -> AMPERSAND + u"'" # 0x0027 -> APOSTROPHE + u'(' # 0x0028 -> LEFT PARENTHESIS + u')' # 0x0029 -> RIGHT PARENTHESIS + u'*' # 0x002a -> ASTERISK + u'+' # 0x002b -> PLUS SIGN + u',' # 0x002c -> COMMA + u'-' # 0x002d -> HYPHEN-MINUS + u'.' # 0x002e -> FULL STOP + u'/' # 0x002f -> SOLIDUS + u'0' # 0x0030 -> DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE + u':' # 0x003a -> COLON + u';' # 0x003b -> SEMICOLON + u'<' # 0x003c -> LESS-THAN SIGN + u'=' # 0x003d -> EQUALS SIGN + u'>' # 0x003e -> GREATER-THAN SIGN + u'?' # 0x003f -> QUESTION MARK + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET + u'\\' # 0x005c -> REVERSE SOLIDUS + u']' # 0x005d -> RIGHT SQUARE BRACKET + u'^' # 0x005e -> CIRCUMFLEX ACCENT + u'_' # 0x005f -> LOW LINE + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET + u'|' # 0x007c -> VERTICAL LINE + u'}' # 0x007d -> RIGHT CURLY BRACKET + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> DELETE + u'\u0106' # 0x0080 -> LATIN CAPITAL LETTER C WITH ACUTE + u'\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + u'\u0101' # 0x0083 -> LATIN SMALL LETTER A WITH MACRON + u'\xe4' # 0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\u0123' # 0x0085 -> LATIN SMALL LETTER G WITH CEDILLA + u'\xe5' # 0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\u0107' # 0x0087 -> LATIN SMALL LETTER C WITH ACUTE + u'\u0142' # 0x0088 -> LATIN SMALL LETTER L WITH STROKE + u'\u0113' # 0x0089 -> LATIN SMALL LETTER E WITH MACRON + u'\u0156' # 0x008a -> LATIN CAPITAL LETTER R WITH CEDILLA + u'\u0157' # 0x008b -> LATIN SMALL LETTER R WITH CEDILLA + u'\u012b' # 0x008c -> LATIN SMALL LETTER I WITH MACRON + u'\u0179' # 0x008d -> LATIN CAPITAL LETTER Z WITH ACUTE + u'\xc4' # 0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xe6' # 0x0091 -> LATIN SMALL LIGATURE AE + u'\xc6' # 0x0092 -> LATIN CAPITAL LIGATURE AE + u'\u014d' # 0x0093 -> LATIN SMALL LETTER O WITH MACRON + u'\xf6' # 0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\u0122' # 0x0095 -> LATIN CAPITAL LETTER G WITH CEDILLA + u'\xa2' # 0x0096 -> CENT SIGN + u'\u015a' # 0x0097 -> LATIN CAPITAL LETTER S WITH ACUTE + u'\u015b' # 0x0098 -> LATIN SMALL LETTER S WITH ACUTE + u'\xd6' # 0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xf8' # 0x009b -> LATIN SMALL LETTER O WITH STROKE + u'\xa3' # 0x009c -> POUND SIGN + u'\xd8' # 0x009d -> LATIN CAPITAL LETTER O WITH STROKE + u'\xd7' # 0x009e -> MULTIPLICATION SIGN + u'\xa4' # 0x009f -> CURRENCY SIGN + u'\u0100' # 0x00a0 -> LATIN CAPITAL LETTER A WITH MACRON + u'\u012a' # 0x00a1 -> LATIN CAPITAL LETTER I WITH MACRON + u'\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + u'\u017b' # 0x00a3 -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + u'\u017c' # 0x00a4 -> LATIN SMALL LETTER Z WITH DOT ABOVE + u'\u017a' # 0x00a5 -> LATIN SMALL LETTER Z WITH ACUTE + u'\u201d' # 0x00a6 -> RIGHT DOUBLE QUOTATION MARK + u'\xa6' # 0x00a7 -> BROKEN BAR + u'\xa9' # 0x00a8 -> COPYRIGHT SIGN + u'\xae' # 0x00a9 -> REGISTERED SIGN + u'\xac' # 0x00aa -> NOT SIGN + u'\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + u'\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + u'\u0141' # 0x00ad -> LATIN CAPITAL LETTER L WITH STROKE + u'\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2591' # 0x00b0 -> LIGHT SHADE + u'\u2592' # 0x00b1 -> MEDIUM SHADE + u'\u2593' # 0x00b2 -> DARK SHADE + u'\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\u0104' # 0x00b5 -> LATIN CAPITAL LETTER A WITH OGONEK + u'\u010c' # 0x00b6 -> LATIN CAPITAL LETTER C WITH CARON + u'\u0118' # 0x00b7 -> LATIN CAPITAL LETTER E WITH OGONEK + u'\u0116' # 0x00b8 -> LATIN CAPITAL LETTER E WITH DOT ABOVE + u'\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\u012e' # 0x00bd -> LATIN CAPITAL LETTER I WITH OGONEK + u'\u0160' # 0x00be -> LATIN CAPITAL LETTER S WITH CARON + u'\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\u0172' # 0x00c6 -> LATIN CAPITAL LETTER U WITH OGONEK + u'\u016a' # 0x00c7 -> LATIN CAPITAL LETTER U WITH MACRON + u'\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\u017d' # 0x00cf -> LATIN CAPITAL LETTER Z WITH CARON + u'\u0105' # 0x00d0 -> LATIN SMALL LETTER A WITH OGONEK + u'\u010d' # 0x00d1 -> LATIN SMALL LETTER C WITH CARON + u'\u0119' # 0x00d2 -> LATIN SMALL LETTER E WITH OGONEK + u'\u0117' # 0x00d3 -> LATIN SMALL LETTER E WITH DOT ABOVE + u'\u012f' # 0x00d4 -> LATIN SMALL LETTER I WITH OGONEK + u'\u0161' # 0x00d5 -> LATIN SMALL LETTER S WITH CARON + u'\u0173' # 0x00d6 -> LATIN SMALL LETTER U WITH OGONEK + u'\u016b' # 0x00d7 -> LATIN SMALL LETTER U WITH MACRON + u'\u017e' # 0x00d8 -> LATIN SMALL LETTER Z WITH CARON + u'\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0x00db -> FULL BLOCK + u'\u2584' # 0x00dc -> LOWER HALF BLOCK + u'\u258c' # 0x00dd -> LEFT HALF BLOCK + u'\u2590' # 0x00de -> RIGHT HALF BLOCK + u'\u2580' # 0x00df -> UPPER HALF BLOCK + u'\xd3' # 0x00e0 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S (GERMAN) + u'\u014c' # 0x00e2 -> LATIN CAPITAL LETTER O WITH MACRON + u'\u0143' # 0x00e3 -> LATIN CAPITAL LETTER N WITH ACUTE + u'\xf5' # 0x00e4 -> LATIN SMALL LETTER O WITH TILDE + u'\xd5' # 0x00e5 -> LATIN CAPITAL LETTER O WITH TILDE + u'\xb5' # 0x00e6 -> MICRO SIGN + u'\u0144' # 0x00e7 -> LATIN SMALL LETTER N WITH ACUTE + u'\u0136' # 0x00e8 -> LATIN CAPITAL LETTER K WITH CEDILLA + u'\u0137' # 0x00e9 -> LATIN SMALL LETTER K WITH CEDILLA + u'\u013b' # 0x00ea -> LATIN CAPITAL LETTER L WITH CEDILLA + u'\u013c' # 0x00eb -> LATIN SMALL LETTER L WITH CEDILLA + u'\u0146' # 0x00ec -> LATIN SMALL LETTER N WITH CEDILLA + u'\u0112' # 0x00ed -> LATIN CAPITAL LETTER E WITH MACRON + u'\u0145' # 0x00ee -> LATIN CAPITAL LETTER N WITH CEDILLA + u'\u2019' # 0x00ef -> RIGHT SINGLE QUOTATION MARK + u'\xad' # 0x00f0 -> SOFT HYPHEN + u'\xb1' # 0x00f1 -> PLUS-MINUS SIGN + u'\u201c' # 0x00f2 -> LEFT DOUBLE QUOTATION MARK + u'\xbe' # 0x00f3 -> VULGAR FRACTION THREE QUARTERS + u'\xb6' # 0x00f4 -> PILCROW SIGN + u'\xa7' # 0x00f5 -> SECTION SIGN + u'\xf7' # 0x00f6 -> DIVISION SIGN + u'\u201e' # 0x00f7 -> DOUBLE LOW-9 QUOTATION MARK + u'\xb0' # 0x00f8 -> DEGREE SIGN + u'\u2219' # 0x00f9 -> BULLET OPERATOR + u'\xb7' # 0x00fa -> MIDDLE DOT + u'\xb9' # 0x00fb -> SUPERSCRIPT ONE + u'\xb3' # 0x00fc -> SUPERSCRIPT THREE + u'\xb2' # 0x00fd -> SUPERSCRIPT TWO + u'\u25a0' # 0x00fe -> BLACK SQUARE + u'\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a2: 0x0096, # CENT SIGN + 0x00a3: 0x009c, # POUND SIGN + 0x00a4: 0x009f, # CURRENCY SIGN + 0x00a6: 0x00a7, # BROKEN BAR + 0x00a7: 0x00f5, # SECTION SIGN + 0x00a9: 0x00a8, # COPYRIGHT SIGN + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00ad: 0x00f0, # SOFT HYPHEN + 0x00ae: 0x00a9, # REGISTERED SIGN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b3: 0x00fc, # SUPERSCRIPT THREE + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b6: 0x00f4, # PILCROW SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00b9: 0x00fb, # SUPERSCRIPT ONE + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00be: 0x00f3, # VULGAR FRACTION THREE QUARTERS + 0x00c4: 0x008e, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5: 0x008f, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c6: 0x0092, # LATIN CAPITAL LIGATURE AE + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00d3: 0x00e0, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00d5: 0x00e5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00d6: 0x0099, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00d7: 0x009e, # MULTIPLICATION SIGN + 0x00d8: 0x009d, # LATIN CAPITAL LETTER O WITH STROKE + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S (GERMAN) + 0x00e4: 0x0084, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e5: 0x0086, # LATIN SMALL LETTER A WITH RING ABOVE + 0x00e6: 0x0091, # LATIN SMALL LIGATURE AE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f5: 0x00e4, # LATIN SMALL LETTER O WITH TILDE + 0x00f6: 0x0094, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f8: 0x009b, # LATIN SMALL LETTER O WITH STROKE + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0100: 0x00a0, # LATIN CAPITAL LETTER A WITH MACRON + 0x0101: 0x0083, # LATIN SMALL LETTER A WITH MACRON + 0x0104: 0x00b5, # LATIN CAPITAL LETTER A WITH OGONEK + 0x0105: 0x00d0, # LATIN SMALL LETTER A WITH OGONEK + 0x0106: 0x0080, # LATIN CAPITAL LETTER C WITH ACUTE + 0x0107: 0x0087, # LATIN SMALL LETTER C WITH ACUTE + 0x010c: 0x00b6, # LATIN CAPITAL LETTER C WITH CARON + 0x010d: 0x00d1, # LATIN SMALL LETTER C WITH CARON + 0x0112: 0x00ed, # LATIN CAPITAL LETTER E WITH MACRON + 0x0113: 0x0089, # LATIN SMALL LETTER E WITH MACRON + 0x0116: 0x00b8, # LATIN CAPITAL LETTER E WITH DOT ABOVE + 0x0117: 0x00d3, # LATIN SMALL LETTER E WITH DOT ABOVE + 0x0118: 0x00b7, # LATIN CAPITAL LETTER E WITH OGONEK + 0x0119: 0x00d2, # LATIN SMALL LETTER E WITH OGONEK + 0x0122: 0x0095, # LATIN CAPITAL LETTER G WITH CEDILLA + 0x0123: 0x0085, # LATIN SMALL LETTER G WITH CEDILLA + 0x012a: 0x00a1, # LATIN CAPITAL LETTER I WITH MACRON + 0x012b: 0x008c, # LATIN SMALL LETTER I WITH MACRON + 0x012e: 0x00bd, # LATIN CAPITAL LETTER I WITH OGONEK + 0x012f: 0x00d4, # LATIN SMALL LETTER I WITH OGONEK + 0x0136: 0x00e8, # LATIN CAPITAL LETTER K WITH CEDILLA + 0x0137: 0x00e9, # LATIN SMALL LETTER K WITH CEDILLA + 0x013b: 0x00ea, # LATIN CAPITAL LETTER L WITH CEDILLA + 0x013c: 0x00eb, # LATIN SMALL LETTER L WITH CEDILLA + 0x0141: 0x00ad, # LATIN CAPITAL LETTER L WITH STROKE + 0x0142: 0x0088, # LATIN SMALL LETTER L WITH STROKE + 0x0143: 0x00e3, # LATIN CAPITAL LETTER N WITH ACUTE + 0x0144: 0x00e7, # LATIN SMALL LETTER N WITH ACUTE + 0x0145: 0x00ee, # LATIN CAPITAL LETTER N WITH CEDILLA + 0x0146: 0x00ec, # LATIN SMALL LETTER N WITH CEDILLA + 0x014c: 0x00e2, # LATIN CAPITAL LETTER O WITH MACRON + 0x014d: 0x0093, # LATIN SMALL LETTER O WITH MACRON + 0x0156: 0x008a, # LATIN CAPITAL LETTER R WITH CEDILLA + 0x0157: 0x008b, # LATIN SMALL LETTER R WITH CEDILLA + 0x015a: 0x0097, # LATIN CAPITAL LETTER S WITH ACUTE + 0x015b: 0x0098, # LATIN SMALL LETTER S WITH ACUTE + 0x0160: 0x00be, # LATIN CAPITAL LETTER S WITH CARON + 0x0161: 0x00d5, # LATIN SMALL LETTER S WITH CARON + 0x016a: 0x00c7, # LATIN CAPITAL LETTER U WITH MACRON + 0x016b: 0x00d7, # LATIN SMALL LETTER U WITH MACRON + 0x0172: 0x00c6, # LATIN CAPITAL LETTER U WITH OGONEK + 0x0173: 0x00d6, # LATIN SMALL LETTER U WITH OGONEK + 0x0179: 0x008d, # LATIN CAPITAL LETTER Z WITH ACUTE + 0x017a: 0x00a5, # LATIN SMALL LETTER Z WITH ACUTE + 0x017b: 0x00a3, # LATIN CAPITAL LETTER Z WITH DOT ABOVE + 0x017c: 0x00a4, # LATIN SMALL LETTER Z WITH DOT ABOVE + 0x017d: 0x00cf, # LATIN CAPITAL LETTER Z WITH CARON + 0x017e: 0x00d8, # LATIN SMALL LETTER Z WITH CARON + 0x2019: 0x00ef, # RIGHT SINGLE QUOTATION MARK + 0x201c: 0x00f2, # LEFT DOUBLE QUOTATION MARK + 0x201d: 0x00a6, # RIGHT DOUBLE QUOTATION MARK + 0x201e: 0x00f7, # DOUBLE LOW-9 QUOTATION MARK + 0x2219: 0x00f9, # BULLET OPERATOR + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/PythonHome/Lib/encodings/cp775.pyc b/PythonHome/Lib/encodings/cp775.pyc deleted file mode 100644 index bbf977e30fe9c85793f6dcc7503a49c61aa14c16..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7943 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 DQcQio diff --git a/PythonHome/Lib/encodings/cp850.py b/PythonHome/Lib/encodings/cp850.py new file mode 100644 index 0000000000..0c8478c8b2 --- /dev/null +++ b/PythonHome/Lib/encodings/cp850.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP850.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp850', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x00c7, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x0081: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0082: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x0083: 0x00e2, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x0084: 0x00e4, # LATIN SMALL LETTER A WITH DIAERESIS + 0x0085: 0x00e0, # LATIN SMALL LETTER A WITH GRAVE + 0x0086: 0x00e5, # LATIN SMALL LETTER A WITH RING ABOVE + 0x0087: 0x00e7, # LATIN SMALL LETTER C WITH CEDILLA + 0x0088: 0x00ea, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x0089: 0x00eb, # LATIN SMALL LETTER E WITH DIAERESIS + 0x008a: 0x00e8, # LATIN SMALL LETTER E WITH GRAVE + 0x008b: 0x00ef, # LATIN SMALL LETTER I WITH DIAERESIS + 0x008c: 0x00ee, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x008d: 0x00ec, # LATIN SMALL LETTER I WITH GRAVE + 0x008e: 0x00c4, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x008f: 0x00c5, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x0090: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0091: 0x00e6, # LATIN SMALL LIGATURE AE + 0x0092: 0x00c6, # LATIN CAPITAL LIGATURE AE + 0x0093: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x0094: 0x00f6, # LATIN SMALL LETTER O WITH DIAERESIS + 0x0095: 0x00f2, # LATIN SMALL LETTER O WITH GRAVE + 0x0096: 0x00fb, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x0097: 0x00f9, # LATIN SMALL LETTER U WITH GRAVE + 0x0098: 0x00ff, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x0099: 0x00d6, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x009a: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x009b: 0x00f8, # LATIN SMALL LETTER O WITH STROKE + 0x009c: 0x00a3, # POUND SIGN + 0x009d: 0x00d8, # LATIN CAPITAL LETTER O WITH STROKE + 0x009e: 0x00d7, # MULTIPLICATION SIGN + 0x009f: 0x0192, # LATIN SMALL LETTER F WITH HOOK + 0x00a0: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE + 0x00a1: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE + 0x00a2: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00a3: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x00a4: 0x00f1, # LATIN SMALL LETTER N WITH TILDE + 0x00a5: 0x00d1, # LATIN CAPITAL LETTER N WITH TILDE + 0x00a6: 0x00aa, # FEMININE ORDINAL INDICATOR + 0x00a7: 0x00ba, # MASCULINE ORDINAL INDICATOR + 0x00a8: 0x00bf, # INVERTED QUESTION MARK + 0x00a9: 0x00ae, # REGISTERED SIGN + 0x00aa: 0x00ac, # NOT SIGN + 0x00ab: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00ac: 0x00bc, # VULGAR FRACTION ONE QUARTER + 0x00ad: 0x00a1, # INVERTED EXCLAMATION MARK + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x00c1, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00b6: 0x00c2, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00b7: 0x00c0, # LATIN CAPITAL LETTER A WITH GRAVE + 0x00b8: 0x00a9, # COPYRIGHT SIGN + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x00a2, # CENT SIGN + 0x00be: 0x00a5, # YEN SIGN + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x00e3, # LATIN SMALL LETTER A WITH TILDE + 0x00c7: 0x00c3, # LATIN CAPITAL LETTER A WITH TILDE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x00a4, # CURRENCY SIGN + 0x00d0: 0x00f0, # LATIN SMALL LETTER ETH + 0x00d1: 0x00d0, # LATIN CAPITAL LETTER ETH + 0x00d2: 0x00ca, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00d3: 0x00cb, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00d4: 0x00c8, # LATIN CAPITAL LETTER E WITH GRAVE + 0x00d5: 0x0131, # LATIN SMALL LETTER DOTLESS I + 0x00d6: 0x00cd, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00d7: 0x00ce, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00d8: 0x00cf, # LATIN CAPITAL LETTER I WITH DIAERESIS + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x00a6, # BROKEN BAR + 0x00de: 0x00cc, # LATIN CAPITAL LETTER I WITH GRAVE + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x00d3, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00e1: 0x00df, # LATIN SMALL LETTER SHARP S + 0x00e2: 0x00d4, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00e3: 0x00d2, # LATIN CAPITAL LETTER O WITH GRAVE + 0x00e4: 0x00f5, # LATIN SMALL LETTER O WITH TILDE + 0x00e5: 0x00d5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00e6: 0x00b5, # MICRO SIGN + 0x00e7: 0x00fe, # LATIN SMALL LETTER THORN + 0x00e8: 0x00de, # LATIN CAPITAL LETTER THORN + 0x00e9: 0x00da, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00ea: 0x00db, # LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x00eb: 0x00d9, # LATIN CAPITAL LETTER U WITH GRAVE + 0x00ec: 0x00fd, # LATIN SMALL LETTER Y WITH ACUTE + 0x00ed: 0x00dd, # LATIN CAPITAL LETTER Y WITH ACUTE + 0x00ee: 0x00af, # MACRON + 0x00ef: 0x00b4, # ACUTE ACCENT + 0x00f0: 0x00ad, # SOFT HYPHEN + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: 0x2017, # DOUBLE LOW LINE + 0x00f3: 0x00be, # VULGAR FRACTION THREE QUARTERS + 0x00f4: 0x00b6, # PILCROW SIGN + 0x00f5: 0x00a7, # SECTION SIGN + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x00b8, # CEDILLA + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x00a8, # DIAERESIS + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x00b9, # SUPERSCRIPT ONE + 0x00fc: 0x00b3, # SUPERSCRIPT THREE + 0x00fd: 0x00b2, # SUPERSCRIPT TWO + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x0000 -> NULL + u'\x01' # 0x0001 -> START OF HEADING + u'\x02' # 0x0002 -> START OF TEXT + u'\x03' # 0x0003 -> END OF TEXT + u'\x04' # 0x0004 -> END OF TRANSMISSION + u'\x05' # 0x0005 -> ENQUIRY + u'\x06' # 0x0006 -> ACKNOWLEDGE + u'\x07' # 0x0007 -> BELL + u'\x08' # 0x0008 -> BACKSPACE + u'\t' # 0x0009 -> HORIZONTAL TABULATION + u'\n' # 0x000a -> LINE FEED + u'\x0b' # 0x000b -> VERTICAL TABULATION + u'\x0c' # 0x000c -> FORM FEED + u'\r' # 0x000d -> CARRIAGE RETURN + u'\x0e' # 0x000e -> SHIFT OUT + u'\x0f' # 0x000f -> SHIFT IN + u'\x10' # 0x0010 -> DATA LINK ESCAPE + u'\x11' # 0x0011 -> DEVICE CONTROL ONE + u'\x12' # 0x0012 -> DEVICE CONTROL TWO + u'\x13' # 0x0013 -> DEVICE CONTROL THREE + u'\x14' # 0x0014 -> DEVICE CONTROL FOUR + u'\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x0016 -> SYNCHRONOUS IDLE + u'\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x0018 -> CANCEL + u'\x19' # 0x0019 -> END OF MEDIUM + u'\x1a' # 0x001a -> SUBSTITUTE + u'\x1b' # 0x001b -> ESCAPE + u'\x1c' # 0x001c -> FILE SEPARATOR + u'\x1d' # 0x001d -> GROUP SEPARATOR + u'\x1e' # 0x001e -> RECORD SEPARATOR + u'\x1f' # 0x001f -> UNIT SEPARATOR + u' ' # 0x0020 -> SPACE + u'!' # 0x0021 -> EXCLAMATION MARK + u'"' # 0x0022 -> QUOTATION MARK + u'#' # 0x0023 -> NUMBER SIGN + u'$' # 0x0024 -> DOLLAR SIGN + u'%' # 0x0025 -> PERCENT SIGN + u'&' # 0x0026 -> AMPERSAND + u"'" # 0x0027 -> APOSTROPHE + u'(' # 0x0028 -> LEFT PARENTHESIS + u')' # 0x0029 -> RIGHT PARENTHESIS + u'*' # 0x002a -> ASTERISK + u'+' # 0x002b -> PLUS SIGN + u',' # 0x002c -> COMMA + u'-' # 0x002d -> HYPHEN-MINUS + u'.' # 0x002e -> FULL STOP + u'/' # 0x002f -> SOLIDUS + u'0' # 0x0030 -> DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE + u':' # 0x003a -> COLON + u';' # 0x003b -> SEMICOLON + u'<' # 0x003c -> LESS-THAN SIGN + u'=' # 0x003d -> EQUALS SIGN + u'>' # 0x003e -> GREATER-THAN SIGN + u'?' # 0x003f -> QUESTION MARK + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET + u'\\' # 0x005c -> REVERSE SOLIDUS + u']' # 0x005d -> RIGHT SQUARE BRACKET + u'^' # 0x005e -> CIRCUMFLEX ACCENT + u'_' # 0x005f -> LOW LINE + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET + u'|' # 0x007c -> VERTICAL LINE + u'}' # 0x007d -> RIGHT CURLY BRACKET + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> DELETE + u'\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + u'\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe0' # 0x0085 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe5' # 0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xea' # 0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xe8' # 0x008a -> LATIN SMALL LETTER E WITH GRAVE + u'\xef' # 0x008b -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xee' # 0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xec' # 0x008d -> LATIN SMALL LETTER I WITH GRAVE + u'\xc4' # 0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xe6' # 0x0091 -> LATIN SMALL LIGATURE AE + u'\xc6' # 0x0092 -> LATIN CAPITAL LIGATURE AE + u'\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf2' # 0x0095 -> LATIN SMALL LETTER O WITH GRAVE + u'\xfb' # 0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xf9' # 0x0097 -> LATIN SMALL LETTER U WITH GRAVE + u'\xff' # 0x0098 -> LATIN SMALL LETTER Y WITH DIAERESIS + u'\xd6' # 0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xf8' # 0x009b -> LATIN SMALL LETTER O WITH STROKE + u'\xa3' # 0x009c -> POUND SIGN + u'\xd8' # 0x009d -> LATIN CAPITAL LETTER O WITH STROKE + u'\xd7' # 0x009e -> MULTIPLICATION SIGN + u'\u0192' # 0x009f -> LATIN SMALL LETTER F WITH HOOK + u'\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + u'\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + u'\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + u'\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + u'\xf1' # 0x00a4 -> LATIN SMALL LETTER N WITH TILDE + u'\xd1' # 0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xaa' # 0x00a6 -> FEMININE ORDINAL INDICATOR + u'\xba' # 0x00a7 -> MASCULINE ORDINAL INDICATOR + u'\xbf' # 0x00a8 -> INVERTED QUESTION MARK + u'\xae' # 0x00a9 -> REGISTERED SIGN + u'\xac' # 0x00aa -> NOT SIGN + u'\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + u'\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + u'\xa1' # 0x00ad -> INVERTED EXCLAMATION MARK + u'\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2591' # 0x00b0 -> LIGHT SHADE + u'\u2592' # 0x00b1 -> MEDIUM SHADE + u'\u2593' # 0x00b2 -> DARK SHADE + u'\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\xc1' # 0x00b5 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0x00b6 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xc0' # 0x00b7 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xa9' # 0x00b8 -> COPYRIGHT SIGN + u'\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\xa2' # 0x00bd -> CENT SIGN + u'\xa5' # 0x00be -> YEN SIGN + u'\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\xe3' # 0x00c6 -> LATIN SMALL LETTER A WITH TILDE + u'\xc3' # 0x00c7 -> LATIN CAPITAL LETTER A WITH TILDE + u'\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\xa4' # 0x00cf -> CURRENCY SIGN + u'\xf0' # 0x00d0 -> LATIN SMALL LETTER ETH + u'\xd0' # 0x00d1 -> LATIN CAPITAL LETTER ETH + u'\xca' # 0x00d2 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xcb' # 0x00d3 -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xc8' # 0x00d4 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\u0131' # 0x00d5 -> LATIN SMALL LETTER DOTLESS I + u'\xcd' # 0x00d6 -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0x00d7 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0x00d8 -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0x00db -> FULL BLOCK + u'\u2584' # 0x00dc -> LOWER HALF BLOCK + u'\xa6' # 0x00dd -> BROKEN BAR + u'\xcc' # 0x00de -> LATIN CAPITAL LETTER I WITH GRAVE + u'\u2580' # 0x00df -> UPPER HALF BLOCK + u'\xd3' # 0x00e0 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + u'\xd4' # 0x00e2 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\xd2' # 0x00e3 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xf5' # 0x00e4 -> LATIN SMALL LETTER O WITH TILDE + u'\xd5' # 0x00e5 -> LATIN CAPITAL LETTER O WITH TILDE + u'\xb5' # 0x00e6 -> MICRO SIGN + u'\xfe' # 0x00e7 -> LATIN SMALL LETTER THORN + u'\xde' # 0x00e8 -> LATIN CAPITAL LETTER THORN + u'\xda' # 0x00e9 -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0x00ea -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xd9' # 0x00eb -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xfd' # 0x00ec -> LATIN SMALL LETTER Y WITH ACUTE + u'\xdd' # 0x00ed -> LATIN CAPITAL LETTER Y WITH ACUTE + u'\xaf' # 0x00ee -> MACRON + u'\xb4' # 0x00ef -> ACUTE ACCENT + u'\xad' # 0x00f0 -> SOFT HYPHEN + u'\xb1' # 0x00f1 -> PLUS-MINUS SIGN + u'\u2017' # 0x00f2 -> DOUBLE LOW LINE + u'\xbe' # 0x00f3 -> VULGAR FRACTION THREE QUARTERS + u'\xb6' # 0x00f4 -> PILCROW SIGN + u'\xa7' # 0x00f5 -> SECTION SIGN + u'\xf7' # 0x00f6 -> DIVISION SIGN + u'\xb8' # 0x00f7 -> CEDILLA + u'\xb0' # 0x00f8 -> DEGREE SIGN + u'\xa8' # 0x00f9 -> DIAERESIS + u'\xb7' # 0x00fa -> MIDDLE DOT + u'\xb9' # 0x00fb -> SUPERSCRIPT ONE + u'\xb3' # 0x00fc -> SUPERSCRIPT THREE + u'\xb2' # 0x00fd -> SUPERSCRIPT TWO + u'\u25a0' # 0x00fe -> BLACK SQUARE + u'\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a1: 0x00ad, # INVERTED EXCLAMATION MARK + 0x00a2: 0x00bd, # CENT SIGN + 0x00a3: 0x009c, # POUND SIGN + 0x00a4: 0x00cf, # CURRENCY SIGN + 0x00a5: 0x00be, # YEN SIGN + 0x00a6: 0x00dd, # BROKEN BAR + 0x00a7: 0x00f5, # SECTION SIGN + 0x00a8: 0x00f9, # DIAERESIS + 0x00a9: 0x00b8, # COPYRIGHT SIGN + 0x00aa: 0x00a6, # FEMININE ORDINAL INDICATOR + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00ad: 0x00f0, # SOFT HYPHEN + 0x00ae: 0x00a9, # REGISTERED SIGN + 0x00af: 0x00ee, # MACRON + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b3: 0x00fc, # SUPERSCRIPT THREE + 0x00b4: 0x00ef, # ACUTE ACCENT + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b6: 0x00f4, # PILCROW SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00b8: 0x00f7, # CEDILLA + 0x00b9: 0x00fb, # SUPERSCRIPT ONE + 0x00ba: 0x00a7, # MASCULINE ORDINAL INDICATOR + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00be: 0x00f3, # VULGAR FRACTION THREE QUARTERS + 0x00bf: 0x00a8, # INVERTED QUESTION MARK + 0x00c0: 0x00b7, # LATIN CAPITAL LETTER A WITH GRAVE + 0x00c1: 0x00b5, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00c2: 0x00b6, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00c3: 0x00c7, # LATIN CAPITAL LETTER A WITH TILDE + 0x00c4: 0x008e, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5: 0x008f, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c6: 0x0092, # LATIN CAPITAL LIGATURE AE + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c8: 0x00d4, # LATIN CAPITAL LETTER E WITH GRAVE + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00ca: 0x00d2, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00cb: 0x00d3, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00cc: 0x00de, # LATIN CAPITAL LETTER I WITH GRAVE + 0x00cd: 0x00d6, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00ce: 0x00d7, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00cf: 0x00d8, # LATIN CAPITAL LETTER I WITH DIAERESIS + 0x00d0: 0x00d1, # LATIN CAPITAL LETTER ETH + 0x00d1: 0x00a5, # LATIN CAPITAL LETTER N WITH TILDE + 0x00d2: 0x00e3, # LATIN CAPITAL LETTER O WITH GRAVE + 0x00d3: 0x00e0, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00d4: 0x00e2, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00d5: 0x00e5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00d6: 0x0099, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00d7: 0x009e, # MULTIPLICATION SIGN + 0x00d8: 0x009d, # LATIN CAPITAL LETTER O WITH STROKE + 0x00d9: 0x00eb, # LATIN CAPITAL LETTER U WITH GRAVE + 0x00da: 0x00e9, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00db: 0x00ea, # LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00dd: 0x00ed, # LATIN CAPITAL LETTER Y WITH ACUTE + 0x00de: 0x00e8, # LATIN CAPITAL LETTER THORN + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e0: 0x0085, # LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e3: 0x00c6, # LATIN SMALL LETTER A WITH TILDE + 0x00e4: 0x0084, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e5: 0x0086, # LATIN SMALL LETTER A WITH RING ABOVE + 0x00e6: 0x0091, # LATIN SMALL LIGATURE AE + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008a, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0088, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x0089, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ec: 0x008d, # LATIN SMALL LETTER I WITH GRAVE + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00ee: 0x008c, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ef: 0x008b, # LATIN SMALL LETTER I WITH DIAERESIS + 0x00f0: 0x00d0, # LATIN SMALL LETTER ETH + 0x00f1: 0x00a4, # LATIN SMALL LETTER N WITH TILDE + 0x00f2: 0x0095, # LATIN SMALL LETTER O WITH GRAVE + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f5: 0x00e4, # LATIN SMALL LETTER O WITH TILDE + 0x00f6: 0x0094, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f8: 0x009b, # LATIN SMALL LETTER O WITH STROKE + 0x00f9: 0x0097, # LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x0096, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00fd: 0x00ec, # LATIN SMALL LETTER Y WITH ACUTE + 0x00fe: 0x00e7, # LATIN SMALL LETTER THORN + 0x00ff: 0x0098, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x0131: 0x00d5, # LATIN SMALL LETTER DOTLESS I + 0x0192: 0x009f, # LATIN SMALL LETTER F WITH HOOK + 0x2017: 0x00f2, # DOUBLE LOW LINE + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/PythonHome/Lib/encodings/cp850.pyc b/PythonHome/Lib/encodings/cp850.pyc deleted file mode 100644 index 69d4f6b491ac263f9dd6374f7f89e836910c330b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7676 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 NULL + u'\x01' # 0x0001 -> START OF HEADING + u'\x02' # 0x0002 -> START OF TEXT + u'\x03' # 0x0003 -> END OF TEXT + u'\x04' # 0x0004 -> END OF TRANSMISSION + u'\x05' # 0x0005 -> ENQUIRY + u'\x06' # 0x0006 -> ACKNOWLEDGE + u'\x07' # 0x0007 -> BELL + u'\x08' # 0x0008 -> BACKSPACE + u'\t' # 0x0009 -> HORIZONTAL TABULATION + u'\n' # 0x000a -> LINE FEED + u'\x0b' # 0x000b -> VERTICAL TABULATION + u'\x0c' # 0x000c -> FORM FEED + u'\r' # 0x000d -> CARRIAGE RETURN + u'\x0e' # 0x000e -> SHIFT OUT + u'\x0f' # 0x000f -> SHIFT IN + u'\x10' # 0x0010 -> DATA LINK ESCAPE + u'\x11' # 0x0011 -> DEVICE CONTROL ONE + u'\x12' # 0x0012 -> DEVICE CONTROL TWO + u'\x13' # 0x0013 -> DEVICE CONTROL THREE + u'\x14' # 0x0014 -> DEVICE CONTROL FOUR + u'\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x0016 -> SYNCHRONOUS IDLE + u'\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x0018 -> CANCEL + u'\x19' # 0x0019 -> END OF MEDIUM + u'\x1a' # 0x001a -> SUBSTITUTE + u'\x1b' # 0x001b -> ESCAPE + u'\x1c' # 0x001c -> FILE SEPARATOR + u'\x1d' # 0x001d -> GROUP SEPARATOR + u'\x1e' # 0x001e -> RECORD SEPARATOR + u'\x1f' # 0x001f -> UNIT SEPARATOR + u' ' # 0x0020 -> SPACE + u'!' # 0x0021 -> EXCLAMATION MARK + u'"' # 0x0022 -> QUOTATION MARK + u'#' # 0x0023 -> NUMBER SIGN + u'$' # 0x0024 -> DOLLAR SIGN + u'%' # 0x0025 -> PERCENT SIGN + u'&' # 0x0026 -> AMPERSAND + u"'" # 0x0027 -> APOSTROPHE + u'(' # 0x0028 -> LEFT PARENTHESIS + u')' # 0x0029 -> RIGHT PARENTHESIS + u'*' # 0x002a -> ASTERISK + u'+' # 0x002b -> PLUS SIGN + u',' # 0x002c -> COMMA + u'-' # 0x002d -> HYPHEN-MINUS + u'.' # 0x002e -> FULL STOP + u'/' # 0x002f -> SOLIDUS + u'0' # 0x0030 -> DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE + u':' # 0x003a -> COLON + u';' # 0x003b -> SEMICOLON + u'<' # 0x003c -> LESS-THAN SIGN + u'=' # 0x003d -> EQUALS SIGN + u'>' # 0x003e -> GREATER-THAN SIGN + u'?' # 0x003f -> QUESTION MARK + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET + u'\\' # 0x005c -> REVERSE SOLIDUS + u']' # 0x005d -> RIGHT SQUARE BRACKET + u'^' # 0x005e -> CIRCUMFLEX ACCENT + u'_' # 0x005f -> LOW LINE + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET + u'|' # 0x007c -> VERTICAL LINE + u'}' # 0x007d -> RIGHT CURLY BRACKET + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> DELETE + u'\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + u'\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\u016f' # 0x0085 -> LATIN SMALL LETTER U WITH RING ABOVE + u'\u0107' # 0x0086 -> LATIN SMALL LETTER C WITH ACUTE + u'\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + u'\u0142' # 0x0088 -> LATIN SMALL LETTER L WITH STROKE + u'\xeb' # 0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\u0150' # 0x008a -> LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + u'\u0151' # 0x008b -> LATIN SMALL LETTER O WITH DOUBLE ACUTE + u'\xee' # 0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\u0179' # 0x008d -> LATIN CAPITAL LETTER Z WITH ACUTE + u'\xc4' # 0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\u0106' # 0x008f -> LATIN CAPITAL LETTER C WITH ACUTE + u'\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\u0139' # 0x0091 -> LATIN CAPITAL LETTER L WITH ACUTE + u'\u013a' # 0x0092 -> LATIN SMALL LETTER L WITH ACUTE + u'\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\u013d' # 0x0095 -> LATIN CAPITAL LETTER L WITH CARON + u'\u013e' # 0x0096 -> LATIN SMALL LETTER L WITH CARON + u'\u015a' # 0x0097 -> LATIN CAPITAL LETTER S WITH ACUTE + u'\u015b' # 0x0098 -> LATIN SMALL LETTER S WITH ACUTE + u'\xd6' # 0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\u0164' # 0x009b -> LATIN CAPITAL LETTER T WITH CARON + u'\u0165' # 0x009c -> LATIN SMALL LETTER T WITH CARON + u'\u0141' # 0x009d -> LATIN CAPITAL LETTER L WITH STROKE + u'\xd7' # 0x009e -> MULTIPLICATION SIGN + u'\u010d' # 0x009f -> LATIN SMALL LETTER C WITH CARON + u'\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + u'\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + u'\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + u'\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + u'\u0104' # 0x00a4 -> LATIN CAPITAL LETTER A WITH OGONEK + u'\u0105' # 0x00a5 -> LATIN SMALL LETTER A WITH OGONEK + u'\u017d' # 0x00a6 -> LATIN CAPITAL LETTER Z WITH CARON + u'\u017e' # 0x00a7 -> LATIN SMALL LETTER Z WITH CARON + u'\u0118' # 0x00a8 -> LATIN CAPITAL LETTER E WITH OGONEK + u'\u0119' # 0x00a9 -> LATIN SMALL LETTER E WITH OGONEK + u'\xac' # 0x00aa -> NOT SIGN + u'\u017a' # 0x00ab -> LATIN SMALL LETTER Z WITH ACUTE + u'\u010c' # 0x00ac -> LATIN CAPITAL LETTER C WITH CARON + u'\u015f' # 0x00ad -> LATIN SMALL LETTER S WITH CEDILLA + u'\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2591' # 0x00b0 -> LIGHT SHADE + u'\u2592' # 0x00b1 -> MEDIUM SHADE + u'\u2593' # 0x00b2 -> DARK SHADE + u'\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\xc1' # 0x00b5 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0x00b6 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\u011a' # 0x00b7 -> LATIN CAPITAL LETTER E WITH CARON + u'\u015e' # 0x00b8 -> LATIN CAPITAL LETTER S WITH CEDILLA + u'\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\u017b' # 0x00bd -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + u'\u017c' # 0x00be -> LATIN SMALL LETTER Z WITH DOT ABOVE + u'\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\u0102' # 0x00c6 -> LATIN CAPITAL LETTER A WITH BREVE + u'\u0103' # 0x00c7 -> LATIN SMALL LETTER A WITH BREVE + u'\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\xa4' # 0x00cf -> CURRENCY SIGN + u'\u0111' # 0x00d0 -> LATIN SMALL LETTER D WITH STROKE + u'\u0110' # 0x00d1 -> LATIN CAPITAL LETTER D WITH STROKE + u'\u010e' # 0x00d2 -> LATIN CAPITAL LETTER D WITH CARON + u'\xcb' # 0x00d3 -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\u010f' # 0x00d4 -> LATIN SMALL LETTER D WITH CARON + u'\u0147' # 0x00d5 -> LATIN CAPITAL LETTER N WITH CARON + u'\xcd' # 0x00d6 -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0x00d7 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\u011b' # 0x00d8 -> LATIN SMALL LETTER E WITH CARON + u'\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0x00db -> FULL BLOCK + u'\u2584' # 0x00dc -> LOWER HALF BLOCK + u'\u0162' # 0x00dd -> LATIN CAPITAL LETTER T WITH CEDILLA + u'\u016e' # 0x00de -> LATIN CAPITAL LETTER U WITH RING ABOVE + u'\u2580' # 0x00df -> UPPER HALF BLOCK + u'\xd3' # 0x00e0 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + u'\xd4' # 0x00e2 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\u0143' # 0x00e3 -> LATIN CAPITAL LETTER N WITH ACUTE + u'\u0144' # 0x00e4 -> LATIN SMALL LETTER N WITH ACUTE + u'\u0148' # 0x00e5 -> LATIN SMALL LETTER N WITH CARON + u'\u0160' # 0x00e6 -> LATIN CAPITAL LETTER S WITH CARON + u'\u0161' # 0x00e7 -> LATIN SMALL LETTER S WITH CARON + u'\u0154' # 0x00e8 -> LATIN CAPITAL LETTER R WITH ACUTE + u'\xda' # 0x00e9 -> LATIN CAPITAL LETTER U WITH ACUTE + u'\u0155' # 0x00ea -> LATIN SMALL LETTER R WITH ACUTE + u'\u0170' # 0x00eb -> LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + u'\xfd' # 0x00ec -> LATIN SMALL LETTER Y WITH ACUTE + u'\xdd' # 0x00ed -> LATIN CAPITAL LETTER Y WITH ACUTE + u'\u0163' # 0x00ee -> LATIN SMALL LETTER T WITH CEDILLA + u'\xb4' # 0x00ef -> ACUTE ACCENT + u'\xad' # 0x00f0 -> SOFT HYPHEN + u'\u02dd' # 0x00f1 -> DOUBLE ACUTE ACCENT + u'\u02db' # 0x00f2 -> OGONEK + u'\u02c7' # 0x00f3 -> CARON + u'\u02d8' # 0x00f4 -> BREVE + u'\xa7' # 0x00f5 -> SECTION SIGN + u'\xf7' # 0x00f6 -> DIVISION SIGN + u'\xb8' # 0x00f7 -> CEDILLA + u'\xb0' # 0x00f8 -> DEGREE SIGN + u'\xa8' # 0x00f9 -> DIAERESIS + u'\u02d9' # 0x00fa -> DOT ABOVE + u'\u0171' # 0x00fb -> LATIN SMALL LETTER U WITH DOUBLE ACUTE + u'\u0158' # 0x00fc -> LATIN CAPITAL LETTER R WITH CARON + u'\u0159' # 0x00fd -> LATIN SMALL LETTER R WITH CARON + u'\u25a0' # 0x00fe -> BLACK SQUARE + u'\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a4: 0x00cf, # CURRENCY SIGN + 0x00a7: 0x00f5, # SECTION SIGN + 0x00a8: 0x00f9, # DIAERESIS + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00ad: 0x00f0, # SOFT HYPHEN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b4: 0x00ef, # ACUTE ACCENT + 0x00b8: 0x00f7, # CEDILLA + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00c1: 0x00b5, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00c2: 0x00b6, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00c4: 0x008e, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00cb: 0x00d3, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00cd: 0x00d6, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00ce: 0x00d7, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00d3: 0x00e0, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00d4: 0x00e2, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00d6: 0x0099, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00d7: 0x009e, # MULTIPLICATION SIGN + 0x00da: 0x00e9, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00dd: 0x00ed, # LATIN CAPITAL LETTER Y WITH ACUTE + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e4: 0x0084, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00eb: 0x0089, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00ee: 0x008c, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f6: 0x0094, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00fd: 0x00ec, # LATIN SMALL LETTER Y WITH ACUTE + 0x0102: 0x00c6, # LATIN CAPITAL LETTER A WITH BREVE + 0x0103: 0x00c7, # LATIN SMALL LETTER A WITH BREVE + 0x0104: 0x00a4, # LATIN CAPITAL LETTER A WITH OGONEK + 0x0105: 0x00a5, # LATIN SMALL LETTER A WITH OGONEK + 0x0106: 0x008f, # LATIN CAPITAL LETTER C WITH ACUTE + 0x0107: 0x0086, # LATIN SMALL LETTER C WITH ACUTE + 0x010c: 0x00ac, # LATIN CAPITAL LETTER C WITH CARON + 0x010d: 0x009f, # LATIN SMALL LETTER C WITH CARON + 0x010e: 0x00d2, # LATIN CAPITAL LETTER D WITH CARON + 0x010f: 0x00d4, # LATIN SMALL LETTER D WITH CARON + 0x0110: 0x00d1, # LATIN CAPITAL LETTER D WITH STROKE + 0x0111: 0x00d0, # LATIN SMALL LETTER D WITH STROKE + 0x0118: 0x00a8, # LATIN CAPITAL LETTER E WITH OGONEK + 0x0119: 0x00a9, # LATIN SMALL LETTER E WITH OGONEK + 0x011a: 0x00b7, # LATIN CAPITAL LETTER E WITH CARON + 0x011b: 0x00d8, # LATIN SMALL LETTER E WITH CARON + 0x0139: 0x0091, # LATIN CAPITAL LETTER L WITH ACUTE + 0x013a: 0x0092, # LATIN SMALL LETTER L WITH ACUTE + 0x013d: 0x0095, # LATIN CAPITAL LETTER L WITH CARON + 0x013e: 0x0096, # LATIN SMALL LETTER L WITH CARON + 0x0141: 0x009d, # LATIN CAPITAL LETTER L WITH STROKE + 0x0142: 0x0088, # LATIN SMALL LETTER L WITH STROKE + 0x0143: 0x00e3, # LATIN CAPITAL LETTER N WITH ACUTE + 0x0144: 0x00e4, # LATIN SMALL LETTER N WITH ACUTE + 0x0147: 0x00d5, # LATIN CAPITAL LETTER N WITH CARON + 0x0148: 0x00e5, # LATIN SMALL LETTER N WITH CARON + 0x0150: 0x008a, # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + 0x0151: 0x008b, # LATIN SMALL LETTER O WITH DOUBLE ACUTE + 0x0154: 0x00e8, # LATIN CAPITAL LETTER R WITH ACUTE + 0x0155: 0x00ea, # LATIN SMALL LETTER R WITH ACUTE + 0x0158: 0x00fc, # LATIN CAPITAL LETTER R WITH CARON + 0x0159: 0x00fd, # LATIN SMALL LETTER R WITH CARON + 0x015a: 0x0097, # LATIN CAPITAL LETTER S WITH ACUTE + 0x015b: 0x0098, # LATIN SMALL LETTER S WITH ACUTE + 0x015e: 0x00b8, # LATIN CAPITAL LETTER S WITH CEDILLA + 0x015f: 0x00ad, # LATIN SMALL LETTER S WITH CEDILLA + 0x0160: 0x00e6, # LATIN CAPITAL LETTER S WITH CARON + 0x0161: 0x00e7, # LATIN SMALL LETTER S WITH CARON + 0x0162: 0x00dd, # LATIN CAPITAL LETTER T WITH CEDILLA + 0x0163: 0x00ee, # LATIN SMALL LETTER T WITH CEDILLA + 0x0164: 0x009b, # LATIN CAPITAL LETTER T WITH CARON + 0x0165: 0x009c, # LATIN SMALL LETTER T WITH CARON + 0x016e: 0x00de, # LATIN CAPITAL LETTER U WITH RING ABOVE + 0x016f: 0x0085, # LATIN SMALL LETTER U WITH RING ABOVE + 0x0170: 0x00eb, # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + 0x0171: 0x00fb, # LATIN SMALL LETTER U WITH DOUBLE ACUTE + 0x0179: 0x008d, # LATIN CAPITAL LETTER Z WITH ACUTE + 0x017a: 0x00ab, # LATIN SMALL LETTER Z WITH ACUTE + 0x017b: 0x00bd, # LATIN CAPITAL LETTER Z WITH DOT ABOVE + 0x017c: 0x00be, # LATIN SMALL LETTER Z WITH DOT ABOVE + 0x017d: 0x00a6, # LATIN CAPITAL LETTER Z WITH CARON + 0x017e: 0x00a7, # LATIN SMALL LETTER Z WITH CARON + 0x02c7: 0x00f3, # CARON + 0x02d8: 0x00f4, # BREVE + 0x02d9: 0x00fa, # DOT ABOVE + 0x02db: 0x00f2, # OGONEK + 0x02dd: 0x00f1, # DOUBLE ACUTE ACCENT + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/PythonHome/Lib/encodings/cp852.pyc b/PythonHome/Lib/encodings/cp852.pyc deleted file mode 100644 index 24383e76c52ea0afa09e9a62e71fd43ceda0a61d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7945 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 NULL + u'\x01' # 0x0001 -> START OF HEADING + u'\x02' # 0x0002 -> START OF TEXT + u'\x03' # 0x0003 -> END OF TEXT + u'\x04' # 0x0004 -> END OF TRANSMISSION + u'\x05' # 0x0005 -> ENQUIRY + u'\x06' # 0x0006 -> ACKNOWLEDGE + u'\x07' # 0x0007 -> BELL + u'\x08' # 0x0008 -> BACKSPACE + u'\t' # 0x0009 -> HORIZONTAL TABULATION + u'\n' # 0x000a -> LINE FEED + u'\x0b' # 0x000b -> VERTICAL TABULATION + u'\x0c' # 0x000c -> FORM FEED + u'\r' # 0x000d -> CARRIAGE RETURN + u'\x0e' # 0x000e -> SHIFT OUT + u'\x0f' # 0x000f -> SHIFT IN + u'\x10' # 0x0010 -> DATA LINK ESCAPE + u'\x11' # 0x0011 -> DEVICE CONTROL ONE + u'\x12' # 0x0012 -> DEVICE CONTROL TWO + u'\x13' # 0x0013 -> DEVICE CONTROL THREE + u'\x14' # 0x0014 -> DEVICE CONTROL FOUR + u'\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x0016 -> SYNCHRONOUS IDLE + u'\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x0018 -> CANCEL + u'\x19' # 0x0019 -> END OF MEDIUM + u'\x1a' # 0x001a -> SUBSTITUTE + u'\x1b' # 0x001b -> ESCAPE + u'\x1c' # 0x001c -> FILE SEPARATOR + u'\x1d' # 0x001d -> GROUP SEPARATOR + u'\x1e' # 0x001e -> RECORD SEPARATOR + u'\x1f' # 0x001f -> UNIT SEPARATOR + u' ' # 0x0020 -> SPACE + u'!' # 0x0021 -> EXCLAMATION MARK + u'"' # 0x0022 -> QUOTATION MARK + u'#' # 0x0023 -> NUMBER SIGN + u'$' # 0x0024 -> DOLLAR SIGN + u'%' # 0x0025 -> PERCENT SIGN + u'&' # 0x0026 -> AMPERSAND + u"'" # 0x0027 -> APOSTROPHE + u'(' # 0x0028 -> LEFT PARENTHESIS + u')' # 0x0029 -> RIGHT PARENTHESIS + u'*' # 0x002a -> ASTERISK + u'+' # 0x002b -> PLUS SIGN + u',' # 0x002c -> COMMA + u'-' # 0x002d -> HYPHEN-MINUS + u'.' # 0x002e -> FULL STOP + u'/' # 0x002f -> SOLIDUS + u'0' # 0x0030 -> DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE + u':' # 0x003a -> COLON + u';' # 0x003b -> SEMICOLON + u'<' # 0x003c -> LESS-THAN SIGN + u'=' # 0x003d -> EQUALS SIGN + u'>' # 0x003e -> GREATER-THAN SIGN + u'?' # 0x003f -> QUESTION MARK + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET + u'\\' # 0x005c -> REVERSE SOLIDUS + u']' # 0x005d -> RIGHT SQUARE BRACKET + u'^' # 0x005e -> CIRCUMFLEX ACCENT + u'_' # 0x005f -> LOW LINE + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET + u'|' # 0x007c -> VERTICAL LINE + u'}' # 0x007d -> RIGHT CURLY BRACKET + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> DELETE + u'\u0452' # 0x0080 -> CYRILLIC SMALL LETTER DJE + u'\u0402' # 0x0081 -> CYRILLIC CAPITAL LETTER DJE + u'\u0453' # 0x0082 -> CYRILLIC SMALL LETTER GJE + u'\u0403' # 0x0083 -> CYRILLIC CAPITAL LETTER GJE + u'\u0451' # 0x0084 -> CYRILLIC SMALL LETTER IO + u'\u0401' # 0x0085 -> CYRILLIC CAPITAL LETTER IO + u'\u0454' # 0x0086 -> CYRILLIC SMALL LETTER UKRAINIAN IE + u'\u0404' # 0x0087 -> CYRILLIC CAPITAL LETTER UKRAINIAN IE + u'\u0455' # 0x0088 -> CYRILLIC SMALL LETTER DZE + u'\u0405' # 0x0089 -> CYRILLIC CAPITAL LETTER DZE + u'\u0456' # 0x008a -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + u'\u0406' # 0x008b -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + u'\u0457' # 0x008c -> CYRILLIC SMALL LETTER YI + u'\u0407' # 0x008d -> CYRILLIC CAPITAL LETTER YI + u'\u0458' # 0x008e -> CYRILLIC SMALL LETTER JE + u'\u0408' # 0x008f -> CYRILLIC CAPITAL LETTER JE + u'\u0459' # 0x0090 -> CYRILLIC SMALL LETTER LJE + u'\u0409' # 0x0091 -> CYRILLIC CAPITAL LETTER LJE + u'\u045a' # 0x0092 -> CYRILLIC SMALL LETTER NJE + u'\u040a' # 0x0093 -> CYRILLIC CAPITAL LETTER NJE + u'\u045b' # 0x0094 -> CYRILLIC SMALL LETTER TSHE + u'\u040b' # 0x0095 -> CYRILLIC CAPITAL LETTER TSHE + u'\u045c' # 0x0096 -> CYRILLIC SMALL LETTER KJE + u'\u040c' # 0x0097 -> CYRILLIC CAPITAL LETTER KJE + u'\u045e' # 0x0098 -> CYRILLIC SMALL LETTER SHORT U + u'\u040e' # 0x0099 -> CYRILLIC CAPITAL LETTER SHORT U + u'\u045f' # 0x009a -> CYRILLIC SMALL LETTER DZHE + u'\u040f' # 0x009b -> CYRILLIC CAPITAL LETTER DZHE + u'\u044e' # 0x009c -> CYRILLIC SMALL LETTER YU + u'\u042e' # 0x009d -> CYRILLIC CAPITAL LETTER YU + u'\u044a' # 0x009e -> CYRILLIC SMALL LETTER HARD SIGN + u'\u042a' # 0x009f -> CYRILLIC CAPITAL LETTER HARD SIGN + u'\u0430' # 0x00a0 -> CYRILLIC SMALL LETTER A + u'\u0410' # 0x00a1 -> CYRILLIC CAPITAL LETTER A + u'\u0431' # 0x00a2 -> CYRILLIC SMALL LETTER BE + u'\u0411' # 0x00a3 -> CYRILLIC CAPITAL LETTER BE + u'\u0446' # 0x00a4 -> CYRILLIC SMALL LETTER TSE + u'\u0426' # 0x00a5 -> CYRILLIC CAPITAL LETTER TSE + u'\u0434' # 0x00a6 -> CYRILLIC SMALL LETTER DE + u'\u0414' # 0x00a7 -> CYRILLIC CAPITAL LETTER DE + u'\u0435' # 0x00a8 -> CYRILLIC SMALL LETTER IE + u'\u0415' # 0x00a9 -> CYRILLIC CAPITAL LETTER IE + u'\u0444' # 0x00aa -> CYRILLIC SMALL LETTER EF + u'\u0424' # 0x00ab -> CYRILLIC CAPITAL LETTER EF + u'\u0433' # 0x00ac -> CYRILLIC SMALL LETTER GHE + u'\u0413' # 0x00ad -> CYRILLIC CAPITAL LETTER GHE + u'\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2591' # 0x00b0 -> LIGHT SHADE + u'\u2592' # 0x00b1 -> MEDIUM SHADE + u'\u2593' # 0x00b2 -> DARK SHADE + u'\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\u0445' # 0x00b5 -> CYRILLIC SMALL LETTER HA + u'\u0425' # 0x00b6 -> CYRILLIC CAPITAL LETTER HA + u'\u0438' # 0x00b7 -> CYRILLIC SMALL LETTER I + u'\u0418' # 0x00b8 -> CYRILLIC CAPITAL LETTER I + u'\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\u0439' # 0x00bd -> CYRILLIC SMALL LETTER SHORT I + u'\u0419' # 0x00be -> CYRILLIC CAPITAL LETTER SHORT I + u'\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\u043a' # 0x00c6 -> CYRILLIC SMALL LETTER KA + u'\u041a' # 0x00c7 -> CYRILLIC CAPITAL LETTER KA + u'\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\xa4' # 0x00cf -> CURRENCY SIGN + u'\u043b' # 0x00d0 -> CYRILLIC SMALL LETTER EL + u'\u041b' # 0x00d1 -> CYRILLIC CAPITAL LETTER EL + u'\u043c' # 0x00d2 -> CYRILLIC SMALL LETTER EM + u'\u041c' # 0x00d3 -> CYRILLIC CAPITAL LETTER EM + u'\u043d' # 0x00d4 -> CYRILLIC SMALL LETTER EN + u'\u041d' # 0x00d5 -> CYRILLIC CAPITAL LETTER EN + u'\u043e' # 0x00d6 -> CYRILLIC SMALL LETTER O + u'\u041e' # 0x00d7 -> CYRILLIC CAPITAL LETTER O + u'\u043f' # 0x00d8 -> CYRILLIC SMALL LETTER PE + u'\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0x00db -> FULL BLOCK + u'\u2584' # 0x00dc -> LOWER HALF BLOCK + u'\u041f' # 0x00dd -> CYRILLIC CAPITAL LETTER PE + u'\u044f' # 0x00de -> CYRILLIC SMALL LETTER YA + u'\u2580' # 0x00df -> UPPER HALF BLOCK + u'\u042f' # 0x00e0 -> CYRILLIC CAPITAL LETTER YA + u'\u0440' # 0x00e1 -> CYRILLIC SMALL LETTER ER + u'\u0420' # 0x00e2 -> CYRILLIC CAPITAL LETTER ER + u'\u0441' # 0x00e3 -> CYRILLIC SMALL LETTER ES + u'\u0421' # 0x00e4 -> CYRILLIC CAPITAL LETTER ES + u'\u0442' # 0x00e5 -> CYRILLIC SMALL LETTER TE + u'\u0422' # 0x00e6 -> CYRILLIC CAPITAL LETTER TE + u'\u0443' # 0x00e7 -> CYRILLIC SMALL LETTER U + u'\u0423' # 0x00e8 -> CYRILLIC CAPITAL LETTER U + u'\u0436' # 0x00e9 -> CYRILLIC SMALL LETTER ZHE + u'\u0416' # 0x00ea -> CYRILLIC CAPITAL LETTER ZHE + u'\u0432' # 0x00eb -> CYRILLIC SMALL LETTER VE + u'\u0412' # 0x00ec -> CYRILLIC CAPITAL LETTER VE + u'\u044c' # 0x00ed -> CYRILLIC SMALL LETTER SOFT SIGN + u'\u042c' # 0x00ee -> CYRILLIC CAPITAL LETTER SOFT SIGN + u'\u2116' # 0x00ef -> NUMERO SIGN + u'\xad' # 0x00f0 -> SOFT HYPHEN + u'\u044b' # 0x00f1 -> CYRILLIC SMALL LETTER YERU + u'\u042b' # 0x00f2 -> CYRILLIC CAPITAL LETTER YERU + u'\u0437' # 0x00f3 -> CYRILLIC SMALL LETTER ZE + u'\u0417' # 0x00f4 -> CYRILLIC CAPITAL LETTER ZE + u'\u0448' # 0x00f5 -> CYRILLIC SMALL LETTER SHA + u'\u0428' # 0x00f6 -> CYRILLIC CAPITAL LETTER SHA + u'\u044d' # 0x00f7 -> CYRILLIC SMALL LETTER E + u'\u042d' # 0x00f8 -> CYRILLIC CAPITAL LETTER E + u'\u0449' # 0x00f9 -> CYRILLIC SMALL LETTER SHCHA + u'\u0429' # 0x00fa -> CYRILLIC CAPITAL LETTER SHCHA + u'\u0447' # 0x00fb -> CYRILLIC SMALL LETTER CHE + u'\u0427' # 0x00fc -> CYRILLIC CAPITAL LETTER CHE + u'\xa7' # 0x00fd -> SECTION SIGN + u'\u25a0' # 0x00fe -> BLACK SQUARE + u'\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a4: 0x00cf, # CURRENCY SIGN + 0x00a7: 0x00fd, # SECTION SIGN + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ad: 0x00f0, # SOFT HYPHEN + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x0401: 0x0085, # CYRILLIC CAPITAL LETTER IO + 0x0402: 0x0081, # CYRILLIC CAPITAL LETTER DJE + 0x0403: 0x0083, # CYRILLIC CAPITAL LETTER GJE + 0x0404: 0x0087, # CYRILLIC CAPITAL LETTER UKRAINIAN IE + 0x0405: 0x0089, # CYRILLIC CAPITAL LETTER DZE + 0x0406: 0x008b, # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + 0x0407: 0x008d, # CYRILLIC CAPITAL LETTER YI + 0x0408: 0x008f, # CYRILLIC CAPITAL LETTER JE + 0x0409: 0x0091, # CYRILLIC CAPITAL LETTER LJE + 0x040a: 0x0093, # CYRILLIC CAPITAL LETTER NJE + 0x040b: 0x0095, # CYRILLIC CAPITAL LETTER TSHE + 0x040c: 0x0097, # CYRILLIC CAPITAL LETTER KJE + 0x040e: 0x0099, # CYRILLIC CAPITAL LETTER SHORT U + 0x040f: 0x009b, # CYRILLIC CAPITAL LETTER DZHE + 0x0410: 0x00a1, # CYRILLIC CAPITAL LETTER A + 0x0411: 0x00a3, # CYRILLIC CAPITAL LETTER BE + 0x0412: 0x00ec, # CYRILLIC CAPITAL LETTER VE + 0x0413: 0x00ad, # CYRILLIC CAPITAL LETTER GHE + 0x0414: 0x00a7, # CYRILLIC CAPITAL LETTER DE + 0x0415: 0x00a9, # CYRILLIC CAPITAL LETTER IE + 0x0416: 0x00ea, # CYRILLIC CAPITAL LETTER ZHE + 0x0417: 0x00f4, # CYRILLIC CAPITAL LETTER ZE + 0x0418: 0x00b8, # CYRILLIC CAPITAL LETTER I + 0x0419: 0x00be, # CYRILLIC CAPITAL LETTER SHORT I + 0x041a: 0x00c7, # CYRILLIC CAPITAL LETTER KA + 0x041b: 0x00d1, # CYRILLIC CAPITAL LETTER EL + 0x041c: 0x00d3, # CYRILLIC CAPITAL LETTER EM + 0x041d: 0x00d5, # CYRILLIC CAPITAL LETTER EN + 0x041e: 0x00d7, # CYRILLIC CAPITAL LETTER O + 0x041f: 0x00dd, # CYRILLIC CAPITAL LETTER PE + 0x0420: 0x00e2, # CYRILLIC CAPITAL LETTER ER + 0x0421: 0x00e4, # CYRILLIC CAPITAL LETTER ES + 0x0422: 0x00e6, # CYRILLIC CAPITAL LETTER TE + 0x0423: 0x00e8, # CYRILLIC CAPITAL LETTER U + 0x0424: 0x00ab, # CYRILLIC CAPITAL LETTER EF + 0x0425: 0x00b6, # CYRILLIC CAPITAL LETTER HA + 0x0426: 0x00a5, # CYRILLIC CAPITAL LETTER TSE + 0x0427: 0x00fc, # CYRILLIC CAPITAL LETTER CHE + 0x0428: 0x00f6, # CYRILLIC CAPITAL LETTER SHA + 0x0429: 0x00fa, # CYRILLIC CAPITAL LETTER SHCHA + 0x042a: 0x009f, # CYRILLIC CAPITAL LETTER HARD SIGN + 0x042b: 0x00f2, # CYRILLIC CAPITAL LETTER YERU + 0x042c: 0x00ee, # CYRILLIC CAPITAL LETTER SOFT SIGN + 0x042d: 0x00f8, # CYRILLIC CAPITAL LETTER E + 0x042e: 0x009d, # CYRILLIC CAPITAL LETTER YU + 0x042f: 0x00e0, # CYRILLIC CAPITAL LETTER YA + 0x0430: 0x00a0, # CYRILLIC SMALL LETTER A + 0x0431: 0x00a2, # CYRILLIC SMALL LETTER BE + 0x0432: 0x00eb, # CYRILLIC SMALL LETTER VE + 0x0433: 0x00ac, # CYRILLIC SMALL LETTER GHE + 0x0434: 0x00a6, # CYRILLIC SMALL LETTER DE + 0x0435: 0x00a8, # CYRILLIC SMALL LETTER IE + 0x0436: 0x00e9, # CYRILLIC SMALL LETTER ZHE + 0x0437: 0x00f3, # CYRILLIC SMALL LETTER ZE + 0x0438: 0x00b7, # CYRILLIC SMALL LETTER I + 0x0439: 0x00bd, # CYRILLIC SMALL LETTER SHORT I + 0x043a: 0x00c6, # CYRILLIC SMALL LETTER KA + 0x043b: 0x00d0, # CYRILLIC SMALL LETTER EL + 0x043c: 0x00d2, # CYRILLIC SMALL LETTER EM + 0x043d: 0x00d4, # CYRILLIC SMALL LETTER EN + 0x043e: 0x00d6, # CYRILLIC SMALL LETTER O + 0x043f: 0x00d8, # CYRILLIC SMALL LETTER PE + 0x0440: 0x00e1, # CYRILLIC SMALL LETTER ER + 0x0441: 0x00e3, # CYRILLIC SMALL LETTER ES + 0x0442: 0x00e5, # CYRILLIC SMALL LETTER TE + 0x0443: 0x00e7, # CYRILLIC SMALL LETTER U + 0x0444: 0x00aa, # CYRILLIC SMALL LETTER EF + 0x0445: 0x00b5, # CYRILLIC SMALL LETTER HA + 0x0446: 0x00a4, # CYRILLIC SMALL LETTER TSE + 0x0447: 0x00fb, # CYRILLIC SMALL LETTER CHE + 0x0448: 0x00f5, # CYRILLIC SMALL LETTER SHA + 0x0449: 0x00f9, # CYRILLIC SMALL LETTER SHCHA + 0x044a: 0x009e, # CYRILLIC SMALL LETTER HARD SIGN + 0x044b: 0x00f1, # CYRILLIC SMALL LETTER YERU + 0x044c: 0x00ed, # CYRILLIC SMALL LETTER SOFT SIGN + 0x044d: 0x00f7, # CYRILLIC SMALL LETTER E + 0x044e: 0x009c, # CYRILLIC SMALL LETTER YU + 0x044f: 0x00de, # CYRILLIC SMALL LETTER YA + 0x0451: 0x0084, # CYRILLIC SMALL LETTER IO + 0x0452: 0x0080, # CYRILLIC SMALL LETTER DJE + 0x0453: 0x0082, # CYRILLIC SMALL LETTER GJE + 0x0454: 0x0086, # CYRILLIC SMALL LETTER UKRAINIAN IE + 0x0455: 0x0088, # CYRILLIC SMALL LETTER DZE + 0x0456: 0x008a, # CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + 0x0457: 0x008c, # CYRILLIC SMALL LETTER YI + 0x0458: 0x008e, # CYRILLIC SMALL LETTER JE + 0x0459: 0x0090, # CYRILLIC SMALL LETTER LJE + 0x045a: 0x0092, # CYRILLIC SMALL LETTER NJE + 0x045b: 0x0094, # CYRILLIC SMALL LETTER TSHE + 0x045c: 0x0096, # CYRILLIC SMALL LETTER KJE + 0x045e: 0x0098, # CYRILLIC SMALL LETTER SHORT U + 0x045f: 0x009a, # CYRILLIC SMALL LETTER DZHE + 0x2116: 0x00ef, # NUMERO SIGN + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/PythonHome/Lib/encodings/cp855.pyc b/PythonHome/Lib/encodings/cp855.pyc deleted file mode 100644 index e75ba1a519c0136b96c082f7d2dd196a49896441..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8126 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 diff --git a/PythonHome/Lib/encodings/cp856.py b/PythonHome/Lib/encodings/cp856.py new file mode 100644 index 0000000000..203c2c4ca0 --- /dev/null +++ b/PythonHome/Lib/encodings/cp856.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp856 generated from 'MAPPINGS/VENDORS/MISC/CP856.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp856', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\u05d0' # 0x80 -> HEBREW LETTER ALEF + u'\u05d1' # 0x81 -> HEBREW LETTER BET + u'\u05d2' # 0x82 -> HEBREW LETTER GIMEL + u'\u05d3' # 0x83 -> HEBREW LETTER DALET + u'\u05d4' # 0x84 -> HEBREW LETTER HE + u'\u05d5' # 0x85 -> HEBREW LETTER VAV + u'\u05d6' # 0x86 -> HEBREW LETTER ZAYIN + u'\u05d7' # 0x87 -> HEBREW LETTER HET + u'\u05d8' # 0x88 -> HEBREW LETTER TET + u'\u05d9' # 0x89 -> HEBREW LETTER YOD + u'\u05da' # 0x8A -> HEBREW LETTER FINAL KAF + u'\u05db' # 0x8B -> HEBREW LETTER KAF + u'\u05dc' # 0x8C -> HEBREW LETTER LAMED + u'\u05dd' # 0x8D -> HEBREW LETTER FINAL MEM + u'\u05de' # 0x8E -> HEBREW LETTER MEM + u'\u05df' # 0x8F -> HEBREW LETTER FINAL NUN + u'\u05e0' # 0x90 -> HEBREW LETTER NUN + u'\u05e1' # 0x91 -> HEBREW LETTER SAMEKH + u'\u05e2' # 0x92 -> HEBREW LETTER AYIN + u'\u05e3' # 0x93 -> HEBREW LETTER FINAL PE + u'\u05e4' # 0x94 -> HEBREW LETTER PE + u'\u05e5' # 0x95 -> HEBREW LETTER FINAL TSADI + u'\u05e6' # 0x96 -> HEBREW LETTER TSADI + u'\u05e7' # 0x97 -> HEBREW LETTER QOF + u'\u05e8' # 0x98 -> HEBREW LETTER RESH + u'\u05e9' # 0x99 -> HEBREW LETTER SHIN + u'\u05ea' # 0x9A -> HEBREW LETTER TAV + u'\ufffe' # 0x9B -> UNDEFINED + u'\xa3' # 0x9C -> POUND SIGN + u'\ufffe' # 0x9D -> UNDEFINED + u'\xd7' # 0x9E -> MULTIPLICATION SIGN + u'\ufffe' # 0x9F -> UNDEFINED + u'\ufffe' # 0xA0 -> UNDEFINED + u'\ufffe' # 0xA1 -> UNDEFINED + u'\ufffe' # 0xA2 -> UNDEFINED + u'\ufffe' # 0xA3 -> UNDEFINED + u'\ufffe' # 0xA4 -> UNDEFINED + u'\ufffe' # 0xA5 -> UNDEFINED + u'\ufffe' # 0xA6 -> UNDEFINED + u'\ufffe' # 0xA7 -> UNDEFINED + u'\ufffe' # 0xA8 -> UNDEFINED + u'\xae' # 0xA9 -> REGISTERED SIGN + u'\xac' # 0xAA -> NOT SIGN + u'\xbd' # 0xAB -> VULGAR FRACTION ONE HALF + u'\xbc' # 0xAC -> VULGAR FRACTION ONE QUARTER + u'\ufffe' # 0xAD -> UNDEFINED + u'\xab' # 0xAE -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0xAF -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2591' # 0xB0 -> LIGHT SHADE + u'\u2592' # 0xB1 -> MEDIUM SHADE + u'\u2593' # 0xB2 -> DARK SHADE + u'\u2502' # 0xB3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0xB4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\ufffe' # 0xB5 -> UNDEFINED + u'\ufffe' # 0xB6 -> UNDEFINED + u'\ufffe' # 0xB7 -> UNDEFINED + u'\xa9' # 0xB8 -> COPYRIGHT SIGN + u'\u2563' # 0xB9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0xBA -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0xBB -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0xBC -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\xa2' # 0xBD -> CENT SIGN + u'\xa5' # 0xBE -> YEN SIGN + u'\u2510' # 0xBF -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0xC0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0xC1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0xC2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0xC3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0xC4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0xC5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\ufffe' # 0xC6 -> UNDEFINED + u'\ufffe' # 0xC7 -> UNDEFINED + u'\u255a' # 0xC8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0xC9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0xCA -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0xCB -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0xCC -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0xCD -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0xCE -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\xa4' # 0xCF -> CURRENCY SIGN + u'\ufffe' # 0xD0 -> UNDEFINED + u'\ufffe' # 0xD1 -> UNDEFINED + u'\ufffe' # 0xD2 -> UNDEFINED + u'\ufffe' # 0xD3 -> UNDEFINEDS + u'\ufffe' # 0xD4 -> UNDEFINED + u'\ufffe' # 0xD5 -> UNDEFINED + u'\ufffe' # 0xD6 -> UNDEFINEDE + u'\ufffe' # 0xD7 -> UNDEFINED + u'\ufffe' # 0xD8 -> UNDEFINED + u'\u2518' # 0xD9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0xDA -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0xDB -> FULL BLOCK + u'\u2584' # 0xDC -> LOWER HALF BLOCK + u'\xa6' # 0xDD -> BROKEN BAR + u'\ufffe' # 0xDE -> UNDEFINED + u'\u2580' # 0xDF -> UPPER HALF BLOCK + u'\ufffe' # 0xE0 -> UNDEFINED + u'\ufffe' # 0xE1 -> UNDEFINED + u'\ufffe' # 0xE2 -> UNDEFINED + u'\ufffe' # 0xE3 -> UNDEFINED + u'\ufffe' # 0xE4 -> UNDEFINED + u'\ufffe' # 0xE5 -> UNDEFINED + u'\xb5' # 0xE6 -> MICRO SIGN + u'\ufffe' # 0xE7 -> UNDEFINED + u'\ufffe' # 0xE8 -> UNDEFINED + u'\ufffe' # 0xE9 -> UNDEFINED + u'\ufffe' # 0xEA -> UNDEFINED + u'\ufffe' # 0xEB -> UNDEFINED + u'\ufffe' # 0xEC -> UNDEFINED + u'\ufffe' # 0xED -> UNDEFINED + u'\xaf' # 0xEE -> MACRON + u'\xb4' # 0xEF -> ACUTE ACCENT + u'\xad' # 0xF0 -> SOFT HYPHEN + u'\xb1' # 0xF1 -> PLUS-MINUS SIGN + u'\u2017' # 0xF2 -> DOUBLE LOW LINE + u'\xbe' # 0xF3 -> VULGAR FRACTION THREE QUARTERS + u'\xb6' # 0xF4 -> PILCROW SIGN + u'\xa7' # 0xF5 -> SECTION SIGN + u'\xf7' # 0xF6 -> DIVISION SIGN + u'\xb8' # 0xF7 -> CEDILLA + u'\xb0' # 0xF8 -> DEGREE SIGN + u'\xa8' # 0xF9 -> DIAERESIS + u'\xb7' # 0xFA -> MIDDLE DOT + u'\xb9' # 0xFB -> SUPERSCRIPT ONE + u'\xb3' # 0xFC -> SUPERSCRIPT THREE + u'\xb2' # 0xFD -> SUPERSCRIPT TWO + u'\u25a0' # 0xFE -> BLACK SQUARE + u'\xa0' # 0xFF -> NO-BREAK SPACE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp856.pyc b/PythonHome/Lib/encodings/cp856.pyc deleted file mode 100644 index dd163eb8e26a3be58247227c99a4f7b5e8eb2569..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2756 zcmc&$TUQ%Z6h65U!mW3k7B%%oyn(mYsW ze%s(7YK<^>g&|-YyhN=fnp@a>Bn1wFw#`S>x{A#&Z1uLyPt*o{NYoIukt71b0eA|K zNeD2Ak;WrUn7{~#aPPP=oX>@$!?G?bhNg#m+S819f-Fb?uvCDlHzSW-SKE!v=`oO?K{%f5*|w%!?;R8C#{9?)?hGw z13ods2b&7lHlS{p>A-lxAT$UZfD@QbLA;PQ=x&0#he+`V!f*KTbwf`phJw#HyfC6T zy%B^#$cT#^ho74mZZheClwB|%bC!$9ibf;MDv*0tE+nmR#gtG1g`^=5W;AOR?oiY+ zDUm`tR~R)!9Gb4@^;ZAz-OPcbGeI{hK5tT)HBB zKpM~%Q$k%CzJ$O_2%J;{VlDAnjuEMw@kS5|BLE_q%*k0TnKXjpA)8l6Gw>*(O~MSF zeS}sO90}ehwJ?h4-|w#X7#l$8&MCT<)pCZM=@Q843e1X+O`T2fXi*1lj7l83;Hm!= z-fb}Ja0JK#H1Qx!;3kLS5p)|%gCHVP0kwoA6VOQ*ouGt+so+E^os%<8!qsy{gfP41 zkV^HqM*|4qZ@-)=Y642f=|4ab4{CkIv){EE!%jhy{|7@nTnj_w%PI^dEJ{wM)!{>K zZGrLk@JZ{yw08a>YMU!g0XaO5xS?xuwqH*}ZM1oZtm?oQ@f0oIL1_Y=2<|xN=%gdG z>Nz1DLNG*5E4G(3S^dwq$HLj{Y;Pxv#}dW)b`aLBu^Jwf!4b-_hTYJ}$S%>+{zHYJ+w44UJ9f)^FIjY4es_wuZKCZ@%@m+rvBVxbv>N z?`etLd*A&JJlNXy(8G^B`q<80kMDls$*1-_z4w{+eI3!xuKfp|?SAh0gFUfBy)Q`d zz84SoA32(MY2f8olE>shMb%P6!|9P%Gud3e@S0vUMqeL$WBkpxj=%lRyKI`xuoLVg zGg*n1*(^K7K4hoaN9+tc%RXkGusQZAJIChPd3J#n!o5LJHk zOS(vZp+DpMpVOasd4`uy@bXD+zQ@h;_Ck7@m*#nChL>h}=`1}*FK~03neM&tF3VJ6gNNM<@b4ciY}mw@`P=)75crc zE?4MR^a}lge#0kb={0(lUcA0Uf1qE}OLU3;NWY`s^70&=i{POH!Lbvnc?CKj_700# z4xf-p7OA$QhPBVYDqs1>V{kN`QLVNDv&&dlwO)t@yvJ&}dp)qOh+PocrZ*G_c|+c2 NPqVMK$$x`*{{#-qq~QPn diff --git a/PythonHome/Lib/encodings/cp857.py b/PythonHome/Lib/encodings/cp857.py new file mode 100644 index 0000000000..c24191b04d --- /dev/null +++ b/PythonHome/Lib/encodings/cp857.py @@ -0,0 +1,694 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP857.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp857', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x00c7, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x0081: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0082: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x0083: 0x00e2, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x0084: 0x00e4, # LATIN SMALL LETTER A WITH DIAERESIS + 0x0085: 0x00e0, # LATIN SMALL LETTER A WITH GRAVE + 0x0086: 0x00e5, # LATIN SMALL LETTER A WITH RING ABOVE + 0x0087: 0x00e7, # LATIN SMALL LETTER C WITH CEDILLA + 0x0088: 0x00ea, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x0089: 0x00eb, # LATIN SMALL LETTER E WITH DIAERESIS + 0x008a: 0x00e8, # LATIN SMALL LETTER E WITH GRAVE + 0x008b: 0x00ef, # LATIN SMALL LETTER I WITH DIAERESIS + 0x008c: 0x00ee, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x008d: 0x0131, # LATIN SMALL LETTER DOTLESS I + 0x008e: 0x00c4, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x008f: 0x00c5, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x0090: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0091: 0x00e6, # LATIN SMALL LIGATURE AE + 0x0092: 0x00c6, # LATIN CAPITAL LIGATURE AE + 0x0093: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x0094: 0x00f6, # LATIN SMALL LETTER O WITH DIAERESIS + 0x0095: 0x00f2, # LATIN SMALL LETTER O WITH GRAVE + 0x0096: 0x00fb, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x0097: 0x00f9, # LATIN SMALL LETTER U WITH GRAVE + 0x0098: 0x0130, # LATIN CAPITAL LETTER I WITH DOT ABOVE + 0x0099: 0x00d6, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x009a: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x009b: 0x00f8, # LATIN SMALL LETTER O WITH STROKE + 0x009c: 0x00a3, # POUND SIGN + 0x009d: 0x00d8, # LATIN CAPITAL LETTER O WITH STROKE + 0x009e: 0x015e, # LATIN CAPITAL LETTER S WITH CEDILLA + 0x009f: 0x015f, # LATIN SMALL LETTER S WITH CEDILLA + 0x00a0: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE + 0x00a1: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE + 0x00a2: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00a3: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x00a4: 0x00f1, # LATIN SMALL LETTER N WITH TILDE + 0x00a5: 0x00d1, # LATIN CAPITAL LETTER N WITH TILDE + 0x00a6: 0x011e, # LATIN CAPITAL LETTER G WITH BREVE + 0x00a7: 0x011f, # LATIN SMALL LETTER G WITH BREVE + 0x00a8: 0x00bf, # INVERTED QUESTION MARK + 0x00a9: 0x00ae, # REGISTERED SIGN + 0x00aa: 0x00ac, # NOT SIGN + 0x00ab: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00ac: 0x00bc, # VULGAR FRACTION ONE QUARTER + 0x00ad: 0x00a1, # INVERTED EXCLAMATION MARK + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x00c1, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00b6: 0x00c2, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00b7: 0x00c0, # LATIN CAPITAL LETTER A WITH GRAVE + 0x00b8: 0x00a9, # COPYRIGHT SIGN + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x00a2, # CENT SIGN + 0x00be: 0x00a5, # YEN SIGN + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x00e3, # LATIN SMALL LETTER A WITH TILDE + 0x00c7: 0x00c3, # LATIN CAPITAL LETTER A WITH TILDE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x00a4, # CURRENCY SIGN + 0x00d0: 0x00ba, # MASCULINE ORDINAL INDICATOR + 0x00d1: 0x00aa, # FEMININE ORDINAL INDICATOR + 0x00d2: 0x00ca, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00d3: 0x00cb, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00d4: 0x00c8, # LATIN CAPITAL LETTER E WITH GRAVE + 0x00d5: None, # UNDEFINED + 0x00d6: 0x00cd, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00d7: 0x00ce, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00d8: 0x00cf, # LATIN CAPITAL LETTER I WITH DIAERESIS + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x00a6, # BROKEN BAR + 0x00de: 0x00cc, # LATIN CAPITAL LETTER I WITH GRAVE + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x00d3, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00e1: 0x00df, # LATIN SMALL LETTER SHARP S + 0x00e2: 0x00d4, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00e3: 0x00d2, # LATIN CAPITAL LETTER O WITH GRAVE + 0x00e4: 0x00f5, # LATIN SMALL LETTER O WITH TILDE + 0x00e5: 0x00d5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00e6: 0x00b5, # MICRO SIGN + 0x00e7: None, # UNDEFINED + 0x00e8: 0x00d7, # MULTIPLICATION SIGN + 0x00e9: 0x00da, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00ea: 0x00db, # LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x00eb: 0x00d9, # LATIN CAPITAL LETTER U WITH GRAVE + 0x00ed: 0x00ff, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x00ee: 0x00af, # MACRON + 0x00ef: 0x00b4, # ACUTE ACCENT + 0x00f0: 0x00ad, # SOFT HYPHEN + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: None, # UNDEFINED + 0x00f3: 0x00be, # VULGAR FRACTION THREE QUARTERS + 0x00f4: 0x00b6, # PILCROW SIGN + 0x00f5: 0x00a7, # SECTION SIGN + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x00b8, # CEDILLA + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x00a8, # DIAERESIS + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x00b9, # SUPERSCRIPT ONE + 0x00fc: 0x00b3, # SUPERSCRIPT THREE + 0x00fd: 0x00b2, # SUPERSCRIPT TWO + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x0000 -> NULL + u'\x01' # 0x0001 -> START OF HEADING + u'\x02' # 0x0002 -> START OF TEXT + u'\x03' # 0x0003 -> END OF TEXT + u'\x04' # 0x0004 -> END OF TRANSMISSION + u'\x05' # 0x0005 -> ENQUIRY + u'\x06' # 0x0006 -> ACKNOWLEDGE + u'\x07' # 0x0007 -> BELL + u'\x08' # 0x0008 -> BACKSPACE + u'\t' # 0x0009 -> HORIZONTAL TABULATION + u'\n' # 0x000a -> LINE FEED + u'\x0b' # 0x000b -> VERTICAL TABULATION + u'\x0c' # 0x000c -> FORM FEED + u'\r' # 0x000d -> CARRIAGE RETURN + u'\x0e' # 0x000e -> SHIFT OUT + u'\x0f' # 0x000f -> SHIFT IN + u'\x10' # 0x0010 -> DATA LINK ESCAPE + u'\x11' # 0x0011 -> DEVICE CONTROL ONE + u'\x12' # 0x0012 -> DEVICE CONTROL TWO + u'\x13' # 0x0013 -> DEVICE CONTROL THREE + u'\x14' # 0x0014 -> DEVICE CONTROL FOUR + u'\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x0016 -> SYNCHRONOUS IDLE + u'\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x0018 -> CANCEL + u'\x19' # 0x0019 -> END OF MEDIUM + u'\x1a' # 0x001a -> SUBSTITUTE + u'\x1b' # 0x001b -> ESCAPE + u'\x1c' # 0x001c -> FILE SEPARATOR + u'\x1d' # 0x001d -> GROUP SEPARATOR + u'\x1e' # 0x001e -> RECORD SEPARATOR + u'\x1f' # 0x001f -> UNIT SEPARATOR + u' ' # 0x0020 -> SPACE + u'!' # 0x0021 -> EXCLAMATION MARK + u'"' # 0x0022 -> QUOTATION MARK + u'#' # 0x0023 -> NUMBER SIGN + u'$' # 0x0024 -> DOLLAR SIGN + u'%' # 0x0025 -> PERCENT SIGN + u'&' # 0x0026 -> AMPERSAND + u"'" # 0x0027 -> APOSTROPHE + u'(' # 0x0028 -> LEFT PARENTHESIS + u')' # 0x0029 -> RIGHT PARENTHESIS + u'*' # 0x002a -> ASTERISK + u'+' # 0x002b -> PLUS SIGN + u',' # 0x002c -> COMMA + u'-' # 0x002d -> HYPHEN-MINUS + u'.' # 0x002e -> FULL STOP + u'/' # 0x002f -> SOLIDUS + u'0' # 0x0030 -> DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE + u':' # 0x003a -> COLON + u';' # 0x003b -> SEMICOLON + u'<' # 0x003c -> LESS-THAN SIGN + u'=' # 0x003d -> EQUALS SIGN + u'>' # 0x003e -> GREATER-THAN SIGN + u'?' # 0x003f -> QUESTION MARK + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET + u'\\' # 0x005c -> REVERSE SOLIDUS + u']' # 0x005d -> RIGHT SQUARE BRACKET + u'^' # 0x005e -> CIRCUMFLEX ACCENT + u'_' # 0x005f -> LOW LINE + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET + u'|' # 0x007c -> VERTICAL LINE + u'}' # 0x007d -> RIGHT CURLY BRACKET + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> DELETE + u'\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + u'\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe0' # 0x0085 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe5' # 0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xea' # 0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xe8' # 0x008a -> LATIN SMALL LETTER E WITH GRAVE + u'\xef' # 0x008b -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xee' # 0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\u0131' # 0x008d -> LATIN SMALL LETTER DOTLESS I + u'\xc4' # 0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xe6' # 0x0091 -> LATIN SMALL LIGATURE AE + u'\xc6' # 0x0092 -> LATIN CAPITAL LIGATURE AE + u'\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf2' # 0x0095 -> LATIN SMALL LETTER O WITH GRAVE + u'\xfb' # 0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xf9' # 0x0097 -> LATIN SMALL LETTER U WITH GRAVE + u'\u0130' # 0x0098 -> LATIN CAPITAL LETTER I WITH DOT ABOVE + u'\xd6' # 0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xf8' # 0x009b -> LATIN SMALL LETTER O WITH STROKE + u'\xa3' # 0x009c -> POUND SIGN + u'\xd8' # 0x009d -> LATIN CAPITAL LETTER O WITH STROKE + u'\u015e' # 0x009e -> LATIN CAPITAL LETTER S WITH CEDILLA + u'\u015f' # 0x009f -> LATIN SMALL LETTER S WITH CEDILLA + u'\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + u'\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + u'\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + u'\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + u'\xf1' # 0x00a4 -> LATIN SMALL LETTER N WITH TILDE + u'\xd1' # 0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE + u'\u011e' # 0x00a6 -> LATIN CAPITAL LETTER G WITH BREVE + u'\u011f' # 0x00a7 -> LATIN SMALL LETTER G WITH BREVE + u'\xbf' # 0x00a8 -> INVERTED QUESTION MARK + u'\xae' # 0x00a9 -> REGISTERED SIGN + u'\xac' # 0x00aa -> NOT SIGN + u'\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + u'\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + u'\xa1' # 0x00ad -> INVERTED EXCLAMATION MARK + u'\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2591' # 0x00b0 -> LIGHT SHADE + u'\u2592' # 0x00b1 -> MEDIUM SHADE + u'\u2593' # 0x00b2 -> DARK SHADE + u'\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\xc1' # 0x00b5 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0x00b6 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xc0' # 0x00b7 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xa9' # 0x00b8 -> COPYRIGHT SIGN + u'\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\xa2' # 0x00bd -> CENT SIGN + u'\xa5' # 0x00be -> YEN SIGN + u'\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\xe3' # 0x00c6 -> LATIN SMALL LETTER A WITH TILDE + u'\xc3' # 0x00c7 -> LATIN CAPITAL LETTER A WITH TILDE + u'\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\xa4' # 0x00cf -> CURRENCY SIGN + u'\xba' # 0x00d0 -> MASCULINE ORDINAL INDICATOR + u'\xaa' # 0x00d1 -> FEMININE ORDINAL INDICATOR + u'\xca' # 0x00d2 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xcb' # 0x00d3 -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xc8' # 0x00d4 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\ufffe' # 0x00d5 -> UNDEFINED + u'\xcd' # 0x00d6 -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0x00d7 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0x00d8 -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0x00db -> FULL BLOCK + u'\u2584' # 0x00dc -> LOWER HALF BLOCK + u'\xa6' # 0x00dd -> BROKEN BAR + u'\xcc' # 0x00de -> LATIN CAPITAL LETTER I WITH GRAVE + u'\u2580' # 0x00df -> UPPER HALF BLOCK + u'\xd3' # 0x00e0 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + u'\xd4' # 0x00e2 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\xd2' # 0x00e3 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xf5' # 0x00e4 -> LATIN SMALL LETTER O WITH TILDE + u'\xd5' # 0x00e5 -> LATIN CAPITAL LETTER O WITH TILDE + u'\xb5' # 0x00e6 -> MICRO SIGN + u'\ufffe' # 0x00e7 -> UNDEFINED + u'\xd7' # 0x00e8 -> MULTIPLICATION SIGN + u'\xda' # 0x00e9 -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0x00ea -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xd9' # 0x00eb -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xec' # 0x00ec -> LATIN SMALL LETTER I WITH GRAVE + u'\xff' # 0x00ed -> LATIN SMALL LETTER Y WITH DIAERESIS + u'\xaf' # 0x00ee -> MACRON + u'\xb4' # 0x00ef -> ACUTE ACCENT + u'\xad' # 0x00f0 -> SOFT HYPHEN + u'\xb1' # 0x00f1 -> PLUS-MINUS SIGN + u'\ufffe' # 0x00f2 -> UNDEFINED + u'\xbe' # 0x00f3 -> VULGAR FRACTION THREE QUARTERS + u'\xb6' # 0x00f4 -> PILCROW SIGN + u'\xa7' # 0x00f5 -> SECTION SIGN + u'\xf7' # 0x00f6 -> DIVISION SIGN + u'\xb8' # 0x00f7 -> CEDILLA + u'\xb0' # 0x00f8 -> DEGREE SIGN + u'\xa8' # 0x00f9 -> DIAERESIS + u'\xb7' # 0x00fa -> MIDDLE DOT + u'\xb9' # 0x00fb -> SUPERSCRIPT ONE + u'\xb3' # 0x00fc -> SUPERSCRIPT THREE + u'\xb2' # 0x00fd -> SUPERSCRIPT TWO + u'\u25a0' # 0x00fe -> BLACK SQUARE + u'\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a1: 0x00ad, # INVERTED EXCLAMATION MARK + 0x00a2: 0x00bd, # CENT SIGN + 0x00a3: 0x009c, # POUND SIGN + 0x00a4: 0x00cf, # CURRENCY SIGN + 0x00a5: 0x00be, # YEN SIGN + 0x00a6: 0x00dd, # BROKEN BAR + 0x00a7: 0x00f5, # SECTION SIGN + 0x00a8: 0x00f9, # DIAERESIS + 0x00a9: 0x00b8, # COPYRIGHT SIGN + 0x00aa: 0x00d1, # FEMININE ORDINAL INDICATOR + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00ad: 0x00f0, # SOFT HYPHEN + 0x00ae: 0x00a9, # REGISTERED SIGN + 0x00af: 0x00ee, # MACRON + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b3: 0x00fc, # SUPERSCRIPT THREE + 0x00b4: 0x00ef, # ACUTE ACCENT + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b6: 0x00f4, # PILCROW SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00b8: 0x00f7, # CEDILLA + 0x00b9: 0x00fb, # SUPERSCRIPT ONE + 0x00ba: 0x00d0, # MASCULINE ORDINAL INDICATOR + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00be: 0x00f3, # VULGAR FRACTION THREE QUARTERS + 0x00bf: 0x00a8, # INVERTED QUESTION MARK + 0x00c0: 0x00b7, # LATIN CAPITAL LETTER A WITH GRAVE + 0x00c1: 0x00b5, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00c2: 0x00b6, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00c3: 0x00c7, # LATIN CAPITAL LETTER A WITH TILDE + 0x00c4: 0x008e, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5: 0x008f, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c6: 0x0092, # LATIN CAPITAL LIGATURE AE + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c8: 0x00d4, # LATIN CAPITAL LETTER E WITH GRAVE + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00ca: 0x00d2, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00cb: 0x00d3, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00cc: 0x00de, # LATIN CAPITAL LETTER I WITH GRAVE + 0x00cd: 0x00d6, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00ce: 0x00d7, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00cf: 0x00d8, # LATIN CAPITAL LETTER I WITH DIAERESIS + 0x00d1: 0x00a5, # LATIN CAPITAL LETTER N WITH TILDE + 0x00d2: 0x00e3, # LATIN CAPITAL LETTER O WITH GRAVE + 0x00d3: 0x00e0, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00d4: 0x00e2, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00d5: 0x00e5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00d6: 0x0099, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00d7: 0x00e8, # MULTIPLICATION SIGN + 0x00d8: 0x009d, # LATIN CAPITAL LETTER O WITH STROKE + 0x00d9: 0x00eb, # LATIN CAPITAL LETTER U WITH GRAVE + 0x00da: 0x00e9, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00db: 0x00ea, # LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e0: 0x0085, # LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e3: 0x00c6, # LATIN SMALL LETTER A WITH TILDE + 0x00e4: 0x0084, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e5: 0x0086, # LATIN SMALL LETTER A WITH RING ABOVE + 0x00e6: 0x0091, # LATIN SMALL LIGATURE AE + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008a, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0088, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x0089, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ec: 0x00ec, # LATIN SMALL LETTER I WITH GRAVE + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00ee: 0x008c, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ef: 0x008b, # LATIN SMALL LETTER I WITH DIAERESIS + 0x00f1: 0x00a4, # LATIN SMALL LETTER N WITH TILDE + 0x00f2: 0x0095, # LATIN SMALL LETTER O WITH GRAVE + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f5: 0x00e4, # LATIN SMALL LETTER O WITH TILDE + 0x00f6: 0x0094, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f8: 0x009b, # LATIN SMALL LETTER O WITH STROKE + 0x00f9: 0x0097, # LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x0096, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00ff: 0x00ed, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x011e: 0x00a6, # LATIN CAPITAL LETTER G WITH BREVE + 0x011f: 0x00a7, # LATIN SMALL LETTER G WITH BREVE + 0x0130: 0x0098, # LATIN CAPITAL LETTER I WITH DOT ABOVE + 0x0131: 0x008d, # LATIN SMALL LETTER DOTLESS I + 0x015e: 0x009e, # LATIN CAPITAL LETTER S WITH CEDILLA + 0x015f: 0x009f, # LATIN SMALL LETTER S WITH CEDILLA + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/PythonHome/Lib/encodings/cp857.pyc b/PythonHome/Lib/encodings/cp857.pyc deleted file mode 100644 index 8418831b7f16b47fdc6fab62f00e2bb034cf8d64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7666 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 NULL + u'\x01' # 0x0001 -> START OF HEADING + u'\x02' # 0x0002 -> START OF TEXT + u'\x03' # 0x0003 -> END OF TEXT + u'\x04' # 0x0004 -> END OF TRANSMISSION + u'\x05' # 0x0005 -> ENQUIRY + u'\x06' # 0x0006 -> ACKNOWLEDGE + u'\x07' # 0x0007 -> BELL + u'\x08' # 0x0008 -> BACKSPACE + u'\t' # 0x0009 -> HORIZONTAL TABULATION + u'\n' # 0x000a -> LINE FEED + u'\x0b' # 0x000b -> VERTICAL TABULATION + u'\x0c' # 0x000c -> FORM FEED + u'\r' # 0x000d -> CARRIAGE RETURN + u'\x0e' # 0x000e -> SHIFT OUT + u'\x0f' # 0x000f -> SHIFT IN + u'\x10' # 0x0010 -> DATA LINK ESCAPE + u'\x11' # 0x0011 -> DEVICE CONTROL ONE + u'\x12' # 0x0012 -> DEVICE CONTROL TWO + u'\x13' # 0x0013 -> DEVICE CONTROL THREE + u'\x14' # 0x0014 -> DEVICE CONTROL FOUR + u'\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x0016 -> SYNCHRONOUS IDLE + u'\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x0018 -> CANCEL + u'\x19' # 0x0019 -> END OF MEDIUM + u'\x1a' # 0x001a -> SUBSTITUTE + u'\x1b' # 0x001b -> ESCAPE + u'\x1c' # 0x001c -> FILE SEPARATOR + u'\x1d' # 0x001d -> GROUP SEPARATOR + u'\x1e' # 0x001e -> RECORD SEPARATOR + u'\x1f' # 0x001f -> UNIT SEPARATOR + u' ' # 0x0020 -> SPACE + u'!' # 0x0021 -> EXCLAMATION MARK + u'"' # 0x0022 -> QUOTATION MARK + u'#' # 0x0023 -> NUMBER SIGN + u'$' # 0x0024 -> DOLLAR SIGN + u'%' # 0x0025 -> PERCENT SIGN + u'&' # 0x0026 -> AMPERSAND + u"'" # 0x0027 -> APOSTROPHE + u'(' # 0x0028 -> LEFT PARENTHESIS + u')' # 0x0029 -> RIGHT PARENTHESIS + u'*' # 0x002a -> ASTERISK + u'+' # 0x002b -> PLUS SIGN + u',' # 0x002c -> COMMA + u'-' # 0x002d -> HYPHEN-MINUS + u'.' # 0x002e -> FULL STOP + u'/' # 0x002f -> SOLIDUS + u'0' # 0x0030 -> DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE + u':' # 0x003a -> COLON + u';' # 0x003b -> SEMICOLON + u'<' # 0x003c -> LESS-THAN SIGN + u'=' # 0x003d -> EQUALS SIGN + u'>' # 0x003e -> GREATER-THAN SIGN + u'?' # 0x003f -> QUESTION MARK + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET + u'\\' # 0x005c -> REVERSE SOLIDUS + u']' # 0x005d -> RIGHT SQUARE BRACKET + u'^' # 0x005e -> CIRCUMFLEX ACCENT + u'_' # 0x005f -> LOW LINE + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET + u'|' # 0x007c -> VERTICAL LINE + u'}' # 0x007d -> RIGHT CURLY BRACKET + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> DELETE + u'\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + u'\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe0' # 0x0085 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe5' # 0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xea' # 0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xe8' # 0x008a -> LATIN SMALL LETTER E WITH GRAVE + u'\xef' # 0x008b -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xee' # 0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xec' # 0x008d -> LATIN SMALL LETTER I WITH GRAVE + u'\xc4' # 0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xe6' # 0x0091 -> LATIN SMALL LIGATURE AE + u'\xc6' # 0x0092 -> LATIN CAPITAL LIGATURE AE + u'\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf2' # 0x0095 -> LATIN SMALL LETTER O WITH GRAVE + u'\xfb' # 0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xf9' # 0x0097 -> LATIN SMALL LETTER U WITH GRAVE + u'\xff' # 0x0098 -> LATIN SMALL LETTER Y WITH DIAERESIS + u'\xd6' # 0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xf8' # 0x009b -> LATIN SMALL LETTER O WITH STROKE + u'\xa3' # 0x009c -> POUND SIGN + u'\xd8' # 0x009d -> LATIN CAPITAL LETTER O WITH STROKE + u'\xd7' # 0x009e -> MULTIPLICATION SIGN + u'\u0192' # 0x009f -> LATIN SMALL LETTER F WITH HOOK + u'\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + u'\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + u'\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + u'\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + u'\xf1' # 0x00a4 -> LATIN SMALL LETTER N WITH TILDE + u'\xd1' # 0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xaa' # 0x00a6 -> FEMININE ORDINAL INDICATOR + u'\xba' # 0x00a7 -> MASCULINE ORDINAL INDICATOR + u'\xbf' # 0x00a8 -> INVERTED QUESTION MARK + u'\xae' # 0x00a9 -> REGISTERED SIGN + u'\xac' # 0x00aa -> NOT SIGN + u'\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + u'\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + u'\xa1' # 0x00ad -> INVERTED EXCLAMATION MARK + u'\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2591' # 0x00b0 -> LIGHT SHADE + u'\u2592' # 0x00b1 -> MEDIUM SHADE + u'\u2593' # 0x00b2 -> DARK SHADE + u'\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\xc1' # 0x00b5 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0x00b6 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xc0' # 0x00b7 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xa9' # 0x00b8 -> COPYRIGHT SIGN + u'\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\xa2' # 0x00bd -> CENT SIGN + u'\xa5' # 0x00be -> YEN SIGN + u'\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\xe3' # 0x00c6 -> LATIN SMALL LETTER A WITH TILDE + u'\xc3' # 0x00c7 -> LATIN CAPITAL LETTER A WITH TILDE + u'\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\xa4' # 0x00cf -> CURRENCY SIGN + u'\xf0' # 0x00d0 -> LATIN SMALL LETTER ETH + u'\xd0' # 0x00d1 -> LATIN CAPITAL LETTER ETH + u'\xca' # 0x00d2 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xcb' # 0x00d3 -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xc8' # 0x00d4 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\u20ac' # 0x00d5 -> EURO SIGN + u'\xcd' # 0x00d6 -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0x00d7 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0x00d8 -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0x00db -> FULL BLOCK + u'\u2584' # 0x00dc -> LOWER HALF BLOCK + u'\xa6' # 0x00dd -> BROKEN BAR + u'\xcc' # 0x00de -> LATIN CAPITAL LETTER I WITH GRAVE + u'\u2580' # 0x00df -> UPPER HALF BLOCK + u'\xd3' # 0x00e0 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + u'\xd4' # 0x00e2 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\xd2' # 0x00e3 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xf5' # 0x00e4 -> LATIN SMALL LETTER O WITH TILDE + u'\xd5' # 0x00e5 -> LATIN CAPITAL LETTER O WITH TILDE + u'\xb5' # 0x00e6 -> MICRO SIGN + u'\xfe' # 0x00e7 -> LATIN SMALL LETTER THORN + u'\xde' # 0x00e8 -> LATIN CAPITAL LETTER THORN + u'\xda' # 0x00e9 -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0x00ea -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xd9' # 0x00eb -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xfd' # 0x00ec -> LATIN SMALL LETTER Y WITH ACUTE + u'\xdd' # 0x00ed -> LATIN CAPITAL LETTER Y WITH ACUTE + u'\xaf' # 0x00ee -> MACRON + u'\xb4' # 0x00ef -> ACUTE ACCENT + u'\xad' # 0x00f0 -> SOFT HYPHEN + u'\xb1' # 0x00f1 -> PLUS-MINUS SIGN + u'\u2017' # 0x00f2 -> DOUBLE LOW LINE + u'\xbe' # 0x00f3 -> VULGAR FRACTION THREE QUARTERS + u'\xb6' # 0x00f4 -> PILCROW SIGN + u'\xa7' # 0x00f5 -> SECTION SIGN + u'\xf7' # 0x00f6 -> DIVISION SIGN + u'\xb8' # 0x00f7 -> CEDILLA + u'\xb0' # 0x00f8 -> DEGREE SIGN + u'\xa8' # 0x00f9 -> DIAERESIS + u'\xb7' # 0x00fa -> MIDDLE DOT + u'\xb9' # 0x00fb -> SUPERSCRIPT ONE + u'\xb3' # 0x00fc -> SUPERSCRIPT THREE + u'\xb2' # 0x00fd -> SUPERSCRIPT TWO + u'\u25a0' # 0x00fe -> BLACK SQUARE + u'\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a1: 0x00ad, # INVERTED EXCLAMATION MARK + 0x00a2: 0x00bd, # CENT SIGN + 0x00a3: 0x009c, # POUND SIGN + 0x00a4: 0x00cf, # CURRENCY SIGN + 0x00a5: 0x00be, # YEN SIGN + 0x00a6: 0x00dd, # BROKEN BAR + 0x00a7: 0x00f5, # SECTION SIGN + 0x00a8: 0x00f9, # DIAERESIS + 0x00a9: 0x00b8, # COPYRIGHT SIGN + 0x00aa: 0x00a6, # FEMININE ORDINAL INDICATOR + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00ad: 0x00f0, # SOFT HYPHEN + 0x00ae: 0x00a9, # REGISTERED SIGN + 0x00af: 0x00ee, # MACRON + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b3: 0x00fc, # SUPERSCRIPT THREE + 0x00b4: 0x00ef, # ACUTE ACCENT + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b6: 0x00f4, # PILCROW SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00b8: 0x00f7, # CEDILLA + 0x00b9: 0x00fb, # SUPERSCRIPT ONE + 0x00ba: 0x00a7, # MASCULINE ORDINAL INDICATOR + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00be: 0x00f3, # VULGAR FRACTION THREE QUARTERS + 0x00bf: 0x00a8, # INVERTED QUESTION MARK + 0x00c0: 0x00b7, # LATIN CAPITAL LETTER A WITH GRAVE + 0x00c1: 0x00b5, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00c2: 0x00b6, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00c3: 0x00c7, # LATIN CAPITAL LETTER A WITH TILDE + 0x00c4: 0x008e, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5: 0x008f, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c6: 0x0092, # LATIN CAPITAL LIGATURE AE + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c8: 0x00d4, # LATIN CAPITAL LETTER E WITH GRAVE + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00ca: 0x00d2, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00cb: 0x00d3, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00cc: 0x00de, # LATIN CAPITAL LETTER I WITH GRAVE + 0x00cd: 0x00d6, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00ce: 0x00d7, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00cf: 0x00d8, # LATIN CAPITAL LETTER I WITH DIAERESIS + 0x00d0: 0x00d1, # LATIN CAPITAL LETTER ETH + 0x00d1: 0x00a5, # LATIN CAPITAL LETTER N WITH TILDE + 0x00d2: 0x00e3, # LATIN CAPITAL LETTER O WITH GRAVE + 0x00d3: 0x00e0, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00d4: 0x00e2, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00d5: 0x00e5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00d6: 0x0099, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00d7: 0x009e, # MULTIPLICATION SIGN + 0x00d8: 0x009d, # LATIN CAPITAL LETTER O WITH STROKE + 0x00d9: 0x00eb, # LATIN CAPITAL LETTER U WITH GRAVE + 0x00da: 0x00e9, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00db: 0x00ea, # LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00dd: 0x00ed, # LATIN CAPITAL LETTER Y WITH ACUTE + 0x00de: 0x00e8, # LATIN CAPITAL LETTER THORN + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e0: 0x0085, # LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e3: 0x00c6, # LATIN SMALL LETTER A WITH TILDE + 0x00e4: 0x0084, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e5: 0x0086, # LATIN SMALL LETTER A WITH RING ABOVE + 0x00e6: 0x0091, # LATIN SMALL LIGATURE AE + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008a, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0088, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x0089, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ec: 0x008d, # LATIN SMALL LETTER I WITH GRAVE + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00ee: 0x008c, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ef: 0x008b, # LATIN SMALL LETTER I WITH DIAERESIS + 0x00f0: 0x00d0, # LATIN SMALL LETTER ETH + 0x00f1: 0x00a4, # LATIN SMALL LETTER N WITH TILDE + 0x00f2: 0x0095, # LATIN SMALL LETTER O WITH GRAVE + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f5: 0x00e4, # LATIN SMALL LETTER O WITH TILDE + 0x00f6: 0x0094, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f8: 0x009b, # LATIN SMALL LETTER O WITH STROKE + 0x00f9: 0x0097, # LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x0096, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00fd: 0x00ec, # LATIN SMALL LETTER Y WITH ACUTE + 0x00fe: 0x00e7, # LATIN SMALL LETTER THORN + 0x00ff: 0x0098, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x20ac: 0x00d5, # EURO SIGN + 0x0192: 0x009f, # LATIN SMALL LETTER F WITH HOOK + 0x2017: 0x00f2, # DOUBLE LOW LINE + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/PythonHome/Lib/encodings/cp858.pyc b/PythonHome/Lib/encodings/cp858.pyc deleted file mode 100644 index a3807c4f83a31d9b6113b4a5ad86e65d99f39f7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7646 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 KPj&_H>Hh)ss#&Q3 diff --git a/PythonHome/Lib/encodings/cp860.py b/PythonHome/Lib/encodings/cp860.py new file mode 100644 index 0000000000..4acb0cf362 --- /dev/null +++ b/PythonHome/Lib/encodings/cp860.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP860.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp860', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x00c7, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x0081: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0082: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x0083: 0x00e2, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x0084: 0x00e3, # LATIN SMALL LETTER A WITH TILDE + 0x0085: 0x00e0, # LATIN SMALL LETTER A WITH GRAVE + 0x0086: 0x00c1, # LATIN CAPITAL LETTER A WITH ACUTE + 0x0087: 0x00e7, # LATIN SMALL LETTER C WITH CEDILLA + 0x0088: 0x00ea, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x0089: 0x00ca, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x008a: 0x00e8, # LATIN SMALL LETTER E WITH GRAVE + 0x008b: 0x00cd, # LATIN CAPITAL LETTER I WITH ACUTE + 0x008c: 0x00d4, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x008d: 0x00ec, # LATIN SMALL LETTER I WITH GRAVE + 0x008e: 0x00c3, # LATIN CAPITAL LETTER A WITH TILDE + 0x008f: 0x00c2, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x0090: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0091: 0x00c0, # LATIN CAPITAL LETTER A WITH GRAVE + 0x0092: 0x00c8, # LATIN CAPITAL LETTER E WITH GRAVE + 0x0093: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x0094: 0x00f5, # LATIN SMALL LETTER O WITH TILDE + 0x0095: 0x00f2, # LATIN SMALL LETTER O WITH GRAVE + 0x0096: 0x00da, # LATIN CAPITAL LETTER U WITH ACUTE + 0x0097: 0x00f9, # LATIN SMALL LETTER U WITH GRAVE + 0x0098: 0x00cc, # LATIN CAPITAL LETTER I WITH GRAVE + 0x0099: 0x00d5, # LATIN CAPITAL LETTER O WITH TILDE + 0x009a: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x009b: 0x00a2, # CENT SIGN + 0x009c: 0x00a3, # POUND SIGN + 0x009d: 0x00d9, # LATIN CAPITAL LETTER U WITH GRAVE + 0x009e: 0x20a7, # PESETA SIGN + 0x009f: 0x00d3, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00a0: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE + 0x00a1: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE + 0x00a2: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00a3: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x00a4: 0x00f1, # LATIN SMALL LETTER N WITH TILDE + 0x00a5: 0x00d1, # LATIN CAPITAL LETTER N WITH TILDE + 0x00a6: 0x00aa, # FEMININE ORDINAL INDICATOR + 0x00a7: 0x00ba, # MASCULINE ORDINAL INDICATOR + 0x00a8: 0x00bf, # INVERTED QUESTION MARK + 0x00a9: 0x00d2, # LATIN CAPITAL LETTER O WITH GRAVE + 0x00aa: 0x00ac, # NOT SIGN + 0x00ab: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00ac: 0x00bc, # VULGAR FRACTION ONE QUARTER + 0x00ad: 0x00a1, # INVERTED EXCLAMATION MARK + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x2561, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x00b6: 0x2562, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x00b7: 0x2556, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x00b8: 0x2555, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x255c, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x00be: 0x255b, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x255e, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x00c7: 0x255f, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x2567, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x00d0: 0x2568, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x00d1: 0x2564, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x00d2: 0x2565, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x00d3: 0x2559, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x00d4: 0x2558, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x00d5: 0x2552, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x00d6: 0x2553, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x00d7: 0x256b, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x00d8: 0x256a, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x258c, # LEFT HALF BLOCK + 0x00de: 0x2590, # RIGHT HALF BLOCK + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x03b1, # GREEK SMALL LETTER ALPHA + 0x00e1: 0x00df, # LATIN SMALL LETTER SHARP S + 0x00e2: 0x0393, # GREEK CAPITAL LETTER GAMMA + 0x00e3: 0x03c0, # GREEK SMALL LETTER PI + 0x00e4: 0x03a3, # GREEK CAPITAL LETTER SIGMA + 0x00e5: 0x03c3, # GREEK SMALL LETTER SIGMA + 0x00e6: 0x00b5, # MICRO SIGN + 0x00e7: 0x03c4, # GREEK SMALL LETTER TAU + 0x00e8: 0x03a6, # GREEK CAPITAL LETTER PHI + 0x00e9: 0x0398, # GREEK CAPITAL LETTER THETA + 0x00ea: 0x03a9, # GREEK CAPITAL LETTER OMEGA + 0x00eb: 0x03b4, # GREEK SMALL LETTER DELTA + 0x00ec: 0x221e, # INFINITY + 0x00ed: 0x03c6, # GREEK SMALL LETTER PHI + 0x00ee: 0x03b5, # GREEK SMALL LETTER EPSILON + 0x00ef: 0x2229, # INTERSECTION + 0x00f0: 0x2261, # IDENTICAL TO + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: 0x2265, # GREATER-THAN OR EQUAL TO + 0x00f3: 0x2264, # LESS-THAN OR EQUAL TO + 0x00f4: 0x2320, # TOP HALF INTEGRAL + 0x00f5: 0x2321, # BOTTOM HALF INTEGRAL + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x2248, # ALMOST EQUAL TO + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x2219, # BULLET OPERATOR + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x221a, # SQUARE ROOT + 0x00fc: 0x207f, # SUPERSCRIPT LATIN SMALL LETTER N + 0x00fd: 0x00b2, # SUPERSCRIPT TWO + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x0000 -> NULL + u'\x01' # 0x0001 -> START OF HEADING + u'\x02' # 0x0002 -> START OF TEXT + u'\x03' # 0x0003 -> END OF TEXT + u'\x04' # 0x0004 -> END OF TRANSMISSION + u'\x05' # 0x0005 -> ENQUIRY + u'\x06' # 0x0006 -> ACKNOWLEDGE + u'\x07' # 0x0007 -> BELL + u'\x08' # 0x0008 -> BACKSPACE + u'\t' # 0x0009 -> HORIZONTAL TABULATION + u'\n' # 0x000a -> LINE FEED + u'\x0b' # 0x000b -> VERTICAL TABULATION + u'\x0c' # 0x000c -> FORM FEED + u'\r' # 0x000d -> CARRIAGE RETURN + u'\x0e' # 0x000e -> SHIFT OUT + u'\x0f' # 0x000f -> SHIFT IN + u'\x10' # 0x0010 -> DATA LINK ESCAPE + u'\x11' # 0x0011 -> DEVICE CONTROL ONE + u'\x12' # 0x0012 -> DEVICE CONTROL TWO + u'\x13' # 0x0013 -> DEVICE CONTROL THREE + u'\x14' # 0x0014 -> DEVICE CONTROL FOUR + u'\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x0016 -> SYNCHRONOUS IDLE + u'\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x0018 -> CANCEL + u'\x19' # 0x0019 -> END OF MEDIUM + u'\x1a' # 0x001a -> SUBSTITUTE + u'\x1b' # 0x001b -> ESCAPE + u'\x1c' # 0x001c -> FILE SEPARATOR + u'\x1d' # 0x001d -> GROUP SEPARATOR + u'\x1e' # 0x001e -> RECORD SEPARATOR + u'\x1f' # 0x001f -> UNIT SEPARATOR + u' ' # 0x0020 -> SPACE + u'!' # 0x0021 -> EXCLAMATION MARK + u'"' # 0x0022 -> QUOTATION MARK + u'#' # 0x0023 -> NUMBER SIGN + u'$' # 0x0024 -> DOLLAR SIGN + u'%' # 0x0025 -> PERCENT SIGN + u'&' # 0x0026 -> AMPERSAND + u"'" # 0x0027 -> APOSTROPHE + u'(' # 0x0028 -> LEFT PARENTHESIS + u')' # 0x0029 -> RIGHT PARENTHESIS + u'*' # 0x002a -> ASTERISK + u'+' # 0x002b -> PLUS SIGN + u',' # 0x002c -> COMMA + u'-' # 0x002d -> HYPHEN-MINUS + u'.' # 0x002e -> FULL STOP + u'/' # 0x002f -> SOLIDUS + u'0' # 0x0030 -> DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE + u':' # 0x003a -> COLON + u';' # 0x003b -> SEMICOLON + u'<' # 0x003c -> LESS-THAN SIGN + u'=' # 0x003d -> EQUALS SIGN + u'>' # 0x003e -> GREATER-THAN SIGN + u'?' # 0x003f -> QUESTION MARK + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET + u'\\' # 0x005c -> REVERSE SOLIDUS + u']' # 0x005d -> RIGHT SQUARE BRACKET + u'^' # 0x005e -> CIRCUMFLEX ACCENT + u'_' # 0x005f -> LOW LINE + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET + u'|' # 0x007c -> VERTICAL LINE + u'}' # 0x007d -> RIGHT CURLY BRACKET + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> DELETE + u'\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + u'\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe3' # 0x0084 -> LATIN SMALL LETTER A WITH TILDE + u'\xe0' # 0x0085 -> LATIN SMALL LETTER A WITH GRAVE + u'\xc1' # 0x0086 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xea' # 0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xca' # 0x0089 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xe8' # 0x008a -> LATIN SMALL LETTER E WITH GRAVE + u'\xcd' # 0x008b -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xd4' # 0x008c -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\xec' # 0x008d -> LATIN SMALL LETTER I WITH GRAVE + u'\xc3' # 0x008e -> LATIN CAPITAL LETTER A WITH TILDE + u'\xc2' # 0x008f -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xc0' # 0x0091 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc8' # 0x0092 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf5' # 0x0094 -> LATIN SMALL LETTER O WITH TILDE + u'\xf2' # 0x0095 -> LATIN SMALL LETTER O WITH GRAVE + u'\xda' # 0x0096 -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xf9' # 0x0097 -> LATIN SMALL LETTER U WITH GRAVE + u'\xcc' # 0x0098 -> LATIN CAPITAL LETTER I WITH GRAVE + u'\xd5' # 0x0099 -> LATIN CAPITAL LETTER O WITH TILDE + u'\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xa2' # 0x009b -> CENT SIGN + u'\xa3' # 0x009c -> POUND SIGN + u'\xd9' # 0x009d -> LATIN CAPITAL LETTER U WITH GRAVE + u'\u20a7' # 0x009e -> PESETA SIGN + u'\xd3' # 0x009f -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + u'\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + u'\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + u'\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + u'\xf1' # 0x00a4 -> LATIN SMALL LETTER N WITH TILDE + u'\xd1' # 0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xaa' # 0x00a6 -> FEMININE ORDINAL INDICATOR + u'\xba' # 0x00a7 -> MASCULINE ORDINAL INDICATOR + u'\xbf' # 0x00a8 -> INVERTED QUESTION MARK + u'\xd2' # 0x00a9 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xac' # 0x00aa -> NOT SIGN + u'\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + u'\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + u'\xa1' # 0x00ad -> INVERTED EXCLAMATION MARK + u'\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2591' # 0x00b0 -> LIGHT SHADE + u'\u2592' # 0x00b1 -> MEDIUM SHADE + u'\u2593' # 0x00b2 -> DARK SHADE + u'\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + u'\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + u'\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + u'\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + u'\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + u'\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + u'\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + u'\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + u'\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + u'\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + u'\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + u'\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + u'\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + u'\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + u'\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + u'\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + u'\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + u'\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + u'\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0x00db -> FULL BLOCK + u'\u2584' # 0x00dc -> LOWER HALF BLOCK + u'\u258c' # 0x00dd -> LEFT HALF BLOCK + u'\u2590' # 0x00de -> RIGHT HALF BLOCK + u'\u2580' # 0x00df -> UPPER HALF BLOCK + u'\u03b1' # 0x00e0 -> GREEK SMALL LETTER ALPHA + u'\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + u'\u0393' # 0x00e2 -> GREEK CAPITAL LETTER GAMMA + u'\u03c0' # 0x00e3 -> GREEK SMALL LETTER PI + u'\u03a3' # 0x00e4 -> GREEK CAPITAL LETTER SIGMA + u'\u03c3' # 0x00e5 -> GREEK SMALL LETTER SIGMA + u'\xb5' # 0x00e6 -> MICRO SIGN + u'\u03c4' # 0x00e7 -> GREEK SMALL LETTER TAU + u'\u03a6' # 0x00e8 -> GREEK CAPITAL LETTER PHI + u'\u0398' # 0x00e9 -> GREEK CAPITAL LETTER THETA + u'\u03a9' # 0x00ea -> GREEK CAPITAL LETTER OMEGA + u'\u03b4' # 0x00eb -> GREEK SMALL LETTER DELTA + u'\u221e' # 0x00ec -> INFINITY + u'\u03c6' # 0x00ed -> GREEK SMALL LETTER PHI + u'\u03b5' # 0x00ee -> GREEK SMALL LETTER EPSILON + u'\u2229' # 0x00ef -> INTERSECTION + u'\u2261' # 0x00f0 -> IDENTICAL TO + u'\xb1' # 0x00f1 -> PLUS-MINUS SIGN + u'\u2265' # 0x00f2 -> GREATER-THAN OR EQUAL TO + u'\u2264' # 0x00f3 -> LESS-THAN OR EQUAL TO + u'\u2320' # 0x00f4 -> TOP HALF INTEGRAL + u'\u2321' # 0x00f5 -> BOTTOM HALF INTEGRAL + u'\xf7' # 0x00f6 -> DIVISION SIGN + u'\u2248' # 0x00f7 -> ALMOST EQUAL TO + u'\xb0' # 0x00f8 -> DEGREE SIGN + u'\u2219' # 0x00f9 -> BULLET OPERATOR + u'\xb7' # 0x00fa -> MIDDLE DOT + u'\u221a' # 0x00fb -> SQUARE ROOT + u'\u207f' # 0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N + u'\xb2' # 0x00fd -> SUPERSCRIPT TWO + u'\u25a0' # 0x00fe -> BLACK SQUARE + u'\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a1: 0x00ad, # INVERTED EXCLAMATION MARK + 0x00a2: 0x009b, # CENT SIGN + 0x00a3: 0x009c, # POUND SIGN + 0x00aa: 0x00a6, # FEMININE ORDINAL INDICATOR + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00ba: 0x00a7, # MASCULINE ORDINAL INDICATOR + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00bf: 0x00a8, # INVERTED QUESTION MARK + 0x00c0: 0x0091, # LATIN CAPITAL LETTER A WITH GRAVE + 0x00c1: 0x0086, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00c2: 0x008f, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00c3: 0x008e, # LATIN CAPITAL LETTER A WITH TILDE + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c8: 0x0092, # LATIN CAPITAL LETTER E WITH GRAVE + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00ca: 0x0089, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00cc: 0x0098, # LATIN CAPITAL LETTER I WITH GRAVE + 0x00cd: 0x008b, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00d1: 0x00a5, # LATIN CAPITAL LETTER N WITH TILDE + 0x00d2: 0x00a9, # LATIN CAPITAL LETTER O WITH GRAVE + 0x00d3: 0x009f, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00d4: 0x008c, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00d5: 0x0099, # LATIN CAPITAL LETTER O WITH TILDE + 0x00d9: 0x009d, # LATIN CAPITAL LETTER U WITH GRAVE + 0x00da: 0x0096, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e0: 0x0085, # LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e3: 0x0084, # LATIN SMALL LETTER A WITH TILDE + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008a, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0088, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00ec: 0x008d, # LATIN SMALL LETTER I WITH GRAVE + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00f1: 0x00a4, # LATIN SMALL LETTER N WITH TILDE + 0x00f2: 0x0095, # LATIN SMALL LETTER O WITH GRAVE + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f5: 0x0094, # LATIN SMALL LETTER O WITH TILDE + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f9: 0x0097, # LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0393: 0x00e2, # GREEK CAPITAL LETTER GAMMA + 0x0398: 0x00e9, # GREEK CAPITAL LETTER THETA + 0x03a3: 0x00e4, # GREEK CAPITAL LETTER SIGMA + 0x03a6: 0x00e8, # GREEK CAPITAL LETTER PHI + 0x03a9: 0x00ea, # GREEK CAPITAL LETTER OMEGA + 0x03b1: 0x00e0, # GREEK SMALL LETTER ALPHA + 0x03b4: 0x00eb, # GREEK SMALL LETTER DELTA + 0x03b5: 0x00ee, # GREEK SMALL LETTER EPSILON + 0x03c0: 0x00e3, # GREEK SMALL LETTER PI + 0x03c3: 0x00e5, # GREEK SMALL LETTER SIGMA + 0x03c4: 0x00e7, # GREEK SMALL LETTER TAU + 0x03c6: 0x00ed, # GREEK SMALL LETTER PHI + 0x207f: 0x00fc, # SUPERSCRIPT LATIN SMALL LETTER N + 0x20a7: 0x009e, # PESETA SIGN + 0x2219: 0x00f9, # BULLET OPERATOR + 0x221a: 0x00fb, # SQUARE ROOT + 0x221e: 0x00ec, # INFINITY + 0x2229: 0x00ef, # INTERSECTION + 0x2248: 0x00f7, # ALMOST EQUAL TO + 0x2261: 0x00f0, # IDENTICAL TO + 0x2264: 0x00f3, # LESS-THAN OR EQUAL TO + 0x2265: 0x00f2, # GREATER-THAN OR EQUAL TO + 0x2320: 0x00f4, # TOP HALF INTEGRAL + 0x2321: 0x00f5, # BOTTOM HALF INTEGRAL + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/PythonHome/Lib/encodings/cp860.pyc b/PythonHome/Lib/encodings/cp860.pyc deleted file mode 100644 index fe5c8e465fd9513dd2f1b67faa48553f62915ae4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7912 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 NULL + u'\x01' # 0x0001 -> START OF HEADING + u'\x02' # 0x0002 -> START OF TEXT + u'\x03' # 0x0003 -> END OF TEXT + u'\x04' # 0x0004 -> END OF TRANSMISSION + u'\x05' # 0x0005 -> ENQUIRY + u'\x06' # 0x0006 -> ACKNOWLEDGE + u'\x07' # 0x0007 -> BELL + u'\x08' # 0x0008 -> BACKSPACE + u'\t' # 0x0009 -> HORIZONTAL TABULATION + u'\n' # 0x000a -> LINE FEED + u'\x0b' # 0x000b -> VERTICAL TABULATION + u'\x0c' # 0x000c -> FORM FEED + u'\r' # 0x000d -> CARRIAGE RETURN + u'\x0e' # 0x000e -> SHIFT OUT + u'\x0f' # 0x000f -> SHIFT IN + u'\x10' # 0x0010 -> DATA LINK ESCAPE + u'\x11' # 0x0011 -> DEVICE CONTROL ONE + u'\x12' # 0x0012 -> DEVICE CONTROL TWO + u'\x13' # 0x0013 -> DEVICE CONTROL THREE + u'\x14' # 0x0014 -> DEVICE CONTROL FOUR + u'\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x0016 -> SYNCHRONOUS IDLE + u'\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x0018 -> CANCEL + u'\x19' # 0x0019 -> END OF MEDIUM + u'\x1a' # 0x001a -> SUBSTITUTE + u'\x1b' # 0x001b -> ESCAPE + u'\x1c' # 0x001c -> FILE SEPARATOR + u'\x1d' # 0x001d -> GROUP SEPARATOR + u'\x1e' # 0x001e -> RECORD SEPARATOR + u'\x1f' # 0x001f -> UNIT SEPARATOR + u' ' # 0x0020 -> SPACE + u'!' # 0x0021 -> EXCLAMATION MARK + u'"' # 0x0022 -> QUOTATION MARK + u'#' # 0x0023 -> NUMBER SIGN + u'$' # 0x0024 -> DOLLAR SIGN + u'%' # 0x0025 -> PERCENT SIGN + u'&' # 0x0026 -> AMPERSAND + u"'" # 0x0027 -> APOSTROPHE + u'(' # 0x0028 -> LEFT PARENTHESIS + u')' # 0x0029 -> RIGHT PARENTHESIS + u'*' # 0x002a -> ASTERISK + u'+' # 0x002b -> PLUS SIGN + u',' # 0x002c -> COMMA + u'-' # 0x002d -> HYPHEN-MINUS + u'.' # 0x002e -> FULL STOP + u'/' # 0x002f -> SOLIDUS + u'0' # 0x0030 -> DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE + u':' # 0x003a -> COLON + u';' # 0x003b -> SEMICOLON + u'<' # 0x003c -> LESS-THAN SIGN + u'=' # 0x003d -> EQUALS SIGN + u'>' # 0x003e -> GREATER-THAN SIGN + u'?' # 0x003f -> QUESTION MARK + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET + u'\\' # 0x005c -> REVERSE SOLIDUS + u']' # 0x005d -> RIGHT SQUARE BRACKET + u'^' # 0x005e -> CIRCUMFLEX ACCENT + u'_' # 0x005f -> LOW LINE + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET + u'|' # 0x007c -> VERTICAL LINE + u'}' # 0x007d -> RIGHT CURLY BRACKET + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> DELETE + u'\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + u'\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe0' # 0x0085 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe5' # 0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xea' # 0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xe8' # 0x008a -> LATIN SMALL LETTER E WITH GRAVE + u'\xd0' # 0x008b -> LATIN CAPITAL LETTER ETH + u'\xf0' # 0x008c -> LATIN SMALL LETTER ETH + u'\xde' # 0x008d -> LATIN CAPITAL LETTER THORN + u'\xc4' # 0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xe6' # 0x0091 -> LATIN SMALL LIGATURE AE + u'\xc6' # 0x0092 -> LATIN CAPITAL LIGATURE AE + u'\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xfe' # 0x0095 -> LATIN SMALL LETTER THORN + u'\xfb' # 0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xdd' # 0x0097 -> LATIN CAPITAL LETTER Y WITH ACUTE + u'\xfd' # 0x0098 -> LATIN SMALL LETTER Y WITH ACUTE + u'\xd6' # 0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xf8' # 0x009b -> LATIN SMALL LETTER O WITH STROKE + u'\xa3' # 0x009c -> POUND SIGN + u'\xd8' # 0x009d -> LATIN CAPITAL LETTER O WITH STROKE + u'\u20a7' # 0x009e -> PESETA SIGN + u'\u0192' # 0x009f -> LATIN SMALL LETTER F WITH HOOK + u'\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + u'\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + u'\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + u'\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + u'\xc1' # 0x00a4 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xcd' # 0x00a5 -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xd3' # 0x00a6 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xda' # 0x00a7 -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xbf' # 0x00a8 -> INVERTED QUESTION MARK + u'\u2310' # 0x00a9 -> REVERSED NOT SIGN + u'\xac' # 0x00aa -> NOT SIGN + u'\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + u'\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + u'\xa1' # 0x00ad -> INVERTED EXCLAMATION MARK + u'\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2591' # 0x00b0 -> LIGHT SHADE + u'\u2592' # 0x00b1 -> MEDIUM SHADE + u'\u2593' # 0x00b2 -> DARK SHADE + u'\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + u'\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + u'\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + u'\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + u'\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + u'\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + u'\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + u'\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + u'\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + u'\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + u'\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + u'\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + u'\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + u'\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + u'\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + u'\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + u'\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + u'\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + u'\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0x00db -> FULL BLOCK + u'\u2584' # 0x00dc -> LOWER HALF BLOCK + u'\u258c' # 0x00dd -> LEFT HALF BLOCK + u'\u2590' # 0x00de -> RIGHT HALF BLOCK + u'\u2580' # 0x00df -> UPPER HALF BLOCK + u'\u03b1' # 0x00e0 -> GREEK SMALL LETTER ALPHA + u'\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + u'\u0393' # 0x00e2 -> GREEK CAPITAL LETTER GAMMA + u'\u03c0' # 0x00e3 -> GREEK SMALL LETTER PI + u'\u03a3' # 0x00e4 -> GREEK CAPITAL LETTER SIGMA + u'\u03c3' # 0x00e5 -> GREEK SMALL LETTER SIGMA + u'\xb5' # 0x00e6 -> MICRO SIGN + u'\u03c4' # 0x00e7 -> GREEK SMALL LETTER TAU + u'\u03a6' # 0x00e8 -> GREEK CAPITAL LETTER PHI + u'\u0398' # 0x00e9 -> GREEK CAPITAL LETTER THETA + u'\u03a9' # 0x00ea -> GREEK CAPITAL LETTER OMEGA + u'\u03b4' # 0x00eb -> GREEK SMALL LETTER DELTA + u'\u221e' # 0x00ec -> INFINITY + u'\u03c6' # 0x00ed -> GREEK SMALL LETTER PHI + u'\u03b5' # 0x00ee -> GREEK SMALL LETTER EPSILON + u'\u2229' # 0x00ef -> INTERSECTION + u'\u2261' # 0x00f0 -> IDENTICAL TO + u'\xb1' # 0x00f1 -> PLUS-MINUS SIGN + u'\u2265' # 0x00f2 -> GREATER-THAN OR EQUAL TO + u'\u2264' # 0x00f3 -> LESS-THAN OR EQUAL TO + u'\u2320' # 0x00f4 -> TOP HALF INTEGRAL + u'\u2321' # 0x00f5 -> BOTTOM HALF INTEGRAL + u'\xf7' # 0x00f6 -> DIVISION SIGN + u'\u2248' # 0x00f7 -> ALMOST EQUAL TO + u'\xb0' # 0x00f8 -> DEGREE SIGN + u'\u2219' # 0x00f9 -> BULLET OPERATOR + u'\xb7' # 0x00fa -> MIDDLE DOT + u'\u221a' # 0x00fb -> SQUARE ROOT + u'\u207f' # 0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N + u'\xb2' # 0x00fd -> SUPERSCRIPT TWO + u'\u25a0' # 0x00fe -> BLACK SQUARE + u'\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a1: 0x00ad, # INVERTED EXCLAMATION MARK + 0x00a3: 0x009c, # POUND SIGN + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00bf: 0x00a8, # INVERTED QUESTION MARK + 0x00c1: 0x00a4, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00c4: 0x008e, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5: 0x008f, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c6: 0x0092, # LATIN CAPITAL LIGATURE AE + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00cd: 0x00a5, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00d0: 0x008b, # LATIN CAPITAL LETTER ETH + 0x00d3: 0x00a6, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00d6: 0x0099, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00d8: 0x009d, # LATIN CAPITAL LETTER O WITH STROKE + 0x00da: 0x00a7, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00dd: 0x0097, # LATIN CAPITAL LETTER Y WITH ACUTE + 0x00de: 0x008d, # LATIN CAPITAL LETTER THORN + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e0: 0x0085, # LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e4: 0x0084, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e5: 0x0086, # LATIN SMALL LETTER A WITH RING ABOVE + 0x00e6: 0x0091, # LATIN SMALL LIGATURE AE + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008a, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0088, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x0089, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00f0: 0x008c, # LATIN SMALL LETTER ETH + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f6: 0x0094, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f8: 0x009b, # LATIN SMALL LETTER O WITH STROKE + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x0096, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00fd: 0x0098, # LATIN SMALL LETTER Y WITH ACUTE + 0x00fe: 0x0095, # LATIN SMALL LETTER THORN + 0x0192: 0x009f, # LATIN SMALL LETTER F WITH HOOK + 0x0393: 0x00e2, # GREEK CAPITAL LETTER GAMMA + 0x0398: 0x00e9, # GREEK CAPITAL LETTER THETA + 0x03a3: 0x00e4, # GREEK CAPITAL LETTER SIGMA + 0x03a6: 0x00e8, # GREEK CAPITAL LETTER PHI + 0x03a9: 0x00ea, # GREEK CAPITAL LETTER OMEGA + 0x03b1: 0x00e0, # GREEK SMALL LETTER ALPHA + 0x03b4: 0x00eb, # GREEK SMALL LETTER DELTA + 0x03b5: 0x00ee, # GREEK SMALL LETTER EPSILON + 0x03c0: 0x00e3, # GREEK SMALL LETTER PI + 0x03c3: 0x00e5, # GREEK SMALL LETTER SIGMA + 0x03c4: 0x00e7, # GREEK SMALL LETTER TAU + 0x03c6: 0x00ed, # GREEK SMALL LETTER PHI + 0x207f: 0x00fc, # SUPERSCRIPT LATIN SMALL LETTER N + 0x20a7: 0x009e, # PESETA SIGN + 0x2219: 0x00f9, # BULLET OPERATOR + 0x221a: 0x00fb, # SQUARE ROOT + 0x221e: 0x00ec, # INFINITY + 0x2229: 0x00ef, # INTERSECTION + 0x2248: 0x00f7, # ALMOST EQUAL TO + 0x2261: 0x00f0, # IDENTICAL TO + 0x2264: 0x00f3, # LESS-THAN OR EQUAL TO + 0x2265: 0x00f2, # GREATER-THAN OR EQUAL TO + 0x2310: 0x00a9, # REVERSED NOT SIGN + 0x2320: 0x00f4, # TOP HALF INTEGRAL + 0x2321: 0x00f5, # BOTTOM HALF INTEGRAL + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/PythonHome/Lib/encodings/cp861.pyc b/PythonHome/Lib/encodings/cp861.pyc deleted file mode 100644 index 531f1fcdcc89344a49cff9751e5a8a548a0be56e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7923 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 NULL + u'\x01' # 0x0001 -> START OF HEADING + u'\x02' # 0x0002 -> START OF TEXT + u'\x03' # 0x0003 -> END OF TEXT + u'\x04' # 0x0004 -> END OF TRANSMISSION + u'\x05' # 0x0005 -> ENQUIRY + u'\x06' # 0x0006 -> ACKNOWLEDGE + u'\x07' # 0x0007 -> BELL + u'\x08' # 0x0008 -> BACKSPACE + u'\t' # 0x0009 -> HORIZONTAL TABULATION + u'\n' # 0x000a -> LINE FEED + u'\x0b' # 0x000b -> VERTICAL TABULATION + u'\x0c' # 0x000c -> FORM FEED + u'\r' # 0x000d -> CARRIAGE RETURN + u'\x0e' # 0x000e -> SHIFT OUT + u'\x0f' # 0x000f -> SHIFT IN + u'\x10' # 0x0010 -> DATA LINK ESCAPE + u'\x11' # 0x0011 -> DEVICE CONTROL ONE + u'\x12' # 0x0012 -> DEVICE CONTROL TWO + u'\x13' # 0x0013 -> DEVICE CONTROL THREE + u'\x14' # 0x0014 -> DEVICE CONTROL FOUR + u'\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x0016 -> SYNCHRONOUS IDLE + u'\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x0018 -> CANCEL + u'\x19' # 0x0019 -> END OF MEDIUM + u'\x1a' # 0x001a -> SUBSTITUTE + u'\x1b' # 0x001b -> ESCAPE + u'\x1c' # 0x001c -> FILE SEPARATOR + u'\x1d' # 0x001d -> GROUP SEPARATOR + u'\x1e' # 0x001e -> RECORD SEPARATOR + u'\x1f' # 0x001f -> UNIT SEPARATOR + u' ' # 0x0020 -> SPACE + u'!' # 0x0021 -> EXCLAMATION MARK + u'"' # 0x0022 -> QUOTATION MARK + u'#' # 0x0023 -> NUMBER SIGN + u'$' # 0x0024 -> DOLLAR SIGN + u'%' # 0x0025 -> PERCENT SIGN + u'&' # 0x0026 -> AMPERSAND + u"'" # 0x0027 -> APOSTROPHE + u'(' # 0x0028 -> LEFT PARENTHESIS + u')' # 0x0029 -> RIGHT PARENTHESIS + u'*' # 0x002a -> ASTERISK + u'+' # 0x002b -> PLUS SIGN + u',' # 0x002c -> COMMA + u'-' # 0x002d -> HYPHEN-MINUS + u'.' # 0x002e -> FULL STOP + u'/' # 0x002f -> SOLIDUS + u'0' # 0x0030 -> DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE + u':' # 0x003a -> COLON + u';' # 0x003b -> SEMICOLON + u'<' # 0x003c -> LESS-THAN SIGN + u'=' # 0x003d -> EQUALS SIGN + u'>' # 0x003e -> GREATER-THAN SIGN + u'?' # 0x003f -> QUESTION MARK + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET + u'\\' # 0x005c -> REVERSE SOLIDUS + u']' # 0x005d -> RIGHT SQUARE BRACKET + u'^' # 0x005e -> CIRCUMFLEX ACCENT + u'_' # 0x005f -> LOW LINE + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET + u'|' # 0x007c -> VERTICAL LINE + u'}' # 0x007d -> RIGHT CURLY BRACKET + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> DELETE + u'\u05d0' # 0x0080 -> HEBREW LETTER ALEF + u'\u05d1' # 0x0081 -> HEBREW LETTER BET + u'\u05d2' # 0x0082 -> HEBREW LETTER GIMEL + u'\u05d3' # 0x0083 -> HEBREW LETTER DALET + u'\u05d4' # 0x0084 -> HEBREW LETTER HE + u'\u05d5' # 0x0085 -> HEBREW LETTER VAV + u'\u05d6' # 0x0086 -> HEBREW LETTER ZAYIN + u'\u05d7' # 0x0087 -> HEBREW LETTER HET + u'\u05d8' # 0x0088 -> HEBREW LETTER TET + u'\u05d9' # 0x0089 -> HEBREW LETTER YOD + u'\u05da' # 0x008a -> HEBREW LETTER FINAL KAF + u'\u05db' # 0x008b -> HEBREW LETTER KAF + u'\u05dc' # 0x008c -> HEBREW LETTER LAMED + u'\u05dd' # 0x008d -> HEBREW LETTER FINAL MEM + u'\u05de' # 0x008e -> HEBREW LETTER MEM + u'\u05df' # 0x008f -> HEBREW LETTER FINAL NUN + u'\u05e0' # 0x0090 -> HEBREW LETTER NUN + u'\u05e1' # 0x0091 -> HEBREW LETTER SAMEKH + u'\u05e2' # 0x0092 -> HEBREW LETTER AYIN + u'\u05e3' # 0x0093 -> HEBREW LETTER FINAL PE + u'\u05e4' # 0x0094 -> HEBREW LETTER PE + u'\u05e5' # 0x0095 -> HEBREW LETTER FINAL TSADI + u'\u05e6' # 0x0096 -> HEBREW LETTER TSADI + u'\u05e7' # 0x0097 -> HEBREW LETTER QOF + u'\u05e8' # 0x0098 -> HEBREW LETTER RESH + u'\u05e9' # 0x0099 -> HEBREW LETTER SHIN + u'\u05ea' # 0x009a -> HEBREW LETTER TAV + u'\xa2' # 0x009b -> CENT SIGN + u'\xa3' # 0x009c -> POUND SIGN + u'\xa5' # 0x009d -> YEN SIGN + u'\u20a7' # 0x009e -> PESETA SIGN + u'\u0192' # 0x009f -> LATIN SMALL LETTER F WITH HOOK + u'\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + u'\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + u'\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + u'\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + u'\xf1' # 0x00a4 -> LATIN SMALL LETTER N WITH TILDE + u'\xd1' # 0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xaa' # 0x00a6 -> FEMININE ORDINAL INDICATOR + u'\xba' # 0x00a7 -> MASCULINE ORDINAL INDICATOR + u'\xbf' # 0x00a8 -> INVERTED QUESTION MARK + u'\u2310' # 0x00a9 -> REVERSED NOT SIGN + u'\xac' # 0x00aa -> NOT SIGN + u'\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + u'\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + u'\xa1' # 0x00ad -> INVERTED EXCLAMATION MARK + u'\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2591' # 0x00b0 -> LIGHT SHADE + u'\u2592' # 0x00b1 -> MEDIUM SHADE + u'\u2593' # 0x00b2 -> DARK SHADE + u'\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + u'\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + u'\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + u'\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + u'\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + u'\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + u'\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + u'\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + u'\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + u'\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + u'\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + u'\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + u'\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + u'\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + u'\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + u'\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + u'\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + u'\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + u'\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0x00db -> FULL BLOCK + u'\u2584' # 0x00dc -> LOWER HALF BLOCK + u'\u258c' # 0x00dd -> LEFT HALF BLOCK + u'\u2590' # 0x00de -> RIGHT HALF BLOCK + u'\u2580' # 0x00df -> UPPER HALF BLOCK + u'\u03b1' # 0x00e0 -> GREEK SMALL LETTER ALPHA + u'\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S (GERMAN) + u'\u0393' # 0x00e2 -> GREEK CAPITAL LETTER GAMMA + u'\u03c0' # 0x00e3 -> GREEK SMALL LETTER PI + u'\u03a3' # 0x00e4 -> GREEK CAPITAL LETTER SIGMA + u'\u03c3' # 0x00e5 -> GREEK SMALL LETTER SIGMA + u'\xb5' # 0x00e6 -> MICRO SIGN + u'\u03c4' # 0x00e7 -> GREEK SMALL LETTER TAU + u'\u03a6' # 0x00e8 -> GREEK CAPITAL LETTER PHI + u'\u0398' # 0x00e9 -> GREEK CAPITAL LETTER THETA + u'\u03a9' # 0x00ea -> GREEK CAPITAL LETTER OMEGA + u'\u03b4' # 0x00eb -> GREEK SMALL LETTER DELTA + u'\u221e' # 0x00ec -> INFINITY + u'\u03c6' # 0x00ed -> GREEK SMALL LETTER PHI + u'\u03b5' # 0x00ee -> GREEK SMALL LETTER EPSILON + u'\u2229' # 0x00ef -> INTERSECTION + u'\u2261' # 0x00f0 -> IDENTICAL TO + u'\xb1' # 0x00f1 -> PLUS-MINUS SIGN + u'\u2265' # 0x00f2 -> GREATER-THAN OR EQUAL TO + u'\u2264' # 0x00f3 -> LESS-THAN OR EQUAL TO + u'\u2320' # 0x00f4 -> TOP HALF INTEGRAL + u'\u2321' # 0x00f5 -> BOTTOM HALF INTEGRAL + u'\xf7' # 0x00f6 -> DIVISION SIGN + u'\u2248' # 0x00f7 -> ALMOST EQUAL TO + u'\xb0' # 0x00f8 -> DEGREE SIGN + u'\u2219' # 0x00f9 -> BULLET OPERATOR + u'\xb7' # 0x00fa -> MIDDLE DOT + u'\u221a' # 0x00fb -> SQUARE ROOT + u'\u207f' # 0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N + u'\xb2' # 0x00fd -> SUPERSCRIPT TWO + u'\u25a0' # 0x00fe -> BLACK SQUARE + u'\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a1: 0x00ad, # INVERTED EXCLAMATION MARK + 0x00a2: 0x009b, # CENT SIGN + 0x00a3: 0x009c, # POUND SIGN + 0x00a5: 0x009d, # YEN SIGN + 0x00aa: 0x00a6, # FEMININE ORDINAL INDICATOR + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00ba: 0x00a7, # MASCULINE ORDINAL INDICATOR + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00bf: 0x00a8, # INVERTED QUESTION MARK + 0x00d1: 0x00a5, # LATIN CAPITAL LETTER N WITH TILDE + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S (GERMAN) + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00f1: 0x00a4, # LATIN SMALL LETTER N WITH TILDE + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x0192: 0x009f, # LATIN SMALL LETTER F WITH HOOK + 0x0393: 0x00e2, # GREEK CAPITAL LETTER GAMMA + 0x0398: 0x00e9, # GREEK CAPITAL LETTER THETA + 0x03a3: 0x00e4, # GREEK CAPITAL LETTER SIGMA + 0x03a6: 0x00e8, # GREEK CAPITAL LETTER PHI + 0x03a9: 0x00ea, # GREEK CAPITAL LETTER OMEGA + 0x03b1: 0x00e0, # GREEK SMALL LETTER ALPHA + 0x03b4: 0x00eb, # GREEK SMALL LETTER DELTA + 0x03b5: 0x00ee, # GREEK SMALL LETTER EPSILON + 0x03c0: 0x00e3, # GREEK SMALL LETTER PI + 0x03c3: 0x00e5, # GREEK SMALL LETTER SIGMA + 0x03c4: 0x00e7, # GREEK SMALL LETTER TAU + 0x03c6: 0x00ed, # GREEK SMALL LETTER PHI + 0x05d0: 0x0080, # HEBREW LETTER ALEF + 0x05d1: 0x0081, # HEBREW LETTER BET + 0x05d2: 0x0082, # HEBREW LETTER GIMEL + 0x05d3: 0x0083, # HEBREW LETTER DALET + 0x05d4: 0x0084, # HEBREW LETTER HE + 0x05d5: 0x0085, # HEBREW LETTER VAV + 0x05d6: 0x0086, # HEBREW LETTER ZAYIN + 0x05d7: 0x0087, # HEBREW LETTER HET + 0x05d8: 0x0088, # HEBREW LETTER TET + 0x05d9: 0x0089, # HEBREW LETTER YOD + 0x05da: 0x008a, # HEBREW LETTER FINAL KAF + 0x05db: 0x008b, # HEBREW LETTER KAF + 0x05dc: 0x008c, # HEBREW LETTER LAMED + 0x05dd: 0x008d, # HEBREW LETTER FINAL MEM + 0x05de: 0x008e, # HEBREW LETTER MEM + 0x05df: 0x008f, # HEBREW LETTER FINAL NUN + 0x05e0: 0x0090, # HEBREW LETTER NUN + 0x05e1: 0x0091, # HEBREW LETTER SAMEKH + 0x05e2: 0x0092, # HEBREW LETTER AYIN + 0x05e3: 0x0093, # HEBREW LETTER FINAL PE + 0x05e4: 0x0094, # HEBREW LETTER PE + 0x05e5: 0x0095, # HEBREW LETTER FINAL TSADI + 0x05e6: 0x0096, # HEBREW LETTER TSADI + 0x05e7: 0x0097, # HEBREW LETTER QOF + 0x05e8: 0x0098, # HEBREW LETTER RESH + 0x05e9: 0x0099, # HEBREW LETTER SHIN + 0x05ea: 0x009a, # HEBREW LETTER TAV + 0x207f: 0x00fc, # SUPERSCRIPT LATIN SMALL LETTER N + 0x20a7: 0x009e, # PESETA SIGN + 0x2219: 0x00f9, # BULLET OPERATOR + 0x221a: 0x00fb, # SQUARE ROOT + 0x221e: 0x00ec, # INFINITY + 0x2229: 0x00ef, # INTERSECTION + 0x2248: 0x00f7, # ALMOST EQUAL TO + 0x2261: 0x00f0, # IDENTICAL TO + 0x2264: 0x00f3, # LESS-THAN OR EQUAL TO + 0x2265: 0x00f2, # GREATER-THAN OR EQUAL TO + 0x2310: 0x00a9, # REVERSED NOT SIGN + 0x2320: 0x00f4, # TOP HALF INTEGRAL + 0x2321: 0x00f5, # BOTTOM HALF INTEGRAL + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/PythonHome/Lib/encodings/cp862.pyc b/PythonHome/Lib/encodings/cp862.pyc deleted file mode 100644 index 8a7d27ac8fedf081c0c61b4c26e074e58a0ba128..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8058 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 diff --git a/PythonHome/Lib/encodings/cp863.py b/PythonHome/Lib/encodings/cp863.py new file mode 100644 index 0000000000..62dfabf66a --- /dev/null +++ b/PythonHome/Lib/encodings/cp863.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP863.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp863', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x00c7, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x0081: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0082: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x0083: 0x00e2, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x0084: 0x00c2, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x0085: 0x00e0, # LATIN SMALL LETTER A WITH GRAVE + 0x0086: 0x00b6, # PILCROW SIGN + 0x0087: 0x00e7, # LATIN SMALL LETTER C WITH CEDILLA + 0x0088: 0x00ea, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x0089: 0x00eb, # LATIN SMALL LETTER E WITH DIAERESIS + 0x008a: 0x00e8, # LATIN SMALL LETTER E WITH GRAVE + 0x008b: 0x00ef, # LATIN SMALL LETTER I WITH DIAERESIS + 0x008c: 0x00ee, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x008d: 0x2017, # DOUBLE LOW LINE + 0x008e: 0x00c0, # LATIN CAPITAL LETTER A WITH GRAVE + 0x008f: 0x00a7, # SECTION SIGN + 0x0090: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0091: 0x00c8, # LATIN CAPITAL LETTER E WITH GRAVE + 0x0092: 0x00ca, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x0093: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x0094: 0x00cb, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x0095: 0x00cf, # LATIN CAPITAL LETTER I WITH DIAERESIS + 0x0096: 0x00fb, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x0097: 0x00f9, # LATIN SMALL LETTER U WITH GRAVE + 0x0098: 0x00a4, # CURRENCY SIGN + 0x0099: 0x00d4, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x009a: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x009b: 0x00a2, # CENT SIGN + 0x009c: 0x00a3, # POUND SIGN + 0x009d: 0x00d9, # LATIN CAPITAL LETTER U WITH GRAVE + 0x009e: 0x00db, # LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x009f: 0x0192, # LATIN SMALL LETTER F WITH HOOK + 0x00a0: 0x00a6, # BROKEN BAR + 0x00a1: 0x00b4, # ACUTE ACCENT + 0x00a2: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00a3: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x00a4: 0x00a8, # DIAERESIS + 0x00a5: 0x00b8, # CEDILLA + 0x00a6: 0x00b3, # SUPERSCRIPT THREE + 0x00a7: 0x00af, # MACRON + 0x00a8: 0x00ce, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00a9: 0x2310, # REVERSED NOT SIGN + 0x00aa: 0x00ac, # NOT SIGN + 0x00ab: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00ac: 0x00bc, # VULGAR FRACTION ONE QUARTER + 0x00ad: 0x00be, # VULGAR FRACTION THREE QUARTERS + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x2561, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x00b6: 0x2562, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x00b7: 0x2556, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x00b8: 0x2555, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x255c, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x00be: 0x255b, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x255e, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x00c7: 0x255f, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x2567, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x00d0: 0x2568, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x00d1: 0x2564, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x00d2: 0x2565, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x00d3: 0x2559, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x00d4: 0x2558, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x00d5: 0x2552, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x00d6: 0x2553, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x00d7: 0x256b, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x00d8: 0x256a, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x258c, # LEFT HALF BLOCK + 0x00de: 0x2590, # RIGHT HALF BLOCK + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x03b1, # GREEK SMALL LETTER ALPHA + 0x00e1: 0x00df, # LATIN SMALL LETTER SHARP S + 0x00e2: 0x0393, # GREEK CAPITAL LETTER GAMMA + 0x00e3: 0x03c0, # GREEK SMALL LETTER PI + 0x00e4: 0x03a3, # GREEK CAPITAL LETTER SIGMA + 0x00e5: 0x03c3, # GREEK SMALL LETTER SIGMA + 0x00e6: 0x00b5, # MICRO SIGN + 0x00e7: 0x03c4, # GREEK SMALL LETTER TAU + 0x00e8: 0x03a6, # GREEK CAPITAL LETTER PHI + 0x00e9: 0x0398, # GREEK CAPITAL LETTER THETA + 0x00ea: 0x03a9, # GREEK CAPITAL LETTER OMEGA + 0x00eb: 0x03b4, # GREEK SMALL LETTER DELTA + 0x00ec: 0x221e, # INFINITY + 0x00ed: 0x03c6, # GREEK SMALL LETTER PHI + 0x00ee: 0x03b5, # GREEK SMALL LETTER EPSILON + 0x00ef: 0x2229, # INTERSECTION + 0x00f0: 0x2261, # IDENTICAL TO + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: 0x2265, # GREATER-THAN OR EQUAL TO + 0x00f3: 0x2264, # LESS-THAN OR EQUAL TO + 0x00f4: 0x2320, # TOP HALF INTEGRAL + 0x00f5: 0x2321, # BOTTOM HALF INTEGRAL + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x2248, # ALMOST EQUAL TO + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x2219, # BULLET OPERATOR + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x221a, # SQUARE ROOT + 0x00fc: 0x207f, # SUPERSCRIPT LATIN SMALL LETTER N + 0x00fd: 0x00b2, # SUPERSCRIPT TWO + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x0000 -> NULL + u'\x01' # 0x0001 -> START OF HEADING + u'\x02' # 0x0002 -> START OF TEXT + u'\x03' # 0x0003 -> END OF TEXT + u'\x04' # 0x0004 -> END OF TRANSMISSION + u'\x05' # 0x0005 -> ENQUIRY + u'\x06' # 0x0006 -> ACKNOWLEDGE + u'\x07' # 0x0007 -> BELL + u'\x08' # 0x0008 -> BACKSPACE + u'\t' # 0x0009 -> HORIZONTAL TABULATION + u'\n' # 0x000a -> LINE FEED + u'\x0b' # 0x000b -> VERTICAL TABULATION + u'\x0c' # 0x000c -> FORM FEED + u'\r' # 0x000d -> CARRIAGE RETURN + u'\x0e' # 0x000e -> SHIFT OUT + u'\x0f' # 0x000f -> SHIFT IN + u'\x10' # 0x0010 -> DATA LINK ESCAPE + u'\x11' # 0x0011 -> DEVICE CONTROL ONE + u'\x12' # 0x0012 -> DEVICE CONTROL TWO + u'\x13' # 0x0013 -> DEVICE CONTROL THREE + u'\x14' # 0x0014 -> DEVICE CONTROL FOUR + u'\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x0016 -> SYNCHRONOUS IDLE + u'\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x0018 -> CANCEL + u'\x19' # 0x0019 -> END OF MEDIUM + u'\x1a' # 0x001a -> SUBSTITUTE + u'\x1b' # 0x001b -> ESCAPE + u'\x1c' # 0x001c -> FILE SEPARATOR + u'\x1d' # 0x001d -> GROUP SEPARATOR + u'\x1e' # 0x001e -> RECORD SEPARATOR + u'\x1f' # 0x001f -> UNIT SEPARATOR + u' ' # 0x0020 -> SPACE + u'!' # 0x0021 -> EXCLAMATION MARK + u'"' # 0x0022 -> QUOTATION MARK + u'#' # 0x0023 -> NUMBER SIGN + u'$' # 0x0024 -> DOLLAR SIGN + u'%' # 0x0025 -> PERCENT SIGN + u'&' # 0x0026 -> AMPERSAND + u"'" # 0x0027 -> APOSTROPHE + u'(' # 0x0028 -> LEFT PARENTHESIS + u')' # 0x0029 -> RIGHT PARENTHESIS + u'*' # 0x002a -> ASTERISK + u'+' # 0x002b -> PLUS SIGN + u',' # 0x002c -> COMMA + u'-' # 0x002d -> HYPHEN-MINUS + u'.' # 0x002e -> FULL STOP + u'/' # 0x002f -> SOLIDUS + u'0' # 0x0030 -> DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE + u':' # 0x003a -> COLON + u';' # 0x003b -> SEMICOLON + u'<' # 0x003c -> LESS-THAN SIGN + u'=' # 0x003d -> EQUALS SIGN + u'>' # 0x003e -> GREATER-THAN SIGN + u'?' # 0x003f -> QUESTION MARK + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET + u'\\' # 0x005c -> REVERSE SOLIDUS + u']' # 0x005d -> RIGHT SQUARE BRACKET + u'^' # 0x005e -> CIRCUMFLEX ACCENT + u'_' # 0x005f -> LOW LINE + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET + u'|' # 0x007c -> VERTICAL LINE + u'}' # 0x007d -> RIGHT CURLY BRACKET + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> DELETE + u'\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + u'\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xc2' # 0x0084 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xe0' # 0x0085 -> LATIN SMALL LETTER A WITH GRAVE + u'\xb6' # 0x0086 -> PILCROW SIGN + u'\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xea' # 0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xe8' # 0x008a -> LATIN SMALL LETTER E WITH GRAVE + u'\xef' # 0x008b -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xee' # 0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\u2017' # 0x008d -> DOUBLE LOW LINE + u'\xc0' # 0x008e -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xa7' # 0x008f -> SECTION SIGN + u'\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xc8' # 0x0091 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xca' # 0x0092 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xcb' # 0x0094 -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xcf' # 0x0095 -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\xfb' # 0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xf9' # 0x0097 -> LATIN SMALL LETTER U WITH GRAVE + u'\xa4' # 0x0098 -> CURRENCY SIGN + u'\xd4' # 0x0099 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xa2' # 0x009b -> CENT SIGN + u'\xa3' # 0x009c -> POUND SIGN + u'\xd9' # 0x009d -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xdb' # 0x009e -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\u0192' # 0x009f -> LATIN SMALL LETTER F WITH HOOK + u'\xa6' # 0x00a0 -> BROKEN BAR + u'\xb4' # 0x00a1 -> ACUTE ACCENT + u'\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + u'\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + u'\xa8' # 0x00a4 -> DIAERESIS + u'\xb8' # 0x00a5 -> CEDILLA + u'\xb3' # 0x00a6 -> SUPERSCRIPT THREE + u'\xaf' # 0x00a7 -> MACRON + u'\xce' # 0x00a8 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\u2310' # 0x00a9 -> REVERSED NOT SIGN + u'\xac' # 0x00aa -> NOT SIGN + u'\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + u'\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + u'\xbe' # 0x00ad -> VULGAR FRACTION THREE QUARTERS + u'\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2591' # 0x00b0 -> LIGHT SHADE + u'\u2592' # 0x00b1 -> MEDIUM SHADE + u'\u2593' # 0x00b2 -> DARK SHADE + u'\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + u'\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + u'\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + u'\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + u'\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + u'\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + u'\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + u'\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + u'\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + u'\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + u'\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + u'\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + u'\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + u'\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + u'\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + u'\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + u'\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + u'\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + u'\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0x00db -> FULL BLOCK + u'\u2584' # 0x00dc -> LOWER HALF BLOCK + u'\u258c' # 0x00dd -> LEFT HALF BLOCK + u'\u2590' # 0x00de -> RIGHT HALF BLOCK + u'\u2580' # 0x00df -> UPPER HALF BLOCK + u'\u03b1' # 0x00e0 -> GREEK SMALL LETTER ALPHA + u'\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + u'\u0393' # 0x00e2 -> GREEK CAPITAL LETTER GAMMA + u'\u03c0' # 0x00e3 -> GREEK SMALL LETTER PI + u'\u03a3' # 0x00e4 -> GREEK CAPITAL LETTER SIGMA + u'\u03c3' # 0x00e5 -> GREEK SMALL LETTER SIGMA + u'\xb5' # 0x00e6 -> MICRO SIGN + u'\u03c4' # 0x00e7 -> GREEK SMALL LETTER TAU + u'\u03a6' # 0x00e8 -> GREEK CAPITAL LETTER PHI + u'\u0398' # 0x00e9 -> GREEK CAPITAL LETTER THETA + u'\u03a9' # 0x00ea -> GREEK CAPITAL LETTER OMEGA + u'\u03b4' # 0x00eb -> GREEK SMALL LETTER DELTA + u'\u221e' # 0x00ec -> INFINITY + u'\u03c6' # 0x00ed -> GREEK SMALL LETTER PHI + u'\u03b5' # 0x00ee -> GREEK SMALL LETTER EPSILON + u'\u2229' # 0x00ef -> INTERSECTION + u'\u2261' # 0x00f0 -> IDENTICAL TO + u'\xb1' # 0x00f1 -> PLUS-MINUS SIGN + u'\u2265' # 0x00f2 -> GREATER-THAN OR EQUAL TO + u'\u2264' # 0x00f3 -> LESS-THAN OR EQUAL TO + u'\u2320' # 0x00f4 -> TOP HALF INTEGRAL + u'\u2321' # 0x00f5 -> BOTTOM HALF INTEGRAL + u'\xf7' # 0x00f6 -> DIVISION SIGN + u'\u2248' # 0x00f7 -> ALMOST EQUAL TO + u'\xb0' # 0x00f8 -> DEGREE SIGN + u'\u2219' # 0x00f9 -> BULLET OPERATOR + u'\xb7' # 0x00fa -> MIDDLE DOT + u'\u221a' # 0x00fb -> SQUARE ROOT + u'\u207f' # 0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N + u'\xb2' # 0x00fd -> SUPERSCRIPT TWO + u'\u25a0' # 0x00fe -> BLACK SQUARE + u'\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a2: 0x009b, # CENT SIGN + 0x00a3: 0x009c, # POUND SIGN + 0x00a4: 0x0098, # CURRENCY SIGN + 0x00a6: 0x00a0, # BROKEN BAR + 0x00a7: 0x008f, # SECTION SIGN + 0x00a8: 0x00a4, # DIAERESIS + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00af: 0x00a7, # MACRON + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b3: 0x00a6, # SUPERSCRIPT THREE + 0x00b4: 0x00a1, # ACUTE ACCENT + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b6: 0x0086, # PILCROW SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00b8: 0x00a5, # CEDILLA + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00be: 0x00ad, # VULGAR FRACTION THREE QUARTERS + 0x00c0: 0x008e, # LATIN CAPITAL LETTER A WITH GRAVE + 0x00c2: 0x0084, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c8: 0x0091, # LATIN CAPITAL LETTER E WITH GRAVE + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00ca: 0x0092, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00cb: 0x0094, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00ce: 0x00a8, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00cf: 0x0095, # LATIN CAPITAL LETTER I WITH DIAERESIS + 0x00d4: 0x0099, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00d9: 0x009d, # LATIN CAPITAL LETTER U WITH GRAVE + 0x00db: 0x009e, # LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e0: 0x0085, # LATIN SMALL LETTER A WITH GRAVE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008a, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0088, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x0089, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ee: 0x008c, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ef: 0x008b, # LATIN SMALL LETTER I WITH DIAERESIS + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f9: 0x0097, # LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x0096, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0192: 0x009f, # LATIN SMALL LETTER F WITH HOOK + 0x0393: 0x00e2, # GREEK CAPITAL LETTER GAMMA + 0x0398: 0x00e9, # GREEK CAPITAL LETTER THETA + 0x03a3: 0x00e4, # GREEK CAPITAL LETTER SIGMA + 0x03a6: 0x00e8, # GREEK CAPITAL LETTER PHI + 0x03a9: 0x00ea, # GREEK CAPITAL LETTER OMEGA + 0x03b1: 0x00e0, # GREEK SMALL LETTER ALPHA + 0x03b4: 0x00eb, # GREEK SMALL LETTER DELTA + 0x03b5: 0x00ee, # GREEK SMALL LETTER EPSILON + 0x03c0: 0x00e3, # GREEK SMALL LETTER PI + 0x03c3: 0x00e5, # GREEK SMALL LETTER SIGMA + 0x03c4: 0x00e7, # GREEK SMALL LETTER TAU + 0x03c6: 0x00ed, # GREEK SMALL LETTER PHI + 0x2017: 0x008d, # DOUBLE LOW LINE + 0x207f: 0x00fc, # SUPERSCRIPT LATIN SMALL LETTER N + 0x2219: 0x00f9, # BULLET OPERATOR + 0x221a: 0x00fb, # SQUARE ROOT + 0x221e: 0x00ec, # INFINITY + 0x2229: 0x00ef, # INTERSECTION + 0x2248: 0x00f7, # ALMOST EQUAL TO + 0x2261: 0x00f0, # IDENTICAL TO + 0x2264: 0x00f3, # LESS-THAN OR EQUAL TO + 0x2265: 0x00f2, # GREATER-THAN OR EQUAL TO + 0x2310: 0x00a9, # REVERSED NOT SIGN + 0x2320: 0x00f4, # TOP HALF INTEGRAL + 0x2321: 0x00f5, # BOTTOM HALF INTEGRAL + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/PythonHome/Lib/encodings/cp863.pyc b/PythonHome/Lib/encodings/cp863.pyc deleted file mode 100644 index 1874c58cb5855163664ac9a6f0dfd8aa1e373456..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7923 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 diff --git a/PythonHome/Lib/encodings/cp864.py b/PythonHome/Lib/encodings/cp864.py new file mode 100644 index 0000000000..02a0e733a8 --- /dev/null +++ b/PythonHome/Lib/encodings/cp864.py @@ -0,0 +1,690 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP864.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp864', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0025: 0x066a, # ARABIC PERCENT SIGN + 0x0080: 0x00b0, # DEGREE SIGN + 0x0081: 0x00b7, # MIDDLE DOT + 0x0082: 0x2219, # BULLET OPERATOR + 0x0083: 0x221a, # SQUARE ROOT + 0x0084: 0x2592, # MEDIUM SHADE + 0x0085: 0x2500, # FORMS LIGHT HORIZONTAL + 0x0086: 0x2502, # FORMS LIGHT VERTICAL + 0x0087: 0x253c, # FORMS LIGHT VERTICAL AND HORIZONTAL + 0x0088: 0x2524, # FORMS LIGHT VERTICAL AND LEFT + 0x0089: 0x252c, # FORMS LIGHT DOWN AND HORIZONTAL + 0x008a: 0x251c, # FORMS LIGHT VERTICAL AND RIGHT + 0x008b: 0x2534, # FORMS LIGHT UP AND HORIZONTAL + 0x008c: 0x2510, # FORMS LIGHT DOWN AND LEFT + 0x008d: 0x250c, # FORMS LIGHT DOWN AND RIGHT + 0x008e: 0x2514, # FORMS LIGHT UP AND RIGHT + 0x008f: 0x2518, # FORMS LIGHT UP AND LEFT + 0x0090: 0x03b2, # GREEK SMALL BETA + 0x0091: 0x221e, # INFINITY + 0x0092: 0x03c6, # GREEK SMALL PHI + 0x0093: 0x00b1, # PLUS-OR-MINUS SIGN + 0x0094: 0x00bd, # FRACTION 1/2 + 0x0095: 0x00bc, # FRACTION 1/4 + 0x0096: 0x2248, # ALMOST EQUAL TO + 0x0097: 0x00ab, # LEFT POINTING GUILLEMET + 0x0098: 0x00bb, # RIGHT POINTING GUILLEMET + 0x0099: 0xfef7, # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM + 0x009a: 0xfef8, # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM + 0x009b: None, # UNDEFINED + 0x009c: None, # UNDEFINED + 0x009d: 0xfefb, # ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM + 0x009e: 0xfefc, # ARABIC LIGATURE LAM WITH ALEF FINAL FORM + 0x009f: None, # UNDEFINED + 0x00a1: 0x00ad, # SOFT HYPHEN + 0x00a2: 0xfe82, # ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM + 0x00a5: 0xfe84, # ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM + 0x00a6: None, # UNDEFINED + 0x00a7: None, # UNDEFINED + 0x00a8: 0xfe8e, # ARABIC LETTER ALEF FINAL FORM + 0x00a9: 0xfe8f, # ARABIC LETTER BEH ISOLATED FORM + 0x00aa: 0xfe95, # ARABIC LETTER TEH ISOLATED FORM + 0x00ab: 0xfe99, # ARABIC LETTER THEH ISOLATED FORM + 0x00ac: 0x060c, # ARABIC COMMA + 0x00ad: 0xfe9d, # ARABIC LETTER JEEM ISOLATED FORM + 0x00ae: 0xfea1, # ARABIC LETTER HAH ISOLATED FORM + 0x00af: 0xfea5, # ARABIC LETTER KHAH ISOLATED FORM + 0x00b0: 0x0660, # ARABIC-INDIC DIGIT ZERO + 0x00b1: 0x0661, # ARABIC-INDIC DIGIT ONE + 0x00b2: 0x0662, # ARABIC-INDIC DIGIT TWO + 0x00b3: 0x0663, # ARABIC-INDIC DIGIT THREE + 0x00b4: 0x0664, # ARABIC-INDIC DIGIT FOUR + 0x00b5: 0x0665, # ARABIC-INDIC DIGIT FIVE + 0x00b6: 0x0666, # ARABIC-INDIC DIGIT SIX + 0x00b7: 0x0667, # ARABIC-INDIC DIGIT SEVEN + 0x00b8: 0x0668, # ARABIC-INDIC DIGIT EIGHT + 0x00b9: 0x0669, # ARABIC-INDIC DIGIT NINE + 0x00ba: 0xfed1, # ARABIC LETTER FEH ISOLATED FORM + 0x00bb: 0x061b, # ARABIC SEMICOLON + 0x00bc: 0xfeb1, # ARABIC LETTER SEEN ISOLATED FORM + 0x00bd: 0xfeb5, # ARABIC LETTER SHEEN ISOLATED FORM + 0x00be: 0xfeb9, # ARABIC LETTER SAD ISOLATED FORM + 0x00bf: 0x061f, # ARABIC QUESTION MARK + 0x00c0: 0x00a2, # CENT SIGN + 0x00c1: 0xfe80, # ARABIC LETTER HAMZA ISOLATED FORM + 0x00c2: 0xfe81, # ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM + 0x00c3: 0xfe83, # ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM + 0x00c4: 0xfe85, # ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM + 0x00c5: 0xfeca, # ARABIC LETTER AIN FINAL FORM + 0x00c6: 0xfe8b, # ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM + 0x00c7: 0xfe8d, # ARABIC LETTER ALEF ISOLATED FORM + 0x00c8: 0xfe91, # ARABIC LETTER BEH INITIAL FORM + 0x00c9: 0xfe93, # ARABIC LETTER TEH MARBUTA ISOLATED FORM + 0x00ca: 0xfe97, # ARABIC LETTER TEH INITIAL FORM + 0x00cb: 0xfe9b, # ARABIC LETTER THEH INITIAL FORM + 0x00cc: 0xfe9f, # ARABIC LETTER JEEM INITIAL FORM + 0x00cd: 0xfea3, # ARABIC LETTER HAH INITIAL FORM + 0x00ce: 0xfea7, # ARABIC LETTER KHAH INITIAL FORM + 0x00cf: 0xfea9, # ARABIC LETTER DAL ISOLATED FORM + 0x00d0: 0xfeab, # ARABIC LETTER THAL ISOLATED FORM + 0x00d1: 0xfead, # ARABIC LETTER REH ISOLATED FORM + 0x00d2: 0xfeaf, # ARABIC LETTER ZAIN ISOLATED FORM + 0x00d3: 0xfeb3, # ARABIC LETTER SEEN INITIAL FORM + 0x00d4: 0xfeb7, # ARABIC LETTER SHEEN INITIAL FORM + 0x00d5: 0xfebb, # ARABIC LETTER SAD INITIAL FORM + 0x00d6: 0xfebf, # ARABIC LETTER DAD INITIAL FORM + 0x00d7: 0xfec1, # ARABIC LETTER TAH ISOLATED FORM + 0x00d8: 0xfec5, # ARABIC LETTER ZAH ISOLATED FORM + 0x00d9: 0xfecb, # ARABIC LETTER AIN INITIAL FORM + 0x00da: 0xfecf, # ARABIC LETTER GHAIN INITIAL FORM + 0x00db: 0x00a6, # BROKEN VERTICAL BAR + 0x00dc: 0x00ac, # NOT SIGN + 0x00dd: 0x00f7, # DIVISION SIGN + 0x00de: 0x00d7, # MULTIPLICATION SIGN + 0x00df: 0xfec9, # ARABIC LETTER AIN ISOLATED FORM + 0x00e0: 0x0640, # ARABIC TATWEEL + 0x00e1: 0xfed3, # ARABIC LETTER FEH INITIAL FORM + 0x00e2: 0xfed7, # ARABIC LETTER QAF INITIAL FORM + 0x00e3: 0xfedb, # ARABIC LETTER KAF INITIAL FORM + 0x00e4: 0xfedf, # ARABIC LETTER LAM INITIAL FORM + 0x00e5: 0xfee3, # ARABIC LETTER MEEM INITIAL FORM + 0x00e6: 0xfee7, # ARABIC LETTER NOON INITIAL FORM + 0x00e7: 0xfeeb, # ARABIC LETTER HEH INITIAL FORM + 0x00e8: 0xfeed, # ARABIC LETTER WAW ISOLATED FORM + 0x00e9: 0xfeef, # ARABIC LETTER ALEF MAKSURA ISOLATED FORM + 0x00ea: 0xfef3, # ARABIC LETTER YEH INITIAL FORM + 0x00eb: 0xfebd, # ARABIC LETTER DAD ISOLATED FORM + 0x00ec: 0xfecc, # ARABIC LETTER AIN MEDIAL FORM + 0x00ed: 0xfece, # ARABIC LETTER GHAIN FINAL FORM + 0x00ee: 0xfecd, # ARABIC LETTER GHAIN ISOLATED FORM + 0x00ef: 0xfee1, # ARABIC LETTER MEEM ISOLATED FORM + 0x00f0: 0xfe7d, # ARABIC SHADDA MEDIAL FORM + 0x00f1: 0x0651, # ARABIC SHADDAH + 0x00f2: 0xfee5, # ARABIC LETTER NOON ISOLATED FORM + 0x00f3: 0xfee9, # ARABIC LETTER HEH ISOLATED FORM + 0x00f4: 0xfeec, # ARABIC LETTER HEH MEDIAL FORM + 0x00f5: 0xfef0, # ARABIC LETTER ALEF MAKSURA FINAL FORM + 0x00f6: 0xfef2, # ARABIC LETTER YEH FINAL FORM + 0x00f7: 0xfed0, # ARABIC LETTER GHAIN MEDIAL FORM + 0x00f8: 0xfed5, # ARABIC LETTER QAF ISOLATED FORM + 0x00f9: 0xfef5, # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM + 0x00fa: 0xfef6, # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM + 0x00fb: 0xfedd, # ARABIC LETTER LAM ISOLATED FORM + 0x00fc: 0xfed9, # ARABIC LETTER KAF ISOLATED FORM + 0x00fd: 0xfef1, # ARABIC LETTER YEH ISOLATED FORM + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: None, # UNDEFINED +}) + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x0000 -> NULL + u'\x01' # 0x0001 -> START OF HEADING + u'\x02' # 0x0002 -> START OF TEXT + u'\x03' # 0x0003 -> END OF TEXT + u'\x04' # 0x0004 -> END OF TRANSMISSION + u'\x05' # 0x0005 -> ENQUIRY + u'\x06' # 0x0006 -> ACKNOWLEDGE + u'\x07' # 0x0007 -> BELL + u'\x08' # 0x0008 -> BACKSPACE + u'\t' # 0x0009 -> HORIZONTAL TABULATION + u'\n' # 0x000a -> LINE FEED + u'\x0b' # 0x000b -> VERTICAL TABULATION + u'\x0c' # 0x000c -> FORM FEED + u'\r' # 0x000d -> CARRIAGE RETURN + u'\x0e' # 0x000e -> SHIFT OUT + u'\x0f' # 0x000f -> SHIFT IN + u'\x10' # 0x0010 -> DATA LINK ESCAPE + u'\x11' # 0x0011 -> DEVICE CONTROL ONE + u'\x12' # 0x0012 -> DEVICE CONTROL TWO + u'\x13' # 0x0013 -> DEVICE CONTROL THREE + u'\x14' # 0x0014 -> DEVICE CONTROL FOUR + u'\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x0016 -> SYNCHRONOUS IDLE + u'\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x0018 -> CANCEL + u'\x19' # 0x0019 -> END OF MEDIUM + u'\x1a' # 0x001a -> SUBSTITUTE + u'\x1b' # 0x001b -> ESCAPE + u'\x1c' # 0x001c -> FILE SEPARATOR + u'\x1d' # 0x001d -> GROUP SEPARATOR + u'\x1e' # 0x001e -> RECORD SEPARATOR + u'\x1f' # 0x001f -> UNIT SEPARATOR + u' ' # 0x0020 -> SPACE + u'!' # 0x0021 -> EXCLAMATION MARK + u'"' # 0x0022 -> QUOTATION MARK + u'#' # 0x0023 -> NUMBER SIGN + u'$' # 0x0024 -> DOLLAR SIGN + u'\u066a' # 0x0025 -> ARABIC PERCENT SIGN + u'&' # 0x0026 -> AMPERSAND + u"'" # 0x0027 -> APOSTROPHE + u'(' # 0x0028 -> LEFT PARENTHESIS + u')' # 0x0029 -> RIGHT PARENTHESIS + u'*' # 0x002a -> ASTERISK + u'+' # 0x002b -> PLUS SIGN + u',' # 0x002c -> COMMA + u'-' # 0x002d -> HYPHEN-MINUS + u'.' # 0x002e -> FULL STOP + u'/' # 0x002f -> SOLIDUS + u'0' # 0x0030 -> DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE + u':' # 0x003a -> COLON + u';' # 0x003b -> SEMICOLON + u'<' # 0x003c -> LESS-THAN SIGN + u'=' # 0x003d -> EQUALS SIGN + u'>' # 0x003e -> GREATER-THAN SIGN + u'?' # 0x003f -> QUESTION MARK + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET + u'\\' # 0x005c -> REVERSE SOLIDUS + u']' # 0x005d -> RIGHT SQUARE BRACKET + u'^' # 0x005e -> CIRCUMFLEX ACCENT + u'_' # 0x005f -> LOW LINE + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET + u'|' # 0x007c -> VERTICAL LINE + u'}' # 0x007d -> RIGHT CURLY BRACKET + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> DELETE + u'\xb0' # 0x0080 -> DEGREE SIGN + u'\xb7' # 0x0081 -> MIDDLE DOT + u'\u2219' # 0x0082 -> BULLET OPERATOR + u'\u221a' # 0x0083 -> SQUARE ROOT + u'\u2592' # 0x0084 -> MEDIUM SHADE + u'\u2500' # 0x0085 -> FORMS LIGHT HORIZONTAL + u'\u2502' # 0x0086 -> FORMS LIGHT VERTICAL + u'\u253c' # 0x0087 -> FORMS LIGHT VERTICAL AND HORIZONTAL + u'\u2524' # 0x0088 -> FORMS LIGHT VERTICAL AND LEFT + u'\u252c' # 0x0089 -> FORMS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0x008a -> FORMS LIGHT VERTICAL AND RIGHT + u'\u2534' # 0x008b -> FORMS LIGHT UP AND HORIZONTAL + u'\u2510' # 0x008c -> FORMS LIGHT DOWN AND LEFT + u'\u250c' # 0x008d -> FORMS LIGHT DOWN AND RIGHT + u'\u2514' # 0x008e -> FORMS LIGHT UP AND RIGHT + u'\u2518' # 0x008f -> FORMS LIGHT UP AND LEFT + u'\u03b2' # 0x0090 -> GREEK SMALL BETA + u'\u221e' # 0x0091 -> INFINITY + u'\u03c6' # 0x0092 -> GREEK SMALL PHI + u'\xb1' # 0x0093 -> PLUS-OR-MINUS SIGN + u'\xbd' # 0x0094 -> FRACTION 1/2 + u'\xbc' # 0x0095 -> FRACTION 1/4 + u'\u2248' # 0x0096 -> ALMOST EQUAL TO + u'\xab' # 0x0097 -> LEFT POINTING GUILLEMET + u'\xbb' # 0x0098 -> RIGHT POINTING GUILLEMET + u'\ufef7' # 0x0099 -> ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM + u'\ufef8' # 0x009a -> ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM + u'\ufffe' # 0x009b -> UNDEFINED + u'\ufffe' # 0x009c -> UNDEFINED + u'\ufefb' # 0x009d -> ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM + u'\ufefc' # 0x009e -> ARABIC LIGATURE LAM WITH ALEF FINAL FORM + u'\ufffe' # 0x009f -> UNDEFINED + u'\xa0' # 0x00a0 -> NON-BREAKING SPACE + u'\xad' # 0x00a1 -> SOFT HYPHEN + u'\ufe82' # 0x00a2 -> ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM + u'\xa3' # 0x00a3 -> POUND SIGN + u'\xa4' # 0x00a4 -> CURRENCY SIGN + u'\ufe84' # 0x00a5 -> ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM + u'\ufffe' # 0x00a6 -> UNDEFINED + u'\ufffe' # 0x00a7 -> UNDEFINED + u'\ufe8e' # 0x00a8 -> ARABIC LETTER ALEF FINAL FORM + u'\ufe8f' # 0x00a9 -> ARABIC LETTER BEH ISOLATED FORM + u'\ufe95' # 0x00aa -> ARABIC LETTER TEH ISOLATED FORM + u'\ufe99' # 0x00ab -> ARABIC LETTER THEH ISOLATED FORM + u'\u060c' # 0x00ac -> ARABIC COMMA + u'\ufe9d' # 0x00ad -> ARABIC LETTER JEEM ISOLATED FORM + u'\ufea1' # 0x00ae -> ARABIC LETTER HAH ISOLATED FORM + u'\ufea5' # 0x00af -> ARABIC LETTER KHAH ISOLATED FORM + u'\u0660' # 0x00b0 -> ARABIC-INDIC DIGIT ZERO + u'\u0661' # 0x00b1 -> ARABIC-INDIC DIGIT ONE + u'\u0662' # 0x00b2 -> ARABIC-INDIC DIGIT TWO + u'\u0663' # 0x00b3 -> ARABIC-INDIC DIGIT THREE + u'\u0664' # 0x00b4 -> ARABIC-INDIC DIGIT FOUR + u'\u0665' # 0x00b5 -> ARABIC-INDIC DIGIT FIVE + u'\u0666' # 0x00b6 -> ARABIC-INDIC DIGIT SIX + u'\u0667' # 0x00b7 -> ARABIC-INDIC DIGIT SEVEN + u'\u0668' # 0x00b8 -> ARABIC-INDIC DIGIT EIGHT + u'\u0669' # 0x00b9 -> ARABIC-INDIC DIGIT NINE + u'\ufed1' # 0x00ba -> ARABIC LETTER FEH ISOLATED FORM + u'\u061b' # 0x00bb -> ARABIC SEMICOLON + u'\ufeb1' # 0x00bc -> ARABIC LETTER SEEN ISOLATED FORM + u'\ufeb5' # 0x00bd -> ARABIC LETTER SHEEN ISOLATED FORM + u'\ufeb9' # 0x00be -> ARABIC LETTER SAD ISOLATED FORM + u'\u061f' # 0x00bf -> ARABIC QUESTION MARK + u'\xa2' # 0x00c0 -> CENT SIGN + u'\ufe80' # 0x00c1 -> ARABIC LETTER HAMZA ISOLATED FORM + u'\ufe81' # 0x00c2 -> ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM + u'\ufe83' # 0x00c3 -> ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM + u'\ufe85' # 0x00c4 -> ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM + u'\ufeca' # 0x00c5 -> ARABIC LETTER AIN FINAL FORM + u'\ufe8b' # 0x00c6 -> ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM + u'\ufe8d' # 0x00c7 -> ARABIC LETTER ALEF ISOLATED FORM + u'\ufe91' # 0x00c8 -> ARABIC LETTER BEH INITIAL FORM + u'\ufe93' # 0x00c9 -> ARABIC LETTER TEH MARBUTA ISOLATED FORM + u'\ufe97' # 0x00ca -> ARABIC LETTER TEH INITIAL FORM + u'\ufe9b' # 0x00cb -> ARABIC LETTER THEH INITIAL FORM + u'\ufe9f' # 0x00cc -> ARABIC LETTER JEEM INITIAL FORM + u'\ufea3' # 0x00cd -> ARABIC LETTER HAH INITIAL FORM + u'\ufea7' # 0x00ce -> ARABIC LETTER KHAH INITIAL FORM + u'\ufea9' # 0x00cf -> ARABIC LETTER DAL ISOLATED FORM + u'\ufeab' # 0x00d0 -> ARABIC LETTER THAL ISOLATED FORM + u'\ufead' # 0x00d1 -> ARABIC LETTER REH ISOLATED FORM + u'\ufeaf' # 0x00d2 -> ARABIC LETTER ZAIN ISOLATED FORM + u'\ufeb3' # 0x00d3 -> ARABIC LETTER SEEN INITIAL FORM + u'\ufeb7' # 0x00d4 -> ARABIC LETTER SHEEN INITIAL FORM + u'\ufebb' # 0x00d5 -> ARABIC LETTER SAD INITIAL FORM + u'\ufebf' # 0x00d6 -> ARABIC LETTER DAD INITIAL FORM + u'\ufec1' # 0x00d7 -> ARABIC LETTER TAH ISOLATED FORM + u'\ufec5' # 0x00d8 -> ARABIC LETTER ZAH ISOLATED FORM + u'\ufecb' # 0x00d9 -> ARABIC LETTER AIN INITIAL FORM + u'\ufecf' # 0x00da -> ARABIC LETTER GHAIN INITIAL FORM + u'\xa6' # 0x00db -> BROKEN VERTICAL BAR + u'\xac' # 0x00dc -> NOT SIGN + u'\xf7' # 0x00dd -> DIVISION SIGN + u'\xd7' # 0x00de -> MULTIPLICATION SIGN + u'\ufec9' # 0x00df -> ARABIC LETTER AIN ISOLATED FORM + u'\u0640' # 0x00e0 -> ARABIC TATWEEL + u'\ufed3' # 0x00e1 -> ARABIC LETTER FEH INITIAL FORM + u'\ufed7' # 0x00e2 -> ARABIC LETTER QAF INITIAL FORM + u'\ufedb' # 0x00e3 -> ARABIC LETTER KAF INITIAL FORM + u'\ufedf' # 0x00e4 -> ARABIC LETTER LAM INITIAL FORM + u'\ufee3' # 0x00e5 -> ARABIC LETTER MEEM INITIAL FORM + u'\ufee7' # 0x00e6 -> ARABIC LETTER NOON INITIAL FORM + u'\ufeeb' # 0x00e7 -> ARABIC LETTER HEH INITIAL FORM + u'\ufeed' # 0x00e8 -> ARABIC LETTER WAW ISOLATED FORM + u'\ufeef' # 0x00e9 -> ARABIC LETTER ALEF MAKSURA ISOLATED FORM + u'\ufef3' # 0x00ea -> ARABIC LETTER YEH INITIAL FORM + u'\ufebd' # 0x00eb -> ARABIC LETTER DAD ISOLATED FORM + u'\ufecc' # 0x00ec -> ARABIC LETTER AIN MEDIAL FORM + u'\ufece' # 0x00ed -> ARABIC LETTER GHAIN FINAL FORM + u'\ufecd' # 0x00ee -> ARABIC LETTER GHAIN ISOLATED FORM + u'\ufee1' # 0x00ef -> ARABIC LETTER MEEM ISOLATED FORM + u'\ufe7d' # 0x00f0 -> ARABIC SHADDA MEDIAL FORM + u'\u0651' # 0x00f1 -> ARABIC SHADDAH + u'\ufee5' # 0x00f2 -> ARABIC LETTER NOON ISOLATED FORM + u'\ufee9' # 0x00f3 -> ARABIC LETTER HEH ISOLATED FORM + u'\ufeec' # 0x00f4 -> ARABIC LETTER HEH MEDIAL FORM + u'\ufef0' # 0x00f5 -> ARABIC LETTER ALEF MAKSURA FINAL FORM + u'\ufef2' # 0x00f6 -> ARABIC LETTER YEH FINAL FORM + u'\ufed0' # 0x00f7 -> ARABIC LETTER GHAIN MEDIAL FORM + u'\ufed5' # 0x00f8 -> ARABIC LETTER QAF ISOLATED FORM + u'\ufef5' # 0x00f9 -> ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM + u'\ufef6' # 0x00fa -> ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM + u'\ufedd' # 0x00fb -> ARABIC LETTER LAM ISOLATED FORM + u'\ufed9' # 0x00fc -> ARABIC LETTER KAF ISOLATED FORM + u'\ufef1' # 0x00fd -> ARABIC LETTER YEH ISOLATED FORM + u'\u25a0' # 0x00fe -> BLACK SQUARE + u'\ufffe' # 0x00ff -> UNDEFINED +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00a0, # NON-BREAKING SPACE + 0x00a2: 0x00c0, # CENT SIGN + 0x00a3: 0x00a3, # POUND SIGN + 0x00a4: 0x00a4, # CURRENCY SIGN + 0x00a6: 0x00db, # BROKEN VERTICAL BAR + 0x00ab: 0x0097, # LEFT POINTING GUILLEMET + 0x00ac: 0x00dc, # NOT SIGN + 0x00ad: 0x00a1, # SOFT HYPHEN + 0x00b0: 0x0080, # DEGREE SIGN + 0x00b1: 0x0093, # PLUS-OR-MINUS SIGN + 0x00b7: 0x0081, # MIDDLE DOT + 0x00bb: 0x0098, # RIGHT POINTING GUILLEMET + 0x00bc: 0x0095, # FRACTION 1/4 + 0x00bd: 0x0094, # FRACTION 1/2 + 0x00d7: 0x00de, # MULTIPLICATION SIGN + 0x00f7: 0x00dd, # DIVISION SIGN + 0x03b2: 0x0090, # GREEK SMALL BETA + 0x03c6: 0x0092, # GREEK SMALL PHI + 0x060c: 0x00ac, # ARABIC COMMA + 0x061b: 0x00bb, # ARABIC SEMICOLON + 0x061f: 0x00bf, # ARABIC QUESTION MARK + 0x0640: 0x00e0, # ARABIC TATWEEL + 0x0651: 0x00f1, # ARABIC SHADDAH + 0x0660: 0x00b0, # ARABIC-INDIC DIGIT ZERO + 0x0661: 0x00b1, # ARABIC-INDIC DIGIT ONE + 0x0662: 0x00b2, # ARABIC-INDIC DIGIT TWO + 0x0663: 0x00b3, # ARABIC-INDIC DIGIT THREE + 0x0664: 0x00b4, # ARABIC-INDIC DIGIT FOUR + 0x0665: 0x00b5, # ARABIC-INDIC DIGIT FIVE + 0x0666: 0x00b6, # ARABIC-INDIC DIGIT SIX + 0x0667: 0x00b7, # ARABIC-INDIC DIGIT SEVEN + 0x0668: 0x00b8, # ARABIC-INDIC DIGIT EIGHT + 0x0669: 0x00b9, # ARABIC-INDIC DIGIT NINE + 0x066a: 0x0025, # ARABIC PERCENT SIGN + 0x2219: 0x0082, # BULLET OPERATOR + 0x221a: 0x0083, # SQUARE ROOT + 0x221e: 0x0091, # INFINITY + 0x2248: 0x0096, # ALMOST EQUAL TO + 0x2500: 0x0085, # FORMS LIGHT HORIZONTAL + 0x2502: 0x0086, # FORMS LIGHT VERTICAL + 0x250c: 0x008d, # FORMS LIGHT DOWN AND RIGHT + 0x2510: 0x008c, # FORMS LIGHT DOWN AND LEFT + 0x2514: 0x008e, # FORMS LIGHT UP AND RIGHT + 0x2518: 0x008f, # FORMS LIGHT UP AND LEFT + 0x251c: 0x008a, # FORMS LIGHT VERTICAL AND RIGHT + 0x2524: 0x0088, # FORMS LIGHT VERTICAL AND LEFT + 0x252c: 0x0089, # FORMS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x008b, # FORMS LIGHT UP AND HORIZONTAL + 0x253c: 0x0087, # FORMS LIGHT VERTICAL AND HORIZONTAL + 0x2592: 0x0084, # MEDIUM SHADE + 0x25a0: 0x00fe, # BLACK SQUARE + 0xfe7d: 0x00f0, # ARABIC SHADDA MEDIAL FORM + 0xfe80: 0x00c1, # ARABIC LETTER HAMZA ISOLATED FORM + 0xfe81: 0x00c2, # ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM + 0xfe82: 0x00a2, # ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM + 0xfe83: 0x00c3, # ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM + 0xfe84: 0x00a5, # ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM + 0xfe85: 0x00c4, # ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM + 0xfe8b: 0x00c6, # ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM + 0xfe8d: 0x00c7, # ARABIC LETTER ALEF ISOLATED FORM + 0xfe8e: 0x00a8, # ARABIC LETTER ALEF FINAL FORM + 0xfe8f: 0x00a9, # ARABIC LETTER BEH ISOLATED FORM + 0xfe91: 0x00c8, # ARABIC LETTER BEH INITIAL FORM + 0xfe93: 0x00c9, # ARABIC LETTER TEH MARBUTA ISOLATED FORM + 0xfe95: 0x00aa, # ARABIC LETTER TEH ISOLATED FORM + 0xfe97: 0x00ca, # ARABIC LETTER TEH INITIAL FORM + 0xfe99: 0x00ab, # ARABIC LETTER THEH ISOLATED FORM + 0xfe9b: 0x00cb, # ARABIC LETTER THEH INITIAL FORM + 0xfe9d: 0x00ad, # ARABIC LETTER JEEM ISOLATED FORM + 0xfe9f: 0x00cc, # ARABIC LETTER JEEM INITIAL FORM + 0xfea1: 0x00ae, # ARABIC LETTER HAH ISOLATED FORM + 0xfea3: 0x00cd, # ARABIC LETTER HAH INITIAL FORM + 0xfea5: 0x00af, # ARABIC LETTER KHAH ISOLATED FORM + 0xfea7: 0x00ce, # ARABIC LETTER KHAH INITIAL FORM + 0xfea9: 0x00cf, # ARABIC LETTER DAL ISOLATED FORM + 0xfeab: 0x00d0, # ARABIC LETTER THAL ISOLATED FORM + 0xfead: 0x00d1, # ARABIC LETTER REH ISOLATED FORM + 0xfeaf: 0x00d2, # ARABIC LETTER ZAIN ISOLATED FORM + 0xfeb1: 0x00bc, # ARABIC LETTER SEEN ISOLATED FORM + 0xfeb3: 0x00d3, # ARABIC LETTER SEEN INITIAL FORM + 0xfeb5: 0x00bd, # ARABIC LETTER SHEEN ISOLATED FORM + 0xfeb7: 0x00d4, # ARABIC LETTER SHEEN INITIAL FORM + 0xfeb9: 0x00be, # ARABIC LETTER SAD ISOLATED FORM + 0xfebb: 0x00d5, # ARABIC LETTER SAD INITIAL FORM + 0xfebd: 0x00eb, # ARABIC LETTER DAD ISOLATED FORM + 0xfebf: 0x00d6, # ARABIC LETTER DAD INITIAL FORM + 0xfec1: 0x00d7, # ARABIC LETTER TAH ISOLATED FORM + 0xfec5: 0x00d8, # ARABIC LETTER ZAH ISOLATED FORM + 0xfec9: 0x00df, # ARABIC LETTER AIN ISOLATED FORM + 0xfeca: 0x00c5, # ARABIC LETTER AIN FINAL FORM + 0xfecb: 0x00d9, # ARABIC LETTER AIN INITIAL FORM + 0xfecc: 0x00ec, # ARABIC LETTER AIN MEDIAL FORM + 0xfecd: 0x00ee, # ARABIC LETTER GHAIN ISOLATED FORM + 0xfece: 0x00ed, # ARABIC LETTER GHAIN FINAL FORM + 0xfecf: 0x00da, # ARABIC LETTER GHAIN INITIAL FORM + 0xfed0: 0x00f7, # ARABIC LETTER GHAIN MEDIAL FORM + 0xfed1: 0x00ba, # ARABIC LETTER FEH ISOLATED FORM + 0xfed3: 0x00e1, # ARABIC LETTER FEH INITIAL FORM + 0xfed5: 0x00f8, # ARABIC LETTER QAF ISOLATED FORM + 0xfed7: 0x00e2, # ARABIC LETTER QAF INITIAL FORM + 0xfed9: 0x00fc, # ARABIC LETTER KAF ISOLATED FORM + 0xfedb: 0x00e3, # ARABIC LETTER KAF INITIAL FORM + 0xfedd: 0x00fb, # ARABIC LETTER LAM ISOLATED FORM + 0xfedf: 0x00e4, # ARABIC LETTER LAM INITIAL FORM + 0xfee1: 0x00ef, # ARABIC LETTER MEEM ISOLATED FORM + 0xfee3: 0x00e5, # ARABIC LETTER MEEM INITIAL FORM + 0xfee5: 0x00f2, # ARABIC LETTER NOON ISOLATED FORM + 0xfee7: 0x00e6, # ARABIC LETTER NOON INITIAL FORM + 0xfee9: 0x00f3, # ARABIC LETTER HEH ISOLATED FORM + 0xfeeb: 0x00e7, # ARABIC LETTER HEH INITIAL FORM + 0xfeec: 0x00f4, # ARABIC LETTER HEH MEDIAL FORM + 0xfeed: 0x00e8, # ARABIC LETTER WAW ISOLATED FORM + 0xfeef: 0x00e9, # ARABIC LETTER ALEF MAKSURA ISOLATED FORM + 0xfef0: 0x00f5, # ARABIC LETTER ALEF MAKSURA FINAL FORM + 0xfef1: 0x00fd, # ARABIC LETTER YEH ISOLATED FORM + 0xfef2: 0x00f6, # ARABIC LETTER YEH FINAL FORM + 0xfef3: 0x00ea, # ARABIC LETTER YEH INITIAL FORM + 0xfef5: 0x00f9, # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM + 0xfef6: 0x00fa, # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM + 0xfef7: 0x0099, # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM + 0xfef8: 0x009a, # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM + 0xfefb: 0x009d, # ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM + 0xfefc: 0x009e, # ARABIC LIGATURE LAM WITH ALEF FINAL FORM +} diff --git a/PythonHome/Lib/encodings/cp864.pyc b/PythonHome/Lib/encodings/cp864.pyc deleted file mode 100644 index 52ea66432ae4ebb20634c472704c3123c5dc0e1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8054 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 NULL + u'\x01' # 0x0001 -> START OF HEADING + u'\x02' # 0x0002 -> START OF TEXT + u'\x03' # 0x0003 -> END OF TEXT + u'\x04' # 0x0004 -> END OF TRANSMISSION + u'\x05' # 0x0005 -> ENQUIRY + u'\x06' # 0x0006 -> ACKNOWLEDGE + u'\x07' # 0x0007 -> BELL + u'\x08' # 0x0008 -> BACKSPACE + u'\t' # 0x0009 -> HORIZONTAL TABULATION + u'\n' # 0x000a -> LINE FEED + u'\x0b' # 0x000b -> VERTICAL TABULATION + u'\x0c' # 0x000c -> FORM FEED + u'\r' # 0x000d -> CARRIAGE RETURN + u'\x0e' # 0x000e -> SHIFT OUT + u'\x0f' # 0x000f -> SHIFT IN + u'\x10' # 0x0010 -> DATA LINK ESCAPE + u'\x11' # 0x0011 -> DEVICE CONTROL ONE + u'\x12' # 0x0012 -> DEVICE CONTROL TWO + u'\x13' # 0x0013 -> DEVICE CONTROL THREE + u'\x14' # 0x0014 -> DEVICE CONTROL FOUR + u'\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x0016 -> SYNCHRONOUS IDLE + u'\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x0018 -> CANCEL + u'\x19' # 0x0019 -> END OF MEDIUM + u'\x1a' # 0x001a -> SUBSTITUTE + u'\x1b' # 0x001b -> ESCAPE + u'\x1c' # 0x001c -> FILE SEPARATOR + u'\x1d' # 0x001d -> GROUP SEPARATOR + u'\x1e' # 0x001e -> RECORD SEPARATOR + u'\x1f' # 0x001f -> UNIT SEPARATOR + u' ' # 0x0020 -> SPACE + u'!' # 0x0021 -> EXCLAMATION MARK + u'"' # 0x0022 -> QUOTATION MARK + u'#' # 0x0023 -> NUMBER SIGN + u'$' # 0x0024 -> DOLLAR SIGN + u'%' # 0x0025 -> PERCENT SIGN + u'&' # 0x0026 -> AMPERSAND + u"'" # 0x0027 -> APOSTROPHE + u'(' # 0x0028 -> LEFT PARENTHESIS + u')' # 0x0029 -> RIGHT PARENTHESIS + u'*' # 0x002a -> ASTERISK + u'+' # 0x002b -> PLUS SIGN + u',' # 0x002c -> COMMA + u'-' # 0x002d -> HYPHEN-MINUS + u'.' # 0x002e -> FULL STOP + u'/' # 0x002f -> SOLIDUS + u'0' # 0x0030 -> DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE + u':' # 0x003a -> COLON + u';' # 0x003b -> SEMICOLON + u'<' # 0x003c -> LESS-THAN SIGN + u'=' # 0x003d -> EQUALS SIGN + u'>' # 0x003e -> GREATER-THAN SIGN + u'?' # 0x003f -> QUESTION MARK + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET + u'\\' # 0x005c -> REVERSE SOLIDUS + u']' # 0x005d -> RIGHT SQUARE BRACKET + u'^' # 0x005e -> CIRCUMFLEX ACCENT + u'_' # 0x005f -> LOW LINE + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET + u'|' # 0x007c -> VERTICAL LINE + u'}' # 0x007d -> RIGHT CURLY BRACKET + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> DELETE + u'\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + u'\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe0' # 0x0085 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe5' # 0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xea' # 0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xe8' # 0x008a -> LATIN SMALL LETTER E WITH GRAVE + u'\xef' # 0x008b -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xee' # 0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xec' # 0x008d -> LATIN SMALL LETTER I WITH GRAVE + u'\xc4' # 0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xe6' # 0x0091 -> LATIN SMALL LIGATURE AE + u'\xc6' # 0x0092 -> LATIN CAPITAL LIGATURE AE + u'\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf2' # 0x0095 -> LATIN SMALL LETTER O WITH GRAVE + u'\xfb' # 0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xf9' # 0x0097 -> LATIN SMALL LETTER U WITH GRAVE + u'\xff' # 0x0098 -> LATIN SMALL LETTER Y WITH DIAERESIS + u'\xd6' # 0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xf8' # 0x009b -> LATIN SMALL LETTER O WITH STROKE + u'\xa3' # 0x009c -> POUND SIGN + u'\xd8' # 0x009d -> LATIN CAPITAL LETTER O WITH STROKE + u'\u20a7' # 0x009e -> PESETA SIGN + u'\u0192' # 0x009f -> LATIN SMALL LETTER F WITH HOOK + u'\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + u'\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + u'\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + u'\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + u'\xf1' # 0x00a4 -> LATIN SMALL LETTER N WITH TILDE + u'\xd1' # 0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xaa' # 0x00a6 -> FEMININE ORDINAL INDICATOR + u'\xba' # 0x00a7 -> MASCULINE ORDINAL INDICATOR + u'\xbf' # 0x00a8 -> INVERTED QUESTION MARK + u'\u2310' # 0x00a9 -> REVERSED NOT SIGN + u'\xac' # 0x00aa -> NOT SIGN + u'\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + u'\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + u'\xa1' # 0x00ad -> INVERTED EXCLAMATION MARK + u'\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xa4' # 0x00af -> CURRENCY SIGN + u'\u2591' # 0x00b0 -> LIGHT SHADE + u'\u2592' # 0x00b1 -> MEDIUM SHADE + u'\u2593' # 0x00b2 -> DARK SHADE + u'\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + u'\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + u'\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + u'\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + u'\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + u'\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + u'\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + u'\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + u'\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + u'\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + u'\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + u'\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + u'\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + u'\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + u'\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + u'\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + u'\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + u'\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + u'\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0x00db -> FULL BLOCK + u'\u2584' # 0x00dc -> LOWER HALF BLOCK + u'\u258c' # 0x00dd -> LEFT HALF BLOCK + u'\u2590' # 0x00de -> RIGHT HALF BLOCK + u'\u2580' # 0x00df -> UPPER HALF BLOCK + u'\u03b1' # 0x00e0 -> GREEK SMALL LETTER ALPHA + u'\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + u'\u0393' # 0x00e2 -> GREEK CAPITAL LETTER GAMMA + u'\u03c0' # 0x00e3 -> GREEK SMALL LETTER PI + u'\u03a3' # 0x00e4 -> GREEK CAPITAL LETTER SIGMA + u'\u03c3' # 0x00e5 -> GREEK SMALL LETTER SIGMA + u'\xb5' # 0x00e6 -> MICRO SIGN + u'\u03c4' # 0x00e7 -> GREEK SMALL LETTER TAU + u'\u03a6' # 0x00e8 -> GREEK CAPITAL LETTER PHI + u'\u0398' # 0x00e9 -> GREEK CAPITAL LETTER THETA + u'\u03a9' # 0x00ea -> GREEK CAPITAL LETTER OMEGA + u'\u03b4' # 0x00eb -> GREEK SMALL LETTER DELTA + u'\u221e' # 0x00ec -> INFINITY + u'\u03c6' # 0x00ed -> GREEK SMALL LETTER PHI + u'\u03b5' # 0x00ee -> GREEK SMALL LETTER EPSILON + u'\u2229' # 0x00ef -> INTERSECTION + u'\u2261' # 0x00f0 -> IDENTICAL TO + u'\xb1' # 0x00f1 -> PLUS-MINUS SIGN + u'\u2265' # 0x00f2 -> GREATER-THAN OR EQUAL TO + u'\u2264' # 0x00f3 -> LESS-THAN OR EQUAL TO + u'\u2320' # 0x00f4 -> TOP HALF INTEGRAL + u'\u2321' # 0x00f5 -> BOTTOM HALF INTEGRAL + u'\xf7' # 0x00f6 -> DIVISION SIGN + u'\u2248' # 0x00f7 -> ALMOST EQUAL TO + u'\xb0' # 0x00f8 -> DEGREE SIGN + u'\u2219' # 0x00f9 -> BULLET OPERATOR + u'\xb7' # 0x00fa -> MIDDLE DOT + u'\u221a' # 0x00fb -> SQUARE ROOT + u'\u207f' # 0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N + u'\xb2' # 0x00fd -> SUPERSCRIPT TWO + u'\u25a0' # 0x00fe -> BLACK SQUARE + u'\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a1: 0x00ad, # INVERTED EXCLAMATION MARK + 0x00a3: 0x009c, # POUND SIGN + 0x00a4: 0x00af, # CURRENCY SIGN + 0x00aa: 0x00a6, # FEMININE ORDINAL INDICATOR + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00ba: 0x00a7, # MASCULINE ORDINAL INDICATOR + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00bf: 0x00a8, # INVERTED QUESTION MARK + 0x00c4: 0x008e, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5: 0x008f, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c6: 0x0092, # LATIN CAPITAL LIGATURE AE + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00d1: 0x00a5, # LATIN CAPITAL LETTER N WITH TILDE + 0x00d6: 0x0099, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00d8: 0x009d, # LATIN CAPITAL LETTER O WITH STROKE + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e0: 0x0085, # LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e4: 0x0084, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e5: 0x0086, # LATIN SMALL LETTER A WITH RING ABOVE + 0x00e6: 0x0091, # LATIN SMALL LIGATURE AE + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008a, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0088, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x0089, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ec: 0x008d, # LATIN SMALL LETTER I WITH GRAVE + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00ee: 0x008c, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ef: 0x008b, # LATIN SMALL LETTER I WITH DIAERESIS + 0x00f1: 0x00a4, # LATIN SMALL LETTER N WITH TILDE + 0x00f2: 0x0095, # LATIN SMALL LETTER O WITH GRAVE + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f6: 0x0094, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f8: 0x009b, # LATIN SMALL LETTER O WITH STROKE + 0x00f9: 0x0097, # LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x0096, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00ff: 0x0098, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x0192: 0x009f, # LATIN SMALL LETTER F WITH HOOK + 0x0393: 0x00e2, # GREEK CAPITAL LETTER GAMMA + 0x0398: 0x00e9, # GREEK CAPITAL LETTER THETA + 0x03a3: 0x00e4, # GREEK CAPITAL LETTER SIGMA + 0x03a6: 0x00e8, # GREEK CAPITAL LETTER PHI + 0x03a9: 0x00ea, # GREEK CAPITAL LETTER OMEGA + 0x03b1: 0x00e0, # GREEK SMALL LETTER ALPHA + 0x03b4: 0x00eb, # GREEK SMALL LETTER DELTA + 0x03b5: 0x00ee, # GREEK SMALL LETTER EPSILON + 0x03c0: 0x00e3, # GREEK SMALL LETTER PI + 0x03c3: 0x00e5, # GREEK SMALL LETTER SIGMA + 0x03c4: 0x00e7, # GREEK SMALL LETTER TAU + 0x03c6: 0x00ed, # GREEK SMALL LETTER PHI + 0x207f: 0x00fc, # SUPERSCRIPT LATIN SMALL LETTER N + 0x20a7: 0x009e, # PESETA SIGN + 0x2219: 0x00f9, # BULLET OPERATOR + 0x221a: 0x00fb, # SQUARE ROOT + 0x221e: 0x00ec, # INFINITY + 0x2229: 0x00ef, # INTERSECTION + 0x2248: 0x00f7, # ALMOST EQUAL TO + 0x2261: 0x00f0, # IDENTICAL TO + 0x2264: 0x00f3, # LESS-THAN OR EQUAL TO + 0x2265: 0x00f2, # GREATER-THAN OR EQUAL TO + 0x2310: 0x00a9, # REVERSED NOT SIGN + 0x2320: 0x00f4, # TOP HALF INTEGRAL + 0x2321: 0x00f5, # BOTTOM HALF INTEGRAL + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/PythonHome/Lib/encodings/cp865.pyc b/PythonHome/Lib/encodings/cp865.pyc deleted file mode 100644 index da1103e3d19767eab28681a776b6ee55eaff4690..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7923 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 NULL + u'\x01' # 0x0001 -> START OF HEADING + u'\x02' # 0x0002 -> START OF TEXT + u'\x03' # 0x0003 -> END OF TEXT + u'\x04' # 0x0004 -> END OF TRANSMISSION + u'\x05' # 0x0005 -> ENQUIRY + u'\x06' # 0x0006 -> ACKNOWLEDGE + u'\x07' # 0x0007 -> BELL + u'\x08' # 0x0008 -> BACKSPACE + u'\t' # 0x0009 -> HORIZONTAL TABULATION + u'\n' # 0x000a -> LINE FEED + u'\x0b' # 0x000b -> VERTICAL TABULATION + u'\x0c' # 0x000c -> FORM FEED + u'\r' # 0x000d -> CARRIAGE RETURN + u'\x0e' # 0x000e -> SHIFT OUT + u'\x0f' # 0x000f -> SHIFT IN + u'\x10' # 0x0010 -> DATA LINK ESCAPE + u'\x11' # 0x0011 -> DEVICE CONTROL ONE + u'\x12' # 0x0012 -> DEVICE CONTROL TWO + u'\x13' # 0x0013 -> DEVICE CONTROL THREE + u'\x14' # 0x0014 -> DEVICE CONTROL FOUR + u'\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x0016 -> SYNCHRONOUS IDLE + u'\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x0018 -> CANCEL + u'\x19' # 0x0019 -> END OF MEDIUM + u'\x1a' # 0x001a -> SUBSTITUTE + u'\x1b' # 0x001b -> ESCAPE + u'\x1c' # 0x001c -> FILE SEPARATOR + u'\x1d' # 0x001d -> GROUP SEPARATOR + u'\x1e' # 0x001e -> RECORD SEPARATOR + u'\x1f' # 0x001f -> UNIT SEPARATOR + u' ' # 0x0020 -> SPACE + u'!' # 0x0021 -> EXCLAMATION MARK + u'"' # 0x0022 -> QUOTATION MARK + u'#' # 0x0023 -> NUMBER SIGN + u'$' # 0x0024 -> DOLLAR SIGN + u'%' # 0x0025 -> PERCENT SIGN + u'&' # 0x0026 -> AMPERSAND + u"'" # 0x0027 -> APOSTROPHE + u'(' # 0x0028 -> LEFT PARENTHESIS + u')' # 0x0029 -> RIGHT PARENTHESIS + u'*' # 0x002a -> ASTERISK + u'+' # 0x002b -> PLUS SIGN + u',' # 0x002c -> COMMA + u'-' # 0x002d -> HYPHEN-MINUS + u'.' # 0x002e -> FULL STOP + u'/' # 0x002f -> SOLIDUS + u'0' # 0x0030 -> DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE + u':' # 0x003a -> COLON + u';' # 0x003b -> SEMICOLON + u'<' # 0x003c -> LESS-THAN SIGN + u'=' # 0x003d -> EQUALS SIGN + u'>' # 0x003e -> GREATER-THAN SIGN + u'?' # 0x003f -> QUESTION MARK + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET + u'\\' # 0x005c -> REVERSE SOLIDUS + u']' # 0x005d -> RIGHT SQUARE BRACKET + u'^' # 0x005e -> CIRCUMFLEX ACCENT + u'_' # 0x005f -> LOW LINE + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET + u'|' # 0x007c -> VERTICAL LINE + u'}' # 0x007d -> RIGHT CURLY BRACKET + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> DELETE + u'\u0410' # 0x0080 -> CYRILLIC CAPITAL LETTER A + u'\u0411' # 0x0081 -> CYRILLIC CAPITAL LETTER BE + u'\u0412' # 0x0082 -> CYRILLIC CAPITAL LETTER VE + u'\u0413' # 0x0083 -> CYRILLIC CAPITAL LETTER GHE + u'\u0414' # 0x0084 -> CYRILLIC CAPITAL LETTER DE + u'\u0415' # 0x0085 -> CYRILLIC CAPITAL LETTER IE + u'\u0416' # 0x0086 -> CYRILLIC CAPITAL LETTER ZHE + u'\u0417' # 0x0087 -> CYRILLIC CAPITAL LETTER ZE + u'\u0418' # 0x0088 -> CYRILLIC CAPITAL LETTER I + u'\u0419' # 0x0089 -> CYRILLIC CAPITAL LETTER SHORT I + u'\u041a' # 0x008a -> CYRILLIC CAPITAL LETTER KA + u'\u041b' # 0x008b -> CYRILLIC CAPITAL LETTER EL + u'\u041c' # 0x008c -> CYRILLIC CAPITAL LETTER EM + u'\u041d' # 0x008d -> CYRILLIC CAPITAL LETTER EN + u'\u041e' # 0x008e -> CYRILLIC CAPITAL LETTER O + u'\u041f' # 0x008f -> CYRILLIC CAPITAL LETTER PE + u'\u0420' # 0x0090 -> CYRILLIC CAPITAL LETTER ER + u'\u0421' # 0x0091 -> CYRILLIC CAPITAL LETTER ES + u'\u0422' # 0x0092 -> CYRILLIC CAPITAL LETTER TE + u'\u0423' # 0x0093 -> CYRILLIC CAPITAL LETTER U + u'\u0424' # 0x0094 -> CYRILLIC CAPITAL LETTER EF + u'\u0425' # 0x0095 -> CYRILLIC CAPITAL LETTER HA + u'\u0426' # 0x0096 -> CYRILLIC CAPITAL LETTER TSE + u'\u0427' # 0x0097 -> CYRILLIC CAPITAL LETTER CHE + u'\u0428' # 0x0098 -> CYRILLIC CAPITAL LETTER SHA + u'\u0429' # 0x0099 -> CYRILLIC CAPITAL LETTER SHCHA + u'\u042a' # 0x009a -> CYRILLIC CAPITAL LETTER HARD SIGN + u'\u042b' # 0x009b -> CYRILLIC CAPITAL LETTER YERU + u'\u042c' # 0x009c -> CYRILLIC CAPITAL LETTER SOFT SIGN + u'\u042d' # 0x009d -> CYRILLIC CAPITAL LETTER E + u'\u042e' # 0x009e -> CYRILLIC CAPITAL LETTER YU + u'\u042f' # 0x009f -> CYRILLIC CAPITAL LETTER YA + u'\u0430' # 0x00a0 -> CYRILLIC SMALL LETTER A + u'\u0431' # 0x00a1 -> CYRILLIC SMALL LETTER BE + u'\u0432' # 0x00a2 -> CYRILLIC SMALL LETTER VE + u'\u0433' # 0x00a3 -> CYRILLIC SMALL LETTER GHE + u'\u0434' # 0x00a4 -> CYRILLIC SMALL LETTER DE + u'\u0435' # 0x00a5 -> CYRILLIC SMALL LETTER IE + u'\u0436' # 0x00a6 -> CYRILLIC SMALL LETTER ZHE + u'\u0437' # 0x00a7 -> CYRILLIC SMALL LETTER ZE + u'\u0438' # 0x00a8 -> CYRILLIC SMALL LETTER I + u'\u0439' # 0x00a9 -> CYRILLIC SMALL LETTER SHORT I + u'\u043a' # 0x00aa -> CYRILLIC SMALL LETTER KA + u'\u043b' # 0x00ab -> CYRILLIC SMALL LETTER EL + u'\u043c' # 0x00ac -> CYRILLIC SMALL LETTER EM + u'\u043d' # 0x00ad -> CYRILLIC SMALL LETTER EN + u'\u043e' # 0x00ae -> CYRILLIC SMALL LETTER O + u'\u043f' # 0x00af -> CYRILLIC SMALL LETTER PE + u'\u2591' # 0x00b0 -> LIGHT SHADE + u'\u2592' # 0x00b1 -> MEDIUM SHADE + u'\u2593' # 0x00b2 -> DARK SHADE + u'\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + u'\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + u'\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + u'\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + u'\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + u'\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + u'\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + u'\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + u'\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + u'\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + u'\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + u'\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + u'\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + u'\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + u'\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + u'\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + u'\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + u'\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + u'\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0x00db -> FULL BLOCK + u'\u2584' # 0x00dc -> LOWER HALF BLOCK + u'\u258c' # 0x00dd -> LEFT HALF BLOCK + u'\u2590' # 0x00de -> RIGHT HALF BLOCK + u'\u2580' # 0x00df -> UPPER HALF BLOCK + u'\u0440' # 0x00e0 -> CYRILLIC SMALL LETTER ER + u'\u0441' # 0x00e1 -> CYRILLIC SMALL LETTER ES + u'\u0442' # 0x00e2 -> CYRILLIC SMALL LETTER TE + u'\u0443' # 0x00e3 -> CYRILLIC SMALL LETTER U + u'\u0444' # 0x00e4 -> CYRILLIC SMALL LETTER EF + u'\u0445' # 0x00e5 -> CYRILLIC SMALL LETTER HA + u'\u0446' # 0x00e6 -> CYRILLIC SMALL LETTER TSE + u'\u0447' # 0x00e7 -> CYRILLIC SMALL LETTER CHE + u'\u0448' # 0x00e8 -> CYRILLIC SMALL LETTER SHA + u'\u0449' # 0x00e9 -> CYRILLIC SMALL LETTER SHCHA + u'\u044a' # 0x00ea -> CYRILLIC SMALL LETTER HARD SIGN + u'\u044b' # 0x00eb -> CYRILLIC SMALL LETTER YERU + u'\u044c' # 0x00ec -> CYRILLIC SMALL LETTER SOFT SIGN + u'\u044d' # 0x00ed -> CYRILLIC SMALL LETTER E + u'\u044e' # 0x00ee -> CYRILLIC SMALL LETTER YU + u'\u044f' # 0x00ef -> CYRILLIC SMALL LETTER YA + u'\u0401' # 0x00f0 -> CYRILLIC CAPITAL LETTER IO + u'\u0451' # 0x00f1 -> CYRILLIC SMALL LETTER IO + u'\u0404' # 0x00f2 -> CYRILLIC CAPITAL LETTER UKRAINIAN IE + u'\u0454' # 0x00f3 -> CYRILLIC SMALL LETTER UKRAINIAN IE + u'\u0407' # 0x00f4 -> CYRILLIC CAPITAL LETTER YI + u'\u0457' # 0x00f5 -> CYRILLIC SMALL LETTER YI + u'\u040e' # 0x00f6 -> CYRILLIC CAPITAL LETTER SHORT U + u'\u045e' # 0x00f7 -> CYRILLIC SMALL LETTER SHORT U + u'\xb0' # 0x00f8 -> DEGREE SIGN + u'\u2219' # 0x00f9 -> BULLET OPERATOR + u'\xb7' # 0x00fa -> MIDDLE DOT + u'\u221a' # 0x00fb -> SQUARE ROOT + u'\u2116' # 0x00fc -> NUMERO SIGN + u'\xa4' # 0x00fd -> CURRENCY SIGN + u'\u25a0' # 0x00fe -> BLACK SQUARE + u'\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a4: 0x00fd, # CURRENCY SIGN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x0401: 0x00f0, # CYRILLIC CAPITAL LETTER IO + 0x0404: 0x00f2, # CYRILLIC CAPITAL LETTER UKRAINIAN IE + 0x0407: 0x00f4, # CYRILLIC CAPITAL LETTER YI + 0x040e: 0x00f6, # CYRILLIC CAPITAL LETTER SHORT U + 0x0410: 0x0080, # CYRILLIC CAPITAL LETTER A + 0x0411: 0x0081, # CYRILLIC CAPITAL LETTER BE + 0x0412: 0x0082, # CYRILLIC CAPITAL LETTER VE + 0x0413: 0x0083, # CYRILLIC CAPITAL LETTER GHE + 0x0414: 0x0084, # CYRILLIC CAPITAL LETTER DE + 0x0415: 0x0085, # CYRILLIC CAPITAL LETTER IE + 0x0416: 0x0086, # CYRILLIC CAPITAL LETTER ZHE + 0x0417: 0x0087, # CYRILLIC CAPITAL LETTER ZE + 0x0418: 0x0088, # CYRILLIC CAPITAL LETTER I + 0x0419: 0x0089, # CYRILLIC CAPITAL LETTER SHORT I + 0x041a: 0x008a, # CYRILLIC CAPITAL LETTER KA + 0x041b: 0x008b, # CYRILLIC CAPITAL LETTER EL + 0x041c: 0x008c, # CYRILLIC CAPITAL LETTER EM + 0x041d: 0x008d, # CYRILLIC CAPITAL LETTER EN + 0x041e: 0x008e, # CYRILLIC CAPITAL LETTER O + 0x041f: 0x008f, # CYRILLIC CAPITAL LETTER PE + 0x0420: 0x0090, # CYRILLIC CAPITAL LETTER ER + 0x0421: 0x0091, # CYRILLIC CAPITAL LETTER ES + 0x0422: 0x0092, # CYRILLIC CAPITAL LETTER TE + 0x0423: 0x0093, # CYRILLIC CAPITAL LETTER U + 0x0424: 0x0094, # CYRILLIC CAPITAL LETTER EF + 0x0425: 0x0095, # CYRILLIC CAPITAL LETTER HA + 0x0426: 0x0096, # CYRILLIC CAPITAL LETTER TSE + 0x0427: 0x0097, # CYRILLIC CAPITAL LETTER CHE + 0x0428: 0x0098, # CYRILLIC CAPITAL LETTER SHA + 0x0429: 0x0099, # CYRILLIC CAPITAL LETTER SHCHA + 0x042a: 0x009a, # CYRILLIC CAPITAL LETTER HARD SIGN + 0x042b: 0x009b, # CYRILLIC CAPITAL LETTER YERU + 0x042c: 0x009c, # CYRILLIC CAPITAL LETTER SOFT SIGN + 0x042d: 0x009d, # CYRILLIC CAPITAL LETTER E + 0x042e: 0x009e, # CYRILLIC CAPITAL LETTER YU + 0x042f: 0x009f, # CYRILLIC CAPITAL LETTER YA + 0x0430: 0x00a0, # CYRILLIC SMALL LETTER A + 0x0431: 0x00a1, # CYRILLIC SMALL LETTER BE + 0x0432: 0x00a2, # CYRILLIC SMALL LETTER VE + 0x0433: 0x00a3, # CYRILLIC SMALL LETTER GHE + 0x0434: 0x00a4, # CYRILLIC SMALL LETTER DE + 0x0435: 0x00a5, # CYRILLIC SMALL LETTER IE + 0x0436: 0x00a6, # CYRILLIC SMALL LETTER ZHE + 0x0437: 0x00a7, # CYRILLIC SMALL LETTER ZE + 0x0438: 0x00a8, # CYRILLIC SMALL LETTER I + 0x0439: 0x00a9, # CYRILLIC SMALL LETTER SHORT I + 0x043a: 0x00aa, # CYRILLIC SMALL LETTER KA + 0x043b: 0x00ab, # CYRILLIC SMALL LETTER EL + 0x043c: 0x00ac, # CYRILLIC SMALL LETTER EM + 0x043d: 0x00ad, # CYRILLIC SMALL LETTER EN + 0x043e: 0x00ae, # CYRILLIC SMALL LETTER O + 0x043f: 0x00af, # CYRILLIC SMALL LETTER PE + 0x0440: 0x00e0, # CYRILLIC SMALL LETTER ER + 0x0441: 0x00e1, # CYRILLIC SMALL LETTER ES + 0x0442: 0x00e2, # CYRILLIC SMALL LETTER TE + 0x0443: 0x00e3, # CYRILLIC SMALL LETTER U + 0x0444: 0x00e4, # CYRILLIC SMALL LETTER EF + 0x0445: 0x00e5, # CYRILLIC SMALL LETTER HA + 0x0446: 0x00e6, # CYRILLIC SMALL LETTER TSE + 0x0447: 0x00e7, # CYRILLIC SMALL LETTER CHE + 0x0448: 0x00e8, # CYRILLIC SMALL LETTER SHA + 0x0449: 0x00e9, # CYRILLIC SMALL LETTER SHCHA + 0x044a: 0x00ea, # CYRILLIC SMALL LETTER HARD SIGN + 0x044b: 0x00eb, # CYRILLIC SMALL LETTER YERU + 0x044c: 0x00ec, # CYRILLIC SMALL LETTER SOFT SIGN + 0x044d: 0x00ed, # CYRILLIC SMALL LETTER E + 0x044e: 0x00ee, # CYRILLIC SMALL LETTER YU + 0x044f: 0x00ef, # CYRILLIC SMALL LETTER YA + 0x0451: 0x00f1, # CYRILLIC SMALL LETTER IO + 0x0454: 0x00f3, # CYRILLIC SMALL LETTER UKRAINIAN IE + 0x0457: 0x00f5, # CYRILLIC SMALL LETTER YI + 0x045e: 0x00f7, # CYRILLIC SMALL LETTER SHORT U + 0x2116: 0x00fc, # NUMERO SIGN + 0x2219: 0x00f9, # BULLET OPERATOR + 0x221a: 0x00fb, # SQUARE ROOT + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/PythonHome/Lib/encodings/cp866.pyc b/PythonHome/Lib/encodings/cp866.pyc deleted file mode 100644 index 7f2b355ef736ddb3410d9cf2b3175f1bde6f4254..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8158 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 NULL + u'\x01' # 0x0001 -> START OF HEADING + u'\x02' # 0x0002 -> START OF TEXT + u'\x03' # 0x0003 -> END OF TEXT + u'\x04' # 0x0004 -> END OF TRANSMISSION + u'\x05' # 0x0005 -> ENQUIRY + u'\x06' # 0x0006 -> ACKNOWLEDGE + u'\x07' # 0x0007 -> BELL + u'\x08' # 0x0008 -> BACKSPACE + u'\t' # 0x0009 -> HORIZONTAL TABULATION + u'\n' # 0x000a -> LINE FEED + u'\x0b' # 0x000b -> VERTICAL TABULATION + u'\x0c' # 0x000c -> FORM FEED + u'\r' # 0x000d -> CARRIAGE RETURN + u'\x0e' # 0x000e -> SHIFT OUT + u'\x0f' # 0x000f -> SHIFT IN + u'\x10' # 0x0010 -> DATA LINK ESCAPE + u'\x11' # 0x0011 -> DEVICE CONTROL ONE + u'\x12' # 0x0012 -> DEVICE CONTROL TWO + u'\x13' # 0x0013 -> DEVICE CONTROL THREE + u'\x14' # 0x0014 -> DEVICE CONTROL FOUR + u'\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x0016 -> SYNCHRONOUS IDLE + u'\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x0018 -> CANCEL + u'\x19' # 0x0019 -> END OF MEDIUM + u'\x1a' # 0x001a -> SUBSTITUTE + u'\x1b' # 0x001b -> ESCAPE + u'\x1c' # 0x001c -> FILE SEPARATOR + u'\x1d' # 0x001d -> GROUP SEPARATOR + u'\x1e' # 0x001e -> RECORD SEPARATOR + u'\x1f' # 0x001f -> UNIT SEPARATOR + u' ' # 0x0020 -> SPACE + u'!' # 0x0021 -> EXCLAMATION MARK + u'"' # 0x0022 -> QUOTATION MARK + u'#' # 0x0023 -> NUMBER SIGN + u'$' # 0x0024 -> DOLLAR SIGN + u'%' # 0x0025 -> PERCENT SIGN + u'&' # 0x0026 -> AMPERSAND + u"'" # 0x0027 -> APOSTROPHE + u'(' # 0x0028 -> LEFT PARENTHESIS + u')' # 0x0029 -> RIGHT PARENTHESIS + u'*' # 0x002a -> ASTERISK + u'+' # 0x002b -> PLUS SIGN + u',' # 0x002c -> COMMA + u'-' # 0x002d -> HYPHEN-MINUS + u'.' # 0x002e -> FULL STOP + u'/' # 0x002f -> SOLIDUS + u'0' # 0x0030 -> DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE + u':' # 0x003a -> COLON + u';' # 0x003b -> SEMICOLON + u'<' # 0x003c -> LESS-THAN SIGN + u'=' # 0x003d -> EQUALS SIGN + u'>' # 0x003e -> GREATER-THAN SIGN + u'?' # 0x003f -> QUESTION MARK + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET + u'\\' # 0x005c -> REVERSE SOLIDUS + u']' # 0x005d -> RIGHT SQUARE BRACKET + u'^' # 0x005e -> CIRCUMFLEX ACCENT + u'_' # 0x005f -> LOW LINE + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET + u'|' # 0x007c -> VERTICAL LINE + u'}' # 0x007d -> RIGHT CURLY BRACKET + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> DELETE + u'\ufffe' # 0x0080 -> UNDEFINED + u'\ufffe' # 0x0081 -> UNDEFINED + u'\ufffe' # 0x0082 -> UNDEFINED + u'\ufffe' # 0x0083 -> UNDEFINED + u'\ufffe' # 0x0084 -> UNDEFINED + u'\ufffe' # 0x0085 -> UNDEFINED + u'\u0386' # 0x0086 -> GREEK CAPITAL LETTER ALPHA WITH TONOS + u'\ufffe' # 0x0087 -> UNDEFINED + u'\xb7' # 0x0088 -> MIDDLE DOT + u'\xac' # 0x0089 -> NOT SIGN + u'\xa6' # 0x008a -> BROKEN BAR + u'\u2018' # 0x008b -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0x008c -> RIGHT SINGLE QUOTATION MARK + u'\u0388' # 0x008d -> GREEK CAPITAL LETTER EPSILON WITH TONOS + u'\u2015' # 0x008e -> HORIZONTAL BAR + u'\u0389' # 0x008f -> GREEK CAPITAL LETTER ETA WITH TONOS + u'\u038a' # 0x0090 -> GREEK CAPITAL LETTER IOTA WITH TONOS + u'\u03aa' # 0x0091 -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + u'\u038c' # 0x0092 -> GREEK CAPITAL LETTER OMICRON WITH TONOS + u'\ufffe' # 0x0093 -> UNDEFINED + u'\ufffe' # 0x0094 -> UNDEFINED + u'\u038e' # 0x0095 -> GREEK CAPITAL LETTER UPSILON WITH TONOS + u'\u03ab' # 0x0096 -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + u'\xa9' # 0x0097 -> COPYRIGHT SIGN + u'\u038f' # 0x0098 -> GREEK CAPITAL LETTER OMEGA WITH TONOS + u'\xb2' # 0x0099 -> SUPERSCRIPT TWO + u'\xb3' # 0x009a -> SUPERSCRIPT THREE + u'\u03ac' # 0x009b -> GREEK SMALL LETTER ALPHA WITH TONOS + u'\xa3' # 0x009c -> POUND SIGN + u'\u03ad' # 0x009d -> GREEK SMALL LETTER EPSILON WITH TONOS + u'\u03ae' # 0x009e -> GREEK SMALL LETTER ETA WITH TONOS + u'\u03af' # 0x009f -> GREEK SMALL LETTER IOTA WITH TONOS + u'\u03ca' # 0x00a0 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA + u'\u0390' # 0x00a1 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + u'\u03cc' # 0x00a2 -> GREEK SMALL LETTER OMICRON WITH TONOS + u'\u03cd' # 0x00a3 -> GREEK SMALL LETTER UPSILON WITH TONOS + u'\u0391' # 0x00a4 -> GREEK CAPITAL LETTER ALPHA + u'\u0392' # 0x00a5 -> GREEK CAPITAL LETTER BETA + u'\u0393' # 0x00a6 -> GREEK CAPITAL LETTER GAMMA + u'\u0394' # 0x00a7 -> GREEK CAPITAL LETTER DELTA + u'\u0395' # 0x00a8 -> GREEK CAPITAL LETTER EPSILON + u'\u0396' # 0x00a9 -> GREEK CAPITAL LETTER ZETA + u'\u0397' # 0x00aa -> GREEK CAPITAL LETTER ETA + u'\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + u'\u0398' # 0x00ac -> GREEK CAPITAL LETTER THETA + u'\u0399' # 0x00ad -> GREEK CAPITAL LETTER IOTA + u'\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2591' # 0x00b0 -> LIGHT SHADE + u'\u2592' # 0x00b1 -> MEDIUM SHADE + u'\u2593' # 0x00b2 -> DARK SHADE + u'\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + u'\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\u039a' # 0x00b5 -> GREEK CAPITAL LETTER KAPPA + u'\u039b' # 0x00b6 -> GREEK CAPITAL LETTER LAMDA + u'\u039c' # 0x00b7 -> GREEK CAPITAL LETTER MU + u'\u039d' # 0x00b8 -> GREEK CAPITAL LETTER NU + u'\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\u039e' # 0x00bd -> GREEK CAPITAL LETTER XI + u'\u039f' # 0x00be -> GREEK CAPITAL LETTER OMICRON + u'\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\u03a0' # 0x00c6 -> GREEK CAPITAL LETTER PI + u'\u03a1' # 0x00c7 -> GREEK CAPITAL LETTER RHO + u'\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\u03a3' # 0x00cf -> GREEK CAPITAL LETTER SIGMA + u'\u03a4' # 0x00d0 -> GREEK CAPITAL LETTER TAU + u'\u03a5' # 0x00d1 -> GREEK CAPITAL LETTER UPSILON + u'\u03a6' # 0x00d2 -> GREEK CAPITAL LETTER PHI + u'\u03a7' # 0x00d3 -> GREEK CAPITAL LETTER CHI + u'\u03a8' # 0x00d4 -> GREEK CAPITAL LETTER PSI + u'\u03a9' # 0x00d5 -> GREEK CAPITAL LETTER OMEGA + u'\u03b1' # 0x00d6 -> GREEK SMALL LETTER ALPHA + u'\u03b2' # 0x00d7 -> GREEK SMALL LETTER BETA + u'\u03b3' # 0x00d8 -> GREEK SMALL LETTER GAMMA + u'\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2588' # 0x00db -> FULL BLOCK + u'\u2584' # 0x00dc -> LOWER HALF BLOCK + u'\u03b4' # 0x00dd -> GREEK SMALL LETTER DELTA + u'\u03b5' # 0x00de -> GREEK SMALL LETTER EPSILON + u'\u2580' # 0x00df -> UPPER HALF BLOCK + u'\u03b6' # 0x00e0 -> GREEK SMALL LETTER ZETA + u'\u03b7' # 0x00e1 -> GREEK SMALL LETTER ETA + u'\u03b8' # 0x00e2 -> GREEK SMALL LETTER THETA + u'\u03b9' # 0x00e3 -> GREEK SMALL LETTER IOTA + u'\u03ba' # 0x00e4 -> GREEK SMALL LETTER KAPPA + u'\u03bb' # 0x00e5 -> GREEK SMALL LETTER LAMDA + u'\u03bc' # 0x00e6 -> GREEK SMALL LETTER MU + u'\u03bd' # 0x00e7 -> GREEK SMALL LETTER NU + u'\u03be' # 0x00e8 -> GREEK SMALL LETTER XI + u'\u03bf' # 0x00e9 -> GREEK SMALL LETTER OMICRON + u'\u03c0' # 0x00ea -> GREEK SMALL LETTER PI + u'\u03c1' # 0x00eb -> GREEK SMALL LETTER RHO + u'\u03c3' # 0x00ec -> GREEK SMALL LETTER SIGMA + u'\u03c2' # 0x00ed -> GREEK SMALL LETTER FINAL SIGMA + u'\u03c4' # 0x00ee -> GREEK SMALL LETTER TAU + u'\u0384' # 0x00ef -> GREEK TONOS + u'\xad' # 0x00f0 -> SOFT HYPHEN + u'\xb1' # 0x00f1 -> PLUS-MINUS SIGN + u'\u03c5' # 0x00f2 -> GREEK SMALL LETTER UPSILON + u'\u03c6' # 0x00f3 -> GREEK SMALL LETTER PHI + u'\u03c7' # 0x00f4 -> GREEK SMALL LETTER CHI + u'\xa7' # 0x00f5 -> SECTION SIGN + u'\u03c8' # 0x00f6 -> GREEK SMALL LETTER PSI + u'\u0385' # 0x00f7 -> GREEK DIALYTIKA TONOS + u'\xb0' # 0x00f8 -> DEGREE SIGN + u'\xa8' # 0x00f9 -> DIAERESIS + u'\u03c9' # 0x00fa -> GREEK SMALL LETTER OMEGA + u'\u03cb' # 0x00fb -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA + u'\u03b0' # 0x00fc -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + u'\u03ce' # 0x00fd -> GREEK SMALL LETTER OMEGA WITH TONOS + u'\u25a0' # 0x00fe -> BLACK SQUARE + u'\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a3: 0x009c, # POUND SIGN + 0x00a6: 0x008a, # BROKEN BAR + 0x00a7: 0x00f5, # SECTION SIGN + 0x00a8: 0x00f9, # DIAERESIS + 0x00a9: 0x0097, # COPYRIGHT SIGN + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x0089, # NOT SIGN + 0x00ad: 0x00f0, # SOFT HYPHEN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x0099, # SUPERSCRIPT TWO + 0x00b3: 0x009a, # SUPERSCRIPT THREE + 0x00b7: 0x0088, # MIDDLE DOT + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x0384: 0x00ef, # GREEK TONOS + 0x0385: 0x00f7, # GREEK DIALYTIKA TONOS + 0x0386: 0x0086, # GREEK CAPITAL LETTER ALPHA WITH TONOS + 0x0388: 0x008d, # GREEK CAPITAL LETTER EPSILON WITH TONOS + 0x0389: 0x008f, # GREEK CAPITAL LETTER ETA WITH TONOS + 0x038a: 0x0090, # GREEK CAPITAL LETTER IOTA WITH TONOS + 0x038c: 0x0092, # GREEK CAPITAL LETTER OMICRON WITH TONOS + 0x038e: 0x0095, # GREEK CAPITAL LETTER UPSILON WITH TONOS + 0x038f: 0x0098, # GREEK CAPITAL LETTER OMEGA WITH TONOS + 0x0390: 0x00a1, # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + 0x0391: 0x00a4, # GREEK CAPITAL LETTER ALPHA + 0x0392: 0x00a5, # GREEK CAPITAL LETTER BETA + 0x0393: 0x00a6, # GREEK CAPITAL LETTER GAMMA + 0x0394: 0x00a7, # GREEK CAPITAL LETTER DELTA + 0x0395: 0x00a8, # GREEK CAPITAL LETTER EPSILON + 0x0396: 0x00a9, # GREEK CAPITAL LETTER ZETA + 0x0397: 0x00aa, # GREEK CAPITAL LETTER ETA + 0x0398: 0x00ac, # GREEK CAPITAL LETTER THETA + 0x0399: 0x00ad, # GREEK CAPITAL LETTER IOTA + 0x039a: 0x00b5, # GREEK CAPITAL LETTER KAPPA + 0x039b: 0x00b6, # GREEK CAPITAL LETTER LAMDA + 0x039c: 0x00b7, # GREEK CAPITAL LETTER MU + 0x039d: 0x00b8, # GREEK CAPITAL LETTER NU + 0x039e: 0x00bd, # GREEK CAPITAL LETTER XI + 0x039f: 0x00be, # GREEK CAPITAL LETTER OMICRON + 0x03a0: 0x00c6, # GREEK CAPITAL LETTER PI + 0x03a1: 0x00c7, # GREEK CAPITAL LETTER RHO + 0x03a3: 0x00cf, # GREEK CAPITAL LETTER SIGMA + 0x03a4: 0x00d0, # GREEK CAPITAL LETTER TAU + 0x03a5: 0x00d1, # GREEK CAPITAL LETTER UPSILON + 0x03a6: 0x00d2, # GREEK CAPITAL LETTER PHI + 0x03a7: 0x00d3, # GREEK CAPITAL LETTER CHI + 0x03a8: 0x00d4, # GREEK CAPITAL LETTER PSI + 0x03a9: 0x00d5, # GREEK CAPITAL LETTER OMEGA + 0x03aa: 0x0091, # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + 0x03ab: 0x0096, # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + 0x03ac: 0x009b, # GREEK SMALL LETTER ALPHA WITH TONOS + 0x03ad: 0x009d, # GREEK SMALL LETTER EPSILON WITH TONOS + 0x03ae: 0x009e, # GREEK SMALL LETTER ETA WITH TONOS + 0x03af: 0x009f, # GREEK SMALL LETTER IOTA WITH TONOS + 0x03b0: 0x00fc, # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + 0x03b1: 0x00d6, # GREEK SMALL LETTER ALPHA + 0x03b2: 0x00d7, # GREEK SMALL LETTER BETA + 0x03b3: 0x00d8, # GREEK SMALL LETTER GAMMA + 0x03b4: 0x00dd, # GREEK SMALL LETTER DELTA + 0x03b5: 0x00de, # GREEK SMALL LETTER EPSILON + 0x03b6: 0x00e0, # GREEK SMALL LETTER ZETA + 0x03b7: 0x00e1, # GREEK SMALL LETTER ETA + 0x03b8: 0x00e2, # GREEK SMALL LETTER THETA + 0x03b9: 0x00e3, # GREEK SMALL LETTER IOTA + 0x03ba: 0x00e4, # GREEK SMALL LETTER KAPPA + 0x03bb: 0x00e5, # GREEK SMALL LETTER LAMDA + 0x03bc: 0x00e6, # GREEK SMALL LETTER MU + 0x03bd: 0x00e7, # GREEK SMALL LETTER NU + 0x03be: 0x00e8, # GREEK SMALL LETTER XI + 0x03bf: 0x00e9, # GREEK SMALL LETTER OMICRON + 0x03c0: 0x00ea, # GREEK SMALL LETTER PI + 0x03c1: 0x00eb, # GREEK SMALL LETTER RHO + 0x03c2: 0x00ed, # GREEK SMALL LETTER FINAL SIGMA + 0x03c3: 0x00ec, # GREEK SMALL LETTER SIGMA + 0x03c4: 0x00ee, # GREEK SMALL LETTER TAU + 0x03c5: 0x00f2, # GREEK SMALL LETTER UPSILON + 0x03c6: 0x00f3, # GREEK SMALL LETTER PHI + 0x03c7: 0x00f4, # GREEK SMALL LETTER CHI + 0x03c8: 0x00f6, # GREEK SMALL LETTER PSI + 0x03c9: 0x00fa, # GREEK SMALL LETTER OMEGA + 0x03ca: 0x00a0, # GREEK SMALL LETTER IOTA WITH DIALYTIKA + 0x03cb: 0x00fb, # GREEK SMALL LETTER UPSILON WITH DIALYTIKA + 0x03cc: 0x00a2, # GREEK SMALL LETTER OMICRON WITH TONOS + 0x03cd: 0x00a3, # GREEK SMALL LETTER UPSILON WITH TONOS + 0x03ce: 0x00fd, # GREEK SMALL LETTER OMEGA WITH TONOS + 0x2015: 0x008e, # HORIZONTAL BAR + 0x2018: 0x008b, # LEFT SINGLE QUOTATION MARK + 0x2019: 0x008c, # RIGHT SINGLE QUOTATION MARK + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/PythonHome/Lib/encodings/cp869.pyc b/PythonHome/Lib/encodings/cp869.pyc deleted file mode 100644 index 2719b17c99f13b706b8a8b02931d8fa60695ce1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7970 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

QMl?k1n5X zG2H_0;C{MpT(^X7A=f=Xw}@^j-D7mi=oZs0r&~cvkd|;=6WuntX1cAUm81u_ZWY~b z(rVHk(i+lsZheq$18FU32iL8mdz|hex+mx!rhAQUJ>62eN9f+5`x4!objwH^xwxF} zQMwg$3DRaRHqmXNYo=RCdW?&QNZUxOxNbFR2NxeF9UwhHT6Q{UC*5+oU34qxGDxS9 z_Hx}C?%+wf2kG|Ft)*K>dWwtXeDl+E6X>3yn?yI2bdZY=@y!pD4s)?1HyoksO7|?? z0J`Vs&Y?@v^`d*8PUv2s8%p;g-FoitCAvrGUZyMM)>r5z(!EL-rF)I8g6?&?>2z<< zji-B)u9D89+ra&$=r+=QneI`#uh4Cx`zqaLy06h~q5C@BR=RJ{?V|f8-EO*X(e0u8 zHeC;X+jr>l=)Oz0fbK22M!L7@_VN?&&^<}_J-P;N{XX43uKNMqe!3shJw=zMdz$V? zbkESeOLu_o$8-njenNMM?x%Ez>3&9cgzi1MXX)OjdyeksbkEcMf-Xt-OS%{6KA>x) z`;hKeq+gR>T-b8f%>=beASg#!laMS})kJY?u4mkt|#*@&W%qefqT#h5Fv8auA| z>hTjoB@?f?cGBeQO0Sp)cup+rXxjnfl-LNX%u-aRYZfNordW*cryv4zry(QkZSTbf#&y5C#oE%#P<39rd(_Eshjd8@qD$!*C4>E>nW=H=<;73sv?>BL5F zjrX9p)?1fu+K_HqmTp>^Zd&I(BQc2VtYEVHl1ilCk}e+y+_hbYtl`L zbko*!)24LO`gGIMbklZkgSXLp)Z653_O^Iiyd z3sd)bJ5x*2&FhovqqtTQQ6e4bUx_<(uJe}q=6(QT|^p08ce#FG=wyibP4HF(lF9+(q*I(q$1Kt z(kRks(&eNpNMlG>lCC0+C5Cru!QNF}6+q-#jmk|vQRlddC`lCCFBAx$Ms zBbAY+lftAKq;isxBBTn^Owue8t06j@bOWi9R7I*L)sSjQHVWl_VN zC>pOXGd!{TlfGEE8j~d!=COxWJZbyS$8%~8zcTo9#NwLjNGO;4W2v)rK1H87oAw`1 zhXxO%m-1$*%K_t|GAqAzepY@~ugqTAZQ6Ci+^p3X`oC>X&L@(c`Gp>XFIols9RV(* AYXATM diff --git a/PythonHome/Lib/encodings/cp874.py b/PythonHome/Lib/encodings/cp874.py new file mode 100644 index 0000000000..6110f46e5b --- /dev/null +++ b/PythonHome/Lib/encodings/cp874.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp874 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP874.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp874', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\u20ac' # 0x80 -> EURO SIGN + u'\ufffe' # 0x81 -> UNDEFINED + u'\ufffe' # 0x82 -> UNDEFINED + u'\ufffe' # 0x83 -> UNDEFINED + u'\ufffe' # 0x84 -> UNDEFINED + u'\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + u'\ufffe' # 0x86 -> UNDEFINED + u'\ufffe' # 0x87 -> UNDEFINED + u'\ufffe' # 0x88 -> UNDEFINED + u'\ufffe' # 0x89 -> UNDEFINED + u'\ufffe' # 0x8A -> UNDEFINED + u'\ufffe' # 0x8B -> UNDEFINED + u'\ufffe' # 0x8C -> UNDEFINED + u'\ufffe' # 0x8D -> UNDEFINED + u'\ufffe' # 0x8E -> UNDEFINED + u'\ufffe' # 0x8F -> UNDEFINED + u'\ufffe' # 0x90 -> UNDEFINED + u'\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + u'\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + u'\u2022' # 0x95 -> BULLET + u'\u2013' # 0x96 -> EN DASH + u'\u2014' # 0x97 -> EM DASH + u'\ufffe' # 0x98 -> UNDEFINED + u'\ufffe' # 0x99 -> UNDEFINED + u'\ufffe' # 0x9A -> UNDEFINED + u'\ufffe' # 0x9B -> UNDEFINED + u'\ufffe' # 0x9C -> UNDEFINED + u'\ufffe' # 0x9D -> UNDEFINED + u'\ufffe' # 0x9E -> UNDEFINED + u'\ufffe' # 0x9F -> UNDEFINED + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\u0e01' # 0xA1 -> THAI CHARACTER KO KAI + u'\u0e02' # 0xA2 -> THAI CHARACTER KHO KHAI + u'\u0e03' # 0xA3 -> THAI CHARACTER KHO KHUAT + u'\u0e04' # 0xA4 -> THAI CHARACTER KHO KHWAI + u'\u0e05' # 0xA5 -> THAI CHARACTER KHO KHON + u'\u0e06' # 0xA6 -> THAI CHARACTER KHO RAKHANG + u'\u0e07' # 0xA7 -> THAI CHARACTER NGO NGU + u'\u0e08' # 0xA8 -> THAI CHARACTER CHO CHAN + u'\u0e09' # 0xA9 -> THAI CHARACTER CHO CHING + u'\u0e0a' # 0xAA -> THAI CHARACTER CHO CHANG + u'\u0e0b' # 0xAB -> THAI CHARACTER SO SO + u'\u0e0c' # 0xAC -> THAI CHARACTER CHO CHOE + u'\u0e0d' # 0xAD -> THAI CHARACTER YO YING + u'\u0e0e' # 0xAE -> THAI CHARACTER DO CHADA + u'\u0e0f' # 0xAF -> THAI CHARACTER TO PATAK + u'\u0e10' # 0xB0 -> THAI CHARACTER THO THAN + u'\u0e11' # 0xB1 -> THAI CHARACTER THO NANGMONTHO + u'\u0e12' # 0xB2 -> THAI CHARACTER THO PHUTHAO + u'\u0e13' # 0xB3 -> THAI CHARACTER NO NEN + u'\u0e14' # 0xB4 -> THAI CHARACTER DO DEK + u'\u0e15' # 0xB5 -> THAI CHARACTER TO TAO + u'\u0e16' # 0xB6 -> THAI CHARACTER THO THUNG + u'\u0e17' # 0xB7 -> THAI CHARACTER THO THAHAN + u'\u0e18' # 0xB8 -> THAI CHARACTER THO THONG + u'\u0e19' # 0xB9 -> THAI CHARACTER NO NU + u'\u0e1a' # 0xBA -> THAI CHARACTER BO BAIMAI + u'\u0e1b' # 0xBB -> THAI CHARACTER PO PLA + u'\u0e1c' # 0xBC -> THAI CHARACTER PHO PHUNG + u'\u0e1d' # 0xBD -> THAI CHARACTER FO FA + u'\u0e1e' # 0xBE -> THAI CHARACTER PHO PHAN + u'\u0e1f' # 0xBF -> THAI CHARACTER FO FAN + u'\u0e20' # 0xC0 -> THAI CHARACTER PHO SAMPHAO + u'\u0e21' # 0xC1 -> THAI CHARACTER MO MA + u'\u0e22' # 0xC2 -> THAI CHARACTER YO YAK + u'\u0e23' # 0xC3 -> THAI CHARACTER RO RUA + u'\u0e24' # 0xC4 -> THAI CHARACTER RU + u'\u0e25' # 0xC5 -> THAI CHARACTER LO LING + u'\u0e26' # 0xC6 -> THAI CHARACTER LU + u'\u0e27' # 0xC7 -> THAI CHARACTER WO WAEN + u'\u0e28' # 0xC8 -> THAI CHARACTER SO SALA + u'\u0e29' # 0xC9 -> THAI CHARACTER SO RUSI + u'\u0e2a' # 0xCA -> THAI CHARACTER SO SUA + u'\u0e2b' # 0xCB -> THAI CHARACTER HO HIP + u'\u0e2c' # 0xCC -> THAI CHARACTER LO CHULA + u'\u0e2d' # 0xCD -> THAI CHARACTER O ANG + u'\u0e2e' # 0xCE -> THAI CHARACTER HO NOKHUK + u'\u0e2f' # 0xCF -> THAI CHARACTER PAIYANNOI + u'\u0e30' # 0xD0 -> THAI CHARACTER SARA A + u'\u0e31' # 0xD1 -> THAI CHARACTER MAI HAN-AKAT + u'\u0e32' # 0xD2 -> THAI CHARACTER SARA AA + u'\u0e33' # 0xD3 -> THAI CHARACTER SARA AM + u'\u0e34' # 0xD4 -> THAI CHARACTER SARA I + u'\u0e35' # 0xD5 -> THAI CHARACTER SARA II + u'\u0e36' # 0xD6 -> THAI CHARACTER SARA UE + u'\u0e37' # 0xD7 -> THAI CHARACTER SARA UEE + u'\u0e38' # 0xD8 -> THAI CHARACTER SARA U + u'\u0e39' # 0xD9 -> THAI CHARACTER SARA UU + u'\u0e3a' # 0xDA -> THAI CHARACTER PHINTHU + u'\ufffe' # 0xDB -> UNDEFINED + u'\ufffe' # 0xDC -> UNDEFINED + u'\ufffe' # 0xDD -> UNDEFINED + u'\ufffe' # 0xDE -> UNDEFINED + u'\u0e3f' # 0xDF -> THAI CURRENCY SYMBOL BAHT + u'\u0e40' # 0xE0 -> THAI CHARACTER SARA E + u'\u0e41' # 0xE1 -> THAI CHARACTER SARA AE + u'\u0e42' # 0xE2 -> THAI CHARACTER SARA O + u'\u0e43' # 0xE3 -> THAI CHARACTER SARA AI MAIMUAN + u'\u0e44' # 0xE4 -> THAI CHARACTER SARA AI MAIMALAI + u'\u0e45' # 0xE5 -> THAI CHARACTER LAKKHANGYAO + u'\u0e46' # 0xE6 -> THAI CHARACTER MAIYAMOK + u'\u0e47' # 0xE7 -> THAI CHARACTER MAITAIKHU + u'\u0e48' # 0xE8 -> THAI CHARACTER MAI EK + u'\u0e49' # 0xE9 -> THAI CHARACTER MAI THO + u'\u0e4a' # 0xEA -> THAI CHARACTER MAI TRI + u'\u0e4b' # 0xEB -> THAI CHARACTER MAI CHATTAWA + u'\u0e4c' # 0xEC -> THAI CHARACTER THANTHAKHAT + u'\u0e4d' # 0xED -> THAI CHARACTER NIKHAHIT + u'\u0e4e' # 0xEE -> THAI CHARACTER YAMAKKAN + u'\u0e4f' # 0xEF -> THAI CHARACTER FONGMAN + u'\u0e50' # 0xF0 -> THAI DIGIT ZERO + u'\u0e51' # 0xF1 -> THAI DIGIT ONE + u'\u0e52' # 0xF2 -> THAI DIGIT TWO + u'\u0e53' # 0xF3 -> THAI DIGIT THREE + u'\u0e54' # 0xF4 -> THAI DIGIT FOUR + u'\u0e55' # 0xF5 -> THAI DIGIT FIVE + u'\u0e56' # 0xF6 -> THAI DIGIT SIX + u'\u0e57' # 0xF7 -> THAI DIGIT SEVEN + u'\u0e58' # 0xF8 -> THAI DIGIT EIGHT + u'\u0e59' # 0xF9 -> THAI DIGIT NINE + u'\u0e5a' # 0xFA -> THAI CHARACTER ANGKHANKHU + u'\u0e5b' # 0xFB -> THAI CHARACTER KHOMUT + u'\ufffe' # 0xFC -> UNDEFINED + u'\ufffe' # 0xFD -> UNDEFINED + u'\ufffe' # 0xFE -> UNDEFINED + u'\ufffe' # 0xFF -> UNDEFINED +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp874.pyc b/PythonHome/Lib/encodings/cp874.pyc deleted file mode 100644 index 6bbbc580dde50fd6dee65d2a6905e57a7c7ea488..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2822 zcmc&$d3RG)5WiWQhL*BRp=xj=ZmkOnDk2aTt2ES?N}*Q6Yu-znn$4G2YZWEXvhS3A zaY4lmcZIqBA?Nr>=Hv_bhaUiE?xT4HrN?@X$0YZ5?w$AM&iv+gXX^W-K76@zb0Q_K ze|+?JIgQd4nhYVjX!Z!hE3zKZMS@S59?|a=X_Eb7M2KM_Hg$Q05l{-BQUt3CpD=2a z!mkves=_afT48#XE+EomAY9c2gfV4I7gV~ssxByudR}zZ2xF?~3Mm6*DI|u;!7zK8 zh&FHlHcgTCA-k`TkHq?POHbLR6=~Cp#Z1085-S*HDv~NLS-dFHYvxT$w@o9GwhFn( z!nPId?XB^(iIxqkBXeuuG&%};gPiUo~-G- z#V3@^Y+8ko$rlG~<%elm1*;S#rBG98E=kSZ>oPsvV^&Jt3Q)qqc|*Z6h0Ss7!t-x} z(D>CG+$W?7ZMCJu8{O9!c#VP6YG|5_zm8!>>bk#ChQbcfluYLJoS978VYSE=jDajI zHP&eyp?i*!CIm;L=S3}z659`Y>wNYM5?b>q%gmX1ThFdm$XO}cRi7$#X3^524&5C? zxOCyH{}tYOwCi$&$U-#nF-_=BHzuNNHlCqLs7Mvm8k0;xr?Gd65-z5S6X{G|&$xO3~#1!H|>dV90#A2}6y` zlN;&8@G-aM(D-}!v}vT8JpUNA*<(ftIZj8ywoEqCVe(jvezU}sPEa< z&;nYPn1{ks>j`@5=o?hufon`3kJsl91ZzUI;VE_XQyZpDpD}aR>^Zm1ZJam1>GnJB zj4Zh8?tAXNZ(;QQ2OfOr;pUb{9)0ZbMNd4rc*#>wKeP1NWzQ{Nu`;%5^_sQMx4!V= zy0-ZG_LsCo$IBZ!H*V^BrTf*_lAHCOlwqcO`!fBnXLI>N@eQkF54<_}*3jGUY^rPoX@G@(jwe;Q>X_Vf97ei4WC}WDoX-;1 zOq;vI*gq^i1DUMhv?JOb$JPn!jB4CVomRcfNAH!mds4ggH-;Mhjs7NIQ=qmXcun~K E1TvV>xc~qF diff --git a/PythonHome/Lib/encodings/cp875.py b/PythonHome/Lib/encodings/cp875.py new file mode 100644 index 0000000000..72b160b02f --- /dev/null +++ b/PythonHome/Lib/encodings/cp875.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp875 generated from 'MAPPINGS/VENDORS/MICSFT/EBCDIC/CP875.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp875', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x9c' # 0x04 -> CONTROL + u'\t' # 0x05 -> HORIZONTAL TABULATION + u'\x86' # 0x06 -> CONTROL + u'\x7f' # 0x07 -> DELETE + u'\x97' # 0x08 -> CONTROL + u'\x8d' # 0x09 -> CONTROL + u'\x8e' # 0x0A -> CONTROL + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x9d' # 0x14 -> CONTROL + u'\x85' # 0x15 -> CONTROL + u'\x08' # 0x16 -> BACKSPACE + u'\x87' # 0x17 -> CONTROL + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x92' # 0x1A -> CONTROL + u'\x8f' # 0x1B -> CONTROL + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u'\x80' # 0x20 -> CONTROL + u'\x81' # 0x21 -> CONTROL + u'\x82' # 0x22 -> CONTROL + u'\x83' # 0x23 -> CONTROL + u'\x84' # 0x24 -> CONTROL + u'\n' # 0x25 -> LINE FEED + u'\x17' # 0x26 -> END OF TRANSMISSION BLOCK + u'\x1b' # 0x27 -> ESCAPE + u'\x88' # 0x28 -> CONTROL + u'\x89' # 0x29 -> CONTROL + u'\x8a' # 0x2A -> CONTROL + u'\x8b' # 0x2B -> CONTROL + u'\x8c' # 0x2C -> CONTROL + u'\x05' # 0x2D -> ENQUIRY + u'\x06' # 0x2E -> ACKNOWLEDGE + u'\x07' # 0x2F -> BELL + u'\x90' # 0x30 -> CONTROL + u'\x91' # 0x31 -> CONTROL + u'\x16' # 0x32 -> SYNCHRONOUS IDLE + u'\x93' # 0x33 -> CONTROL + u'\x94' # 0x34 -> CONTROL + u'\x95' # 0x35 -> CONTROL + u'\x96' # 0x36 -> CONTROL + u'\x04' # 0x37 -> END OF TRANSMISSION + u'\x98' # 0x38 -> CONTROL + u'\x99' # 0x39 -> CONTROL + u'\x9a' # 0x3A -> CONTROL + u'\x9b' # 0x3B -> CONTROL + u'\x14' # 0x3C -> DEVICE CONTROL FOUR + u'\x15' # 0x3D -> NEGATIVE ACKNOWLEDGE + u'\x9e' # 0x3E -> CONTROL + u'\x1a' # 0x3F -> SUBSTITUTE + u' ' # 0x40 -> SPACE + u'\u0391' # 0x41 -> GREEK CAPITAL LETTER ALPHA + u'\u0392' # 0x42 -> GREEK CAPITAL LETTER BETA + u'\u0393' # 0x43 -> GREEK CAPITAL LETTER GAMMA + u'\u0394' # 0x44 -> GREEK CAPITAL LETTER DELTA + u'\u0395' # 0x45 -> GREEK CAPITAL LETTER EPSILON + u'\u0396' # 0x46 -> GREEK CAPITAL LETTER ZETA + u'\u0397' # 0x47 -> GREEK CAPITAL LETTER ETA + u'\u0398' # 0x48 -> GREEK CAPITAL LETTER THETA + u'\u0399' # 0x49 -> GREEK CAPITAL LETTER IOTA + u'[' # 0x4A -> LEFT SQUARE BRACKET + u'.' # 0x4B -> FULL STOP + u'<' # 0x4C -> LESS-THAN SIGN + u'(' # 0x4D -> LEFT PARENTHESIS + u'+' # 0x4E -> PLUS SIGN + u'!' # 0x4F -> EXCLAMATION MARK + u'&' # 0x50 -> AMPERSAND + u'\u039a' # 0x51 -> GREEK CAPITAL LETTER KAPPA + u'\u039b' # 0x52 -> GREEK CAPITAL LETTER LAMDA + u'\u039c' # 0x53 -> GREEK CAPITAL LETTER MU + u'\u039d' # 0x54 -> GREEK CAPITAL LETTER NU + u'\u039e' # 0x55 -> GREEK CAPITAL LETTER XI + u'\u039f' # 0x56 -> GREEK CAPITAL LETTER OMICRON + u'\u03a0' # 0x57 -> GREEK CAPITAL LETTER PI + u'\u03a1' # 0x58 -> GREEK CAPITAL LETTER RHO + u'\u03a3' # 0x59 -> GREEK CAPITAL LETTER SIGMA + u']' # 0x5A -> RIGHT SQUARE BRACKET + u'$' # 0x5B -> DOLLAR SIGN + u'*' # 0x5C -> ASTERISK + u')' # 0x5D -> RIGHT PARENTHESIS + u';' # 0x5E -> SEMICOLON + u'^' # 0x5F -> CIRCUMFLEX ACCENT + u'-' # 0x60 -> HYPHEN-MINUS + u'/' # 0x61 -> SOLIDUS + u'\u03a4' # 0x62 -> GREEK CAPITAL LETTER TAU + u'\u03a5' # 0x63 -> GREEK CAPITAL LETTER UPSILON + u'\u03a6' # 0x64 -> GREEK CAPITAL LETTER PHI + u'\u03a7' # 0x65 -> GREEK CAPITAL LETTER CHI + u'\u03a8' # 0x66 -> GREEK CAPITAL LETTER PSI + u'\u03a9' # 0x67 -> GREEK CAPITAL LETTER OMEGA + u'\u03aa' # 0x68 -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + u'\u03ab' # 0x69 -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + u'|' # 0x6A -> VERTICAL LINE + u',' # 0x6B -> COMMA + u'%' # 0x6C -> PERCENT SIGN + u'_' # 0x6D -> LOW LINE + u'>' # 0x6E -> GREATER-THAN SIGN + u'?' # 0x6F -> QUESTION MARK + u'\xa8' # 0x70 -> DIAERESIS + u'\u0386' # 0x71 -> GREEK CAPITAL LETTER ALPHA WITH TONOS + u'\u0388' # 0x72 -> GREEK CAPITAL LETTER EPSILON WITH TONOS + u'\u0389' # 0x73 -> GREEK CAPITAL LETTER ETA WITH TONOS + u'\xa0' # 0x74 -> NO-BREAK SPACE + u'\u038a' # 0x75 -> GREEK CAPITAL LETTER IOTA WITH TONOS + u'\u038c' # 0x76 -> GREEK CAPITAL LETTER OMICRON WITH TONOS + u'\u038e' # 0x77 -> GREEK CAPITAL LETTER UPSILON WITH TONOS + u'\u038f' # 0x78 -> GREEK CAPITAL LETTER OMEGA WITH TONOS + u'`' # 0x79 -> GRAVE ACCENT + u':' # 0x7A -> COLON + u'#' # 0x7B -> NUMBER SIGN + u'@' # 0x7C -> COMMERCIAL AT + u"'" # 0x7D -> APOSTROPHE + u'=' # 0x7E -> EQUALS SIGN + u'"' # 0x7F -> QUOTATION MARK + u'\u0385' # 0x80 -> GREEK DIALYTIKA TONOS + u'a' # 0x81 -> LATIN SMALL LETTER A + u'b' # 0x82 -> LATIN SMALL LETTER B + u'c' # 0x83 -> LATIN SMALL LETTER C + u'd' # 0x84 -> LATIN SMALL LETTER D + u'e' # 0x85 -> LATIN SMALL LETTER E + u'f' # 0x86 -> LATIN SMALL LETTER F + u'g' # 0x87 -> LATIN SMALL LETTER G + u'h' # 0x88 -> LATIN SMALL LETTER H + u'i' # 0x89 -> LATIN SMALL LETTER I + u'\u03b1' # 0x8A -> GREEK SMALL LETTER ALPHA + u'\u03b2' # 0x8B -> GREEK SMALL LETTER BETA + u'\u03b3' # 0x8C -> GREEK SMALL LETTER GAMMA + u'\u03b4' # 0x8D -> GREEK SMALL LETTER DELTA + u'\u03b5' # 0x8E -> GREEK SMALL LETTER EPSILON + u'\u03b6' # 0x8F -> GREEK SMALL LETTER ZETA + u'\xb0' # 0x90 -> DEGREE SIGN + u'j' # 0x91 -> LATIN SMALL LETTER J + u'k' # 0x92 -> LATIN SMALL LETTER K + u'l' # 0x93 -> LATIN SMALL LETTER L + u'm' # 0x94 -> LATIN SMALL LETTER M + u'n' # 0x95 -> LATIN SMALL LETTER N + u'o' # 0x96 -> LATIN SMALL LETTER O + u'p' # 0x97 -> LATIN SMALL LETTER P + u'q' # 0x98 -> LATIN SMALL LETTER Q + u'r' # 0x99 -> LATIN SMALL LETTER R + u'\u03b7' # 0x9A -> GREEK SMALL LETTER ETA + u'\u03b8' # 0x9B -> GREEK SMALL LETTER THETA + u'\u03b9' # 0x9C -> GREEK SMALL LETTER IOTA + u'\u03ba' # 0x9D -> GREEK SMALL LETTER KAPPA + u'\u03bb' # 0x9E -> GREEK SMALL LETTER LAMDA + u'\u03bc' # 0x9F -> GREEK SMALL LETTER MU + u'\xb4' # 0xA0 -> ACUTE ACCENT + u'~' # 0xA1 -> TILDE + u's' # 0xA2 -> LATIN SMALL LETTER S + u't' # 0xA3 -> LATIN SMALL LETTER T + u'u' # 0xA4 -> LATIN SMALL LETTER U + u'v' # 0xA5 -> LATIN SMALL LETTER V + u'w' # 0xA6 -> LATIN SMALL LETTER W + u'x' # 0xA7 -> LATIN SMALL LETTER X + u'y' # 0xA8 -> LATIN SMALL LETTER Y + u'z' # 0xA9 -> LATIN SMALL LETTER Z + u'\u03bd' # 0xAA -> GREEK SMALL LETTER NU + u'\u03be' # 0xAB -> GREEK SMALL LETTER XI + u'\u03bf' # 0xAC -> GREEK SMALL LETTER OMICRON + u'\u03c0' # 0xAD -> GREEK SMALL LETTER PI + u'\u03c1' # 0xAE -> GREEK SMALL LETTER RHO + u'\u03c3' # 0xAF -> GREEK SMALL LETTER SIGMA + u'\xa3' # 0xB0 -> POUND SIGN + u'\u03ac' # 0xB1 -> GREEK SMALL LETTER ALPHA WITH TONOS + u'\u03ad' # 0xB2 -> GREEK SMALL LETTER EPSILON WITH TONOS + u'\u03ae' # 0xB3 -> GREEK SMALL LETTER ETA WITH TONOS + u'\u03ca' # 0xB4 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA + u'\u03af' # 0xB5 -> GREEK SMALL LETTER IOTA WITH TONOS + u'\u03cc' # 0xB6 -> GREEK SMALL LETTER OMICRON WITH TONOS + u'\u03cd' # 0xB7 -> GREEK SMALL LETTER UPSILON WITH TONOS + u'\u03cb' # 0xB8 -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA + u'\u03ce' # 0xB9 -> GREEK SMALL LETTER OMEGA WITH TONOS + u'\u03c2' # 0xBA -> GREEK SMALL LETTER FINAL SIGMA + u'\u03c4' # 0xBB -> GREEK SMALL LETTER TAU + u'\u03c5' # 0xBC -> GREEK SMALL LETTER UPSILON + u'\u03c6' # 0xBD -> GREEK SMALL LETTER PHI + u'\u03c7' # 0xBE -> GREEK SMALL LETTER CHI + u'\u03c8' # 0xBF -> GREEK SMALL LETTER PSI + u'{' # 0xC0 -> LEFT CURLY BRACKET + u'A' # 0xC1 -> LATIN CAPITAL LETTER A + u'B' # 0xC2 -> LATIN CAPITAL LETTER B + u'C' # 0xC3 -> LATIN CAPITAL LETTER C + u'D' # 0xC4 -> LATIN CAPITAL LETTER D + u'E' # 0xC5 -> LATIN CAPITAL LETTER E + u'F' # 0xC6 -> LATIN CAPITAL LETTER F + u'G' # 0xC7 -> LATIN CAPITAL LETTER G + u'H' # 0xC8 -> LATIN CAPITAL LETTER H + u'I' # 0xC9 -> LATIN CAPITAL LETTER I + u'\xad' # 0xCA -> SOFT HYPHEN + u'\u03c9' # 0xCB -> GREEK SMALL LETTER OMEGA + u'\u0390' # 0xCC -> GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + u'\u03b0' # 0xCD -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + u'\u2018' # 0xCE -> LEFT SINGLE QUOTATION MARK + u'\u2015' # 0xCF -> HORIZONTAL BAR + u'}' # 0xD0 -> RIGHT CURLY BRACKET + u'J' # 0xD1 -> LATIN CAPITAL LETTER J + u'K' # 0xD2 -> LATIN CAPITAL LETTER K + u'L' # 0xD3 -> LATIN CAPITAL LETTER L + u'M' # 0xD4 -> LATIN CAPITAL LETTER M + u'N' # 0xD5 -> LATIN CAPITAL LETTER N + u'O' # 0xD6 -> LATIN CAPITAL LETTER O + u'P' # 0xD7 -> LATIN CAPITAL LETTER P + u'Q' # 0xD8 -> LATIN CAPITAL LETTER Q + u'R' # 0xD9 -> LATIN CAPITAL LETTER R + u'\xb1' # 0xDA -> PLUS-MINUS SIGN + u'\xbd' # 0xDB -> VULGAR FRACTION ONE HALF + u'\x1a' # 0xDC -> SUBSTITUTE + u'\u0387' # 0xDD -> GREEK ANO TELEIA + u'\u2019' # 0xDE -> RIGHT SINGLE QUOTATION MARK + u'\xa6' # 0xDF -> BROKEN BAR + u'\\' # 0xE0 -> REVERSE SOLIDUS + u'\x1a' # 0xE1 -> SUBSTITUTE + u'S' # 0xE2 -> LATIN CAPITAL LETTER S + u'T' # 0xE3 -> LATIN CAPITAL LETTER T + u'U' # 0xE4 -> LATIN CAPITAL LETTER U + u'V' # 0xE5 -> LATIN CAPITAL LETTER V + u'W' # 0xE6 -> LATIN CAPITAL LETTER W + u'X' # 0xE7 -> LATIN CAPITAL LETTER X + u'Y' # 0xE8 -> LATIN CAPITAL LETTER Y + u'Z' # 0xE9 -> LATIN CAPITAL LETTER Z + u'\xb2' # 0xEA -> SUPERSCRIPT TWO + u'\xa7' # 0xEB -> SECTION SIGN + u'\x1a' # 0xEC -> SUBSTITUTE + u'\x1a' # 0xED -> SUBSTITUTE + u'\xab' # 0xEE -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xac' # 0xEF -> NOT SIGN + u'0' # 0xF0 -> DIGIT ZERO + u'1' # 0xF1 -> DIGIT ONE + u'2' # 0xF2 -> DIGIT TWO + u'3' # 0xF3 -> DIGIT THREE + u'4' # 0xF4 -> DIGIT FOUR + u'5' # 0xF5 -> DIGIT FIVE + u'6' # 0xF6 -> DIGIT SIX + u'7' # 0xF7 -> DIGIT SEVEN + u'8' # 0xF8 -> DIGIT EIGHT + u'9' # 0xF9 -> DIGIT NINE + u'\xb3' # 0xFA -> SUPERSCRIPT THREE + u'\xa9' # 0xFB -> COPYRIGHT SIGN + u'\x1a' # 0xFC -> SUBSTITUTE + u'\x1a' # 0xFD -> SUBSTITUTE + u'\xbb' # 0xFE -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\x9f' # 0xFF -> CONTROL +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/cp875.pyc b/PythonHome/Lib/encodings/cp875.pyc deleted file mode 100644 index af78feb2dc98a01e15871c7489164e40d593b693..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2691 zcmc&$30E9N5bix$mMgb`pl-ZaFYt2xgF<_n}0HR6k;*R5USYg3b|ChMx=i)yKa zudIG!LqlC~Q>bEVO|W{46soAN3xsMLD{86&)pdc2Km#r+Z`{^c=Ie^-?X)~X-pbS6 z>K7N9_3wIZLWRbO_riu>c!%4*m5J3TMA08azN7>Fub}%XAr#$FxdR^CI5j{fB zG@LjBq+W`X&RBlV$Wm)J715gq#kW#}z6eA{=2|ZjGzv zD%v5V#-k#HSTfzIi*u-&meMkQG%_(|R-#nivN_h;GVLYPBJe~U%oPHbJaR{|Guyuj zLZYR!j*mzq+CnA7*~ga%c!_|Ma&TJ6c}>TJ)PwW-2@2hVQ#hQI6KXiDd&NT{rF6#e zQ6if}5nB5QXQ`(L7^@g(bR;R)a7`MKu(LGR(!J5S%!}$b@1va z%%Tfr{jczrpw{9Dk_BnvAe!KnE)Mz0Z7_xt6Ojt2B_f%CPNLHZN?4c*PDEo#Ic^0! zf2@QMMK=>tDWCQzz)AS4mE##zKxsMs2Pjga7EgP2+vZ|eEok!pU`WX|F(kgs!BC>= zWJNkZe8jC4IQ||!X%U(h&ObtJ`Lt6+j?xj*HC0YDX)!F4S>6$=s^~?^qRBffO(-+L z9V?GkI6|5~CZake?_J)aeRQwV|*VU%gZk)ELya9$x?ob_j~x@%3^+q z?=OA$kw8f|Nj!F9L+ zH{lli2)FsQj*sJsWGelM26x~m_!)kIyYMT&^<_ry{Iu({?$6;K{06@pJ;rXMm!E?x za238cM&Jiy)Yxb2HO7oRMxW7d3>bsP&=(u=r$tTernl?(RbvE&0}yt;PXYy2j^ zgu1)@jGt14w50x}q$1d_sN$P^uvkC@FsZPLB&t|C)#mA+3$2~8xMDT~)Xw0_ytiDm i&GlxZ+~B}<8R}iw?3~4(VrQ|l)KTinEpp#y&OZTad|&+l diff --git a/PythonHome/Lib/encodings/cp932.py b/PythonHome/Lib/encodings/cp932.py new file mode 100644 index 0000000000..e01f59b719 --- /dev/null +++ b/PythonHome/Lib/encodings/cp932.py @@ -0,0 +1,39 @@ +# +# cp932.py: Python Unicode Codec for CP932 +# +# Written by Hye-Shik Chang +# + +import _codecs_jp, codecs +import _multibytecodec as mbc + +codec = _codecs_jp.getcodec('cp932') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='cp932', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/cp932.pyc b/PythonHome/Lib/encodings/cp932.pyc deleted file mode 100644 index 1108060af0d83d3193136b49b2f732280da91e16..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1673 zcmcgs&2G~`5FY=;`Kgm21gL<-fm2RBz^M{K6@^13=wWlHup*hnyNMjdPGoO|at_bL z%kUUH0DLoUoT!CEF0sAq+4;t^GqdyA``zvQy!kdv=`>%v z^)5vo8KSvQ+NBMk25D#0YV~`r;yG@pVP@mOw)W;jwH~t)mm|6Ax6nZ7C3FkK8A3WCxyvO zZpVvH;=Xv83a4JD61jEw9`wrPNhJ1rP()39@Cc)1AAx&6o{y5_5#!;Lc(NA{S8Hes zGtQJ5Yjea%+Sr*7v#N|^cahu_sXb;S+>kGKk<`u6hwhT~7nm$K4f^5%OFgn6H#8ue zzm>uG2BDq7Ve~J^Yn!B7-25AA4hNj?wdDq49w@v?aqlZ`d+CdG*QXT?iu>w{5{1;N zlvBgW;nemN-=%o6o3MyEl$4ft7ZzXT)1~lax4GgbRooeh%@o(;kS4b$_+Vxb&kQ6h z)~~QEx#mAoqZk75}TS;`vI6j!PY9w+ow2)>b%?SSDOHN#y4N@A8G>`bqef zPwdO~i-#1Kr2cDk$2&>dKHc}UPX;N+zu>AvrBI6hFb7qO3;nM8{k`YPm(0ggCv^Mn NbHD98^LV_*{TF@RGrRx* diff --git a/PythonHome/Lib/encodings/cp949.py b/PythonHome/Lib/encodings/cp949.py new file mode 100644 index 0000000000..627c87125e --- /dev/null +++ b/PythonHome/Lib/encodings/cp949.py @@ -0,0 +1,39 @@ +# +# cp949.py: Python Unicode Codec for CP949 +# +# Written by Hye-Shik Chang +# + +import _codecs_kr, codecs +import _multibytecodec as mbc + +codec = _codecs_kr.getcodec('cp949') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='cp949', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/cp949.pyc b/PythonHome/Lib/encodings/cp949.pyc deleted file mode 100644 index f566ccbfd7a87a0fa1ef1632ba8e6bbd77d2ba3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1673 zcmcgs&2G~`5FY=;`Kgms2v7lu1E-vN;!+8rio&51^sqTpSdmQP-9!$tQ`uXgoYQCG zWq1r80KOSFPSnC7m)PF*?0n$ak%%?k|HPP27Al)G2(Yz^ei>5B=poUwd0RV0b+!44{ z!yVE90-BPs32BefRIS#38d4}=X5d>(=?xzBMJ2MW~Df?5ToQH3!JuNpFp_Glfq;s zx8ubpabG-6g;TFniQGDT4|?VDBoh1GE21VoIL0X1N8mn;=cD9!z4_Gv|f;-R{tL?N{* z<NpY3|uC4-dXUvSl-QYgiLn7yjSg??B4{@!!tOXlN=6S{r( Nh2M6bdpzFY{tHdPGyebp diff --git a/PythonHome/Lib/encodings/cp950.py b/PythonHome/Lib/encodings/cp950.py new file mode 100644 index 0000000000..39eec5ed0d --- /dev/null +++ b/PythonHome/Lib/encodings/cp950.py @@ -0,0 +1,39 @@ +# +# cp950.py: Python Unicode Codec for CP950 +# +# Written by Hye-Shik Chang +# + +import _codecs_tw, codecs +import _multibytecodec as mbc + +codec = _codecs_tw.getcodec('cp950') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='cp950', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/cp950.pyc b/PythonHome/Lib/encodings/cp950.pyc deleted file mode 100644 index b0929a5892fb4a64c4c8c9088b98b8f3ade3a6cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1673 zcmcgs&2G~`5FY=;`Kgm21gL<-fm2Qu7Y;}WRV^GUK@Xclg%!yp-c95vb}D zco`mp2Y_$JjT5zS$R)OSJv-lcc4l@yd%wG#pI1MI3Ef{l-lrJlFH9PbLkps)mK}=Jr^qKY8~~*OJF+cIah#7c6UVkAi)^WH7QB?5 z*uM<`m^^_jB2*A7FF;77@)**|=xaI|iD{b8%8>+ma=lUjfc@l~J?iEoJA3VV**+<|$jOVlDc))o0B%bZW!_^wv z!i+Oz#@ZY(k~Vhc!>lUf*li?NMQRTj2{+{HZ6tMb^r1Uv{V663PJ_O9z*3Ja$PEn$ z=Wk>%zCmbba2Wjy^4ccp7B~Nzn!^F-duh3Wm4L3v6y&?ekqvyJV1Z{0pu+R0^f|53^UbxX>S~-`^*$e93$~c0#xB OzVzG93y;TJ+ +# + +import _codecs_jp, codecs +import _multibytecodec as mbc + +codec = _codecs_jp.getcodec('euc_jis_2004') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='euc_jis_2004', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/euc_jis_2004.pyc b/PythonHome/Lib/encodings/euc_jis_2004.pyc deleted file mode 100644 index cc5e9a9c8dc68d49d9098d00cd72179d727e8e27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1729 zcmc&!&2G~`5FY=;`Kgm21gL-n5~rN13UNfJB5nH<6>*sqBqV&gGeS z86JZNfN#c)6SZ*3q1fK_?9A-${C(s7>UMryejO!r^Z59mVU#~HX?zYXiK3czC~~%Z zmm-f0(ZVO~(lta4(%?9>2xta1pS}}a6McyS(hV{mEt(>3(aa?s)Z!Lt2q12YxFh0L zE$)zpAP|is(Fkegk?zzQA!!IIjjm|)L?f&2Ew2HUw$bNxVqQ z`1R@O8`}V5xY8!6!{UJR9;1B5x;Vul7EXeGf27J}Pi;oAp6FzJIeg zJ&*Rx;@FLBVJ4X}6K(F_pf(IRt_^aeC@X_5i`4!HgScj&?+mI7rw`tc`Dd6c&<~*F z1D-vyXanE?n*NqXZ)gxI9%x621Ln3#y2bdorsinCZeLg~E{2N2pA^GGF*2lB(p?Q# zNGWc!E7TMcvQl!0JR*mCjBgS{xlMp3=qoMXK4c)C=d+byXm`2d%2iw^iq#ay;{X8I zBkY?Sm^B9ui_HrxO9li1q=6IS4dfj#v+5L;b@Ad#36CQlXX~X+ryDDHNi1VBn Vp=7KcJE7ZmpZaa*iO1s=-app;NTdJ& diff --git a/PythonHome/Lib/encodings/euc_jisx0213.py b/PythonHome/Lib/encodings/euc_jisx0213.py new file mode 100644 index 0000000000..cc47d04112 --- /dev/null +++ b/PythonHome/Lib/encodings/euc_jisx0213.py @@ -0,0 +1,39 @@ +# +# euc_jisx0213.py: Python Unicode Codec for EUC_JISX0213 +# +# Written by Hye-Shik Chang +# + +import _codecs_jp, codecs +import _multibytecodec as mbc + +codec = _codecs_jp.getcodec('euc_jisx0213') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='euc_jisx0213', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/euc_jisx0213.pyc b/PythonHome/Lib/encodings/euc_jisx0213.pyc deleted file mode 100644 index 6873ab5e892384020800b90a623c1a9a47d4bce2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1729 zcmc&!OK;Oa5FS6`JemhWfC@+;amuNpa7CyhaHs@5Yz`GxB$IeIk*&n3?2RDj@SFHE z{0x2od^2vGsD(=o#rCdeXJ&Wj^^Nzd)B17wWf;@-M*k(XKSQq&vI_d+gJ&--Un4Z#);a4brUQC{2oQ zFJGO$wly#YOKsvREDkvDFp4Lvi&GpjE~TDC0EADWPiokQl={5gHZVm|HeQ%0vMpIG zmU=bkB`d^yz70T`jA_@=~44kH8 z?}Iqc;@m7uX2OBMwC6QRr4)c;G9SC!zScLr63(*tk7{4-1z=m*g8 z0nZ*;v;lAcO@B+HH`E9f545Ai0drd?-C%rds6Ono+ZUFLi=m?MC&lnkj0`E3WLLu_ zQu3SZ5;eJmtdJZckI3O3ouw+Fh==auwH!Vl~C_H~;|l z2>WIRX3c=ZeEkf|f&oDQY2dW+2J-fqS$2xjx+uL;!sCcXi`CpFleHDR#FjC+n8ea% zaJuYJ97gfNa^gO1ciip*;@dx!t}!XT+lTun?IT2@@;7l=uM#iCP3VxIaoFFK{qim6 Wp +# + +import _codecs_jp, codecs +import _multibytecodec as mbc + +codec = _codecs_jp.getcodec('euc_jp') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='euc_jp', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/euc_jp.pyc b/PythonHome/Lib/encodings/euc_jp.pyc deleted file mode 100644 index 0a882836f7d7b454c662d16e82b24b5c3935672c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1681 zcmcgs&2G~`5FY=;`Kgm21gHgx1E-w&1PE0G4wayX&7s1IWD@Ttauhq2y-}5OcqU$k z$KV0rn{nerEgW)*?Oo5#%gwD3v0w1ufb8XAWd0nOm%(+{F8(YGid-5}%9qABJU&0Nw!ZElf<0p_-tJ7R9t z<_>8X0`WK#kC0{_=}zqtl7^x3=!!>AJi^+eN4m>{sLwHt20g@={=su&1Bhmw#EU!I zfH+)flhg@up!tYazGg4XcgVQ3@FaE!K1DvM(EwH&@O0Zk7svS|GjVJ?GRRhXz2qS~ zB)opLY0k2UP(iF#fe(pPUO>7We@Ulf!>(yQFUJ+q%e#$YXdzn3hZZ<($3BN}ohOCK zOl~L3&$52;G!_oNjwNzy{2uhmH_IQH)Q=4Ityll#Q4Bfk1Qw-4QS`@ zWbnR0sA(`6MGOktCg~P4U`x%>fCIj#@#V|B%gLXuU= zx#8?^ZU>5c$)4;cR1$ubmUkaA)voi|O1QG$TydQ$t_{U*it}+)q1!Xem>U3^gK5R) zErul*K7odT6XFfz9k8;x1u9&)Wt8YR*KxL9+H|_H!i&T*>#}JgR|r;@8Hy7q_$?pV z*WHY#JeR2c>-4}qiQ2wAT +# + +import _codecs_kr, codecs +import _multibytecodec as mbc + +codec = _codecs_kr.getcodec('euc_kr') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='euc_kr', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/euc_kr.pyc b/PythonHome/Lib/encodings/euc_kr.pyc deleted file mode 100644 index f2fad89a65e0b8bcbd61e275ce98c9abad96d7cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1681 zcmcgs&5qMB5T5)r{n@ld2+%G_960r~Pk_*B3x}0p5AI<_R4KHvTctE9N?f6y%QNvZ zJO&Q{-%Pe?wF`${n#9g{W^8{mp3mOzZs+ISmr+9ZkB|QqTKNl|#^=zID5_I|Eq+zH$y5i9jkFfUWk?!&!>T^t^K@ahzfAHMe0HRqZ@z=sO zAP!gBBy~a@Xs*%9m+Xc44jGpgp2QBpr^qKY8o){eo^D&{;y9mVCXQ`K2H8rlmpo*L zgx9Y&%~=)^Du~r8@F9`P3rLsakLh%5*fq`P<+wt6`E8>ZT8LKip#@Icu}>k~F+OnBBMXW{1KRmJ z8N6>0Y8p&N5re|ENxH=h*iv&e;DB!}7ZH;|;ZKSQpqOw{8tJ}PrNB+`P+jq&kYtr| zZa6!f+kxV{WKVVzDha>;0u?UYGD>uu>o{94Z93gp;YDJZb=fqLD+H^{48;i){FaaG z({9FNo=a5!b-L%CL~WlRu5`!;$;ZFURgFrf6kjvPrHfPjwz>u1aqdgz +# + +import _codecs_cn, codecs +import _multibytecodec as mbc + +codec = _codecs_cn.getcodec('gb18030') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='gb18030', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/gb18030.pyc b/PythonHome/Lib/encodings/gb18030.pyc deleted file mode 100644 index dae6efaeb6adb3b0c6e83e7ca523e3bc4137158e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1689 zcmcgs&5qMB5T5)r{n@ld2+#r&2Tnb$7IEQ#(2BxgCD?;|SP@kUZR}R5niM5op`Mp# z;$?UY9ss_Xv}v^qhhCb*&Uj{Q&o`dW-tTVb=k?c7LYv3O{{pT2g-+vhXh{^+vO|%x z)w>jVWQZ0%X_szcYLJG;p+!J5xcT&h=$7b96p(I^@o3Q$bBks!>7X{ZNW%bgTg)9X zw`y~TGz@`woQOwAGmmtq_6SMCP$_|iXku51(HeERCm z`RjArfIM7jlhhe;pm~p0K0^nzz;9eycmf`RPmxb*G=P-`Jl(d?#c@8#OdQ*e46>EJ zS@Mt_5?XGc+e}CJCS(Z17qTBK0qsZmB76l(FehK)QI>z9_>ZM z85`NcOfqFA+8i~OHugTPV{z;*mg^$5$Bl(c^Z728x=8xa4OxGI&Vt{dGCnZYBMYKK z1M>M>8SHNm3LAVzC4*E5C?>?>=O{UFNfu@MX8T;!;&y9g5u)=i{(qw;mh*P8?_^vrHU!3f>)n)jOvtKeVPo2>1 OyHEYL^Tgx!67OG3^fqGv diff --git a/PythonHome/Lib/encodings/gb2312.py b/PythonHome/Lib/encodings/gb2312.py new file mode 100644 index 0000000000..3c3b837d61 --- /dev/null +++ b/PythonHome/Lib/encodings/gb2312.py @@ -0,0 +1,39 @@ +# +# gb2312.py: Python Unicode Codec for GB2312 +# +# Written by Hye-Shik Chang +# + +import _codecs_cn, codecs +import _multibytecodec as mbc + +codec = _codecs_cn.getcodec('gb2312') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='gb2312', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/gb2312.pyc b/PythonHome/Lib/encodings/gb2312.pyc deleted file mode 100644 index aaf77109740a3d2466cc561c0265c37d8ee79f7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1681 zcmcgs&2G~`5FY=;`Kgm21gHgx1E-uSQLYG81P+y;hs~kFiewV+CUO)z$leO&9G;1n z;W2ms_-5QVQ45D$Vtd!KGqbzj%+9yo?{4Sk&DT*vcaM+%C0h9loyO66_uCz(&ggDT=M=PJBL$C_FRvPeh+d>z|`6M%OY&$Z@R{D0y zLv~1bec9CHEQ<&g#A+4zkVxejr1SBobUGH-G@qB_3hDW`wPI)?TFHkNIBmy1hH#Z9 zg~?2AC(Dnre(^9C4!({ha%=n^^vdN;d9@ zjcj2inKBb?jtQlWtxszxj@?1IDN=h>C|s27BgT&&C!4ZzP4OMOa_HNDJFno!bxeQyIQTdP~2BnyeK4D zrJNhi4(GO~_%7L#-GoZQuhR1FL#EnQK3fS_cAG1%Q^mER*iCUh4k~nef*ErIKyxsy zSii)uR-7al9U0dNrVwrW>G?6O=tIG_<2^9R6 zkL>ey#zUSbS*OXlRM6S{r( N%x^o-JZ`V>{smcHG`j!* diff --git a/PythonHome/Lib/encodings/gbk.py b/PythonHome/Lib/encodings/gbk.py new file mode 100644 index 0000000000..1b45db8985 --- /dev/null +++ b/PythonHome/Lib/encodings/gbk.py @@ -0,0 +1,39 @@ +# +# gbk.py: Python Unicode Codec for GBK +# +# Written by Hye-Shik Chang +# + +import _codecs_cn, codecs +import _multibytecodec as mbc + +codec = _codecs_cn.getcodec('gbk') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='gbk', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/gbk.pyc b/PythonHome/Lib/encodings/gbk.pyc index 26905d35fe9a8930b16b4319b40b9782442c5afd..f45478a92e0feebdef8e0aee97a30239c731d32e 100644 GIT binary patch delta 411 zcmdnbyOw{$97aPY1_lOKtC;l6l8n-%nDG1xJ+EMYzn}o;82{3eg3^*0m(--v^q7Fk zl8pR3kNn)!$&4&wlMgbMlBqMAshCWipP6#W)Y-~RhR)55ELP+NkLc!jRv|LAPM*r9 F1pt`biZB2G delta 153 zcmZ3>zn^!*97cWx1_lOatC)bwl8pR3BlF2;8M`sWI+;2##GIL%F~q)OifvxaVufi* O9=q6P9X3I167~QLB`R|O diff --git a/PythonHome/Lib/encodings/hex_codec.py b/PythonHome/Lib/encodings/hex_codec.py new file mode 100644 index 0000000000..91b38d952e --- /dev/null +++ b/PythonHome/Lib/encodings/hex_codec.py @@ -0,0 +1,79 @@ +""" Python 'hex_codec' Codec - 2-digit hex content transfer encoding + + Unlike most of the other codecs which target Unicode, this codec + will return Python string objects for both encode and decode. + + Written by Marc-Andre Lemburg (mal@lemburg.com). + +""" +import codecs, binascii + +### Codec APIs + +def hex_encode(input,errors='strict'): + + """ Encodes the object input and returns a tuple (output + object, length consumed). + + errors defines the error handling to apply. It defaults to + 'strict' handling which is the only currently supported + error handling for this codec. + + """ + assert errors == 'strict' + output = binascii.b2a_hex(input) + return (output, len(input)) + +def hex_decode(input,errors='strict'): + + """ Decodes the object input and returns a tuple (output + object, length consumed). + + input must be an object which provides the bf_getreadbuf + buffer slot. Python strings, buffer objects and memory + mapped files are examples of objects providing this slot. + + errors defines the error handling to apply. It defaults to + 'strict' handling which is the only currently supported + error handling for this codec. + + """ + assert errors == 'strict' + output = binascii.a2b_hex(input) + return (output, len(input)) + +class Codec(codecs.Codec): + + def encode(self, input,errors='strict'): + return hex_encode(input,errors) + def decode(self, input,errors='strict'): + return hex_decode(input,errors) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + assert self.errors == 'strict' + return binascii.b2a_hex(input) + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + assert self.errors == 'strict' + return binascii.a2b_hex(input) + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='hex', + encode=hex_encode, + decode=hex_decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/PythonHome/Lib/encodings/hex_codec.pyc b/PythonHome/Lib/encodings/hex_codec.pyc index 4d91f2aac7d1a6a334ddc4f27c85d73cf66e9d92..1aabdbd20b3e9bbd8a7c04062e56953540b56040 100644 GIT binary patch delta 759 zcmZpc-K((SIJ2P#0|P^On82Uo>#EHUr>N^jDKlKL1{^hOKMVSdQ3oN zNk)F2M}BVVWCuQ(&7YWSnaI;Rc^2DVGIchwr<18ugd>0~ozj#0IBt-sa{{LWnL2-Q nUL;fJS1xNZbw+U~ld1DLxjHwO@Q5>#WvR^MZM@ZF>2wAF%bN#^ delta 317 zcmdn1&@8**I5WQ*0|SGzRZKu-Nk)F2k@;jtF6qg4**G`Lu#__4klcq={5g9DR`J;! zfmp<4CR=h|$08n$MNDS$ORfu8#o2hQFvJUa>M+C{xnw5W@Frms-~5_aj1h~3^kiTD K8m!`?0vZ6@jaIb) diff --git a/PythonHome/Lib/encodings/hp_roman8.py b/PythonHome/Lib/encodings/hp_roman8.py new file mode 100644 index 0000000000..dbaaa72d76 --- /dev/null +++ b/PythonHome/Lib/encodings/hp_roman8.py @@ -0,0 +1,152 @@ +""" Python Character Mapping Codec generated from 'hp_roman8.txt' with gencodec.py. + + Based on data from ftp://dkuug.dk/i18n/charmaps/HP-ROMAN8 (Keld Simonsen) + + Original source: LaserJet IIP Printer User's Manual HP part no + 33471-90901, Hewlet-Packard, June 1989. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_map) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_map)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='hp-roman8', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x00a1: 0x00c0, # LATIN CAPITAL LETTER A WITH GRAVE + 0x00a2: 0x00c2, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00a3: 0x00c8, # LATIN CAPITAL LETTER E WITH GRAVE + 0x00a4: 0x00ca, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00a5: 0x00cb, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00a6: 0x00ce, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00a7: 0x00cf, # LATIN CAPITAL LETTER I WITH DIAERESIS + 0x00a8: 0x00b4, # ACUTE ACCENT + 0x00a9: 0x02cb, # MODIFIER LETTER GRAVE ACCENT (Mandarin Chinese fourth tone) + 0x00aa: 0x02c6, # MODIFIER LETTER CIRCUMFLEX ACCENT + 0x00ab: 0x00a8, # DIAERESIS + 0x00ac: 0x02dc, # SMALL TILDE + 0x00ad: 0x00d9, # LATIN CAPITAL LETTER U WITH GRAVE + 0x00ae: 0x00db, # LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x00af: 0x20a4, # LIRA SIGN + 0x00b0: 0x00af, # MACRON + 0x00b1: 0x00dd, # LATIN CAPITAL LETTER Y WITH ACUTE + 0x00b2: 0x00fd, # LATIN SMALL LETTER Y WITH ACUTE + 0x00b3: 0x00b0, # DEGREE SIGN + 0x00b4: 0x00c7, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00b5: 0x00e7, # LATIN SMALL LETTER C WITH CEDILLA + 0x00b6: 0x00d1, # LATIN CAPITAL LETTER N WITH TILDE + 0x00b7: 0x00f1, # LATIN SMALL LETTER N WITH TILDE + 0x00b8: 0x00a1, # INVERTED EXCLAMATION MARK + 0x00b9: 0x00bf, # INVERTED QUESTION MARK + 0x00ba: 0x00a4, # CURRENCY SIGN + 0x00bb: 0x00a3, # POUND SIGN + 0x00bc: 0x00a5, # YEN SIGN + 0x00bd: 0x00a7, # SECTION SIGN + 0x00be: 0x0192, # LATIN SMALL LETTER F WITH HOOK + 0x00bf: 0x00a2, # CENT SIGN + 0x00c0: 0x00e2, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00c1: 0x00ea, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00c2: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00c3: 0x00fb, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00c4: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE + 0x00c5: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x00c6: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00c7: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x00c8: 0x00e0, # LATIN SMALL LETTER A WITH GRAVE + 0x00c9: 0x00e8, # LATIN SMALL LETTER E WITH GRAVE + 0x00ca: 0x00f2, # LATIN SMALL LETTER O WITH GRAVE + 0x00cb: 0x00f9, # LATIN SMALL LETTER U WITH GRAVE + 0x00cc: 0x00e4, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00cd: 0x00eb, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ce: 0x00f6, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00cf: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00d0: 0x00c5, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00d1: 0x00ee, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00d2: 0x00d8, # LATIN CAPITAL LETTER O WITH STROKE + 0x00d3: 0x00c6, # LATIN CAPITAL LETTER AE + 0x00d4: 0x00e5, # LATIN SMALL LETTER A WITH RING ABOVE + 0x00d5: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE + 0x00d6: 0x00f8, # LATIN SMALL LETTER O WITH STROKE + 0x00d7: 0x00e6, # LATIN SMALL LETTER AE + 0x00d8: 0x00c4, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00d9: 0x00ec, # LATIN SMALL LETTER I WITH GRAVE + 0x00da: 0x00d6, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00db: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00dc: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00dd: 0x00ef, # LATIN SMALL LETTER I WITH DIAERESIS + 0x00de: 0x00df, # LATIN SMALL LETTER SHARP S (German) + 0x00df: 0x00d4, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00e0: 0x00c1, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00e1: 0x00c3, # LATIN CAPITAL LETTER A WITH TILDE + 0x00e2: 0x00e3, # LATIN SMALL LETTER A WITH TILDE + 0x00e3: 0x00d0, # LATIN CAPITAL LETTER ETH (Icelandic) + 0x00e4: 0x00f0, # LATIN SMALL LETTER ETH (Icelandic) + 0x00e5: 0x00cd, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00e6: 0x00cc, # LATIN CAPITAL LETTER I WITH GRAVE + 0x00e7: 0x00d3, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00e8: 0x00d2, # LATIN CAPITAL LETTER O WITH GRAVE + 0x00e9: 0x00d5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00ea: 0x00f5, # LATIN SMALL LETTER O WITH TILDE + 0x00eb: 0x0160, # LATIN CAPITAL LETTER S WITH CARON + 0x00ec: 0x0161, # LATIN SMALL LETTER S WITH CARON + 0x00ed: 0x00da, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00ee: 0x0178, # LATIN CAPITAL LETTER Y WITH DIAERESIS + 0x00ef: 0x00ff, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x00f0: 0x00de, # LATIN CAPITAL LETTER THORN (Icelandic) + 0x00f1: 0x00fe, # LATIN SMALL LETTER THORN (Icelandic) + 0x00f2: 0x00b7, # MIDDLE DOT + 0x00f3: 0x00b5, # MICRO SIGN + 0x00f4: 0x00b6, # PILCROW SIGN + 0x00f5: 0x00be, # VULGAR FRACTION THREE QUARTERS + 0x00f6: 0x2014, # EM DASH + 0x00f7: 0x00bc, # VULGAR FRACTION ONE QUARTER + 0x00f8: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00f9: 0x00aa, # FEMININE ORDINAL INDICATOR + 0x00fa: 0x00ba, # MASCULINE ORDINAL INDICATOR + 0x00fb: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00fc: 0x25a0, # BLACK SQUARE + 0x00fd: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00fe: 0x00b1, # PLUS-MINUS SIGN + 0x00ff: None, +}) + +### Encoding Map + +encoding_map = codecs.make_encoding_map(decoding_map) diff --git a/PythonHome/Lib/encodings/hp_roman8.pyc b/PythonHome/Lib/encodings/hp_roman8.pyc deleted file mode 100644 index 084489767f3b8ee5bd65536a6b6e9950da03eff2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3977 zcmdUx=X)I06~@mNt%@x-jBSB10|{7wC0Q}KNT#@mVi{W&Bfy{-*5f@RX{_DZ&CD#e zo`-MdFW@hrIDzy)5|U68dhh9`rclyDdL!?9$I?2spU1!lcvxwE=gz$|cg}gwxpyY_ zPJ7!O+jfkWaXav(LR_@38po=TJ%hq zPm3Cuvqbx07KjeOtPwpMW{K!IFpEXcg;^$g9!#g`T9|dB>tPlNE;hP>u^Al{Js;)* zL5M~#6uk&$qv#OKCee#wHj8e785a0qbgMuGqa&i1z_9j5%_O(yXaLgTSTvhfzCT%JkgynB~gX(MaN-=1Q#2f5XfdQpp!6x zKs^Hw&@#G9Ae+%C(K5^qLCYX2xM~m%qA^+#1Z>~|T1G>Gs|HTu$p$XtSq6?kU<0=h zn}H(;-)L2!kkOhTD5IYh_+j7yTs0aAqA?l^958q^rZt)f5@V1VNMn#LsArHa2yCD} z<}+FsNMn#0y#{8jAYg+kfrtjlgU$xUf>apYEl|%Om8b`Uy1?uPiwKW2sM8GBP&;dt zMLUnnYqV<*SKY#lh%+*sOjbi@aMFvsQsPI>7Oz$d!U<=vs(#6t@IycH5?`J1s9JGW zOxB99UfAE0>`7KQyMtts*OYj1Pi?xVtG);nTM@(mu#QVNjyN?hN}RB2JzBl`%(MEs2UZQN>Rah-^mmv2 zq7bT-vP-{~9ZAAtM8yZ8+!O%TW`FuPf0(X)ZFIe?E%0h^NDudaivP#f*6 zu$>ckv^~8GNM^QD3yD%sgaVJ_m+cyV0x6jNGZ*Szb zHl5yO^SXdjGJ45;kT6`{`hNkSR8TH90NXq`0GGnM6wYl1-mk~$)YSHX$6XX8X#tAG z(5v{xV$x<$DpjqQaq4o+odYzUWm`v;$i+Rv#Ke3?Av-shEJ9-_EJc3B4->C^fz>Z6 zq1XOqOK34p(-Oj4Nu^OX%>LmbABWyXt)OU7E;*J9-j*GsU7U6}0K`UX1$S9&RzjEF z+2UwuYpY|NOR5p{(c`63OK}`5t;;fW+W|Z0g>l>h0LK^o^Olh zqtUXJF|r(8*3KbXy7SqG<2|k{TWiPT@*~UWa=Cr5dR&M*St@p7D9F@|CXw$|wnYJU z$k{q%m2KdK%xGGN*s{13@t zeKj_=6kEhWV?#){?&bk~Y(!tlO8!gkw)9n^tN$Y&p$Zm4{seL)R{<5jyAH6H77 zEx9ZQmkDtx$@@)Z!Yy&ahc|e=C(-n&IE`7Gl4;EpGIQ})uz!J|oPzIRAh?mZpSX#5 zl(?CAoY+S^L41yQn)p2N3~>wbP2yJK32bV?7ub53tuM0mC1O8Mzs%N8h_4VoBfd)P zbAYe0^>yMU;x^(x#O=g4h)0Mwh;I?k5qA)OB)(02hq#aUE^#Mu7jZXn4{<#szn87o ziMNUG6MrWDMLa;fMm$KoMLa~jLp)6UlX#VQlX#5y6Y&q?7sQjquZgFKzY_l@o+W-q z{Fr#2c!BsO@gnhC;s?avi60WbB7Q{thWIJ5pZGoT3h^@WbK(!gUx*!y*CX~2@3QZ| z#9{~d8(TM=f>N807M2U&xmqpZ9gCcai$ji7nJ)J%yCf>!lwS-K^%f-4Ma6fMeW^rV zIN{r^*M61MYxt`4?b;izhJM02w|CBb$?$6^ee3a&jlw_b_GP~l&Pl%v&TGNFF$Kk& bJ>SvNk?+WN<~o~N+mFQpX#N=g&1w1{?2rV0 diff --git a/PythonHome/Lib/encodings/hz.py b/PythonHome/Lib/encodings/hz.py new file mode 100644 index 0000000000..383442a3c9 --- /dev/null +++ b/PythonHome/Lib/encodings/hz.py @@ -0,0 +1,39 @@ +# +# hz.py: Python Unicode Codec for HZ +# +# Written by Hye-Shik Chang +# + +import _codecs_cn, codecs +import _multibytecodec as mbc + +codec = _codecs_cn.getcodec('hz') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='hz', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/hz.pyc b/PythonHome/Lib/encodings/hz.pyc deleted file mode 100644 index 9a9ae50a658516e43b9d91c8acd2bd5f58d1e078..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1649 zcmcgs&2G~`5FY=;`Kgm21gL<-fm2R>0)(mt4wayX&7s1IWD@Ttbrd_u-U_AH@Jzf6 zkHG`LH{-^MT99&z*Snsb8Sl=_e&2e(yPcocUq=buKR&+a=;bdA8m~i3qNtV~ikz+9 zrN|>gwD3v0w1KHX8XAWd0nOm%(+{Ez(U&M7-5}%9qABJU&0Nw!ZElf<0p_-tJ7R9t z<_>8X0`WKzkC0{_=}zqtl7^x3=!!>AJi^+eN4m?CsLwf#20i4L{=su)U5Gb#wt>%Z zrA<;7!-3`ky?liMi6V95(!!IxA@~&eq(%c+X~4hR7KS*^Cz*+3+mT7O(zi>VvO~h_ z+W?ZuSr!p0h}9~vkVxfoNN3|u>2xfvX+AH){4Ul(Mvw8z-c@7DTK>BDNJT^ zJ6V2|wTs7jaME=ikz2>^L9e(BN+e$Q@Nk;&eu7@|0)hK5m=BWOv4Y_Pc(xY|*J)%6 zGs%>hXmhME+SvBA4#Tm#Fs_T#9xV(;;Oku&H6Z%X4OxGV!GggcD_(HYBhX<34d~@> zW$?Q}z%LjJz=Eo_NxH>o-%xWj;AF2XgNA{x@Fm4ySB!IkL%PFeh5O>6y5c|~g(~H| zaAr8KJ;isaoa`pF5iXUMcONpXF7w$+xUt(@F*X%rLb03TdK?UFdjjvdK`?W$s#w3l zv}B+YC>J;(S|Dw}%8Kn(OmUJc(Q%#Q>~?9>>Dmep63YzBriok?SY7^5Ts(>0@^O9M z{_&X8lF@&i?ztuzTfRW*mG(IxwfL90!lqP7@s)CTskp@Ns+;aT*Sus7o;so1cVGH# K=Y_}pE!tmEO)nz= diff --git a/PythonHome/Lib/encodings/idna.py b/PythonHome/Lib/encodings/idna.py new file mode 100644 index 0000000000..ea90d67142 --- /dev/null +++ b/PythonHome/Lib/encodings/idna.py @@ -0,0 +1,288 @@ +# This module implements the RFCs 3490 (IDNA) and 3491 (Nameprep) + +import stringprep, re, codecs +from unicodedata import ucd_3_2_0 as unicodedata + +# IDNA section 3.1 +dots = re.compile(u"[\u002E\u3002\uFF0E\uFF61]") + +# IDNA section 5 +ace_prefix = "xn--" +uace_prefix = unicode(ace_prefix, "ascii") + +# This assumes query strings, so AllowUnassigned is true +def nameprep(label): + # Map + newlabel = [] + for c in label: + if stringprep.in_table_b1(c): + # Map to nothing + continue + newlabel.append(stringprep.map_table_b2(c)) + label = u"".join(newlabel) + + # Normalize + label = unicodedata.normalize("NFKC", label) + + # Prohibit + for c in label: + if stringprep.in_table_c12(c) or \ + stringprep.in_table_c22(c) or \ + stringprep.in_table_c3(c) or \ + stringprep.in_table_c4(c) or \ + stringprep.in_table_c5(c) or \ + stringprep.in_table_c6(c) or \ + stringprep.in_table_c7(c) or \ + stringprep.in_table_c8(c) or \ + stringprep.in_table_c9(c): + raise UnicodeError("Invalid character %r" % c) + + # Check bidi + RandAL = map(stringprep.in_table_d1, label) + for c in RandAL: + if c: + # There is a RandAL char in the string. Must perform further + # tests: + # 1) The characters in section 5.8 MUST be prohibited. + # This is table C.8, which was already checked + # 2) If a string contains any RandALCat character, the string + # MUST NOT contain any LCat character. + if filter(stringprep.in_table_d2, label): + raise UnicodeError("Violation of BIDI requirement 2") + + # 3) If a string contains any RandALCat character, a + # RandALCat character MUST be the first character of the + # string, and a RandALCat character MUST be the last + # character of the string. + if not RandAL[0] or not RandAL[-1]: + raise UnicodeError("Violation of BIDI requirement 3") + + return label + +def ToASCII(label): + try: + # Step 1: try ASCII + label = label.encode("ascii") + except UnicodeError: + pass + else: + # Skip to step 3: UseSTD3ASCIIRules is false, so + # Skip to step 8. + if 0 < len(label) < 64: + return label + raise UnicodeError("label empty or too long") + + # Step 2: nameprep + label = nameprep(label) + + # Step 3: UseSTD3ASCIIRules is false + # Step 4: try ASCII + try: + label = label.encode("ascii") + except UnicodeError: + pass + else: + # Skip to step 8. + if 0 < len(label) < 64: + return label + raise UnicodeError("label empty or too long") + + # Step 5: Check ACE prefix + if label.startswith(uace_prefix): + raise UnicodeError("Label starts with ACE prefix") + + # Step 6: Encode with PUNYCODE + label = label.encode("punycode") + + # Step 7: Prepend ACE prefix + label = ace_prefix + label + + # Step 8: Check size + if 0 < len(label) < 64: + return label + raise UnicodeError("label empty or too long") + +def ToUnicode(label): + # Step 1: Check for ASCII + if isinstance(label, str): + pure_ascii = True + else: + try: + label = label.encode("ascii") + pure_ascii = True + except UnicodeError: + pure_ascii = False + if not pure_ascii: + # Step 2: Perform nameprep + label = nameprep(label) + # It doesn't say this, but apparently, it should be ASCII now + try: + label = label.encode("ascii") + except UnicodeError: + raise UnicodeError("Invalid character in IDN label") + # Step 3: Check for ACE prefix + if not label.startswith(ace_prefix): + return unicode(label, "ascii") + + # Step 4: Remove ACE prefix + label1 = label[len(ace_prefix):] + + # Step 5: Decode using PUNYCODE + result = label1.decode("punycode") + + # Step 6: Apply ToASCII + label2 = ToASCII(result) + + # Step 7: Compare the result of step 6 with the one of step 3 + # label2 will already be in lower case. + if label.lower() != label2: + raise UnicodeError("IDNA does not round-trip", label, label2) + + # Step 8: return the result of step 5 + return result + +### Codec APIs + +class Codec(codecs.Codec): + def encode(self,input,errors='strict'): + + if errors != 'strict': + # IDNA is quite clear that implementations must be strict + raise UnicodeError("unsupported error handling "+errors) + + if not input: + return "", 0 + + result = [] + labels = dots.split(input) + if labels and len(labels[-1])==0: + trailing_dot = '.' + del labels[-1] + else: + trailing_dot = '' + for label in labels: + result.append(ToASCII(label)) + # Join with U+002E + return ".".join(result)+trailing_dot, len(input) + + def decode(self,input,errors='strict'): + + if errors != 'strict': + raise UnicodeError("Unsupported error handling "+errors) + + if not input: + return u"", 0 + + # IDNA allows decoding to operate on Unicode strings, too. + if isinstance(input, unicode): + labels = dots.split(input) + else: + # Must be ASCII string + input = str(input) + unicode(input, "ascii") + labels = input.split(".") + + if labels and len(labels[-1]) == 0: + trailing_dot = u'.' + del labels[-1] + else: + trailing_dot = u'' + + result = [] + for label in labels: + result.append(ToUnicode(label)) + + return u".".join(result)+trailing_dot, len(input) + +class IncrementalEncoder(codecs.BufferedIncrementalEncoder): + def _buffer_encode(self, input, errors, final): + if errors != 'strict': + # IDNA is quite clear that implementations must be strict + raise UnicodeError("unsupported error handling "+errors) + + if not input: + return ("", 0) + + labels = dots.split(input) + trailing_dot = u'' + if labels: + if not labels[-1]: + trailing_dot = '.' + del labels[-1] + elif not final: + # Keep potentially unfinished label until the next call + del labels[-1] + if labels: + trailing_dot = '.' + + result = [] + size = 0 + for label in labels: + result.append(ToASCII(label)) + if size: + size += 1 + size += len(label) + + # Join with U+002E + result = ".".join(result) + trailing_dot + size += len(trailing_dot) + return (result, size) + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + def _buffer_decode(self, input, errors, final): + if errors != 'strict': + raise UnicodeError("Unsupported error handling "+errors) + + if not input: + return (u"", 0) + + # IDNA allows decoding to operate on Unicode strings, too. + if isinstance(input, unicode): + labels = dots.split(input) + else: + # Must be ASCII string + input = str(input) + unicode(input, "ascii") + labels = input.split(".") + + trailing_dot = u'' + if labels: + if not labels[-1]: + trailing_dot = u'.' + del labels[-1] + elif not final: + # Keep potentially unfinished label until the next call + del labels[-1] + if labels: + trailing_dot = u'.' + + result = [] + size = 0 + for label in labels: + result.append(ToUnicode(label)) + if size: + size += 1 + size += len(label) + + result = u".".join(result) + trailing_dot + size += len(trailing_dot) + return (result, size) + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='idna', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/PythonHome/Lib/encodings/idna.pyc b/PythonHome/Lib/encodings/idna.pyc index 5470ccc29a833e3e17d80c1dc0d6526c04c3367d..260b5bcb7f5c94ad57bd2cbc36cc5ea4bde30db2 100644 GIT binary patch delta 847 zcmdmIILmZH4kIJa=3K@WW|I(6z(vldL z)TGk%n1ITXjQl*0{M^*Zf}&!R#aM$G**0gf{$?c4fX!X(DNN*Poh-~Xi;;EnIRz%-s+fj)?9vMSSy)UJ-+YPR0K0X2M0qEN2_<9I r#3)>XOH&0l4U=oclCX$ZVi6PHd_i0Tn-|0;+e<#dqCsqOmXrYicE@6% diff --git a/PythonHome/Lib/encodings/iso2022_jp.py b/PythonHome/Lib/encodings/iso2022_jp.py new file mode 100644 index 0000000000..ab04060693 --- /dev/null +++ b/PythonHome/Lib/encodings/iso2022_jp.py @@ -0,0 +1,39 @@ +# +# iso2022_jp.py: Python Unicode Codec for ISO2022_JP +# +# Written by Hye-Shik Chang +# + +import _codecs_iso2022, codecs +import _multibytecodec as mbc + +codec = _codecs_iso2022.getcodec('iso2022_jp') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='iso2022_jp', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/iso2022_jp.pyc b/PythonHome/Lib/encodings/iso2022_jp.pyc deleted file mode 100644 index 188d09d03391e12241009a6b4c44dba43aa23732..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1718 zcmcgs&5qMB5T5)r{n@ld2+#t81E-!=sAq&$6b>uF9^AuatHdkRb9p9S zhR5Im;G0RCRJ(BKrAh3J=NsEIco!dtCf4(TZQ_G(L+~L_sB66j*z` zO@Tu((b6St(-u&JG&B}1J(|PJr5{9FqOXBRx>)?Ahv1gNc<373S3g-0Z>CZChpL`;)xQA}!YFK#!A-Sg23K0MEATjnu@ zt1QanG|tR)^-1=~AI8H;sNxCiDh3C7WpgJIuY0^(P0V_PR`5ceec!2%678v-;)8i| z;1uU=Z1Q-Ts(7m7Q@hi~_UDy5mZ{yj$rE#OcbEw;Yj>)G=|eYS{UtgB#)I7Wz+s0B zs1FV3=@$!L!94%;=5!}b`yFD=L*BSkC=W}*?cYBsW(?#vx;j(v607wtwW@*iZe^0$#t2y=!*on%k=!rXLZ&Is zqy%F4?7r-0JiGuTy#E^Q2r1#4r-v&Y5=0X7FSsmNNtxpN=lHyF-rtqi +# + +import _codecs_iso2022, codecs +import _multibytecodec as mbc + +codec = _codecs_iso2022.getcodec('iso2022_jp_1') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='iso2022_jp_1', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/iso2022_jp_1.pyc b/PythonHome/Lib/encodings/iso2022_jp_1.pyc deleted file mode 100644 index 8264d7112dc15d131646eee41e31daff9bda4151..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1734 zcmc&!&5qMB5T5)r{n@ld2+#r&NSu0FLC*-SC>&OTJ-CMzQKitvZk4J{SBY1s=kiRv z43EJBz&DdNt#;wk!;-|#cxG(Re4fwVuXgLl)z@J{+sDWM9Ig0?PUCZEK@?T8Ly@!7 zyA*k3h~_?Nmo_lfNJHb$JfJDueELqbA^H*pq-$h6n%BkLps7nbsLT!0Fu>dtb4$#P z%G@FiLm(a};t|r+Bi*VzLeeml9&PdHh(}m?bV#>(5Oq1HVXuSy(%*P4ZOCG=>c8&y z+eY`ipaY+Eu| zuJp}`Zj=MGL}Vz3SzkmEF@C#64Ke|Q#u)mYnsi9(P6x2*K5TAavlXAVBjGCN*;lwI<>88Hx5Mv+@(;X$ul?nL5sj|r@fc@NMEUMg^JhxI`+zW=cJ zcpe>u#n=sPZpKSx#@gI}KurX2S_R}tQI-K+<*EG-0ddVf-v?9`P8YfX>(9|yupdOn z2R?gbaScENYWh1FcSDU(@nAbj95lCe(hcUvhU&u}r+sO;xR@#me^N{j#mtamN%u8e zG9|yQE?JWcWQCj|&JkyLp!g;j%5Fk5VP9c+_W={}BAc#+L;KAYSFYkZQS7D|k0S_R zPcUz05Y`Ml%-1h4ESL}kk_JwQH;}i-O3UcRWpweD<7#hM-Yjf7Sz94ZVwsrBNg{U* zwvcIxv6NISpWf%)jJsEXB=}FKEinZE`}lCBLz)OQe>0awE1)U9iH<>zv42}$n(z29 V3MTBS6S`gZso!*-c-&s${R4TDNO%AM diff --git a/PythonHome/Lib/encodings/iso2022_jp_2.py b/PythonHome/Lib/encodings/iso2022_jp_2.py new file mode 100644 index 0000000000..9106bf7625 --- /dev/null +++ b/PythonHome/Lib/encodings/iso2022_jp_2.py @@ -0,0 +1,39 @@ +# +# iso2022_jp_2.py: Python Unicode Codec for ISO2022_JP_2 +# +# Written by Hye-Shik Chang +# + +import _codecs_iso2022, codecs +import _multibytecodec as mbc + +codec = _codecs_iso2022.getcodec('iso2022_jp_2') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='iso2022_jp_2', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/iso2022_jp_2.pyc b/PythonHome/Lib/encodings/iso2022_jp_2.pyc deleted file mode 100644 index d8e1404948e5c7f65820d1af82c81bab3163e804..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1734 zcmc&!&2G~`5FY=;`Kgm21gL-n5~rLhlyikD0*6Y_!{$(7MKXzZ6FG{L%H9g)9G;1n z;W2ms_-33qQ45zGitSy`&dl!4d^_KIzuK)I*I$PTZ66>13$)@VI*rev1yNMV4n@vR z?^5KEA)5Q7UE07@BMps1^MIys^XWU$hUiNakgk#OXkHg{gQhO&pfWc|!vJ$r%q=lD zDszi841su@h(}0Mk94c@2uZ_GdbGu(BOYPp(IMUDLDc1(hP@8*OMm0JvLTDbs{gj% zkLNdW-`1cQth7lgSR82HqZKdEA!UGIT$+1=00f^RpVY7iEA@D~ZJ>+e3yc&Wg>8`cNO_~FCi z<9Tur7GpQGxfy55jJ0|AfSL&4v;u?Sk)bw{U?uHtn;=y*5IB0I`q#MkS4b_J|PW#GoaWPdC{-l^5ikTtBlJ0A` zWJ-QlU9u(@$O<__oFmTgK=Dm5l--1A!oI@t?gJ*`<#M_b4(&HrT)B$tM6sJ0awE1)U9iH<>zu|F>_&3Akl V1rzqv3Ei&y+;2M1JZ^9B{sEK-NPqwU diff --git a/PythonHome/Lib/encodings/iso2022_jp_2004.py b/PythonHome/Lib/encodings/iso2022_jp_2004.py new file mode 100644 index 0000000000..40198bf098 --- /dev/null +++ b/PythonHome/Lib/encodings/iso2022_jp_2004.py @@ -0,0 +1,39 @@ +# +# iso2022_jp_2004.py: Python Unicode Codec for ISO2022_JP_2004 +# +# Written by Hye-Shik Chang +# + +import _codecs_iso2022, codecs +import _multibytecodec as mbc + +codec = _codecs_iso2022.getcodec('iso2022_jp_2004') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='iso2022_jp_2004', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/iso2022_jp_2004.pyc b/PythonHome/Lib/encodings/iso2022_jp_2004.pyc deleted file mode 100644 index d53918cb50835e29562f13cd9ad1e8ed6ccde8dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1758 zcmc&!&2G~`5FY=;`Kgm21gL<-p{JaxDB_4vMc_~gde|H)tVkyDI+3H;sqC##&f%GO z86JZNfN#c$6QywJCAN1xJ2SgGf8RL2+pV9s-$oH_9~b{CjN%t2jnASbQBctq1=fyl zQ{Yfcv~Wq=w1KEb8XSuj9?hWU(hs5y(bvEuU8C5cMP0-Vn%ShiO57j~0mMxaw?y2i z#4XYgc%pG88a~Y&(ydCvCk;WV(H4!4X!w;zhjg14L6?0R^*Zn``Ge=ibeSwxgZ^L; zF7CoXzyH?Mz#Fb~995CA!1;htyut*p5r^2Og(E=#;Zop|8ucKh9&a}dOktQ!(l`uF zOBU%$-!FN|3K5@gJWz4Qw2)wdEKh-igeopTU5-B|)3K-~*}NDZnS6P-R&1k>QE(bP zt7)01Ag;40kJC6aljSG5D1Yb_hof>Tuq#I#@RiMzP<-wqZL4GJ6O4jS^Xy~GK8oKb zv5fQd?7%XP;K=0hBvtW5$0xC=2^-EUn=G@p={8TyX>8&We!aJ;Dk8?ukoi}b4Eh0} zj}HiU$e=NR1F*U~8r`Bs008ihiU;sbopgiYvZ4B@$DZF9E;L4t!k-kQMKMsMYLb0D zm%z!7*(Hc_iCQ6HX3q)3p%*MTT*jP9y0) zxI(rm4ySlyIDubwJ05lh@$tV(TaZc&%=5#O4)G$<`IopXU5T6G#`MVGaR%O%o%B7Y Vq+sx#TfW`3U%E}}g~Q_l?_WDbO*jAm diff --git a/PythonHome/Lib/encodings/iso2022_jp_3.py b/PythonHome/Lib/encodings/iso2022_jp_3.py new file mode 100644 index 0000000000..346e08becc --- /dev/null +++ b/PythonHome/Lib/encodings/iso2022_jp_3.py @@ -0,0 +1,39 @@ +# +# iso2022_jp_3.py: Python Unicode Codec for ISO2022_JP_3 +# +# Written by Hye-Shik Chang +# + +import _codecs_iso2022, codecs +import _multibytecodec as mbc + +codec = _codecs_iso2022.getcodec('iso2022_jp_3') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='iso2022_jp_3', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/iso2022_jp_3.pyc b/PythonHome/Lib/encodings/iso2022_jp_3.pyc deleted file mode 100644 index e4f7313a94fa5065a9d4531db918c8643277d260..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1734 zcmc&!&5qMB5T5)r{n@ld2+#r&NSu0Fp>joNMd7d#?7=;(h$@9PcB@ovx=Or4J(p+V zWq1r80KS>DX|)TN9+o6_#xrAk=JR~^ezjXauD%Wv+CD!1=V--GbQ+&S3!y{1R(en`J{$DSgFU;Z3A5#XXB-bW80F! za;0w;JYHyIv~}knIPFWz#l=)n_>*FKC}xHfOS-S& zk}3IZb;+7sAS>hyagI2{1I0JNP<9id3Hu7myAPO%7uj?r9NKTLxN;TOiDEa!cpO0h zdxCj0gRo}cVZMHWVZnqTkTh^Yyn(zuR$4|kE~AUL99Mh8@@8Sv$=V8O63fI~P7=9m zu!T%hjHRSv`Sd>TX576BB*A|=ZHXxW*vE$}9nwUg`J1^cS^-V*O>_)$jQ!j4(tO8< VQ7~aoozU&NPyMFz#N+k~?;oyyNQeLc diff --git a/PythonHome/Lib/encodings/iso2022_jp_ext.py b/PythonHome/Lib/encodings/iso2022_jp_ext.py new file mode 100644 index 0000000000..752bab9813 --- /dev/null +++ b/PythonHome/Lib/encodings/iso2022_jp_ext.py @@ -0,0 +1,39 @@ +# +# iso2022_jp_ext.py: Python Unicode Codec for ISO2022_JP_EXT +# +# Written by Hye-Shik Chang +# + +import _codecs_iso2022, codecs +import _multibytecodec as mbc + +codec = _codecs_iso2022.getcodec('iso2022_jp_ext') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='iso2022_jp_ext', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/iso2022_jp_ext.pyc b/PythonHome/Lib/encodings/iso2022_jp_ext.pyc deleted file mode 100644 index f5db188579074a57110548f332910eed2de94809..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1750 zcmc&!&5qMB5T5)r{n>Pj5TFGlBslf7LOmn2qHtIV_TU~?M3q7tyH%>DT_s*Y&*hnT z86JZNfNv&kT6W>mOOx0c&y4Mv&-2;))o%T`{xV2t^Z58*pcOySX?zaNiK0q&C~~%X zmm-f0(ab09(i)~3X=ogp1vG)1Pv42wM4zL8bd8Khv$~iYG;v7>mAOG02AG>-Zi%^3 znOme`2*l$=JVKgyq+69oNE(LHqb(k%;t^IJr=;6Fh&r6ppnHn^(%*Qltcb<3_qx}M zXE(9=W^E1D{!*Ky0>**n9a`}W9g+qN#-*7j7(nnT@<|Q4uu_+&+XlKgUW_sm$F?Pd zY^iVOJYP9&Qp7okhprE??S2yr~_S}^%v+YZUT@V zAGqz2#gzaJXzFie+!HlI?SuI!c2M5dNjI1&YpM^rocNXHB4g4h{7ErU6mvvMCf(I? z$(j7Fy5vtTpcQhCI7^)4p5m*ZD7y*egolOY-TO?*%f)0VT-t4}xPBGaiefj#cpO9o zdxDu$gTSU>WWIWVVZp>8&^2&Eyn(!3R$9h4F5` +# + +import _codecs_iso2022, codecs +import _multibytecodec as mbc + +codec = _codecs_iso2022.getcodec('iso2022_kr') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='iso2022_kr', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/iso2022_kr.pyc b/PythonHome/Lib/encodings/iso2022_kr.pyc deleted file mode 100644 index 07f1ff3697c7c2bb790a2d0f291c63ebd8fcfcc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1718 zcmcgs&5qMB5T5)r{n@ld2+#t81E-!=sAq&$6b>uF9^AuM(@d}DiNJfEH4-OkUOFXM=IkBk2$TJZ~=#%IxrD5zwM0&B0g zDR3wzTDqid+5&2jhQ^|$M{}6D^n++i^f~ZIHz;;!*%Y`%bDOkR!7b7N0JjD12;8dR z4ru_MSe%K4PjiQKr?T)#11K%JV$l-|zq06&?(!h$b4=qw5Ah{`@LZb?i^Y2QdN>Tf z=B9z+XszR@N{R)|JG9~%Is}Xq#5OG*i64SXflF#U07?U%Zd&NVFq@`v7|Qx#n6CBh ziid0v@%qMt6lW}p2o=O~6(A&1@dDDtmKh`6SE$m6}*sV-*xJ}M0;wd_+TC# zIK_Dzn>?PTDxT{2)b6yg{dwh%WombB^2D6n9cIGw+MTLk`p}J7e~He3@gO%oaM&RO z>O%uMx_cS-L4#1|U^ogJ)HY4hEoQ}*n&SZneQmg?m>>#&QcMcPe2_9p>e?;&k>6F9 zT*)P2g`6MG5a)NG_%0cg-GpAkxx(=7Bc|U~HeU;O>dh6`tl}C`Y^FFLM;E?1!>mON zrxsvezIlmZ!9*ZX)3bcMp1cEA8qRH4`WEhZt!f~>U72LIF+!HeFdfrbB=-xpkZFoD zDS;S1yHEQW_b&hm@4rSnLQ44N@!?8`1d+u23oZ**Ql|L+IX-Wk_c!G=`IZl&V4|K| QzTLN NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\xa1' # 0xA1 -> INVERTED EXCLAMATION MARK + u'\xa2' # 0xA2 -> CENT SIGN + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa4' # 0xA4 -> CURRENCY SIGN + u'\xa5' # 0xA5 -> YEN SIGN + u'\xa6' # 0xA6 -> BROKEN BAR + u'\xa7' # 0xA7 -> SECTION SIGN + u'\xa8' # 0xA8 -> DIAERESIS + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\xaa' # 0xAA -> FEMININE ORDINAL INDICATOR + u'\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xac' # 0xAC -> NOT SIGN + u'\xad' # 0xAD -> SOFT HYPHEN + u'\xae' # 0xAE -> REGISTERED SIGN + u'\xaf' # 0xAF -> MACRON + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\xb2' # 0xB2 -> SUPERSCRIPT TWO + u'\xb3' # 0xB3 -> SUPERSCRIPT THREE + u'\xb4' # 0xB4 -> ACUTE ACCENT + u'\xb5' # 0xB5 -> MICRO SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\xb8' # 0xB8 -> CEDILLA + u'\xb9' # 0xB9 -> SUPERSCRIPT ONE + u'\xba' # 0xBA -> MASCULINE ORDINAL INDICATOR + u'\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + u'\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + u'\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + u'\xbf' # 0xBF -> INVERTED QUESTION MARK + u'\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + u'\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + u'\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + u'\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\xd0' # 0xD0 -> LATIN CAPITAL LETTER ETH (Icelandic) + u'\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + u'\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xd7' # 0xD7 -> MULTIPLICATION SIGN + u'\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + u'\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xdd' # 0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE + u'\xde' # 0xDE -> LATIN CAPITAL LETTER THORN (Icelandic) + u'\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S (German) + u'\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + u'\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe6' # 0xE6 -> LATIN SMALL LETTER AE + u'\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + u'\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + u'\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + u'\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xf0' # 0xF0 -> LATIN SMALL LETTER ETH (Icelandic) + u'\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + u'\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + u'\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + u'\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf7' # 0xF7 -> DIVISION SIGN + u'\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + u'\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + u'\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + u'\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xfd' # 0xFD -> LATIN SMALL LETTER Y WITH ACUTE + u'\xfe' # 0xFE -> LATIN SMALL LETTER THORN (Icelandic) + u'\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/iso8859_1.pyc b/PythonHome/Lib/encodings/iso8859_1.pyc deleted file mode 100644 index d3f1dba1a3574dd6a914c08649cff927fe37a7f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2733 zcmc&$`Bxl85bix$Hjq2fji?(h)&meVnrMs!a)<_kvnUCon_*`b2KT_3!H7mpvgE$+ z`@ZiRa_7COKgmBJR`tM65`7PoA9SIM>aOkTs;|GU!uMxsxW8plJShf0KKffj!x|u= z3DHW@BQ&o_dqgWKKB0R=msg}n_lrIu@m0Z6yU;P-vw*X)O}kNYNUS4#-nTvrgWBC~WILjDIZaPS4J$Ww>Xd1T>S%|a)lJpbwP?!BWuoN`Gn<;~ z8|TKW>f`hID^)Bisw~vBy1tNJYos`dWG#3c^{?h zq4h?0yNt}TN78DNa?hyU2`5~+BvnEoVXN(F-Py$_Sb91oQ!ujKJ+_QPH_e=B#mFe6 zu*yiQY@27aw+(r*+6pid7S1jS%?NhM`3ujpB%<)v$5J4)330h3)yGp%7<`4nQ;JAD zZOo2yMr<(V7(-%*NF)+jHKQjIc34g_Ijtv6Q-y5`XX&0LwP8V0XpbnSVeuJ3Z;8(y zOGPS4s zZW|2}LS`!=SD0`TLWQG~^l-72{74yDHSH!ne7=knXZR?zN(rA+N<#XaqoyrgLh3sH zmuT{(jT!PD^gM~>EJ>UH2TQ(W2TSJ86Id!-sN8IahmpB9k;Xs6sEj7lv+AbwDqExr$tCwr-L#}Od~QsS2o0IrV<9NIs{JP+ zaB=1OHW)%7X}+d9UaukHye6k9Qaj`VOwWoQlz&L4-WFg^YeBB%)BtU2Rv|7Wc~KOP zF(n#pep*~rES?S)(28oeq(~AQZb5L$xB29`yWjC@S~~IKK^9-r!zjQnOR#mYxbPEpVxo!<-CT*`AuIb@#e3;X<4wa_1m`Z zzE3Pt+mo7}>gY7Oen@Asx$YlL%kKGU@z1@#{JP|~-~WK6und+%9{OMftb|pt8rHyC zSO@E218js%uo0NjLIa2xKxUAPDL;Q=niWw;#k*oP}{C9cBNxCYna zI$Vz%a3gNQ&A0`(;x^olJ8&oN!rizB_u@X>j|cD|9>T+T1drk|JdP*uB%Z?4cm~hn zIXsUS@FHHq%XkH^;x)XEH?SWE@Fw2E+js}>;yt{N4`O^<#87T?S}sX#jhli)3zrPc z1BVgZQ4}s_Hka<9|1R2ljI`$T3tD}IGQ&Q6*3jbeQOK{f! diff --git a/PythonHome/Lib/encodings/iso8859_10.py b/PythonHome/Lib/encodings/iso8859_10.py new file mode 100644 index 0000000000..757e5c5eb9 --- /dev/null +++ b/PythonHome/Lib/encodings/iso8859_10.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_10 generated from 'MAPPINGS/ISO8859/8859-10.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-10', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\u0104' # 0xA1 -> LATIN CAPITAL LETTER A WITH OGONEK + u'\u0112' # 0xA2 -> LATIN CAPITAL LETTER E WITH MACRON + u'\u0122' # 0xA3 -> LATIN CAPITAL LETTER G WITH CEDILLA + u'\u012a' # 0xA4 -> LATIN CAPITAL LETTER I WITH MACRON + u'\u0128' # 0xA5 -> LATIN CAPITAL LETTER I WITH TILDE + u'\u0136' # 0xA6 -> LATIN CAPITAL LETTER K WITH CEDILLA + u'\xa7' # 0xA7 -> SECTION SIGN + u'\u013b' # 0xA8 -> LATIN CAPITAL LETTER L WITH CEDILLA + u'\u0110' # 0xA9 -> LATIN CAPITAL LETTER D WITH STROKE + u'\u0160' # 0xAA -> LATIN CAPITAL LETTER S WITH CARON + u'\u0166' # 0xAB -> LATIN CAPITAL LETTER T WITH STROKE + u'\u017d' # 0xAC -> LATIN CAPITAL LETTER Z WITH CARON + u'\xad' # 0xAD -> SOFT HYPHEN + u'\u016a' # 0xAE -> LATIN CAPITAL LETTER U WITH MACRON + u'\u014a' # 0xAF -> LATIN CAPITAL LETTER ENG + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\u0105' # 0xB1 -> LATIN SMALL LETTER A WITH OGONEK + u'\u0113' # 0xB2 -> LATIN SMALL LETTER E WITH MACRON + u'\u0123' # 0xB3 -> LATIN SMALL LETTER G WITH CEDILLA + u'\u012b' # 0xB4 -> LATIN SMALL LETTER I WITH MACRON + u'\u0129' # 0xB5 -> LATIN SMALL LETTER I WITH TILDE + u'\u0137' # 0xB6 -> LATIN SMALL LETTER K WITH CEDILLA + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\u013c' # 0xB8 -> LATIN SMALL LETTER L WITH CEDILLA + u'\u0111' # 0xB9 -> LATIN SMALL LETTER D WITH STROKE + u'\u0161' # 0xBA -> LATIN SMALL LETTER S WITH CARON + u'\u0167' # 0xBB -> LATIN SMALL LETTER T WITH STROKE + u'\u017e' # 0xBC -> LATIN SMALL LETTER Z WITH CARON + u'\u2015' # 0xBD -> HORIZONTAL BAR + u'\u016b' # 0xBE -> LATIN SMALL LETTER U WITH MACRON + u'\u014b' # 0xBF -> LATIN SMALL LETTER ENG + u'\u0100' # 0xC0 -> LATIN CAPITAL LETTER A WITH MACRON + u'\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + u'\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + u'\u012e' # 0xC7 -> LATIN CAPITAL LETTER I WITH OGONEK + u'\u010c' # 0xC8 -> LATIN CAPITAL LETTER C WITH CARON + u'\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\u0118' # 0xCA -> LATIN CAPITAL LETTER E WITH OGONEK + u'\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\u0116' # 0xCC -> LATIN CAPITAL LETTER E WITH DOT ABOVE + u'\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\xd0' # 0xD0 -> LATIN CAPITAL LETTER ETH (Icelandic) + u'\u0145' # 0xD1 -> LATIN CAPITAL LETTER N WITH CEDILLA + u'\u014c' # 0xD2 -> LATIN CAPITAL LETTER O WITH MACRON + u'\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + u'\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\u0168' # 0xD7 -> LATIN CAPITAL LETTER U WITH TILDE + u'\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + u'\u0172' # 0xD9 -> LATIN CAPITAL LETTER U WITH OGONEK + u'\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xdd' # 0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE + u'\xde' # 0xDE -> LATIN CAPITAL LETTER THORN (Icelandic) + u'\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S (German) + u'\u0101' # 0xE0 -> LATIN SMALL LETTER A WITH MACRON + u'\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + u'\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe6' # 0xE6 -> LATIN SMALL LETTER AE + u'\u012f' # 0xE7 -> LATIN SMALL LETTER I WITH OGONEK + u'\u010d' # 0xE8 -> LATIN SMALL LETTER C WITH CARON + u'\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + u'\u0119' # 0xEA -> LATIN SMALL LETTER E WITH OGONEK + u'\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + u'\u0117' # 0xEC -> LATIN SMALL LETTER E WITH DOT ABOVE + u'\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xf0' # 0xF0 -> LATIN SMALL LETTER ETH (Icelandic) + u'\u0146' # 0xF1 -> LATIN SMALL LETTER N WITH CEDILLA + u'\u014d' # 0xF2 -> LATIN SMALL LETTER O WITH MACRON + u'\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + u'\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\u0169' # 0xF7 -> LATIN SMALL LETTER U WITH TILDE + u'\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + u'\u0173' # 0xF9 -> LATIN SMALL LETTER U WITH OGONEK + u'\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + u'\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xfd' # 0xFD -> LATIN SMALL LETTER Y WITH ACUTE + u'\xfe' # 0xFE -> LATIN SMALL LETTER THORN (Icelandic) + u'\u0138' # 0xFF -> LATIN SMALL LETTER KRA +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/iso8859_10.pyc b/PythonHome/Lib/encodings/iso8859_10.pyc deleted file mode 100644 index c03466e447f8aff8a68f82036e31635059ccc779..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2748 zcmc&$c~=}o5br%%mMgasiEg}Dj{s4liN=^f4$-i|S(Ic&H^a^>4DNw5gNR0j0MUey zi$KVIX%fQA@r**AIsWMG`67M=KR~SNft>_>FC>5HF5UE0O;=a_>ep54`Ku^6(YQUD zAX6U?{9g;hn1o3oBnGpKC~lH+kr*sIM0JriH%Y?UOZo`uC1hL7O%$I{c!a{AQ+SAy zClp?x2;>xAqU00REp$GT1OvgG&PSAjX`Nr_3UfL?QHt;(mPeFg5(@|eU@1U)!NDMU z8V#3V04bP4^<8FbHWR98m328`s(PqSZg1BzEuosMq9#I`kzKiR#j5!7s!)rXQFYl= zl~7X8rbFd*>+0)kBb%a?wb3p3P9;vumRD6YY;7nHb!uiSZb_h-iuSIGU{JdUpNQ#$ zV}*Ys@aHC`oAi1hXcx#M&UWFMVHSfl0nw-B_PFh?5Q!z=5I5!Klxpw76AU$#6d`Dt z_6}3{q3U{8H^QJKVltM%s-kJL*4#90#b|PX1TgGv0-FM~i2xAS<3u9i)(2t$xB+q@ z63Yi;kPv+d(UbCEdSs_<>xkKu(_sX~48RnRXXLaRkDEd9kj^R{DR`7nCt;Y*VPf@g zm?YRl@?jWwh~Hi4G3UXeHj~iRw3;#H)CPf}o&c%%KmF>iCH&HG(5(OfU6^Z%fUX|~Zs`piI6!g}R|I}0F@Z;N33 zJCM>GP(3Cm5x<4gmH|V|PSn&@Io+shP(X8BM5a~aiE%~mT~<+9wfwc$-&pbHTPs(+{m$xl*SxoOU3Ja+4I4MTU;Dv_o9iN5>OYdA z4Ih8fxOH3X)27cpk8hWo6N;K_Y1P`kNToB`_AhnA?D(ql>#lFU-SOS`KhSR4LwC|% z+DH58F8U+=iSDL*=m6bI2kAb#pB|tG=^;8q57S{fLXXfxhgf+%)S~u7q z>=wJt?y$T3W*E~2B*liOWE0TfushhqaOi+cusMOPMMB=1Si+}&X*73eDaCFaAia+? m55N7Q*{-(R>lzPiHn7=2cl4G9O1-7tGEbQ=zr=r!c>f0cM{=kD diff --git a/PythonHome/Lib/encodings/iso8859_11.py b/PythonHome/Lib/encodings/iso8859_11.py new file mode 100644 index 0000000000..27ece8dc7b --- /dev/null +++ b/PythonHome/Lib/encodings/iso8859_11.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_11 generated from 'MAPPINGS/ISO8859/8859-11.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-11', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\u0e01' # 0xA1 -> THAI CHARACTER KO KAI + u'\u0e02' # 0xA2 -> THAI CHARACTER KHO KHAI + u'\u0e03' # 0xA3 -> THAI CHARACTER KHO KHUAT + u'\u0e04' # 0xA4 -> THAI CHARACTER KHO KHWAI + u'\u0e05' # 0xA5 -> THAI CHARACTER KHO KHON + u'\u0e06' # 0xA6 -> THAI CHARACTER KHO RAKHANG + u'\u0e07' # 0xA7 -> THAI CHARACTER NGO NGU + u'\u0e08' # 0xA8 -> THAI CHARACTER CHO CHAN + u'\u0e09' # 0xA9 -> THAI CHARACTER CHO CHING + u'\u0e0a' # 0xAA -> THAI CHARACTER CHO CHANG + u'\u0e0b' # 0xAB -> THAI CHARACTER SO SO + u'\u0e0c' # 0xAC -> THAI CHARACTER CHO CHOE + u'\u0e0d' # 0xAD -> THAI CHARACTER YO YING + u'\u0e0e' # 0xAE -> THAI CHARACTER DO CHADA + u'\u0e0f' # 0xAF -> THAI CHARACTER TO PATAK + u'\u0e10' # 0xB0 -> THAI CHARACTER THO THAN + u'\u0e11' # 0xB1 -> THAI CHARACTER THO NANGMONTHO + u'\u0e12' # 0xB2 -> THAI CHARACTER THO PHUTHAO + u'\u0e13' # 0xB3 -> THAI CHARACTER NO NEN + u'\u0e14' # 0xB4 -> THAI CHARACTER DO DEK + u'\u0e15' # 0xB5 -> THAI CHARACTER TO TAO + u'\u0e16' # 0xB6 -> THAI CHARACTER THO THUNG + u'\u0e17' # 0xB7 -> THAI CHARACTER THO THAHAN + u'\u0e18' # 0xB8 -> THAI CHARACTER THO THONG + u'\u0e19' # 0xB9 -> THAI CHARACTER NO NU + u'\u0e1a' # 0xBA -> THAI CHARACTER BO BAIMAI + u'\u0e1b' # 0xBB -> THAI CHARACTER PO PLA + u'\u0e1c' # 0xBC -> THAI CHARACTER PHO PHUNG + u'\u0e1d' # 0xBD -> THAI CHARACTER FO FA + u'\u0e1e' # 0xBE -> THAI CHARACTER PHO PHAN + u'\u0e1f' # 0xBF -> THAI CHARACTER FO FAN + u'\u0e20' # 0xC0 -> THAI CHARACTER PHO SAMPHAO + u'\u0e21' # 0xC1 -> THAI CHARACTER MO MA + u'\u0e22' # 0xC2 -> THAI CHARACTER YO YAK + u'\u0e23' # 0xC3 -> THAI CHARACTER RO RUA + u'\u0e24' # 0xC4 -> THAI CHARACTER RU + u'\u0e25' # 0xC5 -> THAI CHARACTER LO LING + u'\u0e26' # 0xC6 -> THAI CHARACTER LU + u'\u0e27' # 0xC7 -> THAI CHARACTER WO WAEN + u'\u0e28' # 0xC8 -> THAI CHARACTER SO SALA + u'\u0e29' # 0xC9 -> THAI CHARACTER SO RUSI + u'\u0e2a' # 0xCA -> THAI CHARACTER SO SUA + u'\u0e2b' # 0xCB -> THAI CHARACTER HO HIP + u'\u0e2c' # 0xCC -> THAI CHARACTER LO CHULA + u'\u0e2d' # 0xCD -> THAI CHARACTER O ANG + u'\u0e2e' # 0xCE -> THAI CHARACTER HO NOKHUK + u'\u0e2f' # 0xCF -> THAI CHARACTER PAIYANNOI + u'\u0e30' # 0xD0 -> THAI CHARACTER SARA A + u'\u0e31' # 0xD1 -> THAI CHARACTER MAI HAN-AKAT + u'\u0e32' # 0xD2 -> THAI CHARACTER SARA AA + u'\u0e33' # 0xD3 -> THAI CHARACTER SARA AM + u'\u0e34' # 0xD4 -> THAI CHARACTER SARA I + u'\u0e35' # 0xD5 -> THAI CHARACTER SARA II + u'\u0e36' # 0xD6 -> THAI CHARACTER SARA UE + u'\u0e37' # 0xD7 -> THAI CHARACTER SARA UEE + u'\u0e38' # 0xD8 -> THAI CHARACTER SARA U + u'\u0e39' # 0xD9 -> THAI CHARACTER SARA UU + u'\u0e3a' # 0xDA -> THAI CHARACTER PHINTHU + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\u0e3f' # 0xDF -> THAI CURRENCY SYMBOL BAHT + u'\u0e40' # 0xE0 -> THAI CHARACTER SARA E + u'\u0e41' # 0xE1 -> THAI CHARACTER SARA AE + u'\u0e42' # 0xE2 -> THAI CHARACTER SARA O + u'\u0e43' # 0xE3 -> THAI CHARACTER SARA AI MAIMUAN + u'\u0e44' # 0xE4 -> THAI CHARACTER SARA AI MAIMALAI + u'\u0e45' # 0xE5 -> THAI CHARACTER LAKKHANGYAO + u'\u0e46' # 0xE6 -> THAI CHARACTER MAIYAMOK + u'\u0e47' # 0xE7 -> THAI CHARACTER MAITAIKHU + u'\u0e48' # 0xE8 -> THAI CHARACTER MAI EK + u'\u0e49' # 0xE9 -> THAI CHARACTER MAI THO + u'\u0e4a' # 0xEA -> THAI CHARACTER MAI TRI + u'\u0e4b' # 0xEB -> THAI CHARACTER MAI CHATTAWA + u'\u0e4c' # 0xEC -> THAI CHARACTER THANTHAKHAT + u'\u0e4d' # 0xED -> THAI CHARACTER NIKHAHIT + u'\u0e4e' # 0xEE -> THAI CHARACTER YAMAKKAN + u'\u0e4f' # 0xEF -> THAI CHARACTER FONGMAN + u'\u0e50' # 0xF0 -> THAI DIGIT ZERO + u'\u0e51' # 0xF1 -> THAI DIGIT ONE + u'\u0e52' # 0xF2 -> THAI DIGIT TWO + u'\u0e53' # 0xF3 -> THAI DIGIT THREE + u'\u0e54' # 0xF4 -> THAI DIGIT FOUR + u'\u0e55' # 0xF5 -> THAI DIGIT FIVE + u'\u0e56' # 0xF6 -> THAI DIGIT SIX + u'\u0e57' # 0xF7 -> THAI DIGIT SEVEN + u'\u0e58' # 0xF8 -> THAI DIGIT EIGHT + u'\u0e59' # 0xF9 -> THAI DIGIT NINE + u'\u0e5a' # 0xFA -> THAI CHARACTER ANGKHANKHU + u'\u0e5b' # 0xFB -> THAI CHARACTER KHOMUT + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/iso8859_11.pyc b/PythonHome/Lib/encodings/iso8859_11.pyc deleted file mode 100644 index 4f91741fd24c11b6133e47f5230d0cafb58598c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2842 zcmc&$X?qk!5biy*SrWpn!Jvy5>p?Io3W^AX!zhF}ivlsaOm=3I!9C*aM2w;W8}9qQ z!TY`ssP=|DyJl;_NuJvZCdmg=)hwrhH}mCC#2 zVrs^UgwPw|f)CR}v=OsCI(>gHJnoK&E>C@@OXj|>P z25Fcyi#VbbO*Vy2&}meMDPl^Tz?c6yc|FCh|*|h^+cLHA=Zb) zM*4+?7Z%kBB^@GtXRusHR`JG?Hb>bP&4H{Ru2yN0aL9UQZ^8Cg@eUQckk=_VrGY_D z$6>o}*{!6>DD+gBMpA3fa;LXv#7m_o0FuD)muYOquuld+gl;7hgO^^D1Hny@Yn2wS z&B0*w4MxwXqv@uD_PsM^SAtG6C|-i5Y_?<;?QGUd>W5<48Z6MG!8U`_3^vo!jbSoq zk*KFp;Z5Sg- zcZf9+W({5K=1iL1b~-c(ovsGmV9sd}4USGTBtTbFB=3~WLXh<+5@xJ8#jC+J8hE2d znzYlUW}#whPy^4S#gor%{D}K_=z264YwG+zX!0@pXfl1SL(|}T6{I@~AenDdX#6{n z#yB$FA}1NY$s?W#Lq461=h|j*wd+s;t#Of=wuoQkL-n~x)r(}I`4k*$keHT6ksVW{ znTF2pnive*wEmkIxXQK!G1SuLqiSdU0-F3g<@ZPGj9iK7a?!Plj>y#JVoYo+&PAPi zp+|iy!4;({>N07jMW@FXjEhT!xpAeEQl|+@i)OMD)CIqgyVtAz>gDP)qwYaxMuYIW zO0hv7qTbi9tsH@FR~@B%Sy!ZBTZ1o@!Hh5%4uj9-rccvjuJ+j!4z)|q9hy#$6(*<% z)raDt2KvVJckmCUR45#Y#^QB}`sA2~#<5M~#!r|yY4ViYZf~A?N6WN3?@CR-`<{F6 zyMIRdfd?OYcxLOYN7^2J?D5%8JUM6XQ%}!(X8yAa7A|UEykzOJ=Q^H$Vfl*Am0d3y znN=^nyn4;r?pJzVeJ#7r?9EwrzOUa||9YWVDi6HjR=mMCH@r3U_B$KjeeZp>No`hJ zR8XbUI&Zx8MoI0;Q zK-i411)+*CjIb498^U&k9SA!Sb|LIW*n_YaVIRVNgaZf%5e^|7MmU0S6yX@cafA~H zClO8|oJKftthvl+>UYw%AF{8 zq1=sf56ZnL_o3X6@&L+%C=a1LjPeM|qbQG|JdW}N%9AKhp*&slPePi>Kv#g NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\u201d' # 0xA1 -> RIGHT DOUBLE QUOTATION MARK + u'\xa2' # 0xA2 -> CENT SIGN + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa4' # 0xA4 -> CURRENCY SIGN + u'\u201e' # 0xA5 -> DOUBLE LOW-9 QUOTATION MARK + u'\xa6' # 0xA6 -> BROKEN BAR + u'\xa7' # 0xA7 -> SECTION SIGN + u'\xd8' # 0xA8 -> LATIN CAPITAL LETTER O WITH STROKE + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\u0156' # 0xAA -> LATIN CAPITAL LETTER R WITH CEDILLA + u'\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xac' # 0xAC -> NOT SIGN + u'\xad' # 0xAD -> SOFT HYPHEN + u'\xae' # 0xAE -> REGISTERED SIGN + u'\xc6' # 0xAF -> LATIN CAPITAL LETTER AE + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\xb2' # 0xB2 -> SUPERSCRIPT TWO + u'\xb3' # 0xB3 -> SUPERSCRIPT THREE + u'\u201c' # 0xB4 -> LEFT DOUBLE QUOTATION MARK + u'\xb5' # 0xB5 -> MICRO SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\xf8' # 0xB8 -> LATIN SMALL LETTER O WITH STROKE + u'\xb9' # 0xB9 -> SUPERSCRIPT ONE + u'\u0157' # 0xBA -> LATIN SMALL LETTER R WITH CEDILLA + u'\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + u'\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + u'\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + u'\xe6' # 0xBF -> LATIN SMALL LETTER AE + u'\u0104' # 0xC0 -> LATIN CAPITAL LETTER A WITH OGONEK + u'\u012e' # 0xC1 -> LATIN CAPITAL LETTER I WITH OGONEK + u'\u0100' # 0xC2 -> LATIN CAPITAL LETTER A WITH MACRON + u'\u0106' # 0xC3 -> LATIN CAPITAL LETTER C WITH ACUTE + u'\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\u0118' # 0xC6 -> LATIN CAPITAL LETTER E WITH OGONEK + u'\u0112' # 0xC7 -> LATIN CAPITAL LETTER E WITH MACRON + u'\u010c' # 0xC8 -> LATIN CAPITAL LETTER C WITH CARON + u'\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\u0179' # 0xCA -> LATIN CAPITAL LETTER Z WITH ACUTE + u'\u0116' # 0xCB -> LATIN CAPITAL LETTER E WITH DOT ABOVE + u'\u0122' # 0xCC -> LATIN CAPITAL LETTER G WITH CEDILLA + u'\u0136' # 0xCD -> LATIN CAPITAL LETTER K WITH CEDILLA + u'\u012a' # 0xCE -> LATIN CAPITAL LETTER I WITH MACRON + u'\u013b' # 0xCF -> LATIN CAPITAL LETTER L WITH CEDILLA + u'\u0160' # 0xD0 -> LATIN CAPITAL LETTER S WITH CARON + u'\u0143' # 0xD1 -> LATIN CAPITAL LETTER N WITH ACUTE + u'\u0145' # 0xD2 -> LATIN CAPITAL LETTER N WITH CEDILLA + u'\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\u014c' # 0xD4 -> LATIN CAPITAL LETTER O WITH MACRON + u'\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + u'\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xd7' # 0xD7 -> MULTIPLICATION SIGN + u'\u0172' # 0xD8 -> LATIN CAPITAL LETTER U WITH OGONEK + u'\u0141' # 0xD9 -> LATIN CAPITAL LETTER L WITH STROKE + u'\u015a' # 0xDA -> LATIN CAPITAL LETTER S WITH ACUTE + u'\u016a' # 0xDB -> LATIN CAPITAL LETTER U WITH MACRON + u'\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\u017b' # 0xDD -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + u'\u017d' # 0xDE -> LATIN CAPITAL LETTER Z WITH CARON + u'\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S (German) + u'\u0105' # 0xE0 -> LATIN SMALL LETTER A WITH OGONEK + u'\u012f' # 0xE1 -> LATIN SMALL LETTER I WITH OGONEK + u'\u0101' # 0xE2 -> LATIN SMALL LETTER A WITH MACRON + u'\u0107' # 0xE3 -> LATIN SMALL LETTER C WITH ACUTE + u'\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\u0119' # 0xE6 -> LATIN SMALL LETTER E WITH OGONEK + u'\u0113' # 0xE7 -> LATIN SMALL LETTER E WITH MACRON + u'\u010d' # 0xE8 -> LATIN SMALL LETTER C WITH CARON + u'\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + u'\u017a' # 0xEA -> LATIN SMALL LETTER Z WITH ACUTE + u'\u0117' # 0xEB -> LATIN SMALL LETTER E WITH DOT ABOVE + u'\u0123' # 0xEC -> LATIN SMALL LETTER G WITH CEDILLA + u'\u0137' # 0xED -> LATIN SMALL LETTER K WITH CEDILLA + u'\u012b' # 0xEE -> LATIN SMALL LETTER I WITH MACRON + u'\u013c' # 0xEF -> LATIN SMALL LETTER L WITH CEDILLA + u'\u0161' # 0xF0 -> LATIN SMALL LETTER S WITH CARON + u'\u0144' # 0xF1 -> LATIN SMALL LETTER N WITH ACUTE + u'\u0146' # 0xF2 -> LATIN SMALL LETTER N WITH CEDILLA + u'\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + u'\u014d' # 0xF4 -> LATIN SMALL LETTER O WITH MACRON + u'\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + u'\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf7' # 0xF7 -> DIVISION SIGN + u'\u0173' # 0xF8 -> LATIN SMALL LETTER U WITH OGONEK + u'\u0142' # 0xF9 -> LATIN SMALL LETTER L WITH STROKE + u'\u015b' # 0xFA -> LATIN SMALL LETTER S WITH ACUTE + u'\u016b' # 0xFB -> LATIN SMALL LETTER U WITH MACRON + u'\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\u017c' # 0xFD -> LATIN SMALL LETTER Z WITH DOT ABOVE + u'\u017e' # 0xFE -> LATIN SMALL LETTER Z WITH CARON + u'\u2019' # 0xFF -> RIGHT SINGLE QUOTATION MARK +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/iso8859_13.pyc b/PythonHome/Lib/encodings/iso8859_13.pyc deleted file mode 100644 index 64ecc406b8b42e1185daf8bfaeec48d7e71e3ca6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2751 zcmc&$`(G4Q6u?Sp29jIsn5FiU%A z^6;ISeblm&kC1`>aAxKo;a}(vuygLf4p^U$=nu8az1%rx?z!iD&-b3Qp1(?iquY1I zl5FbZ!TTKtpX?ht-lNfzQ>`2(|auHu54hdasP0RK!Izf}uDIS87 z?da6GAF`_ER4sx^#wTq#uBuwLD6K8iR*(FTPMt>oQ@DEdH|EWjoG9sXXLCdrZ;j7)g(&!r@*Ae_-Hc;uaLwX_7DmF3G_0Q zI+Q`~AZt9t8ob(}ScJ?*6`U9kmxC@4=QxN0dB+*zpvx(eQnF&&iFytJ6IK-BOmKw~ zI;a#UZgi8F)?^Nh7qv}36N%$?9wu~53c4E3Ji<#}Jf(5j|MPk}|dXbW9a}lc-t{LZ(lU64%zM4aH zM3E2<9^EV-1X+~+8y~33RyaNs!lqO;kh~rz`%c;Y5j!JQV!T{jAq7gTyDk*jvr?hY;D^6Xo3%Poy*sfkG&lz?P%oz^E zYldJCPa;3puC3$&Z&!`kRE}39=U9O*lt7FS2o8bra?jb+iK}fgx`XXfSG!i=qecW} zu40$pRf1nX|8`;vM4{W`_4$he#ld+crDf&w7c5+~c*)WS9tgi{mU0GHAT+Q>fFRXg;rMlHGzq01lwXfB$Ti>u@YUY z=C|M3zGG+n-In*>PwWy~laicjYgcxEkj`Xt9UrQi-ucmDY7jOz97YfsY+6uv5s11vRq^Q`8?Bv6TC#fw pN@wuq?gfDN+ckEFUF*Tk8udGDkls)r NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\u1e02' # 0xA1 -> LATIN CAPITAL LETTER B WITH DOT ABOVE + u'\u1e03' # 0xA2 -> LATIN SMALL LETTER B WITH DOT ABOVE + u'\xa3' # 0xA3 -> POUND SIGN + u'\u010a' # 0xA4 -> LATIN CAPITAL LETTER C WITH DOT ABOVE + u'\u010b' # 0xA5 -> LATIN SMALL LETTER C WITH DOT ABOVE + u'\u1e0a' # 0xA6 -> LATIN CAPITAL LETTER D WITH DOT ABOVE + u'\xa7' # 0xA7 -> SECTION SIGN + u'\u1e80' # 0xA8 -> LATIN CAPITAL LETTER W WITH GRAVE + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\u1e82' # 0xAA -> LATIN CAPITAL LETTER W WITH ACUTE + u'\u1e0b' # 0xAB -> LATIN SMALL LETTER D WITH DOT ABOVE + u'\u1ef2' # 0xAC -> LATIN CAPITAL LETTER Y WITH GRAVE + u'\xad' # 0xAD -> SOFT HYPHEN + u'\xae' # 0xAE -> REGISTERED SIGN + u'\u0178' # 0xAF -> LATIN CAPITAL LETTER Y WITH DIAERESIS + u'\u1e1e' # 0xB0 -> LATIN CAPITAL LETTER F WITH DOT ABOVE + u'\u1e1f' # 0xB1 -> LATIN SMALL LETTER F WITH DOT ABOVE + u'\u0120' # 0xB2 -> LATIN CAPITAL LETTER G WITH DOT ABOVE + u'\u0121' # 0xB3 -> LATIN SMALL LETTER G WITH DOT ABOVE + u'\u1e40' # 0xB4 -> LATIN CAPITAL LETTER M WITH DOT ABOVE + u'\u1e41' # 0xB5 -> LATIN SMALL LETTER M WITH DOT ABOVE + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\u1e56' # 0xB7 -> LATIN CAPITAL LETTER P WITH DOT ABOVE + u'\u1e81' # 0xB8 -> LATIN SMALL LETTER W WITH GRAVE + u'\u1e57' # 0xB9 -> LATIN SMALL LETTER P WITH DOT ABOVE + u'\u1e83' # 0xBA -> LATIN SMALL LETTER W WITH ACUTE + u'\u1e60' # 0xBB -> LATIN CAPITAL LETTER S WITH DOT ABOVE + u'\u1ef3' # 0xBC -> LATIN SMALL LETTER Y WITH GRAVE + u'\u1e84' # 0xBD -> LATIN CAPITAL LETTER W WITH DIAERESIS + u'\u1e85' # 0xBE -> LATIN SMALL LETTER W WITH DIAERESIS + u'\u1e61' # 0xBF -> LATIN SMALL LETTER S WITH DOT ABOVE + u'\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + u'\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + u'\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + u'\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\u0174' # 0xD0 -> LATIN CAPITAL LETTER W WITH CIRCUMFLEX + u'\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + u'\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\u1e6a' # 0xD7 -> LATIN CAPITAL LETTER T WITH DOT ABOVE + u'\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + u'\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xdd' # 0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE + u'\u0176' # 0xDE -> LATIN CAPITAL LETTER Y WITH CIRCUMFLEX + u'\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + u'\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + u'\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe6' # 0xE6 -> LATIN SMALL LETTER AE + u'\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + u'\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + u'\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + u'\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + u'\u0175' # 0xF0 -> LATIN SMALL LETTER W WITH CIRCUMFLEX + u'\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + u'\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + u'\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + u'\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\u1e6b' # 0xF7 -> LATIN SMALL LETTER T WITH DOT ABOVE + u'\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + u'\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + u'\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + u'\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xfd' # 0xFD -> LATIN SMALL LETTER Y WITH ACUTE + u'\u0177' # 0xFE -> LATIN SMALL LETTER Y WITH CIRCUMFLEX + u'\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/iso8859_14.pyc b/PythonHome/Lib/encodings/iso8859_14.pyc deleted file mode 100644 index 4635b4412916ef171f83d46cb6e8962aab727e86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2769 zcmc&$d3O{=5br&+*(8KpgFzQB)`MUa6ciB>4xE|5fuT!C+F^>&-c2L4>F&@4}euYWG6)5Bk+grraL`V)74eK`gPTM{wfRJ+O#zi zWA{ED{J#Q+aT_Ovu|}L-OmVY>i#6iH!&Db*bF(sK~3)YY$zEUb%cpm!G1w4i!X)yB;m=Z88qvz4~Q$V^pxS5+{m-NjG6 z>BD1%@dBi7l+=(%A)Hin9ibDb_MyiZIIi7{)*dEB!ju5hPp_N07Bge?Ov8(#mc%n~ zG8t=gv2FP0W~Q5EJQ%bK<@L^X;hAAhL1_%5Ps;64+g%|NOT-~+%FPMY-bE)EY9cN| z&{FLkrtm}6^|Wq;QOU$)%*9nz(>krWY0Qez0ZobOl@snHfF!=n z#_{h!N>fqwh@2$+W{p`!3@JMiQ&;8WCSAh>V<12_~fM32~4ae z5gk#a0*8q1J|84iR{k3wsLED4J`}>HRMnDv1y1&zvil=;MykYkx$s(f$JW^9d_-); zPemPjp^1GfKoup!iXvg6MZHNEjEajv+_+asvC}xEMKD=&>VjR!^@(D;dg&r(*gY_3 zI1sOKf=-b{ajsok$pg`@>QeEvs7TJS5?v^X7$FfH66NKgvuP4nTU2xh+oh>@&BI57 z2+CZ=F2Ac3zkc!U7$i!$+#avbUlb?~mXwxFDW5uR`iz;gW7x%_war`!1wZfd_OEaXk^&Rbz8X}e#^=Y zTKOI;cg)IXtlW@w=em{ev+_Hv+%R-Q5A;F?`d|m_gk7*3_CP-jz+Tt~`{BUo4LAsg z;4mD4qcCXYF2Qj)0Vm-UoQ5-_x8NKM!7zLe=ivwV5q^RT@H1S5OK=%}fh%woejU9D zzri)Q4maQ?peL6h3pvQc9rzvo7`+XDhAD^0T NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\xa1' # 0xA1 -> INVERTED EXCLAMATION MARK + u'\xa2' # 0xA2 -> CENT SIGN + u'\xa3' # 0xA3 -> POUND SIGN + u'\u20ac' # 0xA4 -> EURO SIGN + u'\xa5' # 0xA5 -> YEN SIGN + u'\u0160' # 0xA6 -> LATIN CAPITAL LETTER S WITH CARON + u'\xa7' # 0xA7 -> SECTION SIGN + u'\u0161' # 0xA8 -> LATIN SMALL LETTER S WITH CARON + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\xaa' # 0xAA -> FEMININE ORDINAL INDICATOR + u'\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xac' # 0xAC -> NOT SIGN + u'\xad' # 0xAD -> SOFT HYPHEN + u'\xae' # 0xAE -> REGISTERED SIGN + u'\xaf' # 0xAF -> MACRON + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\xb2' # 0xB2 -> SUPERSCRIPT TWO + u'\xb3' # 0xB3 -> SUPERSCRIPT THREE + u'\u017d' # 0xB4 -> LATIN CAPITAL LETTER Z WITH CARON + u'\xb5' # 0xB5 -> MICRO SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\u017e' # 0xB8 -> LATIN SMALL LETTER Z WITH CARON + u'\xb9' # 0xB9 -> SUPERSCRIPT ONE + u'\xba' # 0xBA -> MASCULINE ORDINAL INDICATOR + u'\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u0152' # 0xBC -> LATIN CAPITAL LIGATURE OE + u'\u0153' # 0xBD -> LATIN SMALL LIGATURE OE + u'\u0178' # 0xBE -> LATIN CAPITAL LETTER Y WITH DIAERESIS + u'\xbf' # 0xBF -> INVERTED QUESTION MARK + u'\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + u'\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + u'\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + u'\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\xd0' # 0xD0 -> LATIN CAPITAL LETTER ETH + u'\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + u'\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xd7' # 0xD7 -> MULTIPLICATION SIGN + u'\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + u'\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xdd' # 0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE + u'\xde' # 0xDE -> LATIN CAPITAL LETTER THORN + u'\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + u'\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + u'\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe6' # 0xE6 -> LATIN SMALL LETTER AE + u'\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + u'\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + u'\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + u'\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xf0' # 0xF0 -> LATIN SMALL LETTER ETH + u'\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + u'\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + u'\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + u'\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf7' # 0xF7 -> DIVISION SIGN + u'\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + u'\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + u'\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + u'\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xfd' # 0xFD -> LATIN SMALL LETTER Y WITH ACUTE + u'\xfe' # 0xFE -> LATIN SMALL LETTER THORN + u'\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/iso8859_15.pyc b/PythonHome/Lib/encodings/iso8859_15.pyc deleted file mode 100644 index bc94680a2202ba4cac164c2dbb987e6e639c23e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2748 zcmc&$d3O{=5br&+SrWpn!Jvy*)`P^TQBcH?a2SOUXQP1_T_!uT$>1JwW+FyWfrR_M z?;{{05N=601m3H9`$hZ;egLfMAv*zmkH8ep54`>QxS(7ZI35cfYm z`d>rC8l*`RqJ?IU(7Yn$5iPXv3Ed->c}0@ee$gvLj}S{*yg~~|g-jFX>HKYqlT~S^a6k0Jqv=j(!v}g%Q17s;AddR^rdm4+D zZ~!TqB8}a4M>Z3w>rhQKVe4jOq1xGLWZENjSxrww3@bZ*di9KWRdu9Y&*-LV>slmf zX48@Kg|izQ>l^0BD(hp5_?=3grd3r}G%ao_k1RLr4&IVrGZmfP72&XPk3J1{fR2^M z^N@N;Qp+AiXwu1bf=;5^OCD3;wDt;K`-BpUasuoiziyjG!cOor4?m4M7LTXN7Gjx4 zte`)yu)U(kM?rf?-r#PRo>}&2k|rqnwAvYW+?67^Bpl+l+LqFtU3`M2r;;)RBh%Ss zOFwke%$in|ltNC{6k1iZE->0!hpbqwE|3Isv$_;k}Kr-JZ(fD^D zl`*7xLQXP%6NfAlhMb+4ZR%>e*)*tt=DEmBtK}CtsSX#ZdeK@)KDlXi1Cy%}M8^~< zr6Hqxzz0QFwg1KkuCisW5Bab;Rdp<{p~<;ZPJg7%$d#Bb7hNm=(3;v@fQhXIxu{bw zw5e}}xT5rkf>@Mk(O~lhNIX?kxVw+y5JOY^I@@5y-b-i>K>Fc8idy{ z!E%{Id9G7i*#p_G>NCl#tVr&$3STIN8KE#73g_jqvuQI|+jVk>+NEuFPo+nT2`W5= zo}j0QzCrozTE&#|czymrupm?z9#vF4x@64QapNaUob=SwrIVj2oAT^)k*UwW@Zw7^ zmq%ZD^|jZhRaCxF_2ye|SHJV_^cnBHKl6iGAJ)vSt(!A<-u#d1KmKIF!iGhSpDMAY z&pvNnyrkue)-S(`FIC$Tnx1U$FqVCtN@ud2-w%02^TwY=$kc6}G{4*a16X7wm>Tuow2hemDRJ;Sd~#BXAUs!Exw=6L9j+ z)%|cPcN|XV`rr(lg>%pk=ivfegiCN4uE5pYZMX&lFqpdoH{d4R%I(bU%3X)MxDr?4 zYV5&YT!U+I9j?a>xDhwuX54~XaT{*O9k>&B;cnc6dvPD`#{+l}58+`vf=BTf9>+dB zfhX}7JcYmFY5Wb(;8{F}{dgWP;6=QIm+=Z-#ozH74&WeO#~XMPZ{Z(!8}H!VD5r}^ z$_-D;CaA%2cW{W|(t(-aaDrQl!o0P)gb)4FXzMakn$tK)I*c@rzWuV<&UD)AEFW#Q ZxY<#6^p}Q8{iXggUs<5ABzRBw{|4H+bTa?| diff --git a/PythonHome/Lib/encodings/iso8859_16.py b/PythonHome/Lib/encodings/iso8859_16.py new file mode 100644 index 0000000000..00b9ac8055 --- /dev/null +++ b/PythonHome/Lib/encodings/iso8859_16.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_16 generated from 'MAPPINGS/ISO8859/8859-16.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-16', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\u0104' # 0xA1 -> LATIN CAPITAL LETTER A WITH OGONEK + u'\u0105' # 0xA2 -> LATIN SMALL LETTER A WITH OGONEK + u'\u0141' # 0xA3 -> LATIN CAPITAL LETTER L WITH STROKE + u'\u20ac' # 0xA4 -> EURO SIGN + u'\u201e' # 0xA5 -> DOUBLE LOW-9 QUOTATION MARK + u'\u0160' # 0xA6 -> LATIN CAPITAL LETTER S WITH CARON + u'\xa7' # 0xA7 -> SECTION SIGN + u'\u0161' # 0xA8 -> LATIN SMALL LETTER S WITH CARON + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\u0218' # 0xAA -> LATIN CAPITAL LETTER S WITH COMMA BELOW + u'\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u0179' # 0xAC -> LATIN CAPITAL LETTER Z WITH ACUTE + u'\xad' # 0xAD -> SOFT HYPHEN + u'\u017a' # 0xAE -> LATIN SMALL LETTER Z WITH ACUTE + u'\u017b' # 0xAF -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\u010c' # 0xB2 -> LATIN CAPITAL LETTER C WITH CARON + u'\u0142' # 0xB3 -> LATIN SMALL LETTER L WITH STROKE + u'\u017d' # 0xB4 -> LATIN CAPITAL LETTER Z WITH CARON + u'\u201d' # 0xB5 -> RIGHT DOUBLE QUOTATION MARK + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\u017e' # 0xB8 -> LATIN SMALL LETTER Z WITH CARON + u'\u010d' # 0xB9 -> LATIN SMALL LETTER C WITH CARON + u'\u0219' # 0xBA -> LATIN SMALL LETTER S WITH COMMA BELOW + u'\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u0152' # 0xBC -> LATIN CAPITAL LIGATURE OE + u'\u0153' # 0xBD -> LATIN SMALL LIGATURE OE + u'\u0178' # 0xBE -> LATIN CAPITAL LETTER Y WITH DIAERESIS + u'\u017c' # 0xBF -> LATIN SMALL LETTER Z WITH DOT ABOVE + u'\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\u0102' # 0xC3 -> LATIN CAPITAL LETTER A WITH BREVE + u'\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\u0106' # 0xC5 -> LATIN CAPITAL LETTER C WITH ACUTE + u'\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + u'\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + u'\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\u0110' # 0xD0 -> LATIN CAPITAL LETTER D WITH STROKE + u'\u0143' # 0xD1 -> LATIN CAPITAL LETTER N WITH ACUTE + u'\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\u0150' # 0xD5 -> LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + u'\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\u015a' # 0xD7 -> LATIN CAPITAL LETTER S WITH ACUTE + u'\u0170' # 0xD8 -> LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + u'\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\u0118' # 0xDD -> LATIN CAPITAL LETTER E WITH OGONEK + u'\u021a' # 0xDE -> LATIN CAPITAL LETTER T WITH COMMA BELOW + u'\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + u'\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\u0103' # 0xE3 -> LATIN SMALL LETTER A WITH BREVE + u'\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\u0107' # 0xE5 -> LATIN SMALL LETTER C WITH ACUTE + u'\xe6' # 0xE6 -> LATIN SMALL LETTER AE + u'\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + u'\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + u'\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + u'\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + u'\u0111' # 0xF0 -> LATIN SMALL LETTER D WITH STROKE + u'\u0144' # 0xF1 -> LATIN SMALL LETTER N WITH ACUTE + u'\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + u'\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\u0151' # 0xF5 -> LATIN SMALL LETTER O WITH DOUBLE ACUTE + u'\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\u015b' # 0xF7 -> LATIN SMALL LETTER S WITH ACUTE + u'\u0171' # 0xF8 -> LATIN SMALL LETTER U WITH DOUBLE ACUTE + u'\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + u'\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + u'\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\u0119' # 0xFD -> LATIN SMALL LETTER E WITH OGONEK + u'\u021b' # 0xFE -> LATIN SMALL LETTER T WITH COMMA BELOW + u'\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/iso8859_16.pyc b/PythonHome/Lib/encodings/iso8859_16.pyc deleted file mode 100644 index b8329e7aa31558bf751c7300cbab65b028a591d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2750 zcmc&$c~=}o5br%%mMgasiEg}DkASE_qA?Q4AsPtIq9iN28Fpr2a1WdrL^K*;3FLr; zBSwxK#OE`{B$}u%F(K-E-8=8`Irs{GfLPVT?g08;NdC}Wy6LH!uCDskudCMaSDyDq zOa6DEm}Aj~!**-6w!g0OH9*+$yzBm!$E=_4db$o`<6NG`5$aD_Xg za1berE1X>6$tave$|ka%>s%xP2D}-ai%2_oSdqyvJsfxOPz&OOuge2|7A`k2@rGTr4Oz62aXy4W0*&0TncCPyPY z1SQ_yp>scERZXaxAC!bo+6GvaH0@EEo6=UaCJRUa!`#NP$w8Y40I@wtBm!<-6a&Bw zkaH1VE{;J!^aVsu$b#vA&#-t89_wLndrYRW-^hVKVQO*&m@ZVkL&l1=q@%UPGI6A+aSl z7Io-_I`l0MR+J>k3iy#0bvj-!EG`;yW4@9?r?E;4XR>0|1+$Q=OT}jOQhCmxdqB=$ z0A33Ooji&BT(h>K2fSU?#3Kn_k*s3{yifu%LO?hK%*%aeQ%A10$lwmNOI_{S2#*>P zl-ROuZd)#V-Td1D4IG4ahtuWG@??8+a`W;FR;*mLdd=E(4?SGC{*j^$k3Qzx`1lh~ zKJ|35|Cwi>dwx?%=?i5qzV!0u@>eRhy!zVK*SEbiA-?LD=1d+Xm3 z0uArJ*SK$g@cpI_J`5cYo5PYEX=zp3K8nWTiT00GP4D=m^V6=+K0o-ymxpLK?V-Ii zN&Dzw+D`}Q5qgv!qsQqW9ik`bNjgkN=qMedr|4JoH2s>6(+N6Br|21amY$>M>2#_u zb=c^c>%B79ea@Js7mW+_((E|BY}}$(joZcyy+*I628~|h_qpz~^aj0Y{E-@(ouD(u zs4-^zX53-jtcUfcdRbqppY^i=c7z>e$JlW;$cESnb}}_=B-tn%W2cN^cG{RUuCWO= z$)?zu)cEWqJI|)s1@=uU$-YeuuV$bL$V7=7$#_6z&f7-2Vz zDdRf3#cs11b|*D4JH`I=W5R%@*z%-A7+M_m2a_5WA&?6uE3ml;$Xp$Zc>1?SbB7X@ s%+>+Y1+=;M{pam=tJz?;IbgGf?GE~*v(QuMEOZt*id@+R?z_bKH?MhfqW}N^ diff --git a/PythonHome/Lib/encodings/iso8859_2.py b/PythonHome/Lib/encodings/iso8859_2.py new file mode 100644 index 0000000000..38e91d8e17 --- /dev/null +++ b/PythonHome/Lib/encodings/iso8859_2.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_2 generated from 'MAPPINGS/ISO8859/8859-2.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-2', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\u0104' # 0xA1 -> LATIN CAPITAL LETTER A WITH OGONEK + u'\u02d8' # 0xA2 -> BREVE + u'\u0141' # 0xA3 -> LATIN CAPITAL LETTER L WITH STROKE + u'\xa4' # 0xA4 -> CURRENCY SIGN + u'\u013d' # 0xA5 -> LATIN CAPITAL LETTER L WITH CARON + u'\u015a' # 0xA6 -> LATIN CAPITAL LETTER S WITH ACUTE + u'\xa7' # 0xA7 -> SECTION SIGN + u'\xa8' # 0xA8 -> DIAERESIS + u'\u0160' # 0xA9 -> LATIN CAPITAL LETTER S WITH CARON + u'\u015e' # 0xAA -> LATIN CAPITAL LETTER S WITH CEDILLA + u'\u0164' # 0xAB -> LATIN CAPITAL LETTER T WITH CARON + u'\u0179' # 0xAC -> LATIN CAPITAL LETTER Z WITH ACUTE + u'\xad' # 0xAD -> SOFT HYPHEN + u'\u017d' # 0xAE -> LATIN CAPITAL LETTER Z WITH CARON + u'\u017b' # 0xAF -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\u0105' # 0xB1 -> LATIN SMALL LETTER A WITH OGONEK + u'\u02db' # 0xB2 -> OGONEK + u'\u0142' # 0xB3 -> LATIN SMALL LETTER L WITH STROKE + u'\xb4' # 0xB4 -> ACUTE ACCENT + u'\u013e' # 0xB5 -> LATIN SMALL LETTER L WITH CARON + u'\u015b' # 0xB6 -> LATIN SMALL LETTER S WITH ACUTE + u'\u02c7' # 0xB7 -> CARON + u'\xb8' # 0xB8 -> CEDILLA + u'\u0161' # 0xB9 -> LATIN SMALL LETTER S WITH CARON + u'\u015f' # 0xBA -> LATIN SMALL LETTER S WITH CEDILLA + u'\u0165' # 0xBB -> LATIN SMALL LETTER T WITH CARON + u'\u017a' # 0xBC -> LATIN SMALL LETTER Z WITH ACUTE + u'\u02dd' # 0xBD -> DOUBLE ACUTE ACCENT + u'\u017e' # 0xBE -> LATIN SMALL LETTER Z WITH CARON + u'\u017c' # 0xBF -> LATIN SMALL LETTER Z WITH DOT ABOVE + u'\u0154' # 0xC0 -> LATIN CAPITAL LETTER R WITH ACUTE + u'\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\u0102' # 0xC3 -> LATIN CAPITAL LETTER A WITH BREVE + u'\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\u0139' # 0xC5 -> LATIN CAPITAL LETTER L WITH ACUTE + u'\u0106' # 0xC6 -> LATIN CAPITAL LETTER C WITH ACUTE + u'\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\u010c' # 0xC8 -> LATIN CAPITAL LETTER C WITH CARON + u'\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\u0118' # 0xCA -> LATIN CAPITAL LETTER E WITH OGONEK + u'\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\u011a' # 0xCC -> LATIN CAPITAL LETTER E WITH CARON + u'\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\u010e' # 0xCF -> LATIN CAPITAL LETTER D WITH CARON + u'\u0110' # 0xD0 -> LATIN CAPITAL LETTER D WITH STROKE + u'\u0143' # 0xD1 -> LATIN CAPITAL LETTER N WITH ACUTE + u'\u0147' # 0xD2 -> LATIN CAPITAL LETTER N WITH CARON + u'\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\u0150' # 0xD5 -> LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + u'\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xd7' # 0xD7 -> MULTIPLICATION SIGN + u'\u0158' # 0xD8 -> LATIN CAPITAL LETTER R WITH CARON + u'\u016e' # 0xD9 -> LATIN CAPITAL LETTER U WITH RING ABOVE + u'\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + u'\u0170' # 0xDB -> LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + u'\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xdd' # 0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE + u'\u0162' # 0xDE -> LATIN CAPITAL LETTER T WITH CEDILLA + u'\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + u'\u0155' # 0xE0 -> LATIN SMALL LETTER R WITH ACUTE + u'\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\u0103' # 0xE3 -> LATIN SMALL LETTER A WITH BREVE + u'\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\u013a' # 0xE5 -> LATIN SMALL LETTER L WITH ACUTE + u'\u0107' # 0xE6 -> LATIN SMALL LETTER C WITH ACUTE + u'\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + u'\u010d' # 0xE8 -> LATIN SMALL LETTER C WITH CARON + u'\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + u'\u0119' # 0xEA -> LATIN SMALL LETTER E WITH OGONEK + u'\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + u'\u011b' # 0xEC -> LATIN SMALL LETTER E WITH CARON + u'\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\u010f' # 0xEF -> LATIN SMALL LETTER D WITH CARON + u'\u0111' # 0xF0 -> LATIN SMALL LETTER D WITH STROKE + u'\u0144' # 0xF1 -> LATIN SMALL LETTER N WITH ACUTE + u'\u0148' # 0xF2 -> LATIN SMALL LETTER N WITH CARON + u'\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\u0151' # 0xF5 -> LATIN SMALL LETTER O WITH DOUBLE ACUTE + u'\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf7' # 0xF7 -> DIVISION SIGN + u'\u0159' # 0xF8 -> LATIN SMALL LETTER R WITH CARON + u'\u016f' # 0xF9 -> LATIN SMALL LETTER U WITH RING ABOVE + u'\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + u'\u0171' # 0xFB -> LATIN SMALL LETTER U WITH DOUBLE ACUTE + u'\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xfd' # 0xFD -> LATIN SMALL LETTER Y WITH ACUTE + u'\u0163' # 0xFE -> LATIN SMALL LETTER T WITH CEDILLA + u'\u02d9' # 0xFF -> DOT ABOVE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/iso8859_2.pyc b/PythonHome/Lib/encodings/iso8859_2.pyc deleted file mode 100644 index 42b7edc2e41e3357e2001a75ff3ed65d763ba076..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2733 zcmc&$>sM4&6hHH17(sj&Mm6?gdI&{XSY`-5q6FyO&OUqp&hPAv=g;Ecjh4NU z7@7Nc;BO5K<0c4&kXDc`qPR)IMOs1e5Yt#wSXu~Noznj08asug#d#X zX(U{N33P!7HT9aE=~Sq$Q`Y5}sp_EyIg`;+9ih6kqQ*j+k*==ZurXQ{>QGavE}NC7 zod?tnE43I;2!slO18@S<0f-mU2Hj0i_Yf%(M)*xXe%;iym>I)44lj&4TwV#nB&5ql z_Q9{4m~N8wK*}yyZ*;bc$P9BSti~Ysq@0P`;ff`p0t!)6ZcnK8E_dV=o0fMt_Mj(!mSHZ0JH&du_V-m zDM$#ugy2a9AnrG2+c_dO7jqaPF#{l?(UhE2qfs*`CdstYoq(x?HVLzI&Jx<9AW5)? z6v8m@48Oa`W3B+DJ{8l|q?$72#5RGT9)nf!$rse99b~}YVO|TX4qt#c zKp78G23~b(B#dqwH4sE(DYbiP5B)xdPh!kcxA6lsh&nX5W zd~TN$hAJR+9REu+@zR#(y!&1EV!2h&=KsMGFWJTtxpNPe5*8{a+r?o-uC0Ob&oD~M z!1Q2zMD$kY90P)QH4#%+U&I@=c?e|-bRxLq+^Lh6&=$`P=}`(p zEFGbvbc~MEb9929r<3%8H84BE z`{?jfzGZRa9?!SxnZY`nM{Q_3!QD)JH jFFNcdyQgmUz+MAe9P~tQX`s|w>Miq>`3g(?cZv5e-U@E| diff --git a/PythonHome/Lib/encodings/iso8859_3.py b/PythonHome/Lib/encodings/iso8859_3.py new file mode 100644 index 0000000000..23daafdbb1 --- /dev/null +++ b/PythonHome/Lib/encodings/iso8859_3.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_3 generated from 'MAPPINGS/ISO8859/8859-3.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-3', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\u0126' # 0xA1 -> LATIN CAPITAL LETTER H WITH STROKE + u'\u02d8' # 0xA2 -> BREVE + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa4' # 0xA4 -> CURRENCY SIGN + u'\ufffe' + u'\u0124' # 0xA6 -> LATIN CAPITAL LETTER H WITH CIRCUMFLEX + u'\xa7' # 0xA7 -> SECTION SIGN + u'\xa8' # 0xA8 -> DIAERESIS + u'\u0130' # 0xA9 -> LATIN CAPITAL LETTER I WITH DOT ABOVE + u'\u015e' # 0xAA -> LATIN CAPITAL LETTER S WITH CEDILLA + u'\u011e' # 0xAB -> LATIN CAPITAL LETTER G WITH BREVE + u'\u0134' # 0xAC -> LATIN CAPITAL LETTER J WITH CIRCUMFLEX + u'\xad' # 0xAD -> SOFT HYPHEN + u'\ufffe' + u'\u017b' # 0xAF -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\u0127' # 0xB1 -> LATIN SMALL LETTER H WITH STROKE + u'\xb2' # 0xB2 -> SUPERSCRIPT TWO + u'\xb3' # 0xB3 -> SUPERSCRIPT THREE + u'\xb4' # 0xB4 -> ACUTE ACCENT + u'\xb5' # 0xB5 -> MICRO SIGN + u'\u0125' # 0xB6 -> LATIN SMALL LETTER H WITH CIRCUMFLEX + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\xb8' # 0xB8 -> CEDILLA + u'\u0131' # 0xB9 -> LATIN SMALL LETTER DOTLESS I + u'\u015f' # 0xBA -> LATIN SMALL LETTER S WITH CEDILLA + u'\u011f' # 0xBB -> LATIN SMALL LETTER G WITH BREVE + u'\u0135' # 0xBC -> LATIN SMALL LETTER J WITH CIRCUMFLEX + u'\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + u'\ufffe' + u'\u017c' # 0xBF -> LATIN SMALL LETTER Z WITH DOT ABOVE + u'\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\ufffe' + u'\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\u010a' # 0xC5 -> LATIN CAPITAL LETTER C WITH DOT ABOVE + u'\u0108' # 0xC6 -> LATIN CAPITAL LETTER C WITH CIRCUMFLEX + u'\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + u'\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\ufffe' + u'\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\u0120' # 0xD5 -> LATIN CAPITAL LETTER G WITH DOT ABOVE + u'\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xd7' # 0xD7 -> MULTIPLICATION SIGN + u'\u011c' # 0xD8 -> LATIN CAPITAL LETTER G WITH CIRCUMFLEX + u'\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\u016c' # 0xDD -> LATIN CAPITAL LETTER U WITH BREVE + u'\u015c' # 0xDE -> LATIN CAPITAL LETTER S WITH CIRCUMFLEX + u'\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + u'\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\ufffe' + u'\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\u010b' # 0xE5 -> LATIN SMALL LETTER C WITH DOT ABOVE + u'\u0109' # 0xE6 -> LATIN SMALL LETTER C WITH CIRCUMFLEX + u'\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + u'\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + u'\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + u'\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + u'\ufffe' + u'\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + u'\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + u'\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\u0121' # 0xF5 -> LATIN SMALL LETTER G WITH DOT ABOVE + u'\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf7' # 0xF7 -> DIVISION SIGN + u'\u011d' # 0xF8 -> LATIN SMALL LETTER G WITH CIRCUMFLEX + u'\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + u'\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + u'\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\u016d' # 0xFD -> LATIN SMALL LETTER U WITH BREVE + u'\u015d' # 0xFE -> LATIN SMALL LETTER S WITH CIRCUMFLEX + u'\u02d9' # 0xFF -> DOT ABOVE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/iso8859_3.pyc b/PythonHome/Lib/encodings/iso8859_3.pyc deleted file mode 100644 index 43fd69a31820ed3deef0d718ab271690d8534d91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2740 zcmc&$X$Dc*sYt4H? zQ8M>&!2cQ;+AK^GAz_$pM6#2(jf6pP5ZOjL>?8)Vlk^hOL&)y1ok%WjaBzb=XK)ZH zj~kra;K>=BM9L?!o!eX_1`fPAn~O*VS(}^N3Uf9$k&18;&LdJW346E$@Z=#q5TF+$ z4FyUtfex7bjoo^CD(SCl7gaH;%c{RYOsAD(o4+n4$x*+erK+pfZ-`X++vKFIin=WM zV`?hlFKgJ`*jOLj9;&Pl?ZihaaVoE>Xxi0O=I>JUc6=j>PAbyf6<)7$3qC>J1)Fl$ zIY8~8sl|BwFv$=&0LL-yg?J%tknIFz2N6O6gkN{#LcAssfd z7yj%-x046?jY94TF�(|^VneNni z9I~pWR4o8T!Y8d1q>7duN^48ji`J5Z5wI}d;?NYJOU$3x?j#WbUtN#_pbdy~6&Dw# zARzbxf+ys`bh|N|&JnS>m;(rj?tv*1Ns0+M64AYUkw{6Maaamy6EI6_FD@+!k^t|J zd>9(;;kFk#^c5h~C!?yIkdwL?-^vkGqoC!V9F11N(xegG9*J1gK?eLC=Cz=;_yWWM z$~cfRaI1Zx0J;q-FcF?Dhg?9yaR>#Bj?=@!mh&T~B*nOu^wRkvQkdaCX6w=&jB=1_beFLb@u8iDp%Sx|!o4vaA*##1l1n2xSXo!ntIfsg)L&md*|7;e)|* zTM&XEi_(7*0v1=SZ*w8!lE!1ILwyZQ=4~>YBD6y+z;LbLLOHWC^fniAT5@A8hX$xa zv+`gm=^=Tc08%2TCRLw|rFbc_wiWO$2}lP4(Gc)dZucm4q-mQB(Lj&X)$Vn$)R3FRmTz<0 z3gPSK-_Aaylg;jMy4-o5d~ZQvQE|z#tA_wM?-LD<7+~w>Ge07 zckK?p+49!gkv(E-RFY$D?MlZx@kBC}epl7>&iA_B@BZM!y&rx23EfBc(*v}J_R>%3 zXS9#@(*Zh2hv-3ih#sa#=;!n(Jw}hy6Z8vulAfZc=`cM*&(aY(O2_CpoiM(+d76Gj zC;#~UH)E1c(euW|%$PA|%+P62Wv#>xJrM;2X3%^ zY(F~yBI`8}z~zo?oj#Ax>2sDkN?rLS?pwt97lw;>V*mgE diff --git a/PythonHome/Lib/encodings/iso8859_4.py b/PythonHome/Lib/encodings/iso8859_4.py new file mode 100644 index 0000000000..c8e03b566a --- /dev/null +++ b/PythonHome/Lib/encodings/iso8859_4.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_4 generated from 'MAPPINGS/ISO8859/8859-4.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-4', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\u0104' # 0xA1 -> LATIN CAPITAL LETTER A WITH OGONEK + u'\u0138' # 0xA2 -> LATIN SMALL LETTER KRA + u'\u0156' # 0xA3 -> LATIN CAPITAL LETTER R WITH CEDILLA + u'\xa4' # 0xA4 -> CURRENCY SIGN + u'\u0128' # 0xA5 -> LATIN CAPITAL LETTER I WITH TILDE + u'\u013b' # 0xA6 -> LATIN CAPITAL LETTER L WITH CEDILLA + u'\xa7' # 0xA7 -> SECTION SIGN + u'\xa8' # 0xA8 -> DIAERESIS + u'\u0160' # 0xA9 -> LATIN CAPITAL LETTER S WITH CARON + u'\u0112' # 0xAA -> LATIN CAPITAL LETTER E WITH MACRON + u'\u0122' # 0xAB -> LATIN CAPITAL LETTER G WITH CEDILLA + u'\u0166' # 0xAC -> LATIN CAPITAL LETTER T WITH STROKE + u'\xad' # 0xAD -> SOFT HYPHEN + u'\u017d' # 0xAE -> LATIN CAPITAL LETTER Z WITH CARON + u'\xaf' # 0xAF -> MACRON + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\u0105' # 0xB1 -> LATIN SMALL LETTER A WITH OGONEK + u'\u02db' # 0xB2 -> OGONEK + u'\u0157' # 0xB3 -> LATIN SMALL LETTER R WITH CEDILLA + u'\xb4' # 0xB4 -> ACUTE ACCENT + u'\u0129' # 0xB5 -> LATIN SMALL LETTER I WITH TILDE + u'\u013c' # 0xB6 -> LATIN SMALL LETTER L WITH CEDILLA + u'\u02c7' # 0xB7 -> CARON + u'\xb8' # 0xB8 -> CEDILLA + u'\u0161' # 0xB9 -> LATIN SMALL LETTER S WITH CARON + u'\u0113' # 0xBA -> LATIN SMALL LETTER E WITH MACRON + u'\u0123' # 0xBB -> LATIN SMALL LETTER G WITH CEDILLA + u'\u0167' # 0xBC -> LATIN SMALL LETTER T WITH STROKE + u'\u014a' # 0xBD -> LATIN CAPITAL LETTER ENG + u'\u017e' # 0xBE -> LATIN SMALL LETTER Z WITH CARON + u'\u014b' # 0xBF -> LATIN SMALL LETTER ENG + u'\u0100' # 0xC0 -> LATIN CAPITAL LETTER A WITH MACRON + u'\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + u'\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + u'\u012e' # 0xC7 -> LATIN CAPITAL LETTER I WITH OGONEK + u'\u010c' # 0xC8 -> LATIN CAPITAL LETTER C WITH CARON + u'\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\u0118' # 0xCA -> LATIN CAPITAL LETTER E WITH OGONEK + u'\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\u0116' # 0xCC -> LATIN CAPITAL LETTER E WITH DOT ABOVE + u'\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\u012a' # 0xCF -> LATIN CAPITAL LETTER I WITH MACRON + u'\u0110' # 0xD0 -> LATIN CAPITAL LETTER D WITH STROKE + u'\u0145' # 0xD1 -> LATIN CAPITAL LETTER N WITH CEDILLA + u'\u014c' # 0xD2 -> LATIN CAPITAL LETTER O WITH MACRON + u'\u0136' # 0xD3 -> LATIN CAPITAL LETTER K WITH CEDILLA + u'\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + u'\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xd7' # 0xD7 -> MULTIPLICATION SIGN + u'\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + u'\u0172' # 0xD9 -> LATIN CAPITAL LETTER U WITH OGONEK + u'\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\u0168' # 0xDD -> LATIN CAPITAL LETTER U WITH TILDE + u'\u016a' # 0xDE -> LATIN CAPITAL LETTER U WITH MACRON + u'\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + u'\u0101' # 0xE0 -> LATIN SMALL LETTER A WITH MACRON + u'\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + u'\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe6' # 0xE6 -> LATIN SMALL LETTER AE + u'\u012f' # 0xE7 -> LATIN SMALL LETTER I WITH OGONEK + u'\u010d' # 0xE8 -> LATIN SMALL LETTER C WITH CARON + u'\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + u'\u0119' # 0xEA -> LATIN SMALL LETTER E WITH OGONEK + u'\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + u'\u0117' # 0xEC -> LATIN SMALL LETTER E WITH DOT ABOVE + u'\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\u012b' # 0xEF -> LATIN SMALL LETTER I WITH MACRON + u'\u0111' # 0xF0 -> LATIN SMALL LETTER D WITH STROKE + u'\u0146' # 0xF1 -> LATIN SMALL LETTER N WITH CEDILLA + u'\u014d' # 0xF2 -> LATIN SMALL LETTER O WITH MACRON + u'\u0137' # 0xF3 -> LATIN SMALL LETTER K WITH CEDILLA + u'\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + u'\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf7' # 0xF7 -> DIVISION SIGN + u'\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + u'\u0173' # 0xF9 -> LATIN SMALL LETTER U WITH OGONEK + u'\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + u'\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\u0169' # 0xFD -> LATIN SMALL LETTER U WITH TILDE + u'\u016b' # 0xFE -> LATIN SMALL LETTER U WITH MACRON + u'\u02d9' # 0xFF -> DOT ABOVE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/iso8859_4.pyc b/PythonHome/Lib/encodings/iso8859_4.pyc deleted file mode 100644 index 162ff0dbd25d5057d0bc2a12e82d0d37cf3a9715..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2733 zcmc&$>sM4&6hHH17(sm37}eN|=>hb>(lS%<5v3#Dq0osMFLUp}rFqc3myEIk2Q&rD zCl9fFrl3o0l_@K&59gfwi9e@5!1g{D=AyM0>4zFPn|;onv(MhY^E-Rv`Li^5qiJU> zNv1y@_`42NF1b#C~lH=kvJ$GqPj@Co1{SZl3qgcgzSjBiQ*Fmk1+TP1`kn+ zguyEefr7zHlwzW~h0RA&;2>DA`G_)a#^x8cl7h`olv13;i-eQ>C7 zT>#V#E43I;7=#Le18@S2$WQI8(R+Er>M(#-1;ff`p0tyLJZb_^5E? zMI5TG=X4_iMk0h!4q8?77Okau#*5KhfDy2;cL`|bp-ar4xE>@C3Af&r0-z0uizT7n zoq~kmO9-A+1mb>Uww)tl(=kU75;FiIk;uv!HIXobVv@-zooSd#Xp=BY=PaSk36cbR zNHGip&+xlTJmw-$>a$5*&8S&ZPHz+l>Pc7?p8}1Rz|^J@ydH%()IkRP9p>e*>hJ}K z1C;R~W#CnZVi9y3)j$xDt$)cRar`gQ#7kQ^R}(XJRn9c&8r01K50PcH_(i-?n}<-gKqrDr&Ye1G32pA&kRBlz zBDcFjkW^XuPeQ=riuG+eghJAIO?9}w4ut)h?4}6q5DPFoD|k@e86A3?4>_&)v6e#v zG@)4qu$1IUQ7nR#h?@Acu&Nk1oi3o2HBLzpB-WgQV3%+G-etRL>EgnmXTXKQ0JLT; z>=HL9jR>0IiZW33q z%kL_IAHVqN>_$4d+#avbUlb?~&MPUMU$$W3qQy&=E_>+V(DFyhAARic@QNp%eCp|E zDk9H5_xuZ$Rn;%P^zth;D_?zW)#}&ZSo7xEx7Mw%t=q71)8@D9-+6b-*66l|_oP_k z`yVuI-x2??`J;~$JLQ(7qNZBgwDwQZnQX4(Q{6B-Kil(i3!yo}}N?ALuE1n)mWa zYlxob{8Ge+Xvo2Z(tUs)N z-pzX09+qdltdH&GSNQ-Aiu;9S$)<3zrl{N<7|ixvk~iOc7lzulh(L( ziJjs-> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\u0401' # 0xA1 -> CYRILLIC CAPITAL LETTER IO + u'\u0402' # 0xA2 -> CYRILLIC CAPITAL LETTER DJE + u'\u0403' # 0xA3 -> CYRILLIC CAPITAL LETTER GJE + u'\u0404' # 0xA4 -> CYRILLIC CAPITAL LETTER UKRAINIAN IE + u'\u0405' # 0xA5 -> CYRILLIC CAPITAL LETTER DZE + u'\u0406' # 0xA6 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + u'\u0407' # 0xA7 -> CYRILLIC CAPITAL LETTER YI + u'\u0408' # 0xA8 -> CYRILLIC CAPITAL LETTER JE + u'\u0409' # 0xA9 -> CYRILLIC CAPITAL LETTER LJE + u'\u040a' # 0xAA -> CYRILLIC CAPITAL LETTER NJE + u'\u040b' # 0xAB -> CYRILLIC CAPITAL LETTER TSHE + u'\u040c' # 0xAC -> CYRILLIC CAPITAL LETTER KJE + u'\xad' # 0xAD -> SOFT HYPHEN + u'\u040e' # 0xAE -> CYRILLIC CAPITAL LETTER SHORT U + u'\u040f' # 0xAF -> CYRILLIC CAPITAL LETTER DZHE + u'\u0410' # 0xB0 -> CYRILLIC CAPITAL LETTER A + u'\u0411' # 0xB1 -> CYRILLIC CAPITAL LETTER BE + u'\u0412' # 0xB2 -> CYRILLIC CAPITAL LETTER VE + u'\u0413' # 0xB3 -> CYRILLIC CAPITAL LETTER GHE + u'\u0414' # 0xB4 -> CYRILLIC CAPITAL LETTER DE + u'\u0415' # 0xB5 -> CYRILLIC CAPITAL LETTER IE + u'\u0416' # 0xB6 -> CYRILLIC CAPITAL LETTER ZHE + u'\u0417' # 0xB7 -> CYRILLIC CAPITAL LETTER ZE + u'\u0418' # 0xB8 -> CYRILLIC CAPITAL LETTER I + u'\u0419' # 0xB9 -> CYRILLIC CAPITAL LETTER SHORT I + u'\u041a' # 0xBA -> CYRILLIC CAPITAL LETTER KA + u'\u041b' # 0xBB -> CYRILLIC CAPITAL LETTER EL + u'\u041c' # 0xBC -> CYRILLIC CAPITAL LETTER EM + u'\u041d' # 0xBD -> CYRILLIC CAPITAL LETTER EN + u'\u041e' # 0xBE -> CYRILLIC CAPITAL LETTER O + u'\u041f' # 0xBF -> CYRILLIC CAPITAL LETTER PE + u'\u0420' # 0xC0 -> CYRILLIC CAPITAL LETTER ER + u'\u0421' # 0xC1 -> CYRILLIC CAPITAL LETTER ES + u'\u0422' # 0xC2 -> CYRILLIC CAPITAL LETTER TE + u'\u0423' # 0xC3 -> CYRILLIC CAPITAL LETTER U + u'\u0424' # 0xC4 -> CYRILLIC CAPITAL LETTER EF + u'\u0425' # 0xC5 -> CYRILLIC CAPITAL LETTER HA + u'\u0426' # 0xC6 -> CYRILLIC CAPITAL LETTER TSE + u'\u0427' # 0xC7 -> CYRILLIC CAPITAL LETTER CHE + u'\u0428' # 0xC8 -> CYRILLIC CAPITAL LETTER SHA + u'\u0429' # 0xC9 -> CYRILLIC CAPITAL LETTER SHCHA + u'\u042a' # 0xCA -> CYRILLIC CAPITAL LETTER HARD SIGN + u'\u042b' # 0xCB -> CYRILLIC CAPITAL LETTER YERU + u'\u042c' # 0xCC -> CYRILLIC CAPITAL LETTER SOFT SIGN + u'\u042d' # 0xCD -> CYRILLIC CAPITAL LETTER E + u'\u042e' # 0xCE -> CYRILLIC CAPITAL LETTER YU + u'\u042f' # 0xCF -> CYRILLIC CAPITAL LETTER YA + u'\u0430' # 0xD0 -> CYRILLIC SMALL LETTER A + u'\u0431' # 0xD1 -> CYRILLIC SMALL LETTER BE + u'\u0432' # 0xD2 -> CYRILLIC SMALL LETTER VE + u'\u0433' # 0xD3 -> CYRILLIC SMALL LETTER GHE + u'\u0434' # 0xD4 -> CYRILLIC SMALL LETTER DE + u'\u0435' # 0xD5 -> CYRILLIC SMALL LETTER IE + u'\u0436' # 0xD6 -> CYRILLIC SMALL LETTER ZHE + u'\u0437' # 0xD7 -> CYRILLIC SMALL LETTER ZE + u'\u0438' # 0xD8 -> CYRILLIC SMALL LETTER I + u'\u0439' # 0xD9 -> CYRILLIC SMALL LETTER SHORT I + u'\u043a' # 0xDA -> CYRILLIC SMALL LETTER KA + u'\u043b' # 0xDB -> CYRILLIC SMALL LETTER EL + u'\u043c' # 0xDC -> CYRILLIC SMALL LETTER EM + u'\u043d' # 0xDD -> CYRILLIC SMALL LETTER EN + u'\u043e' # 0xDE -> CYRILLIC SMALL LETTER O + u'\u043f' # 0xDF -> CYRILLIC SMALL LETTER PE + u'\u0440' # 0xE0 -> CYRILLIC SMALL LETTER ER + u'\u0441' # 0xE1 -> CYRILLIC SMALL LETTER ES + u'\u0442' # 0xE2 -> CYRILLIC SMALL LETTER TE + u'\u0443' # 0xE3 -> CYRILLIC SMALL LETTER U + u'\u0444' # 0xE4 -> CYRILLIC SMALL LETTER EF + u'\u0445' # 0xE5 -> CYRILLIC SMALL LETTER HA + u'\u0446' # 0xE6 -> CYRILLIC SMALL LETTER TSE + u'\u0447' # 0xE7 -> CYRILLIC SMALL LETTER CHE + u'\u0448' # 0xE8 -> CYRILLIC SMALL LETTER SHA + u'\u0449' # 0xE9 -> CYRILLIC SMALL LETTER SHCHA + u'\u044a' # 0xEA -> CYRILLIC SMALL LETTER HARD SIGN + u'\u044b' # 0xEB -> CYRILLIC SMALL LETTER YERU + u'\u044c' # 0xEC -> CYRILLIC SMALL LETTER SOFT SIGN + u'\u044d' # 0xED -> CYRILLIC SMALL LETTER E + u'\u044e' # 0xEE -> CYRILLIC SMALL LETTER YU + u'\u044f' # 0xEF -> CYRILLIC SMALL LETTER YA + u'\u2116' # 0xF0 -> NUMERO SIGN + u'\u0451' # 0xF1 -> CYRILLIC SMALL LETTER IO + u'\u0452' # 0xF2 -> CYRILLIC SMALL LETTER DJE + u'\u0453' # 0xF3 -> CYRILLIC SMALL LETTER GJE + u'\u0454' # 0xF4 -> CYRILLIC SMALL LETTER UKRAINIAN IE + u'\u0455' # 0xF5 -> CYRILLIC SMALL LETTER DZE + u'\u0456' # 0xF6 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + u'\u0457' # 0xF7 -> CYRILLIC SMALL LETTER YI + u'\u0458' # 0xF8 -> CYRILLIC SMALL LETTER JE + u'\u0459' # 0xF9 -> CYRILLIC SMALL LETTER LJE + u'\u045a' # 0xFA -> CYRILLIC SMALL LETTER NJE + u'\u045b' # 0xFB -> CYRILLIC SMALL LETTER TSHE + u'\u045c' # 0xFC -> CYRILLIC SMALL LETTER KJE + u'\xa7' # 0xFD -> SECTION SIGN + u'\u045e' # 0xFE -> CYRILLIC SMALL LETTER SHORT U + u'\u045f' # 0xFF -> CYRILLIC SMALL LETTER DZHE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/iso8859_5.pyc b/PythonHome/Lib/encodings/iso8859_5.pyc deleted file mode 100644 index 7c5ab671305e5235d52b8506f9f4f415917bfd83..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2734 zcmc&$c~=}o5br%%76`eOh`RA&JpeB>(HKd{AsPtIq9llJhMid$+yiF@BN|O$NeJW) zS3(HHGhXpF@%Fv`1l3=`uiyuWRXwm1(DyL;Ll?TJ?%J-d`t`4?@cmg5zTC1WmSD3V zAO5YyVO>F?G1iLG!!$2Tc~~ndKBjwEmzO0`_p<@Ua*XY6^)f9W4L)fI<_$ik6-a|$ z8bW!4pJ|0m_exuUCDB1RZwoN3XwDXtw&J`k$g~ogv=%UJ32O~W2k0rpau{HkB8^2$ zDS<8&k)~d|GnS%cd3Y)Pm58H>o zUS@k)&W9;`aJ|vpE+ez-CAgZv+|z1z+zD4MNfl9u+iH7CcXrVUmYzz=6pT!Fk1gZS zO*3m+Q8Y3sta8+<+IAT2ZF63%wmgi8g|kaSQ$#K)f9AQ7L=@UOF9k#!5tmC+ou7h2 z;41{4Qh?%mV|JVqVzV(v2@*SmA|B7EX+0jd!*Y_&YCS2ODr8eAOZP0PEeeu?dsrb3 zi_Qpoi+%QTRO&McQ%~y|TTN}12$~68m7hF~R^rs55xyRcxzr&B{2k^sxa#r+iG!5! z5oPdIm&Kyww$VVrWVRA=g$O4hR46)04;Nd>kED@NQ*P3W=SxUYhSx%?6w^5+D5TGA zYRb|jq^{$Ci6&jzvN`WT&q6G>NZR~ASkfgsSQ2*@V5v}{a z#z#VL)tqBQkgg_Xo4T5AF%7Jnc^(qWHq#gBMjakv*+QL3F1dH=rX{t-b0d0`;gGq_ z3qjFU?LP^DiYwK(*%0zc(>2x6dMyg)H91WY+aVQTd{+3N{Bt_?wg7Qj3sNn|254im z3Q;M^v4U8XDA8!s)1s|Kjfi@3==g`S|N z7=MEDr>BqTN@2QC1 zd*A&JR900#_|U_TJX-VE;9{t=qOgQ~&I9I~p2yHa)MznqPRa zW!LW3m)c%_CB8>(PiT6wqtobmHI>d}yI(UcyXW=2Z}h(T*1osj+0PH~KHkrBe1IS1 zhxi~r%!l|eKf;glWBfQj!B6s2{4^ioqkN2y^9g>2pXHPM9G~Ln`81#57oZRNAqN9+ z5Dvj09EKqnh9hv4UxMRs0#3pyI1M8(3S%%16L1F3!X%u7DL4<)FasChU3d@PhY#RG z_y{h-$M6Y!3ZKE}a0$MEFX1cr8oq&V;XC*qF2fc00e*y^;Ai*+eudxQcX2@UiGGn2 z1LB}KBnHJ{F(ih?5ph%;6UW7gKL*CdDREkih*2>n#>IpLMCrPa zqSWWKYy$flbp?kPE*ppl4kf6iC{)dCs@-${UbOcZDa~mZxOxp|7Jd1$#cpt#>P8># awW!BoQ}maG%KT;ia$k9%urzp;`Tqi}3UcZI diff --git a/PythonHome/Lib/encodings/iso8859_6.py b/PythonHome/Lib/encodings/iso8859_6.py new file mode 100644 index 0000000000..16c34a3f61 --- /dev/null +++ b/PythonHome/Lib/encodings/iso8859_6.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_6 generated from 'MAPPINGS/ISO8859/8859-6.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-6', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\xa4' # 0xA4 -> CURRENCY SIGN + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\u060c' # 0xAC -> ARABIC COMMA + u'\xad' # 0xAD -> SOFT HYPHEN + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\u061b' # 0xBB -> ARABIC SEMICOLON + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\u061f' # 0xBF -> ARABIC QUESTION MARK + u'\ufffe' + u'\u0621' # 0xC1 -> ARABIC LETTER HAMZA + u'\u0622' # 0xC2 -> ARABIC LETTER ALEF WITH MADDA ABOVE + u'\u0623' # 0xC3 -> ARABIC LETTER ALEF WITH HAMZA ABOVE + u'\u0624' # 0xC4 -> ARABIC LETTER WAW WITH HAMZA ABOVE + u'\u0625' # 0xC5 -> ARABIC LETTER ALEF WITH HAMZA BELOW + u'\u0626' # 0xC6 -> ARABIC LETTER YEH WITH HAMZA ABOVE + u'\u0627' # 0xC7 -> ARABIC LETTER ALEF + u'\u0628' # 0xC8 -> ARABIC LETTER BEH + u'\u0629' # 0xC9 -> ARABIC LETTER TEH MARBUTA + u'\u062a' # 0xCA -> ARABIC LETTER TEH + u'\u062b' # 0xCB -> ARABIC LETTER THEH + u'\u062c' # 0xCC -> ARABIC LETTER JEEM + u'\u062d' # 0xCD -> ARABIC LETTER HAH + u'\u062e' # 0xCE -> ARABIC LETTER KHAH + u'\u062f' # 0xCF -> ARABIC LETTER DAL + u'\u0630' # 0xD0 -> ARABIC LETTER THAL + u'\u0631' # 0xD1 -> ARABIC LETTER REH + u'\u0632' # 0xD2 -> ARABIC LETTER ZAIN + u'\u0633' # 0xD3 -> ARABIC LETTER SEEN + u'\u0634' # 0xD4 -> ARABIC LETTER SHEEN + u'\u0635' # 0xD5 -> ARABIC LETTER SAD + u'\u0636' # 0xD6 -> ARABIC LETTER DAD + u'\u0637' # 0xD7 -> ARABIC LETTER TAH + u'\u0638' # 0xD8 -> ARABIC LETTER ZAH + u'\u0639' # 0xD9 -> ARABIC LETTER AIN + u'\u063a' # 0xDA -> ARABIC LETTER GHAIN + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\u0640' # 0xE0 -> ARABIC TATWEEL + u'\u0641' # 0xE1 -> ARABIC LETTER FEH + u'\u0642' # 0xE2 -> ARABIC LETTER QAF + u'\u0643' # 0xE3 -> ARABIC LETTER KAF + u'\u0644' # 0xE4 -> ARABIC LETTER LAM + u'\u0645' # 0xE5 -> ARABIC LETTER MEEM + u'\u0646' # 0xE6 -> ARABIC LETTER NOON + u'\u0647' # 0xE7 -> ARABIC LETTER HEH + u'\u0648' # 0xE8 -> ARABIC LETTER WAW + u'\u0649' # 0xE9 -> ARABIC LETTER ALEF MAKSURA + u'\u064a' # 0xEA -> ARABIC LETTER YEH + u'\u064b' # 0xEB -> ARABIC FATHATAN + u'\u064c' # 0xEC -> ARABIC DAMMATAN + u'\u064d' # 0xED -> ARABIC KASRATAN + u'\u064e' # 0xEE -> ARABIC FATHA + u'\u064f' # 0xEF -> ARABIC DAMMA + u'\u0650' # 0xF0 -> ARABIC KASRA + u'\u0651' # 0xF1 -> ARABIC SHADDA + u'\u0652' # 0xF2 -> ARABIC SUKUN + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/iso8859_6.pyc b/PythonHome/Lib/encodings/iso8859_6.pyc deleted file mode 100644 index 6cf0f040353aa34d8c9aa3c49bcda9054cf44abe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2778 zcmc&$`Cl7F6rar|Ap|JBH5GO1MLYnnBGpbx=V(sE0$C0=vcEh+pY|oMbp-(X(&0nR8X3G zH}v)Oq_(8ndeYnQl{V~J+FSd#_ctr!79GJAIvQy$PqfD4)|afnCU`) z6zEKF9Doy;PJ+J>Hpn4@vP{%;65*#&e4W~sPIVk(3q$M1>1EJSLPjOB3%(&jL!=@@ z$P&z_g5|<9hc1Fy9bzwN<*etfm=YqOkfqvC-t<=C4vv}6i4d$}d5j7_OxrHmP7;(v zbWRgUt%F;wp~0#ZXV8Zcu<%w1XzI`;#!sZn2}H%Eb3y>L0dX-U#JM4;2)>HosWs4D zs?VNrL~O?ABtk-C&}Fkltzc%eG%f~(k};Ntp^7>cqYU;E(t;qVu!ht^b8wGns9vT^ zLFg&!wplQXRLgG?2--T#ipQtXau|9vg4<(|fI7&4Kf}BVW&^$eaey*1QU-2yBArCD zDGNFxq7{&rxf}{0g<=)MR8k=|=_FDj zMe%B3R&j7RlR#VAgOnmjYy}CyOW*eVX)kNp;=rJ0z=1&nv}R3=ixU*vdMOom6h*41 zm@A1?6l|;FT~d(_Dx#s{sa)z&Ql#my3En`Br1r#W7&^#JBGpP!sUAL2@fn*&I!Pfp z9EsM%YU6eF4T~BVFIl>5`HGcST$xyPRnyhiT&t|U?)n>Uys0^P^DVdD*3#N``yF@Q zb@!U~dpg$Md*8bI*FVs?p{sl2rp;R(?0M+nt-YyjeUGT={zo4h*uEq4_}~*yW_M~s zx?$#qN37AO@`Yll{Iu=Rv1i7gop|o~T`#=2o9$tH**;cblWadbzz(uQ>@YjRj}~cAJImhv?blztFFWUpvjslIre}}; zLFQ+CB|i%ye~-V^r%0J_u^Dp=`|B`>jzvkcYZ~1rpd;SAI&oA&F z`A__3--0K&d)&S5KDXjdy8GP&?m_pEd)PhV9(AYOWA1VHgnQCG<({6m=PCt`_kBHSc5MQR(P7fJXJ<_e+E diff --git a/PythonHome/Lib/encodings/iso8859_7.py b/PythonHome/Lib/encodings/iso8859_7.py new file mode 100644 index 0000000000..a560023a08 --- /dev/null +++ b/PythonHome/Lib/encodings/iso8859_7.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_7 generated from 'MAPPINGS/ISO8859/8859-7.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-7', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\u2018' # 0xA1 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0xA2 -> RIGHT SINGLE QUOTATION MARK + u'\xa3' # 0xA3 -> POUND SIGN + u'\u20ac' # 0xA4 -> EURO SIGN + u'\u20af' # 0xA5 -> DRACHMA SIGN + u'\xa6' # 0xA6 -> BROKEN BAR + u'\xa7' # 0xA7 -> SECTION SIGN + u'\xa8' # 0xA8 -> DIAERESIS + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\u037a' # 0xAA -> GREEK YPOGEGRAMMENI + u'\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xac' # 0xAC -> NOT SIGN + u'\xad' # 0xAD -> SOFT HYPHEN + u'\ufffe' + u'\u2015' # 0xAF -> HORIZONTAL BAR + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\xb2' # 0xB2 -> SUPERSCRIPT TWO + u'\xb3' # 0xB3 -> SUPERSCRIPT THREE + u'\u0384' # 0xB4 -> GREEK TONOS + u'\u0385' # 0xB5 -> GREEK DIALYTIKA TONOS + u'\u0386' # 0xB6 -> GREEK CAPITAL LETTER ALPHA WITH TONOS + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\u0388' # 0xB8 -> GREEK CAPITAL LETTER EPSILON WITH TONOS + u'\u0389' # 0xB9 -> GREEK CAPITAL LETTER ETA WITH TONOS + u'\u038a' # 0xBA -> GREEK CAPITAL LETTER IOTA WITH TONOS + u'\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u038c' # 0xBC -> GREEK CAPITAL LETTER OMICRON WITH TONOS + u'\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + u'\u038e' # 0xBE -> GREEK CAPITAL LETTER UPSILON WITH TONOS + u'\u038f' # 0xBF -> GREEK CAPITAL LETTER OMEGA WITH TONOS + u'\u0390' # 0xC0 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + u'\u0391' # 0xC1 -> GREEK CAPITAL LETTER ALPHA + u'\u0392' # 0xC2 -> GREEK CAPITAL LETTER BETA + u'\u0393' # 0xC3 -> GREEK CAPITAL LETTER GAMMA + u'\u0394' # 0xC4 -> GREEK CAPITAL LETTER DELTA + u'\u0395' # 0xC5 -> GREEK CAPITAL LETTER EPSILON + u'\u0396' # 0xC6 -> GREEK CAPITAL LETTER ZETA + u'\u0397' # 0xC7 -> GREEK CAPITAL LETTER ETA + u'\u0398' # 0xC8 -> GREEK CAPITAL LETTER THETA + u'\u0399' # 0xC9 -> GREEK CAPITAL LETTER IOTA + u'\u039a' # 0xCA -> GREEK CAPITAL LETTER KAPPA + u'\u039b' # 0xCB -> GREEK CAPITAL LETTER LAMDA + u'\u039c' # 0xCC -> GREEK CAPITAL LETTER MU + u'\u039d' # 0xCD -> GREEK CAPITAL LETTER NU + u'\u039e' # 0xCE -> GREEK CAPITAL LETTER XI + u'\u039f' # 0xCF -> GREEK CAPITAL LETTER OMICRON + u'\u03a0' # 0xD0 -> GREEK CAPITAL LETTER PI + u'\u03a1' # 0xD1 -> GREEK CAPITAL LETTER RHO + u'\ufffe' + u'\u03a3' # 0xD3 -> GREEK CAPITAL LETTER SIGMA + u'\u03a4' # 0xD4 -> GREEK CAPITAL LETTER TAU + u'\u03a5' # 0xD5 -> GREEK CAPITAL LETTER UPSILON + u'\u03a6' # 0xD6 -> GREEK CAPITAL LETTER PHI + u'\u03a7' # 0xD7 -> GREEK CAPITAL LETTER CHI + u'\u03a8' # 0xD8 -> GREEK CAPITAL LETTER PSI + u'\u03a9' # 0xD9 -> GREEK CAPITAL LETTER OMEGA + u'\u03aa' # 0xDA -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + u'\u03ab' # 0xDB -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + u'\u03ac' # 0xDC -> GREEK SMALL LETTER ALPHA WITH TONOS + u'\u03ad' # 0xDD -> GREEK SMALL LETTER EPSILON WITH TONOS + u'\u03ae' # 0xDE -> GREEK SMALL LETTER ETA WITH TONOS + u'\u03af' # 0xDF -> GREEK SMALL LETTER IOTA WITH TONOS + u'\u03b0' # 0xE0 -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + u'\u03b1' # 0xE1 -> GREEK SMALL LETTER ALPHA + u'\u03b2' # 0xE2 -> GREEK SMALL LETTER BETA + u'\u03b3' # 0xE3 -> GREEK SMALL LETTER GAMMA + u'\u03b4' # 0xE4 -> GREEK SMALL LETTER DELTA + u'\u03b5' # 0xE5 -> GREEK SMALL LETTER EPSILON + u'\u03b6' # 0xE6 -> GREEK SMALL LETTER ZETA + u'\u03b7' # 0xE7 -> GREEK SMALL LETTER ETA + u'\u03b8' # 0xE8 -> GREEK SMALL LETTER THETA + u'\u03b9' # 0xE9 -> GREEK SMALL LETTER IOTA + u'\u03ba' # 0xEA -> GREEK SMALL LETTER KAPPA + u'\u03bb' # 0xEB -> GREEK SMALL LETTER LAMDA + u'\u03bc' # 0xEC -> GREEK SMALL LETTER MU + u'\u03bd' # 0xED -> GREEK SMALL LETTER NU + u'\u03be' # 0xEE -> GREEK SMALL LETTER XI + u'\u03bf' # 0xEF -> GREEK SMALL LETTER OMICRON + u'\u03c0' # 0xF0 -> GREEK SMALL LETTER PI + u'\u03c1' # 0xF1 -> GREEK SMALL LETTER RHO + u'\u03c2' # 0xF2 -> GREEK SMALL LETTER FINAL SIGMA + u'\u03c3' # 0xF3 -> GREEK SMALL LETTER SIGMA + u'\u03c4' # 0xF4 -> GREEK SMALL LETTER TAU + u'\u03c5' # 0xF5 -> GREEK SMALL LETTER UPSILON + u'\u03c6' # 0xF6 -> GREEK SMALL LETTER PHI + u'\u03c7' # 0xF7 -> GREEK SMALL LETTER CHI + u'\u03c8' # 0xF8 -> GREEK SMALL LETTER PSI + u'\u03c9' # 0xF9 -> GREEK SMALL LETTER OMEGA + u'\u03ca' # 0xFA -> GREEK SMALL LETTER IOTA WITH DIALYTIKA + u'\u03cb' # 0xFB -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA + u'\u03cc' # 0xFC -> GREEK SMALL LETTER OMICRON WITH TONOS + u'\u03cd' # 0xFD -> GREEK SMALL LETTER UPSILON WITH TONOS + u'\u03ce' # 0xFE -> GREEK SMALL LETTER OMEGA WITH TONOS + u'\ufffe' +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/iso8859_7.pyc b/PythonHome/Lib/encodings/iso8859_7.pyc deleted file mode 100644 index f9be977965bd580d749af995ef2eb660a477f50a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2741 zcmc&$X4DRL3U__%576=e> z-*3Xf3u3knZY ziiE-|6oG=m%amfKx`ocil4u}U(D|4$WkTl{x{`v<&y-TyG#4>tDr*i1186D0^5|fY zJdH)BQ2-q{g&Vre_G~6x+b-*J!c_Hey`0NwnYM6kR#6jS&B!iXxL{GdI^3paR9!Yz zC7jf=>2P`dvWAAb=&D#%U2F|~rHZDC>dMBojpgADn%Pb#5@e(@*Hsw|YPazdHGO!g zFkJxDjglJjCybMdjw5ga(_Zu!!^X9n(b~hLScKp={q%KH*Aixe_B6aWYDqi`CzG)b z7u$%xZf3e!-h&~#P#$%T3(pL5DoPU=ds@!LZFhx8ED?pcDYvFn`xM<^sHvm~LCfSi zP2q>C>sj51ppuEnD8p4{%WAE)Wx|TlQh*V$uulnSrjSXBpSd0+5Q&c76#}A-hzpTe z-W`HO;7bIaRD{$0`fM8~#KwJ&5F};*r+7Rgr`34e42n%Ut8}JtE0Ip3D4n~+YEqCS zJj04{7<7lG3C?>fuNp1srVFVG#j@zjqvp-%%Ki3;O{WcL#e|T zBo0!>LzKZ+9g0QBY*fREiD(7n5)n>7D3N!99uBsGA4x4Er<|ZCkC%|52=9beDxrHy zaS}FH$|*w?kUEC{C7P79857q1u6wauE@<=rU`a`~u_W%?gQY};%87Pz7>R3har`rk z(sWck7#|6}ITMBvK}t=`)Kxj%q-$6=3p^y2)zB9yqc#t*Y~h*-E;%`M!V;^=VHQ7xO+aVQTd{+3Nyc28eZ9d|(;-^}U z4ba496`)d*XGO6HQ6g&6)1st+NPp6*dtB7Yd&rb;wEzy zyZo*a{PByQ&H5gM5f@;lq3@-^RD|9egL>#dq^Pd@tX}_wxh%AV0(p^CSEyKgN&q6Jy;6 z#<~yklVd$2V?7u6DSn!t;b(up#?SE)e*TYJH^;j7@{9Zuzs#>dFZ4k_AB6!Jgdu(% zhWQQH2HRl=?1Wvg8}`6n*a!RJ033uva2SrjQ8)(2;RJk(mf$3O2j9afI1OjuEc^iH zUy2SKuf38Lq-8`~ttiHMkDH!40?xx2$e!lhtG8tzN6o>bEvq1Jy0X)KZGwH&A*9 nbtWwUqSG$6d+QPpo;9e|VQ=(?0wHh6TjnYA6;JcuX5PO5 NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\ufffe' + u'\xa2' # 0xA2 -> CENT SIGN + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa4' # 0xA4 -> CURRENCY SIGN + u'\xa5' # 0xA5 -> YEN SIGN + u'\xa6' # 0xA6 -> BROKEN BAR + u'\xa7' # 0xA7 -> SECTION SIGN + u'\xa8' # 0xA8 -> DIAERESIS + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\xd7' # 0xAA -> MULTIPLICATION SIGN + u'\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xac' # 0xAC -> NOT SIGN + u'\xad' # 0xAD -> SOFT HYPHEN + u'\xae' # 0xAE -> REGISTERED SIGN + u'\xaf' # 0xAF -> MACRON + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\xb2' # 0xB2 -> SUPERSCRIPT TWO + u'\xb3' # 0xB3 -> SUPERSCRIPT THREE + u'\xb4' # 0xB4 -> ACUTE ACCENT + u'\xb5' # 0xB5 -> MICRO SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\xb8' # 0xB8 -> CEDILLA + u'\xb9' # 0xB9 -> SUPERSCRIPT ONE + u'\xf7' # 0xBA -> DIVISION SIGN + u'\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + u'\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + u'\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\u2017' # 0xDF -> DOUBLE LOW LINE + u'\u05d0' # 0xE0 -> HEBREW LETTER ALEF + u'\u05d1' # 0xE1 -> HEBREW LETTER BET + u'\u05d2' # 0xE2 -> HEBREW LETTER GIMEL + u'\u05d3' # 0xE3 -> HEBREW LETTER DALET + u'\u05d4' # 0xE4 -> HEBREW LETTER HE + u'\u05d5' # 0xE5 -> HEBREW LETTER VAV + u'\u05d6' # 0xE6 -> HEBREW LETTER ZAYIN + u'\u05d7' # 0xE7 -> HEBREW LETTER HET + u'\u05d8' # 0xE8 -> HEBREW LETTER TET + u'\u05d9' # 0xE9 -> HEBREW LETTER YOD + u'\u05da' # 0xEA -> HEBREW LETTER FINAL KAF + u'\u05db' # 0xEB -> HEBREW LETTER KAF + u'\u05dc' # 0xEC -> HEBREW LETTER LAMED + u'\u05dd' # 0xED -> HEBREW LETTER FINAL MEM + u'\u05de' # 0xEE -> HEBREW LETTER MEM + u'\u05df' # 0xEF -> HEBREW LETTER FINAL NUN + u'\u05e0' # 0xF0 -> HEBREW LETTER NUN + u'\u05e1' # 0xF1 -> HEBREW LETTER SAMEKH + u'\u05e2' # 0xF2 -> HEBREW LETTER AYIN + u'\u05e3' # 0xF3 -> HEBREW LETTER FINAL PE + u'\u05e4' # 0xF4 -> HEBREW LETTER PE + u'\u05e5' # 0xF5 -> HEBREW LETTER FINAL TSADI + u'\u05e6' # 0xF6 -> HEBREW LETTER TSADI + u'\u05e7' # 0xF7 -> HEBREW LETTER QOF + u'\u05e8' # 0xF8 -> HEBREW LETTER RESH + u'\u05e9' # 0xF9 -> HEBREW LETTER SHIN + u'\u05ea' # 0xFA -> HEBREW LETTER TAV + u'\ufffe' + u'\ufffe' + u'\u200e' # 0xFD -> LEFT-TO-RIGHT MARK + u'\u200f' # 0xFE -> RIGHT-TO-LEFT MARK + u'\ufffe' +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/iso8859_8.pyc b/PythonHome/Lib/encodings/iso8859_8.pyc deleted file mode 100644 index 13480516f3b55fcf484cef83831439d83f60609a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2772 zcmc&$dsiDp6rW_15CW9GH5E1WMSK9hs;SmWp%2lL;s&LSXu4!Ku$Y&-gNRm(f^Y4+ zrSI0hXnjA69<`ox`yu9kzJP!D0qVW8Bn#*{*q)F`mu|24Dr4~KGNE!Sz4MKR-|1k7R`Kbq_v4<3;VzCt~Q?W>|kvA-j8+s&T z6>^dK_B9rnbZ;dZmfFhFD|g=Fa-apvn7aMVgE>7Ka)`A@d48aqh=WrRg%D zUYuzmeI8*jAVtWi73I(1N1t#%rsBan3@k;D@`xLjx*NpVcYQQ zW!%d~6b#ve^Ko~%^vve-a5jyx=d@zVaaT@B5m88SttV?Zt7r$?$Yx{+X1+MUr5}c6 z6)Zc7N+vtI4yDHKjb=}G$%@@wh7qxFR!L~8$Rx$jJl7J4N=s*ifM_G)a!QIbLr@8P zmB3Rgu)A8H9pi-9l+RIuga@%prSe+NNTqm44sr#3Ad5qlbSg#Z?j@x;K~ixItHfs0 z9szH)!WW{@mQPzo&d75uyG|l#rEyk1Wg0EUp+h6QJvwu#Lk##U%*$}rj0>%xhUU=(*!1q$tAa(5lt6PYrg`=6Wq_ z8xm62@IOS84sAindcZRq%e9g={|}aQ$PSjoomp6_l&IWj=Z2BEwiMgn!>G`h-nLDCb{IEsT-D*=8lc%5ymECo8f|L zX!?KR0wq_u>bjs=iou?kWu z8DSNPC{ZHL>1t6{v1vG!KpSFiN|7Ws-GtzzZ)^6nleH{)U|2Koz_1}&(^LRC)rQYWxJ` zXJDM@TbO0=E(9}ZoTdHJL;o%-gWmq z4UJ9r-go~453YFV;n>PY9$od=>c^Ycw6v~Ww|>JDZBIV6u|2-2<7qX~`OLFjo3|vN z>wf-))K;x0ts9x%KC}PDY%X6YzGT^a;N`(rhF*Pb+v{&^hhcaV-hvSrg}31yco*J- z_u&Kh5I%yBVF&DlU9cPWz+Tt~`{4kL!9h3#hv5hug=26WPQc0Ef4c;y;53|pvv3Z^ z;XGWpJO-b^=kNu5317k2@C|$m-@*6r16+g&_z`}(JOMw$FYqf|!o~mUcXD`4>=L`h z9Aw2_TR(Hw@&Q4?2ocTc(;#E%R dU9I3+n<^oePG2|}_Jw_QN}a#5HgJXc{sa#ynhpQ} diff --git a/PythonHome/Lib/encodings/iso8859_9.py b/PythonHome/Lib/encodings/iso8859_9.py new file mode 100644 index 0000000000..b8029382c0 --- /dev/null +++ b/PythonHome/Lib/encodings/iso8859_9.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_9 generated from 'MAPPINGS/ISO8859/8859-9.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-9', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\xa0' # 0xA0 -> NO-BREAK SPACE + u'\xa1' # 0xA1 -> INVERTED EXCLAMATION MARK + u'\xa2' # 0xA2 -> CENT SIGN + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa4' # 0xA4 -> CURRENCY SIGN + u'\xa5' # 0xA5 -> YEN SIGN + u'\xa6' # 0xA6 -> BROKEN BAR + u'\xa7' # 0xA7 -> SECTION SIGN + u'\xa8' # 0xA8 -> DIAERESIS + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\xaa' # 0xAA -> FEMININE ORDINAL INDICATOR + u'\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xac' # 0xAC -> NOT SIGN + u'\xad' # 0xAD -> SOFT HYPHEN + u'\xae' # 0xAE -> REGISTERED SIGN + u'\xaf' # 0xAF -> MACRON + u'\xb0' # 0xB0 -> DEGREE SIGN + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\xb2' # 0xB2 -> SUPERSCRIPT TWO + u'\xb3' # 0xB3 -> SUPERSCRIPT THREE + u'\xb4' # 0xB4 -> ACUTE ACCENT + u'\xb5' # 0xB5 -> MICRO SIGN + u'\xb6' # 0xB6 -> PILCROW SIGN + u'\xb7' # 0xB7 -> MIDDLE DOT + u'\xb8' # 0xB8 -> CEDILLA + u'\xb9' # 0xB9 -> SUPERSCRIPT ONE + u'\xba' # 0xBA -> MASCULINE ORDINAL INDICATOR + u'\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + u'\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + u'\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + u'\xbf' # 0xBF -> INVERTED QUESTION MARK + u'\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + u'\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + u'\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + u'\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\u011e' # 0xD0 -> LATIN CAPITAL LETTER G WITH BREVE + u'\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + u'\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xd7' # 0xD7 -> MULTIPLICATION SIGN + u'\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + u'\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + u'\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\u0130' # 0xDD -> LATIN CAPITAL LETTER I WITH DOT ABOVE + u'\u015e' # 0xDE -> LATIN CAPITAL LETTER S WITH CEDILLA + u'\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + u'\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + u'\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe6' # 0xE6 -> LATIN SMALL LETTER AE + u'\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + u'\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + u'\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + u'\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + u'\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + u'\u011f' # 0xF0 -> LATIN SMALL LETTER G WITH BREVE + u'\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + u'\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + u'\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + u'\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf7' # 0xF7 -> DIVISION SIGN + u'\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + u'\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + u'\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + u'\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + u'\u0131' # 0xFD -> LATIN SMALL LETTER DOTLESS I + u'\u015f' # 0xFE -> LATIN SMALL LETTER S WITH CEDILLA + u'\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/iso8859_9.pyc b/PythonHome/Lib/encodings/iso8859_9.pyc deleted file mode 100644 index 6792ad8c9738e2e5aaa18cd92b08694e28b00d19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2733 zcmc&$`Bxl85bix$76`eOh`RC0dW3jIL1QG4Lo^VajV3{KGwjU5;2toI)e0=n`l7@AQ zgeF7-NsrLHBIOYcr1*sH5v^X4B;7B1gy-a z7rIy40wPHc!Z}+&Xa$3|ptKd{Y(b$F@uVS7Xk$b}NID=-A<<0%hB?w$w3riUB@wCb zv|F;7NOg;9stH>+BeiNslmfX48>rwR7t0 zYw8xnX4J$M@mFTBm|jt~cA0=uqi82dI};syLnq z37rBb;3TF!6fdPsx>vC76G|+~@Y_NDx@{T>JHc}vej3%hJb{EQM5{-vpkJ@By`tMk zDSK$W&fP8}v+OannxNd%YFpe1S1w7FP>9=VQ%ZMs@d=imO3DB z_IOfiG6_>p>ls^3&65b430jq(9E~Q@)S(f*9!)l<_fT=v9}* zqU^TLAR%P75^{wJCm~cgI!O-~Tgi{4kx^4_(xd0gNO6Wkp;Zd`oFWp^=X^C~=@L@c z@xMfqFKyhQ_n>DamUAU-{vRy)k{v9WJ0q}ExKO#-jt(PpZ8D92hEW+yrYGYgqc>^L zF(JrT6SGZSO)oJGs+&0;GRvy?i+rOF52>)SvGxup4;s(HPVg!7u5rbz9O3otz^dQkpBoqAhFJPA#YF~>y%VJ zQ8uZXOfoA=k$bGdZ%JV~D2#@}xAM4GX){fmb&7_1q-}OirK!c-6rOxf&{If1LHX0( z#dPv`ef~f&FO(lHC@dONJa*jp2@@wxe(LFxDbJKX``q)9sV}_v(#x+*i@y5W>u*di zoAKsbZ@=^I%=g|eulV4@Ss%^*xN=Ta_1t;$7kpCl>1PXT>lW32uEZ99@#T`G%No9F z{Q8^taB;66qxIWVI+Jbt&a~|I?>m0z{PCw1KmW24x?mNohHmJAHLw=e!Ft#L z8(|Y{hApraw!yEk9d^J@*af>`5A20~upbVdVK@Ru;TRl;6L1nv!D%=H zXW<;2hYN5KF2QBE0$1T0T!$NQ6K=t6xC3|L9^8lD;SYF#UAPKYV>kBT8eEI(a6N9o zjkpOn;}+bC+xmNPJMO@pxC?jV9^8xja6cZvgLtU_^21*2!^3z4kK!>rjwkRWp2E|3 z2G8O-JdYRfB3|n6!z*|dui +# + +import _codecs_kr, codecs +import _multibytecodec as mbc + +codec = _codecs_kr.getcodec('johab') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='johab', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/johab.pyc b/PythonHome/Lib/encodings/johab.pyc deleted file mode 100644 index fbd1d8784c909c3df3d1c3f587aa3225bcd01ae9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1673 zcmcgs&2G~`5FY=;`Kgm21gL<-fm2R>0)#38hf2`H=1^fpGKqH+9Ac-kw?a9m&(xRU zF?ay@X52VY3x`}{d)Kowv*VfB@3Z&2+qt{?HcIIJ^6@^$D1TwncpO?1MYZfu9Rh`Cjp zJEUO<#N$LfLYjG`JGDnh8ivZFD;_=Z2y2fX=`Js#KG!rF^iW^=2iK)-KwPZ8Po^Rb zSK1_XKOERTV3e;gp;lCHTv~WiIs~60pVVjoD-Af1ZDESze3F?swjEhyD}A%%B|9V> z-v*FO&a#M5L9C*{LL!x?kj}=R)9F}T(|lfzCDF6%wc^Y|jFOKmaN3T23gIG83X_@K zPL`h}eDSyxF1;=#a_jUx=#|TpNF4W|jGEZ+1f%2_f%`C@k5c0i^Wl?twwDigYh(*E z$&{IBbHq&A_%a`6)fva`GPx>Jd(2E2kgs={)ZpktH)Q=eCJR1*zIeb=k1WUy4G8CN zWiY-$fHOD@{DQo;NxH@0-%xWj;Ce4D1BiK`@FvCBR}6c>MY_XjMT6p@x}roOy(;C@ zaB?`cJ;hIHo_tMMB-AP`e|^X-yU1rN;mPjfib1Lv8H(K$_u~+d+Y@Y<8{{(w$%^$G zEK3GGfq{V&;tu2~j$Jx!&rqi_*P9&BImrWD-c_6y%P~1OB-|~rl z+3t8uaVhG*PWQZ%qV4njNc&`vcKpj+AygWr_z!bXx46;os^8yx?tIC7Jat01@4ocg L&I^ynTikyEG*~!S diff --git a/PythonHome/Lib/encodings/koi8_r.py b/PythonHome/Lib/encodings/koi8_r.py new file mode 100644 index 0000000000..f9eb82c0db --- /dev/null +++ b/PythonHome/Lib/encodings/koi8_r.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec koi8_r generated from 'MAPPINGS/VENDORS/MISC/KOI8-R.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='koi8-r', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\u2500' # 0x80 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u2502' # 0x81 -> BOX DRAWINGS LIGHT VERTICAL + u'\u250c' # 0x82 -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2510' # 0x83 -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x84 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2518' # 0x85 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u251c' # 0x86 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2524' # 0x87 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\u252c' # 0x88 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u2534' # 0x89 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u253c' # 0x8A -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\u2580' # 0x8B -> UPPER HALF BLOCK + u'\u2584' # 0x8C -> LOWER HALF BLOCK + u'\u2588' # 0x8D -> FULL BLOCK + u'\u258c' # 0x8E -> LEFT HALF BLOCK + u'\u2590' # 0x8F -> RIGHT HALF BLOCK + u'\u2591' # 0x90 -> LIGHT SHADE + u'\u2592' # 0x91 -> MEDIUM SHADE + u'\u2593' # 0x92 -> DARK SHADE + u'\u2320' # 0x93 -> TOP HALF INTEGRAL + u'\u25a0' # 0x94 -> BLACK SQUARE + u'\u2219' # 0x95 -> BULLET OPERATOR + u'\u221a' # 0x96 -> SQUARE ROOT + u'\u2248' # 0x97 -> ALMOST EQUAL TO + u'\u2264' # 0x98 -> LESS-THAN OR EQUAL TO + u'\u2265' # 0x99 -> GREATER-THAN OR EQUAL TO + u'\xa0' # 0x9A -> NO-BREAK SPACE + u'\u2321' # 0x9B -> BOTTOM HALF INTEGRAL + u'\xb0' # 0x9C -> DEGREE SIGN + u'\xb2' # 0x9D -> SUPERSCRIPT TWO + u'\xb7' # 0x9E -> MIDDLE DOT + u'\xf7' # 0x9F -> DIVISION SIGN + u'\u2550' # 0xA0 -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u2551' # 0xA1 -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2552' # 0xA2 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + u'\u0451' # 0xA3 -> CYRILLIC SMALL LETTER IO + u'\u2553' # 0xA4 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + u'\u2554' # 0xA5 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u2555' # 0xA6 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + u'\u2556' # 0xA7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + u'\u2557' # 0xA8 -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u2558' # 0xA9 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + u'\u2559' # 0xAA -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + u'\u255a' # 0xAB -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u255b' # 0xAC -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + u'\u255c' # 0xAD -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + u'\u255d' # 0xAE -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\u255e' # 0xAF -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + u'\u255f' # 0xB0 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + u'\u2560' # 0xB1 -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2561' # 0xB2 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + u'\u0401' # 0xB3 -> CYRILLIC CAPITAL LETTER IO + u'\u2562' # 0xB4 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + u'\u2563' # 0xB5 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u2564' # 0xB6 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + u'\u2565' # 0xB7 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + u'\u2566' # 0xB8 -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2567' # 0xB9 -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + u'\u2568' # 0xBA -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + u'\u2569' # 0xBB -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u256a' # 0xBC -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + u'\u256b' # 0xBD -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + u'\u256c' # 0xBE -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\xa9' # 0xBF -> COPYRIGHT SIGN + u'\u044e' # 0xC0 -> CYRILLIC SMALL LETTER YU + u'\u0430' # 0xC1 -> CYRILLIC SMALL LETTER A + u'\u0431' # 0xC2 -> CYRILLIC SMALL LETTER BE + u'\u0446' # 0xC3 -> CYRILLIC SMALL LETTER TSE + u'\u0434' # 0xC4 -> CYRILLIC SMALL LETTER DE + u'\u0435' # 0xC5 -> CYRILLIC SMALL LETTER IE + u'\u0444' # 0xC6 -> CYRILLIC SMALL LETTER EF + u'\u0433' # 0xC7 -> CYRILLIC SMALL LETTER GHE + u'\u0445' # 0xC8 -> CYRILLIC SMALL LETTER HA + u'\u0438' # 0xC9 -> CYRILLIC SMALL LETTER I + u'\u0439' # 0xCA -> CYRILLIC SMALL LETTER SHORT I + u'\u043a' # 0xCB -> CYRILLIC SMALL LETTER KA + u'\u043b' # 0xCC -> CYRILLIC SMALL LETTER EL + u'\u043c' # 0xCD -> CYRILLIC SMALL LETTER EM + u'\u043d' # 0xCE -> CYRILLIC SMALL LETTER EN + u'\u043e' # 0xCF -> CYRILLIC SMALL LETTER O + u'\u043f' # 0xD0 -> CYRILLIC SMALL LETTER PE + u'\u044f' # 0xD1 -> CYRILLIC SMALL LETTER YA + u'\u0440' # 0xD2 -> CYRILLIC SMALL LETTER ER + u'\u0441' # 0xD3 -> CYRILLIC SMALL LETTER ES + u'\u0442' # 0xD4 -> CYRILLIC SMALL LETTER TE + u'\u0443' # 0xD5 -> CYRILLIC SMALL LETTER U + u'\u0436' # 0xD6 -> CYRILLIC SMALL LETTER ZHE + u'\u0432' # 0xD7 -> CYRILLIC SMALL LETTER VE + u'\u044c' # 0xD8 -> CYRILLIC SMALL LETTER SOFT SIGN + u'\u044b' # 0xD9 -> CYRILLIC SMALL LETTER YERU + u'\u0437' # 0xDA -> CYRILLIC SMALL LETTER ZE + u'\u0448' # 0xDB -> CYRILLIC SMALL LETTER SHA + u'\u044d' # 0xDC -> CYRILLIC SMALL LETTER E + u'\u0449' # 0xDD -> CYRILLIC SMALL LETTER SHCHA + u'\u0447' # 0xDE -> CYRILLIC SMALL LETTER CHE + u'\u044a' # 0xDF -> CYRILLIC SMALL LETTER HARD SIGN + u'\u042e' # 0xE0 -> CYRILLIC CAPITAL LETTER YU + u'\u0410' # 0xE1 -> CYRILLIC CAPITAL LETTER A + u'\u0411' # 0xE2 -> CYRILLIC CAPITAL LETTER BE + u'\u0426' # 0xE3 -> CYRILLIC CAPITAL LETTER TSE + u'\u0414' # 0xE4 -> CYRILLIC CAPITAL LETTER DE + u'\u0415' # 0xE5 -> CYRILLIC CAPITAL LETTER IE + u'\u0424' # 0xE6 -> CYRILLIC CAPITAL LETTER EF + u'\u0413' # 0xE7 -> CYRILLIC CAPITAL LETTER GHE + u'\u0425' # 0xE8 -> CYRILLIC CAPITAL LETTER HA + u'\u0418' # 0xE9 -> CYRILLIC CAPITAL LETTER I + u'\u0419' # 0xEA -> CYRILLIC CAPITAL LETTER SHORT I + u'\u041a' # 0xEB -> CYRILLIC CAPITAL LETTER KA + u'\u041b' # 0xEC -> CYRILLIC CAPITAL LETTER EL + u'\u041c' # 0xED -> CYRILLIC CAPITAL LETTER EM + u'\u041d' # 0xEE -> CYRILLIC CAPITAL LETTER EN + u'\u041e' # 0xEF -> CYRILLIC CAPITAL LETTER O + u'\u041f' # 0xF0 -> CYRILLIC CAPITAL LETTER PE + u'\u042f' # 0xF1 -> CYRILLIC CAPITAL LETTER YA + u'\u0420' # 0xF2 -> CYRILLIC CAPITAL LETTER ER + u'\u0421' # 0xF3 -> CYRILLIC CAPITAL LETTER ES + u'\u0422' # 0xF4 -> CYRILLIC CAPITAL LETTER TE + u'\u0423' # 0xF5 -> CYRILLIC CAPITAL LETTER U + u'\u0416' # 0xF6 -> CYRILLIC CAPITAL LETTER ZHE + u'\u0412' # 0xF7 -> CYRILLIC CAPITAL LETTER VE + u'\u042c' # 0xF8 -> CYRILLIC CAPITAL LETTER SOFT SIGN + u'\u042b' # 0xF9 -> CYRILLIC CAPITAL LETTER YERU + u'\u0417' # 0xFA -> CYRILLIC CAPITAL LETTER ZE + u'\u0428' # 0xFB -> CYRILLIC CAPITAL LETTER SHA + u'\u042d' # 0xFC -> CYRILLIC CAPITAL LETTER E + u'\u0429' # 0xFD -> CYRILLIC CAPITAL LETTER SHCHA + u'\u0427' # 0xFE -> CYRILLIC CAPITAL LETTER CHE + u'\u042a' # 0xFF -> CYRILLIC CAPITAL LETTER HARD SIGN +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/koi8_r.pyc b/PythonHome/Lib/encodings/koi8_r.pyc deleted file mode 100644 index dfed09e06e7df1d22840d2ee40bfa72acf76a679..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2755 zcmc&$33n7l5biy*SrTs0VAREn^&s&U6%h!B5wgTt=9=tVie^_)I_5O zm|kuO5N=dNB&ewG#Xr#V7wRwg1F))x>;U>ec+cl-rqf-uU0wCn*Hs(%vpRZl^}1x5 zU3~)he?Gp&5gateT5$9+&Cjwv)`F7&(|v5cpJi|!WW9{_Ft)bE&$N(K1f(KdRs@(< zAr(QXh?EsUrd2ZCFLfc7K?BjUF2uBPW4f@^Rh4yNrd89TrGjbWSxZD3KuZzUgAPW? z(`0-C1(3xd*4%A%6!Ni#4%JlCmTtzH)Xq*L-yUlyXnH!fpX)r(oHJXgTe)WCtk_1w>Y#0DGE>*tT^EfS zSMW(#Av{(ZFGK1_$wKldhJ%i-BXkngUi26P$GM-;JiwG>oDyJ#>Fbthq^&fq=?&uB zK;kJlSd6Xru}%2rXO^G!1TbhH$`jsp=~>YlkJ2e-A8!N_-ZS<(;PGz(@ij!GtnVhzsfT9+Gbtz%Y-tuBxVgu6xJGLGy~@XU87Q7E+a zI{y)Bgjoz+|WrY=w9x!BfaP$qEluNsEk;SF>Kkw+NOn zqVTQ-RjHyws&SA8m#EpIF2VGy{u>-ASChs}hkZAqxJXjv|3Q(`>!L`MxdBCmYLgf0 zEdV5bO~?120aPZU>JB(axJ?_gir7&`l9s8fxz(nDMY7C2V%9?XA|=x09#$xvGszz> zm0mz{c8jQp5>!NFRM(xa=&JVLpHCIE);qr(E~Tb{p_J zPuLYOPxvBE*9bPs#K|+=x=E+YHq@BU6lB%$j#cRLD8vGVpin3ux0OMQc-gL_E7$@p zvwJ2ki$q4|tMr9^Rrm?ZPuC@)kk20ohQbw*%ILVN>hTjMPMSPr>a^*1-CZ-|p4xlw zyFWJbfd?OY_>o!hM<09qiP?4aPd@eZGtWNv{0nnleCg%6ugrUO{(^-Kixw|g`dZ`b z%a%7KRy4n%Bv-z+@0Y5CZ0zU%$DDYw6$ABLPeggPO;HQ9}27U(k+0j$ZSK^%b-uYBq z5I;J-;s@swaY_6neipxo%i>q@oA}-N+S%f4b+$P@;-Wb33^-qi5vR}j(&=|Tb3PZ} zib1hm92d6WVp!}H$HZ>2N9+~*#C~x=92AGdcVb8!7DvQUQ4%}ES#d_}5+}ts;*>Zc zPRA+B$Z6_Ahg$4ft9;BB; diff --git a/PythonHome/Lib/encodings/koi8_u.py b/PythonHome/Lib/encodings/koi8_u.py new file mode 100644 index 0000000000..a9317b12b7 --- /dev/null +++ b/PythonHome/Lib/encodings/koi8_u.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec koi8_u generated from 'python-mappings/KOI8-U.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='koi8-u', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\u2500' # 0x80 -> BOX DRAWINGS LIGHT HORIZONTAL + u'\u2502' # 0x81 -> BOX DRAWINGS LIGHT VERTICAL + u'\u250c' # 0x82 -> BOX DRAWINGS LIGHT DOWN AND RIGHT + u'\u2510' # 0x83 -> BOX DRAWINGS LIGHT DOWN AND LEFT + u'\u2514' # 0x84 -> BOX DRAWINGS LIGHT UP AND RIGHT + u'\u2518' # 0x85 -> BOX DRAWINGS LIGHT UP AND LEFT + u'\u251c' # 0x86 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + u'\u2524' # 0x87 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + u'\u252c' # 0x88 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + u'\u2534' # 0x89 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + u'\u253c' # 0x8A -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + u'\u2580' # 0x8B -> UPPER HALF BLOCK + u'\u2584' # 0x8C -> LOWER HALF BLOCK + u'\u2588' # 0x8D -> FULL BLOCK + u'\u258c' # 0x8E -> LEFT HALF BLOCK + u'\u2590' # 0x8F -> RIGHT HALF BLOCK + u'\u2591' # 0x90 -> LIGHT SHADE + u'\u2592' # 0x91 -> MEDIUM SHADE + u'\u2593' # 0x92 -> DARK SHADE + u'\u2320' # 0x93 -> TOP HALF INTEGRAL + u'\u25a0' # 0x94 -> BLACK SQUARE + u'\u2219' # 0x95 -> BULLET OPERATOR + u'\u221a' # 0x96 -> SQUARE ROOT + u'\u2248' # 0x97 -> ALMOST EQUAL TO + u'\u2264' # 0x98 -> LESS-THAN OR EQUAL TO + u'\u2265' # 0x99 -> GREATER-THAN OR EQUAL TO + u'\xa0' # 0x9A -> NO-BREAK SPACE + u'\u2321' # 0x9B -> BOTTOM HALF INTEGRAL + u'\xb0' # 0x9C -> DEGREE SIGN + u'\xb2' # 0x9D -> SUPERSCRIPT TWO + u'\xb7' # 0x9E -> MIDDLE DOT + u'\xf7' # 0x9F -> DIVISION SIGN + u'\u2550' # 0xA0 -> BOX DRAWINGS DOUBLE HORIZONTAL + u'\u2551' # 0xA1 -> BOX DRAWINGS DOUBLE VERTICAL + u'\u2552' # 0xA2 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + u'\u0451' # 0xA3 -> CYRILLIC SMALL LETTER IO + u'\u0454' # 0xA4 -> CYRILLIC SMALL LETTER UKRAINIAN IE + u'\u2554' # 0xA5 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + u'\u0456' # 0xA6 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + u'\u0457' # 0xA7 -> CYRILLIC SMALL LETTER YI (UKRAINIAN) + u'\u2557' # 0xA8 -> BOX DRAWINGS DOUBLE DOWN AND LEFT + u'\u2558' # 0xA9 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + u'\u2559' # 0xAA -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + u'\u255a' # 0xAB -> BOX DRAWINGS DOUBLE UP AND RIGHT + u'\u255b' # 0xAC -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + u'\u0491' # 0xAD -> CYRILLIC SMALL LETTER UKRAINIAN GHE WITH UPTURN + u'\u255d' # 0xAE -> BOX DRAWINGS DOUBLE UP AND LEFT + u'\u255e' # 0xAF -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + u'\u255f' # 0xB0 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + u'\u2560' # 0xB1 -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + u'\u2561' # 0xB2 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + u'\u0401' # 0xB3 -> CYRILLIC CAPITAL LETTER IO + u'\u0404' # 0xB4 -> CYRILLIC CAPITAL LETTER UKRAINIAN IE + u'\u2563' # 0xB5 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + u'\u0406' # 0xB6 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + u'\u0407' # 0xB7 -> CYRILLIC CAPITAL LETTER YI (UKRAINIAN) + u'\u2566' # 0xB8 -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + u'\u2567' # 0xB9 -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + u'\u2568' # 0xBA -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + u'\u2569' # 0xBB -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + u'\u256a' # 0xBC -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + u'\u0490' # 0xBD -> CYRILLIC CAPITAL LETTER UKRAINIAN GHE WITH UPTURN + u'\u256c' # 0xBE -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + u'\xa9' # 0xBF -> COPYRIGHT SIGN + u'\u044e' # 0xC0 -> CYRILLIC SMALL LETTER YU + u'\u0430' # 0xC1 -> CYRILLIC SMALL LETTER A + u'\u0431' # 0xC2 -> CYRILLIC SMALL LETTER BE + u'\u0446' # 0xC3 -> CYRILLIC SMALL LETTER TSE + u'\u0434' # 0xC4 -> CYRILLIC SMALL LETTER DE + u'\u0435' # 0xC5 -> CYRILLIC SMALL LETTER IE + u'\u0444' # 0xC6 -> CYRILLIC SMALL LETTER EF + u'\u0433' # 0xC7 -> CYRILLIC SMALL LETTER GHE + u'\u0445' # 0xC8 -> CYRILLIC SMALL LETTER HA + u'\u0438' # 0xC9 -> CYRILLIC SMALL LETTER I + u'\u0439' # 0xCA -> CYRILLIC SMALL LETTER SHORT I + u'\u043a' # 0xCB -> CYRILLIC SMALL LETTER KA + u'\u043b' # 0xCC -> CYRILLIC SMALL LETTER EL + u'\u043c' # 0xCD -> CYRILLIC SMALL LETTER EM + u'\u043d' # 0xCE -> CYRILLIC SMALL LETTER EN + u'\u043e' # 0xCF -> CYRILLIC SMALL LETTER O + u'\u043f' # 0xD0 -> CYRILLIC SMALL LETTER PE + u'\u044f' # 0xD1 -> CYRILLIC SMALL LETTER YA + u'\u0440' # 0xD2 -> CYRILLIC SMALL LETTER ER + u'\u0441' # 0xD3 -> CYRILLIC SMALL LETTER ES + u'\u0442' # 0xD4 -> CYRILLIC SMALL LETTER TE + u'\u0443' # 0xD5 -> CYRILLIC SMALL LETTER U + u'\u0436' # 0xD6 -> CYRILLIC SMALL LETTER ZHE + u'\u0432' # 0xD7 -> CYRILLIC SMALL LETTER VE + u'\u044c' # 0xD8 -> CYRILLIC SMALL LETTER SOFT SIGN + u'\u044b' # 0xD9 -> CYRILLIC SMALL LETTER YERU + u'\u0437' # 0xDA -> CYRILLIC SMALL LETTER ZE + u'\u0448' # 0xDB -> CYRILLIC SMALL LETTER SHA + u'\u044d' # 0xDC -> CYRILLIC SMALL LETTER E + u'\u0449' # 0xDD -> CYRILLIC SMALL LETTER SHCHA + u'\u0447' # 0xDE -> CYRILLIC SMALL LETTER CHE + u'\u044a' # 0xDF -> CYRILLIC SMALL LETTER HARD SIGN + u'\u042e' # 0xE0 -> CYRILLIC CAPITAL LETTER YU + u'\u0410' # 0xE1 -> CYRILLIC CAPITAL LETTER A + u'\u0411' # 0xE2 -> CYRILLIC CAPITAL LETTER BE + u'\u0426' # 0xE3 -> CYRILLIC CAPITAL LETTER TSE + u'\u0414' # 0xE4 -> CYRILLIC CAPITAL LETTER DE + u'\u0415' # 0xE5 -> CYRILLIC CAPITAL LETTER IE + u'\u0424' # 0xE6 -> CYRILLIC CAPITAL LETTER EF + u'\u0413' # 0xE7 -> CYRILLIC CAPITAL LETTER GHE + u'\u0425' # 0xE8 -> CYRILLIC CAPITAL LETTER HA + u'\u0418' # 0xE9 -> CYRILLIC CAPITAL LETTER I + u'\u0419' # 0xEA -> CYRILLIC CAPITAL LETTER SHORT I + u'\u041a' # 0xEB -> CYRILLIC CAPITAL LETTER KA + u'\u041b' # 0xEC -> CYRILLIC CAPITAL LETTER EL + u'\u041c' # 0xED -> CYRILLIC CAPITAL LETTER EM + u'\u041d' # 0xEE -> CYRILLIC CAPITAL LETTER EN + u'\u041e' # 0xEF -> CYRILLIC CAPITAL LETTER O + u'\u041f' # 0xF0 -> CYRILLIC CAPITAL LETTER PE + u'\u042f' # 0xF1 -> CYRILLIC CAPITAL LETTER YA + u'\u0420' # 0xF2 -> CYRILLIC CAPITAL LETTER ER + u'\u0421' # 0xF3 -> CYRILLIC CAPITAL LETTER ES + u'\u0422' # 0xF4 -> CYRILLIC CAPITAL LETTER TE + u'\u0423' # 0xF5 -> CYRILLIC CAPITAL LETTER U + u'\u0416' # 0xF6 -> CYRILLIC CAPITAL LETTER ZHE + u'\u0412' # 0xF7 -> CYRILLIC CAPITAL LETTER VE + u'\u042c' # 0xF8 -> CYRILLIC CAPITAL LETTER SOFT SIGN + u'\u042b' # 0xF9 -> CYRILLIC CAPITAL LETTER YERU + u'\u0417' # 0xFA -> CYRILLIC CAPITAL LETTER ZE + u'\u0428' # 0xFB -> CYRILLIC CAPITAL LETTER SHA + u'\u042d' # 0xFC -> CYRILLIC CAPITAL LETTER E + u'\u0429' # 0xFD -> CYRILLIC CAPITAL LETTER SHCHA + u'\u0427' # 0xFE -> CYRILLIC CAPITAL LETTER CHE + u'\u042a' # 0xFF -> CYRILLIC CAPITAL LETTER HARD SIGN +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/koi8_u.pyc b/PythonHome/Lib/encodings/koi8_u.pyc deleted file mode 100644 index 58af99f06499ef0aeb1f2f7fff0ba5b723f4be8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2741 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 diff --git a/PythonHome/Lib/encodings/mac_arabic.py b/PythonHome/Lib/encodings/mac_arabic.py new file mode 100644 index 0000000000..7a7d3c5f7f --- /dev/null +++ b/PythonHome/Lib/encodings/mac_arabic.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec generated from 'VENDORS/APPLE/ARABIC.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-arabic', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x00c4, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x0081: 0x00a0, # NO-BREAK SPACE, right-left + 0x0082: 0x00c7, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x0083: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0084: 0x00d1, # LATIN CAPITAL LETTER N WITH TILDE + 0x0085: 0x00d6, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x0086: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x0087: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE + 0x0088: 0x00e0, # LATIN SMALL LETTER A WITH GRAVE + 0x0089: 0x00e2, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x008a: 0x00e4, # LATIN SMALL LETTER A WITH DIAERESIS + 0x008b: 0x06ba, # ARABIC LETTER NOON GHUNNA + 0x008c: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left + 0x008d: 0x00e7, # LATIN SMALL LETTER C WITH CEDILLA + 0x008e: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x008f: 0x00e8, # LATIN SMALL LETTER E WITH GRAVE + 0x0090: 0x00ea, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x0091: 0x00eb, # LATIN SMALL LETTER E WITH DIAERESIS + 0x0092: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE + 0x0093: 0x2026, # HORIZONTAL ELLIPSIS, right-left + 0x0094: 0x00ee, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x0095: 0x00ef, # LATIN SMALL LETTER I WITH DIAERESIS + 0x0096: 0x00f1, # LATIN SMALL LETTER N WITH TILDE + 0x0097: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x0098: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left + 0x0099: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x009a: 0x00f6, # LATIN SMALL LETTER O WITH DIAERESIS + 0x009b: 0x00f7, # DIVISION SIGN, right-left + 0x009c: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x009d: 0x00f9, # LATIN SMALL LETTER U WITH GRAVE + 0x009e: 0x00fb, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x009f: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00a0: 0x0020, # SPACE, right-left + 0x00a1: 0x0021, # EXCLAMATION MARK, right-left + 0x00a2: 0x0022, # QUOTATION MARK, right-left + 0x00a3: 0x0023, # NUMBER SIGN, right-left + 0x00a4: 0x0024, # DOLLAR SIGN, right-left + 0x00a5: 0x066a, # ARABIC PERCENT SIGN + 0x00a6: 0x0026, # AMPERSAND, right-left + 0x00a7: 0x0027, # APOSTROPHE, right-left + 0x00a8: 0x0028, # LEFT PARENTHESIS, right-left + 0x00a9: 0x0029, # RIGHT PARENTHESIS, right-left + 0x00aa: 0x002a, # ASTERISK, right-left + 0x00ab: 0x002b, # PLUS SIGN, right-left + 0x00ac: 0x060c, # ARABIC COMMA + 0x00ad: 0x002d, # HYPHEN-MINUS, right-left + 0x00ae: 0x002e, # FULL STOP, right-left + 0x00af: 0x002f, # SOLIDUS, right-left + 0x00b0: 0x0660, # ARABIC-INDIC DIGIT ZERO, right-left (need override) + 0x00b1: 0x0661, # ARABIC-INDIC DIGIT ONE, right-left (need override) + 0x00b2: 0x0662, # ARABIC-INDIC DIGIT TWO, right-left (need override) + 0x00b3: 0x0663, # ARABIC-INDIC DIGIT THREE, right-left (need override) + 0x00b4: 0x0664, # ARABIC-INDIC DIGIT FOUR, right-left (need override) + 0x00b5: 0x0665, # ARABIC-INDIC DIGIT FIVE, right-left (need override) + 0x00b6: 0x0666, # ARABIC-INDIC DIGIT SIX, right-left (need override) + 0x00b7: 0x0667, # ARABIC-INDIC DIGIT SEVEN, right-left (need override) + 0x00b8: 0x0668, # ARABIC-INDIC DIGIT EIGHT, right-left (need override) + 0x00b9: 0x0669, # ARABIC-INDIC DIGIT NINE, right-left (need override) + 0x00ba: 0x003a, # COLON, right-left + 0x00bb: 0x061b, # ARABIC SEMICOLON + 0x00bc: 0x003c, # LESS-THAN SIGN, right-left + 0x00bd: 0x003d, # EQUALS SIGN, right-left + 0x00be: 0x003e, # GREATER-THAN SIGN, right-left + 0x00bf: 0x061f, # ARABIC QUESTION MARK + 0x00c0: 0x274a, # EIGHT TEARDROP-SPOKED PROPELLER ASTERISK, right-left + 0x00c1: 0x0621, # ARABIC LETTER HAMZA + 0x00c2: 0x0622, # ARABIC LETTER ALEF WITH MADDA ABOVE + 0x00c3: 0x0623, # ARABIC LETTER ALEF WITH HAMZA ABOVE + 0x00c4: 0x0624, # ARABIC LETTER WAW WITH HAMZA ABOVE + 0x00c5: 0x0625, # ARABIC LETTER ALEF WITH HAMZA BELOW + 0x00c6: 0x0626, # ARABIC LETTER YEH WITH HAMZA ABOVE + 0x00c7: 0x0627, # ARABIC LETTER ALEF + 0x00c8: 0x0628, # ARABIC LETTER BEH + 0x00c9: 0x0629, # ARABIC LETTER TEH MARBUTA + 0x00ca: 0x062a, # ARABIC LETTER TEH + 0x00cb: 0x062b, # ARABIC LETTER THEH + 0x00cc: 0x062c, # ARABIC LETTER JEEM + 0x00cd: 0x062d, # ARABIC LETTER HAH + 0x00ce: 0x062e, # ARABIC LETTER KHAH + 0x00cf: 0x062f, # ARABIC LETTER DAL + 0x00d0: 0x0630, # ARABIC LETTER THAL + 0x00d1: 0x0631, # ARABIC LETTER REH + 0x00d2: 0x0632, # ARABIC LETTER ZAIN + 0x00d3: 0x0633, # ARABIC LETTER SEEN + 0x00d4: 0x0634, # ARABIC LETTER SHEEN + 0x00d5: 0x0635, # ARABIC LETTER SAD + 0x00d6: 0x0636, # ARABIC LETTER DAD + 0x00d7: 0x0637, # ARABIC LETTER TAH + 0x00d8: 0x0638, # ARABIC LETTER ZAH + 0x00d9: 0x0639, # ARABIC LETTER AIN + 0x00da: 0x063a, # ARABIC LETTER GHAIN + 0x00db: 0x005b, # LEFT SQUARE BRACKET, right-left + 0x00dc: 0x005c, # REVERSE SOLIDUS, right-left + 0x00dd: 0x005d, # RIGHT SQUARE BRACKET, right-left + 0x00de: 0x005e, # CIRCUMFLEX ACCENT, right-left + 0x00df: 0x005f, # LOW LINE, right-left + 0x00e0: 0x0640, # ARABIC TATWEEL + 0x00e1: 0x0641, # ARABIC LETTER FEH + 0x00e2: 0x0642, # ARABIC LETTER QAF + 0x00e3: 0x0643, # ARABIC LETTER KAF + 0x00e4: 0x0644, # ARABIC LETTER LAM + 0x00e5: 0x0645, # ARABIC LETTER MEEM + 0x00e6: 0x0646, # ARABIC LETTER NOON + 0x00e7: 0x0647, # ARABIC LETTER HEH + 0x00e8: 0x0648, # ARABIC LETTER WAW + 0x00e9: 0x0649, # ARABIC LETTER ALEF MAKSURA + 0x00ea: 0x064a, # ARABIC LETTER YEH + 0x00eb: 0x064b, # ARABIC FATHATAN + 0x00ec: 0x064c, # ARABIC DAMMATAN + 0x00ed: 0x064d, # ARABIC KASRATAN + 0x00ee: 0x064e, # ARABIC FATHA + 0x00ef: 0x064f, # ARABIC DAMMA + 0x00f0: 0x0650, # ARABIC KASRA + 0x00f1: 0x0651, # ARABIC SHADDA + 0x00f2: 0x0652, # ARABIC SUKUN + 0x00f3: 0x067e, # ARABIC LETTER PEH + 0x00f4: 0x0679, # ARABIC LETTER TTEH + 0x00f5: 0x0686, # ARABIC LETTER TCHEH + 0x00f6: 0x06d5, # ARABIC LETTER AE + 0x00f7: 0x06a4, # ARABIC LETTER VEH + 0x00f8: 0x06af, # ARABIC LETTER GAF + 0x00f9: 0x0688, # ARABIC LETTER DDAL + 0x00fa: 0x0691, # ARABIC LETTER RREH + 0x00fb: 0x007b, # LEFT CURLY BRACKET, right-left + 0x00fc: 0x007c, # VERTICAL LINE, right-left + 0x00fd: 0x007d, # RIGHT CURLY BRACKET, right-left + 0x00fe: 0x0698, # ARABIC LETTER JEH + 0x00ff: 0x06d2, # ARABIC LETTER YEH BARREE +}) + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x0000 -> CONTROL CHARACTER + u'\x01' # 0x0001 -> CONTROL CHARACTER + u'\x02' # 0x0002 -> CONTROL CHARACTER + u'\x03' # 0x0003 -> CONTROL CHARACTER + u'\x04' # 0x0004 -> CONTROL CHARACTER + u'\x05' # 0x0005 -> CONTROL CHARACTER + u'\x06' # 0x0006 -> CONTROL CHARACTER + u'\x07' # 0x0007 -> CONTROL CHARACTER + u'\x08' # 0x0008 -> CONTROL CHARACTER + u'\t' # 0x0009 -> CONTROL CHARACTER + u'\n' # 0x000a -> CONTROL CHARACTER + u'\x0b' # 0x000b -> CONTROL CHARACTER + u'\x0c' # 0x000c -> CONTROL CHARACTER + u'\r' # 0x000d -> CONTROL CHARACTER + u'\x0e' # 0x000e -> CONTROL CHARACTER + u'\x0f' # 0x000f -> CONTROL CHARACTER + u'\x10' # 0x0010 -> CONTROL CHARACTER + u'\x11' # 0x0011 -> CONTROL CHARACTER + u'\x12' # 0x0012 -> CONTROL CHARACTER + u'\x13' # 0x0013 -> CONTROL CHARACTER + u'\x14' # 0x0014 -> CONTROL CHARACTER + u'\x15' # 0x0015 -> CONTROL CHARACTER + u'\x16' # 0x0016 -> CONTROL CHARACTER + u'\x17' # 0x0017 -> CONTROL CHARACTER + u'\x18' # 0x0018 -> CONTROL CHARACTER + u'\x19' # 0x0019 -> CONTROL CHARACTER + u'\x1a' # 0x001a -> CONTROL CHARACTER + u'\x1b' # 0x001b -> CONTROL CHARACTER + u'\x1c' # 0x001c -> CONTROL CHARACTER + u'\x1d' # 0x001d -> CONTROL CHARACTER + u'\x1e' # 0x001e -> CONTROL CHARACTER + u'\x1f' # 0x001f -> CONTROL CHARACTER + u' ' # 0x0020 -> SPACE, left-right + u'!' # 0x0021 -> EXCLAMATION MARK, left-right + u'"' # 0x0022 -> QUOTATION MARK, left-right + u'#' # 0x0023 -> NUMBER SIGN, left-right + u'$' # 0x0024 -> DOLLAR SIGN, left-right + u'%' # 0x0025 -> PERCENT SIGN, left-right + u'&' # 0x0026 -> AMPERSAND, left-right + u"'" # 0x0027 -> APOSTROPHE, left-right + u'(' # 0x0028 -> LEFT PARENTHESIS, left-right + u')' # 0x0029 -> RIGHT PARENTHESIS, left-right + u'*' # 0x002a -> ASTERISK, left-right + u'+' # 0x002b -> PLUS SIGN, left-right + u',' # 0x002c -> COMMA, left-right; in Arabic-script context, displayed as 0x066C ARABIC THOUSANDS SEPARATOR + u'-' # 0x002d -> HYPHEN-MINUS, left-right + u'.' # 0x002e -> FULL STOP, left-right; in Arabic-script context, displayed as 0x066B ARABIC DECIMAL SEPARATOR + u'/' # 0x002f -> SOLIDUS, left-right + u'0' # 0x0030 -> DIGIT ZERO; in Arabic-script context, displayed as 0x0660 ARABIC-INDIC DIGIT ZERO + u'1' # 0x0031 -> DIGIT ONE; in Arabic-script context, displayed as 0x0661 ARABIC-INDIC DIGIT ONE + u'2' # 0x0032 -> DIGIT TWO; in Arabic-script context, displayed as 0x0662 ARABIC-INDIC DIGIT TWO + u'3' # 0x0033 -> DIGIT THREE; in Arabic-script context, displayed as 0x0663 ARABIC-INDIC DIGIT THREE + u'4' # 0x0034 -> DIGIT FOUR; in Arabic-script context, displayed as 0x0664 ARABIC-INDIC DIGIT FOUR + u'5' # 0x0035 -> DIGIT FIVE; in Arabic-script context, displayed as 0x0665 ARABIC-INDIC DIGIT FIVE + u'6' # 0x0036 -> DIGIT SIX; in Arabic-script context, displayed as 0x0666 ARABIC-INDIC DIGIT SIX + u'7' # 0x0037 -> DIGIT SEVEN; in Arabic-script context, displayed as 0x0667 ARABIC-INDIC DIGIT SEVEN + u'8' # 0x0038 -> DIGIT EIGHT; in Arabic-script context, displayed as 0x0668 ARABIC-INDIC DIGIT EIGHT + u'9' # 0x0039 -> DIGIT NINE; in Arabic-script context, displayed as 0x0669 ARABIC-INDIC DIGIT NINE + u':' # 0x003a -> COLON, left-right + u';' # 0x003b -> SEMICOLON, left-right + u'<' # 0x003c -> LESS-THAN SIGN, left-right + u'=' # 0x003d -> EQUALS SIGN, left-right + u'>' # 0x003e -> GREATER-THAN SIGN, left-right + u'?' # 0x003f -> QUESTION MARK, left-right + u'@' # 0x0040 -> COMMERCIAL AT + u'A' # 0x0041 -> LATIN CAPITAL LETTER A + u'B' # 0x0042 -> LATIN CAPITAL LETTER B + u'C' # 0x0043 -> LATIN CAPITAL LETTER C + u'D' # 0x0044 -> LATIN CAPITAL LETTER D + u'E' # 0x0045 -> LATIN CAPITAL LETTER E + u'F' # 0x0046 -> LATIN CAPITAL LETTER F + u'G' # 0x0047 -> LATIN CAPITAL LETTER G + u'H' # 0x0048 -> LATIN CAPITAL LETTER H + u'I' # 0x0049 -> LATIN CAPITAL LETTER I + u'J' # 0x004a -> LATIN CAPITAL LETTER J + u'K' # 0x004b -> LATIN CAPITAL LETTER K + u'L' # 0x004c -> LATIN CAPITAL LETTER L + u'M' # 0x004d -> LATIN CAPITAL LETTER M + u'N' # 0x004e -> LATIN CAPITAL LETTER N + u'O' # 0x004f -> LATIN CAPITAL LETTER O + u'P' # 0x0050 -> LATIN CAPITAL LETTER P + u'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + u'R' # 0x0052 -> LATIN CAPITAL LETTER R + u'S' # 0x0053 -> LATIN CAPITAL LETTER S + u'T' # 0x0054 -> LATIN CAPITAL LETTER T + u'U' # 0x0055 -> LATIN CAPITAL LETTER U + u'V' # 0x0056 -> LATIN CAPITAL LETTER V + u'W' # 0x0057 -> LATIN CAPITAL LETTER W + u'X' # 0x0058 -> LATIN CAPITAL LETTER X + u'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + u'Z' # 0x005a -> LATIN CAPITAL LETTER Z + u'[' # 0x005b -> LEFT SQUARE BRACKET, left-right + u'\\' # 0x005c -> REVERSE SOLIDUS, left-right + u']' # 0x005d -> RIGHT SQUARE BRACKET, left-right + u'^' # 0x005e -> CIRCUMFLEX ACCENT, left-right + u'_' # 0x005f -> LOW LINE, left-right + u'`' # 0x0060 -> GRAVE ACCENT + u'a' # 0x0061 -> LATIN SMALL LETTER A + u'b' # 0x0062 -> LATIN SMALL LETTER B + u'c' # 0x0063 -> LATIN SMALL LETTER C + u'd' # 0x0064 -> LATIN SMALL LETTER D + u'e' # 0x0065 -> LATIN SMALL LETTER E + u'f' # 0x0066 -> LATIN SMALL LETTER F + u'g' # 0x0067 -> LATIN SMALL LETTER G + u'h' # 0x0068 -> LATIN SMALL LETTER H + u'i' # 0x0069 -> LATIN SMALL LETTER I + u'j' # 0x006a -> LATIN SMALL LETTER J + u'k' # 0x006b -> LATIN SMALL LETTER K + u'l' # 0x006c -> LATIN SMALL LETTER L + u'm' # 0x006d -> LATIN SMALL LETTER M + u'n' # 0x006e -> LATIN SMALL LETTER N + u'o' # 0x006f -> LATIN SMALL LETTER O + u'p' # 0x0070 -> LATIN SMALL LETTER P + u'q' # 0x0071 -> LATIN SMALL LETTER Q + u'r' # 0x0072 -> LATIN SMALL LETTER R + u's' # 0x0073 -> LATIN SMALL LETTER S + u't' # 0x0074 -> LATIN SMALL LETTER T + u'u' # 0x0075 -> LATIN SMALL LETTER U + u'v' # 0x0076 -> LATIN SMALL LETTER V + u'w' # 0x0077 -> LATIN SMALL LETTER W + u'x' # 0x0078 -> LATIN SMALL LETTER X + u'y' # 0x0079 -> LATIN SMALL LETTER Y + u'z' # 0x007a -> LATIN SMALL LETTER Z + u'{' # 0x007b -> LEFT CURLY BRACKET, left-right + u'|' # 0x007c -> VERTICAL LINE, left-right + u'}' # 0x007d -> RIGHT CURLY BRACKET, left-right + u'~' # 0x007e -> TILDE + u'\x7f' # 0x007f -> CONTROL CHARACTER + u'\xc4' # 0x0080 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xa0' # 0x0081 -> NO-BREAK SPACE, right-left + u'\xc7' # 0x0082 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xc9' # 0x0083 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xd1' # 0x0084 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xd6' # 0x0085 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x0086 -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xe1' # 0x0087 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe0' # 0x0088 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe2' # 0x0089 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x008a -> LATIN SMALL LETTER A WITH DIAERESIS + u'\u06ba' # 0x008b -> ARABIC LETTER NOON GHUNNA + u'\xab' # 0x008c -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left + u'\xe7' # 0x008d -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe9' # 0x008e -> LATIN SMALL LETTER E WITH ACUTE + u'\xe8' # 0x008f -> LATIN SMALL LETTER E WITH GRAVE + u'\xea' # 0x0090 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x0091 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xed' # 0x0092 -> LATIN SMALL LETTER I WITH ACUTE + u'\u2026' # 0x0093 -> HORIZONTAL ELLIPSIS, right-left + u'\xee' # 0x0094 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0x0095 -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xf1' # 0x0096 -> LATIN SMALL LETTER N WITH TILDE + u'\xf3' # 0x0097 -> LATIN SMALL LETTER O WITH ACUTE + u'\xbb' # 0x0098 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left + u'\xf4' # 0x0099 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0x009a -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf7' # 0x009b -> DIVISION SIGN, right-left + u'\xfa' # 0x009c -> LATIN SMALL LETTER U WITH ACUTE + u'\xf9' # 0x009d -> LATIN SMALL LETTER U WITH GRAVE + u'\xfb' # 0x009e -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0x009f -> LATIN SMALL LETTER U WITH DIAERESIS + u' ' # 0x00a0 -> SPACE, right-left + u'!' # 0x00a1 -> EXCLAMATION MARK, right-left + u'"' # 0x00a2 -> QUOTATION MARK, right-left + u'#' # 0x00a3 -> NUMBER SIGN, right-left + u'$' # 0x00a4 -> DOLLAR SIGN, right-left + u'\u066a' # 0x00a5 -> ARABIC PERCENT SIGN + u'&' # 0x00a6 -> AMPERSAND, right-left + u"'" # 0x00a7 -> APOSTROPHE, right-left + u'(' # 0x00a8 -> LEFT PARENTHESIS, right-left + u')' # 0x00a9 -> RIGHT PARENTHESIS, right-left + u'*' # 0x00aa -> ASTERISK, right-left + u'+' # 0x00ab -> PLUS SIGN, right-left + u'\u060c' # 0x00ac -> ARABIC COMMA + u'-' # 0x00ad -> HYPHEN-MINUS, right-left + u'.' # 0x00ae -> FULL STOP, right-left + u'/' # 0x00af -> SOLIDUS, right-left + u'\u0660' # 0x00b0 -> ARABIC-INDIC DIGIT ZERO, right-left (need override) + u'\u0661' # 0x00b1 -> ARABIC-INDIC DIGIT ONE, right-left (need override) + u'\u0662' # 0x00b2 -> ARABIC-INDIC DIGIT TWO, right-left (need override) + u'\u0663' # 0x00b3 -> ARABIC-INDIC DIGIT THREE, right-left (need override) + u'\u0664' # 0x00b4 -> ARABIC-INDIC DIGIT FOUR, right-left (need override) + u'\u0665' # 0x00b5 -> ARABIC-INDIC DIGIT FIVE, right-left (need override) + u'\u0666' # 0x00b6 -> ARABIC-INDIC DIGIT SIX, right-left (need override) + u'\u0667' # 0x00b7 -> ARABIC-INDIC DIGIT SEVEN, right-left (need override) + u'\u0668' # 0x00b8 -> ARABIC-INDIC DIGIT EIGHT, right-left (need override) + u'\u0669' # 0x00b9 -> ARABIC-INDIC DIGIT NINE, right-left (need override) + u':' # 0x00ba -> COLON, right-left + u'\u061b' # 0x00bb -> ARABIC SEMICOLON + u'<' # 0x00bc -> LESS-THAN SIGN, right-left + u'=' # 0x00bd -> EQUALS SIGN, right-left + u'>' # 0x00be -> GREATER-THAN SIGN, right-left + u'\u061f' # 0x00bf -> ARABIC QUESTION MARK + u'\u274a' # 0x00c0 -> EIGHT TEARDROP-SPOKED PROPELLER ASTERISK, right-left + u'\u0621' # 0x00c1 -> ARABIC LETTER HAMZA + u'\u0622' # 0x00c2 -> ARABIC LETTER ALEF WITH MADDA ABOVE + u'\u0623' # 0x00c3 -> ARABIC LETTER ALEF WITH HAMZA ABOVE + u'\u0624' # 0x00c4 -> ARABIC LETTER WAW WITH HAMZA ABOVE + u'\u0625' # 0x00c5 -> ARABIC LETTER ALEF WITH HAMZA BELOW + u'\u0626' # 0x00c6 -> ARABIC LETTER YEH WITH HAMZA ABOVE + u'\u0627' # 0x00c7 -> ARABIC LETTER ALEF + u'\u0628' # 0x00c8 -> ARABIC LETTER BEH + u'\u0629' # 0x00c9 -> ARABIC LETTER TEH MARBUTA + u'\u062a' # 0x00ca -> ARABIC LETTER TEH + u'\u062b' # 0x00cb -> ARABIC LETTER THEH + u'\u062c' # 0x00cc -> ARABIC LETTER JEEM + u'\u062d' # 0x00cd -> ARABIC LETTER HAH + u'\u062e' # 0x00ce -> ARABIC LETTER KHAH + u'\u062f' # 0x00cf -> ARABIC LETTER DAL + u'\u0630' # 0x00d0 -> ARABIC LETTER THAL + u'\u0631' # 0x00d1 -> ARABIC LETTER REH + u'\u0632' # 0x00d2 -> ARABIC LETTER ZAIN + u'\u0633' # 0x00d3 -> ARABIC LETTER SEEN + u'\u0634' # 0x00d4 -> ARABIC LETTER SHEEN + u'\u0635' # 0x00d5 -> ARABIC LETTER SAD + u'\u0636' # 0x00d6 -> ARABIC LETTER DAD + u'\u0637' # 0x00d7 -> ARABIC LETTER TAH + u'\u0638' # 0x00d8 -> ARABIC LETTER ZAH + u'\u0639' # 0x00d9 -> ARABIC LETTER AIN + u'\u063a' # 0x00da -> ARABIC LETTER GHAIN + u'[' # 0x00db -> LEFT SQUARE BRACKET, right-left + u'\\' # 0x00dc -> REVERSE SOLIDUS, right-left + u']' # 0x00dd -> RIGHT SQUARE BRACKET, right-left + u'^' # 0x00de -> CIRCUMFLEX ACCENT, right-left + u'_' # 0x00df -> LOW LINE, right-left + u'\u0640' # 0x00e0 -> ARABIC TATWEEL + u'\u0641' # 0x00e1 -> ARABIC LETTER FEH + u'\u0642' # 0x00e2 -> ARABIC LETTER QAF + u'\u0643' # 0x00e3 -> ARABIC LETTER KAF + u'\u0644' # 0x00e4 -> ARABIC LETTER LAM + u'\u0645' # 0x00e5 -> ARABIC LETTER MEEM + u'\u0646' # 0x00e6 -> ARABIC LETTER NOON + u'\u0647' # 0x00e7 -> ARABIC LETTER HEH + u'\u0648' # 0x00e8 -> ARABIC LETTER WAW + u'\u0649' # 0x00e9 -> ARABIC LETTER ALEF MAKSURA + u'\u064a' # 0x00ea -> ARABIC LETTER YEH + u'\u064b' # 0x00eb -> ARABIC FATHATAN + u'\u064c' # 0x00ec -> ARABIC DAMMATAN + u'\u064d' # 0x00ed -> ARABIC KASRATAN + u'\u064e' # 0x00ee -> ARABIC FATHA + u'\u064f' # 0x00ef -> ARABIC DAMMA + u'\u0650' # 0x00f0 -> ARABIC KASRA + u'\u0651' # 0x00f1 -> ARABIC SHADDA + u'\u0652' # 0x00f2 -> ARABIC SUKUN + u'\u067e' # 0x00f3 -> ARABIC LETTER PEH + u'\u0679' # 0x00f4 -> ARABIC LETTER TTEH + u'\u0686' # 0x00f5 -> ARABIC LETTER TCHEH + u'\u06d5' # 0x00f6 -> ARABIC LETTER AE + u'\u06a4' # 0x00f7 -> ARABIC LETTER VEH + u'\u06af' # 0x00f8 -> ARABIC LETTER GAF + u'\u0688' # 0x00f9 -> ARABIC LETTER DDAL + u'\u0691' # 0x00fa -> ARABIC LETTER RREH + u'{' # 0x00fb -> LEFT CURLY BRACKET, right-left + u'|' # 0x00fc -> VERTICAL LINE, right-left + u'}' # 0x00fd -> RIGHT CURLY BRACKET, right-left + u'\u0698' # 0x00fe -> ARABIC LETTER JEH + u'\u06d2' # 0x00ff -> ARABIC LETTER YEH BARREE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # CONTROL CHARACTER + 0x0001: 0x0001, # CONTROL CHARACTER + 0x0002: 0x0002, # CONTROL CHARACTER + 0x0003: 0x0003, # CONTROL CHARACTER + 0x0004: 0x0004, # CONTROL CHARACTER + 0x0005: 0x0005, # CONTROL CHARACTER + 0x0006: 0x0006, # CONTROL CHARACTER + 0x0007: 0x0007, # CONTROL CHARACTER + 0x0008: 0x0008, # CONTROL CHARACTER + 0x0009: 0x0009, # CONTROL CHARACTER + 0x000a: 0x000a, # CONTROL CHARACTER + 0x000b: 0x000b, # CONTROL CHARACTER + 0x000c: 0x000c, # CONTROL CHARACTER + 0x000d: 0x000d, # CONTROL CHARACTER + 0x000e: 0x000e, # CONTROL CHARACTER + 0x000f: 0x000f, # CONTROL CHARACTER + 0x0010: 0x0010, # CONTROL CHARACTER + 0x0011: 0x0011, # CONTROL CHARACTER + 0x0012: 0x0012, # CONTROL CHARACTER + 0x0013: 0x0013, # CONTROL CHARACTER + 0x0014: 0x0014, # CONTROL CHARACTER + 0x0015: 0x0015, # CONTROL CHARACTER + 0x0016: 0x0016, # CONTROL CHARACTER + 0x0017: 0x0017, # CONTROL CHARACTER + 0x0018: 0x0018, # CONTROL CHARACTER + 0x0019: 0x0019, # CONTROL CHARACTER + 0x001a: 0x001a, # CONTROL CHARACTER + 0x001b: 0x001b, # CONTROL CHARACTER + 0x001c: 0x001c, # CONTROL CHARACTER + 0x001d: 0x001d, # CONTROL CHARACTER + 0x001e: 0x001e, # CONTROL CHARACTER + 0x001f: 0x001f, # CONTROL CHARACTER + 0x0020: 0x0020, # SPACE, left-right + 0x0020: 0x00a0, # SPACE, right-left + 0x0021: 0x0021, # EXCLAMATION MARK, left-right + 0x0021: 0x00a1, # EXCLAMATION MARK, right-left + 0x0022: 0x0022, # QUOTATION MARK, left-right + 0x0022: 0x00a2, # QUOTATION MARK, right-left + 0x0023: 0x0023, # NUMBER SIGN, left-right + 0x0023: 0x00a3, # NUMBER SIGN, right-left + 0x0024: 0x0024, # DOLLAR SIGN, left-right + 0x0024: 0x00a4, # DOLLAR SIGN, right-left + 0x0025: 0x0025, # PERCENT SIGN, left-right + 0x0026: 0x0026, # AMPERSAND, left-right + 0x0026: 0x00a6, # AMPERSAND, right-left + 0x0027: 0x0027, # APOSTROPHE, left-right + 0x0027: 0x00a7, # APOSTROPHE, right-left + 0x0028: 0x0028, # LEFT PARENTHESIS, left-right + 0x0028: 0x00a8, # LEFT PARENTHESIS, right-left + 0x0029: 0x0029, # RIGHT PARENTHESIS, left-right + 0x0029: 0x00a9, # RIGHT PARENTHESIS, right-left + 0x002a: 0x002a, # ASTERISK, left-right + 0x002a: 0x00aa, # ASTERISK, right-left + 0x002b: 0x002b, # PLUS SIGN, left-right + 0x002b: 0x00ab, # PLUS SIGN, right-left + 0x002c: 0x002c, # COMMA, left-right; in Arabic-script context, displayed as 0x066C ARABIC THOUSANDS SEPARATOR + 0x002d: 0x002d, # HYPHEN-MINUS, left-right + 0x002d: 0x00ad, # HYPHEN-MINUS, right-left + 0x002e: 0x002e, # FULL STOP, left-right; in Arabic-script context, displayed as 0x066B ARABIC DECIMAL SEPARATOR + 0x002e: 0x00ae, # FULL STOP, right-left + 0x002f: 0x002f, # SOLIDUS, left-right + 0x002f: 0x00af, # SOLIDUS, right-left + 0x0030: 0x0030, # DIGIT ZERO; in Arabic-script context, displayed as 0x0660 ARABIC-INDIC DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE; in Arabic-script context, displayed as 0x0661 ARABIC-INDIC DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO; in Arabic-script context, displayed as 0x0662 ARABIC-INDIC DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE; in Arabic-script context, displayed as 0x0663 ARABIC-INDIC DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR; in Arabic-script context, displayed as 0x0664 ARABIC-INDIC DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE; in Arabic-script context, displayed as 0x0665 ARABIC-INDIC DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX; in Arabic-script context, displayed as 0x0666 ARABIC-INDIC DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN; in Arabic-script context, displayed as 0x0667 ARABIC-INDIC DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT; in Arabic-script context, displayed as 0x0668 ARABIC-INDIC DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE; in Arabic-script context, displayed as 0x0669 ARABIC-INDIC DIGIT NINE + 0x003a: 0x003a, # COLON, left-right + 0x003a: 0x00ba, # COLON, right-left + 0x003b: 0x003b, # SEMICOLON, left-right + 0x003c: 0x003c, # LESS-THAN SIGN, left-right + 0x003c: 0x00bc, # LESS-THAN SIGN, right-left + 0x003d: 0x003d, # EQUALS SIGN, left-right + 0x003d: 0x00bd, # EQUALS SIGN, right-left + 0x003e: 0x003e, # GREATER-THAN SIGN, left-right + 0x003e: 0x00be, # GREATER-THAN SIGN, right-left + 0x003f: 0x003f, # QUESTION MARK, left-right + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET, left-right + 0x005b: 0x00db, # LEFT SQUARE BRACKET, right-left + 0x005c: 0x005c, # REVERSE SOLIDUS, left-right + 0x005c: 0x00dc, # REVERSE SOLIDUS, right-left + 0x005d: 0x005d, # RIGHT SQUARE BRACKET, left-right + 0x005d: 0x00dd, # RIGHT SQUARE BRACKET, right-left + 0x005e: 0x005e, # CIRCUMFLEX ACCENT, left-right + 0x005e: 0x00de, # CIRCUMFLEX ACCENT, right-left + 0x005f: 0x005f, # LOW LINE, left-right + 0x005f: 0x00df, # LOW LINE, right-left + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET, left-right + 0x007b: 0x00fb, # LEFT CURLY BRACKET, right-left + 0x007c: 0x007c, # VERTICAL LINE, left-right + 0x007c: 0x00fc, # VERTICAL LINE, right-left + 0x007d: 0x007d, # RIGHT CURLY BRACKET, left-right + 0x007d: 0x00fd, # RIGHT CURLY BRACKET, right-left + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # CONTROL CHARACTER + 0x00a0: 0x0081, # NO-BREAK SPACE, right-left + 0x00ab: 0x008c, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left + 0x00bb: 0x0098, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left + 0x00c4: 0x0080, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c7: 0x0082, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c9: 0x0083, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00d1: 0x0084, # LATIN CAPITAL LETTER N WITH TILDE + 0x00d6: 0x0085, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00dc: 0x0086, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00e0: 0x0088, # LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x0087, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0089, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e4: 0x008a, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e7: 0x008d, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008f, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x008e, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0090, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x0091, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ed: 0x0092, # LATIN SMALL LETTER I WITH ACUTE + 0x00ee: 0x0094, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ef: 0x0095, # LATIN SMALL LETTER I WITH DIAERESIS + 0x00f1: 0x0096, # LATIN SMALL LETTER N WITH TILDE + 0x00f3: 0x0097, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0099, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f6: 0x009a, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x009b, # DIVISION SIGN, right-left + 0x00f9: 0x009d, # LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x009c, # LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x009e, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x009f, # LATIN SMALL LETTER U WITH DIAERESIS + 0x060c: 0x00ac, # ARABIC COMMA + 0x061b: 0x00bb, # ARABIC SEMICOLON + 0x061f: 0x00bf, # ARABIC QUESTION MARK + 0x0621: 0x00c1, # ARABIC LETTER HAMZA + 0x0622: 0x00c2, # ARABIC LETTER ALEF WITH MADDA ABOVE + 0x0623: 0x00c3, # ARABIC LETTER ALEF WITH HAMZA ABOVE + 0x0624: 0x00c4, # ARABIC LETTER WAW WITH HAMZA ABOVE + 0x0625: 0x00c5, # ARABIC LETTER ALEF WITH HAMZA BELOW + 0x0626: 0x00c6, # ARABIC LETTER YEH WITH HAMZA ABOVE + 0x0627: 0x00c7, # ARABIC LETTER ALEF + 0x0628: 0x00c8, # ARABIC LETTER BEH + 0x0629: 0x00c9, # ARABIC LETTER TEH MARBUTA + 0x062a: 0x00ca, # ARABIC LETTER TEH + 0x062b: 0x00cb, # ARABIC LETTER THEH + 0x062c: 0x00cc, # ARABIC LETTER JEEM + 0x062d: 0x00cd, # ARABIC LETTER HAH + 0x062e: 0x00ce, # ARABIC LETTER KHAH + 0x062f: 0x00cf, # ARABIC LETTER DAL + 0x0630: 0x00d0, # ARABIC LETTER THAL + 0x0631: 0x00d1, # ARABIC LETTER REH + 0x0632: 0x00d2, # ARABIC LETTER ZAIN + 0x0633: 0x00d3, # ARABIC LETTER SEEN + 0x0634: 0x00d4, # ARABIC LETTER SHEEN + 0x0635: 0x00d5, # ARABIC LETTER SAD + 0x0636: 0x00d6, # ARABIC LETTER DAD + 0x0637: 0x00d7, # ARABIC LETTER TAH + 0x0638: 0x00d8, # ARABIC LETTER ZAH + 0x0639: 0x00d9, # ARABIC LETTER AIN + 0x063a: 0x00da, # ARABIC LETTER GHAIN + 0x0640: 0x00e0, # ARABIC TATWEEL + 0x0641: 0x00e1, # ARABIC LETTER FEH + 0x0642: 0x00e2, # ARABIC LETTER QAF + 0x0643: 0x00e3, # ARABIC LETTER KAF + 0x0644: 0x00e4, # ARABIC LETTER LAM + 0x0645: 0x00e5, # ARABIC LETTER MEEM + 0x0646: 0x00e6, # ARABIC LETTER NOON + 0x0647: 0x00e7, # ARABIC LETTER HEH + 0x0648: 0x00e8, # ARABIC LETTER WAW + 0x0649: 0x00e9, # ARABIC LETTER ALEF MAKSURA + 0x064a: 0x00ea, # ARABIC LETTER YEH + 0x064b: 0x00eb, # ARABIC FATHATAN + 0x064c: 0x00ec, # ARABIC DAMMATAN + 0x064d: 0x00ed, # ARABIC KASRATAN + 0x064e: 0x00ee, # ARABIC FATHA + 0x064f: 0x00ef, # ARABIC DAMMA + 0x0650: 0x00f0, # ARABIC KASRA + 0x0651: 0x00f1, # ARABIC SHADDA + 0x0652: 0x00f2, # ARABIC SUKUN + 0x0660: 0x00b0, # ARABIC-INDIC DIGIT ZERO, right-left (need override) + 0x0661: 0x00b1, # ARABIC-INDIC DIGIT ONE, right-left (need override) + 0x0662: 0x00b2, # ARABIC-INDIC DIGIT TWO, right-left (need override) + 0x0663: 0x00b3, # ARABIC-INDIC DIGIT THREE, right-left (need override) + 0x0664: 0x00b4, # ARABIC-INDIC DIGIT FOUR, right-left (need override) + 0x0665: 0x00b5, # ARABIC-INDIC DIGIT FIVE, right-left (need override) + 0x0666: 0x00b6, # ARABIC-INDIC DIGIT SIX, right-left (need override) + 0x0667: 0x00b7, # ARABIC-INDIC DIGIT SEVEN, right-left (need override) + 0x0668: 0x00b8, # ARABIC-INDIC DIGIT EIGHT, right-left (need override) + 0x0669: 0x00b9, # ARABIC-INDIC DIGIT NINE, right-left (need override) + 0x066a: 0x00a5, # ARABIC PERCENT SIGN + 0x0679: 0x00f4, # ARABIC LETTER TTEH + 0x067e: 0x00f3, # ARABIC LETTER PEH + 0x0686: 0x00f5, # ARABIC LETTER TCHEH + 0x0688: 0x00f9, # ARABIC LETTER DDAL + 0x0691: 0x00fa, # ARABIC LETTER RREH + 0x0698: 0x00fe, # ARABIC LETTER JEH + 0x06a4: 0x00f7, # ARABIC LETTER VEH + 0x06af: 0x00f8, # ARABIC LETTER GAF + 0x06ba: 0x008b, # ARABIC LETTER NOON GHUNNA + 0x06d2: 0x00ff, # ARABIC LETTER YEH BARREE + 0x06d5: 0x00f6, # ARABIC LETTER AE + 0x2026: 0x0093, # HORIZONTAL ELLIPSIS, right-left + 0x274a: 0x00c0, # EIGHT TEARDROP-SPOKED PROPELLER ASTERISK, right-left +} diff --git a/PythonHome/Lib/encodings/mac_arabic.pyc b/PythonHome/Lib/encodings/mac_arabic.pyc deleted file mode 100644 index 34f77a80e16e7af8cdde204cef189226e8716a8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7879 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 I1aS2K1Vs*D_y7O^ diff --git a/PythonHome/Lib/encodings/mac_centeuro.py b/PythonHome/Lib/encodings/mac_centeuro.py new file mode 100644 index 0000000000..483c8212ac --- /dev/null +++ b/PythonHome/Lib/encodings/mac_centeuro.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec mac_centeuro generated from 'MAPPINGS/VENDORS/APPLE/CENTEURO.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-centeuro', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> CONTROL CHARACTER + u'\x01' # 0x01 -> CONTROL CHARACTER + u'\x02' # 0x02 -> CONTROL CHARACTER + u'\x03' # 0x03 -> CONTROL CHARACTER + u'\x04' # 0x04 -> CONTROL CHARACTER + u'\x05' # 0x05 -> CONTROL CHARACTER + u'\x06' # 0x06 -> CONTROL CHARACTER + u'\x07' # 0x07 -> CONTROL CHARACTER + u'\x08' # 0x08 -> CONTROL CHARACTER + u'\t' # 0x09 -> CONTROL CHARACTER + u'\n' # 0x0A -> CONTROL CHARACTER + u'\x0b' # 0x0B -> CONTROL CHARACTER + u'\x0c' # 0x0C -> CONTROL CHARACTER + u'\r' # 0x0D -> CONTROL CHARACTER + u'\x0e' # 0x0E -> CONTROL CHARACTER + u'\x0f' # 0x0F -> CONTROL CHARACTER + u'\x10' # 0x10 -> CONTROL CHARACTER + u'\x11' # 0x11 -> CONTROL CHARACTER + u'\x12' # 0x12 -> CONTROL CHARACTER + u'\x13' # 0x13 -> CONTROL CHARACTER + u'\x14' # 0x14 -> CONTROL CHARACTER + u'\x15' # 0x15 -> CONTROL CHARACTER + u'\x16' # 0x16 -> CONTROL CHARACTER + u'\x17' # 0x17 -> CONTROL CHARACTER + u'\x18' # 0x18 -> CONTROL CHARACTER + u'\x19' # 0x19 -> CONTROL CHARACTER + u'\x1a' # 0x1A -> CONTROL CHARACTER + u'\x1b' # 0x1B -> CONTROL CHARACTER + u'\x1c' # 0x1C -> CONTROL CHARACTER + u'\x1d' # 0x1D -> CONTROL CHARACTER + u'\x1e' # 0x1E -> CONTROL CHARACTER + u'\x1f' # 0x1F -> CONTROL CHARACTER + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> CONTROL CHARACTER + u'\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\u0100' # 0x81 -> LATIN CAPITAL LETTER A WITH MACRON + u'\u0101' # 0x82 -> LATIN SMALL LETTER A WITH MACRON + u'\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\u0104' # 0x84 -> LATIN CAPITAL LETTER A WITH OGONEK + u'\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xe1' # 0x87 -> LATIN SMALL LETTER A WITH ACUTE + u'\u0105' # 0x88 -> LATIN SMALL LETTER A WITH OGONEK + u'\u010c' # 0x89 -> LATIN CAPITAL LETTER C WITH CARON + u'\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + u'\u010d' # 0x8B -> LATIN SMALL LETTER C WITH CARON + u'\u0106' # 0x8C -> LATIN CAPITAL LETTER C WITH ACUTE + u'\u0107' # 0x8D -> LATIN SMALL LETTER C WITH ACUTE + u'\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + u'\u0179' # 0x8F -> LATIN CAPITAL LETTER Z WITH ACUTE + u'\u017a' # 0x90 -> LATIN SMALL LETTER Z WITH ACUTE + u'\u010e' # 0x91 -> LATIN CAPITAL LETTER D WITH CARON + u'\xed' # 0x92 -> LATIN SMALL LETTER I WITH ACUTE + u'\u010f' # 0x93 -> LATIN SMALL LETTER D WITH CARON + u'\u0112' # 0x94 -> LATIN CAPITAL LETTER E WITH MACRON + u'\u0113' # 0x95 -> LATIN SMALL LETTER E WITH MACRON + u'\u0116' # 0x96 -> LATIN CAPITAL LETTER E WITH DOT ABOVE + u'\xf3' # 0x97 -> LATIN SMALL LETTER O WITH ACUTE + u'\u0117' # 0x98 -> LATIN SMALL LETTER E WITH DOT ABOVE + u'\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf5' # 0x9B -> LATIN SMALL LETTER O WITH TILDE + u'\xfa' # 0x9C -> LATIN SMALL LETTER U WITH ACUTE + u'\u011a' # 0x9D -> LATIN CAPITAL LETTER E WITH CARON + u'\u011b' # 0x9E -> LATIN SMALL LETTER E WITH CARON + u'\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + u'\u2020' # 0xA0 -> DAGGER + u'\xb0' # 0xA1 -> DEGREE SIGN + u'\u0118' # 0xA2 -> LATIN CAPITAL LETTER E WITH OGONEK + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa7' # 0xA4 -> SECTION SIGN + u'\u2022' # 0xA5 -> BULLET + u'\xb6' # 0xA6 -> PILCROW SIGN + u'\xdf' # 0xA7 -> LATIN SMALL LETTER SHARP S + u'\xae' # 0xA8 -> REGISTERED SIGN + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\u2122' # 0xAA -> TRADE MARK SIGN + u'\u0119' # 0xAB -> LATIN SMALL LETTER E WITH OGONEK + u'\xa8' # 0xAC -> DIAERESIS + u'\u2260' # 0xAD -> NOT EQUAL TO + u'\u0123' # 0xAE -> LATIN SMALL LETTER G WITH CEDILLA + u'\u012e' # 0xAF -> LATIN CAPITAL LETTER I WITH OGONEK + u'\u012f' # 0xB0 -> LATIN SMALL LETTER I WITH OGONEK + u'\u012a' # 0xB1 -> LATIN CAPITAL LETTER I WITH MACRON + u'\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + u'\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + u'\u012b' # 0xB4 -> LATIN SMALL LETTER I WITH MACRON + u'\u0136' # 0xB5 -> LATIN CAPITAL LETTER K WITH CEDILLA + u'\u2202' # 0xB6 -> PARTIAL DIFFERENTIAL + u'\u2211' # 0xB7 -> N-ARY SUMMATION + u'\u0142' # 0xB8 -> LATIN SMALL LETTER L WITH STROKE + u'\u013b' # 0xB9 -> LATIN CAPITAL LETTER L WITH CEDILLA + u'\u013c' # 0xBA -> LATIN SMALL LETTER L WITH CEDILLA + u'\u013d' # 0xBB -> LATIN CAPITAL LETTER L WITH CARON + u'\u013e' # 0xBC -> LATIN SMALL LETTER L WITH CARON + u'\u0139' # 0xBD -> LATIN CAPITAL LETTER L WITH ACUTE + u'\u013a' # 0xBE -> LATIN SMALL LETTER L WITH ACUTE + u'\u0145' # 0xBF -> LATIN CAPITAL LETTER N WITH CEDILLA + u'\u0146' # 0xC0 -> LATIN SMALL LETTER N WITH CEDILLA + u'\u0143' # 0xC1 -> LATIN CAPITAL LETTER N WITH ACUTE + u'\xac' # 0xC2 -> NOT SIGN + u'\u221a' # 0xC3 -> SQUARE ROOT + u'\u0144' # 0xC4 -> LATIN SMALL LETTER N WITH ACUTE + u'\u0147' # 0xC5 -> LATIN CAPITAL LETTER N WITH CARON + u'\u2206' # 0xC6 -> INCREMENT + u'\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + u'\xa0' # 0xCA -> NO-BREAK SPACE + u'\u0148' # 0xCB -> LATIN SMALL LETTER N WITH CARON + u'\u0150' # 0xCC -> LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + u'\xd5' # 0xCD -> LATIN CAPITAL LETTER O WITH TILDE + u'\u0151' # 0xCE -> LATIN SMALL LETTER O WITH DOUBLE ACUTE + u'\u014c' # 0xCF -> LATIN CAPITAL LETTER O WITH MACRON + u'\u2013' # 0xD0 -> EN DASH + u'\u2014' # 0xD1 -> EM DASH + u'\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + u'\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + u'\xf7' # 0xD6 -> DIVISION SIGN + u'\u25ca' # 0xD7 -> LOZENGE + u'\u014d' # 0xD8 -> LATIN SMALL LETTER O WITH MACRON + u'\u0154' # 0xD9 -> LATIN CAPITAL LETTER R WITH ACUTE + u'\u0155' # 0xDA -> LATIN SMALL LETTER R WITH ACUTE + u'\u0158' # 0xDB -> LATIN CAPITAL LETTER R WITH CARON + u'\u2039' # 0xDC -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + u'\u203a' # 0xDD -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + u'\u0159' # 0xDE -> LATIN SMALL LETTER R WITH CARON + u'\u0156' # 0xDF -> LATIN CAPITAL LETTER R WITH CEDILLA + u'\u0157' # 0xE0 -> LATIN SMALL LETTER R WITH CEDILLA + u'\u0160' # 0xE1 -> LATIN CAPITAL LETTER S WITH CARON + u'\u201a' # 0xE2 -> SINGLE LOW-9 QUOTATION MARK + u'\u201e' # 0xE3 -> DOUBLE LOW-9 QUOTATION MARK + u'\u0161' # 0xE4 -> LATIN SMALL LETTER S WITH CARON + u'\u015a' # 0xE5 -> LATIN CAPITAL LETTER S WITH ACUTE + u'\u015b' # 0xE6 -> LATIN SMALL LETTER S WITH ACUTE + u'\xc1' # 0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\u0164' # 0xE8 -> LATIN CAPITAL LETTER T WITH CARON + u'\u0165' # 0xE9 -> LATIN SMALL LETTER T WITH CARON + u'\xcd' # 0xEA -> LATIN CAPITAL LETTER I WITH ACUTE + u'\u017d' # 0xEB -> LATIN CAPITAL LETTER Z WITH CARON + u'\u017e' # 0xEC -> LATIN SMALL LETTER Z WITH CARON + u'\u016a' # 0xED -> LATIN CAPITAL LETTER U WITH MACRON + u'\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\u016b' # 0xF0 -> LATIN SMALL LETTER U WITH MACRON + u'\u016e' # 0xF1 -> LATIN CAPITAL LETTER U WITH RING ABOVE + u'\xda' # 0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE + u'\u016f' # 0xF3 -> LATIN SMALL LETTER U WITH RING ABOVE + u'\u0170' # 0xF4 -> LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + u'\u0171' # 0xF5 -> LATIN SMALL LETTER U WITH DOUBLE ACUTE + u'\u0172' # 0xF6 -> LATIN CAPITAL LETTER U WITH OGONEK + u'\u0173' # 0xF7 -> LATIN SMALL LETTER U WITH OGONEK + u'\xdd' # 0xF8 -> LATIN CAPITAL LETTER Y WITH ACUTE + u'\xfd' # 0xF9 -> LATIN SMALL LETTER Y WITH ACUTE + u'\u0137' # 0xFA -> LATIN SMALL LETTER K WITH CEDILLA + u'\u017b' # 0xFB -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + u'\u0141' # 0xFC -> LATIN CAPITAL LETTER L WITH STROKE + u'\u017c' # 0xFD -> LATIN SMALL LETTER Z WITH DOT ABOVE + u'\u0122' # 0xFE -> LATIN CAPITAL LETTER G WITH CEDILLA + u'\u02c7' # 0xFF -> CARON +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/mac_centeuro.pyc b/PythonHome/Lib/encodings/mac_centeuro.pyc deleted file mode 100644 index f648c4fcf4b4a2e541456c6376b563612bbcfc4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2802 zcmc&$Yg<%R6y9@X7;fGRqa3?AU4-seGvuOCIMNxs5j7spIRis;p)+S9%JLwn&?A+p zD5!;sl~QV1@POclIeUNVU!1?t53sfNapnN^frk$@us3V3HGA*1-u3RaaQ#){pWJ&O zERlO37yPY;k)DD{CZq*s2a%m5?jS87xQOB)olX)3*-iQh=_6!+i<8J6Zg6pfH*ate zxquto+~CU_+(a%Uij&(sBnk)k^EMBWi*hzEw-x7YULu#^qNRYyrKH8j4}g<=qz@eQ zqo?6u83vGnDbUoTb)=Gk+73|_B~4KSJH@W9Sh77(o01hNkPxMaq$D*ZqoxAwN>Wip zO_2jpHI)c#+PST%sUfr@T(ze@RJThASHZfmzN)r9)Lg$?*j3rQuX$6TJEnEuP6^Me z?CPoX`(tJ3t?@w{y?ZS}ABHfFU7vMJ#u@ii-e9L=)TM zinR-GNGtIu4r}PGpDq9<4ZLPUe(yj9m1vspY9GxOO6(Jyw z<-{W3)&)@j-~c*TadBZ30^%0E2)#F60ip^zv{Jj}66OB0OLYynxK(Knmy`=ZTFlCrUJy6ytW> zO9~nB!XW1ZEEMBaB{1=0w~O(#!hyBVUOJ|jy_LBOypF|))^Q5`KZs(gEkuz-ix3sC zgxLWv2~6bOIvD>BrmzA`%jPCxxHfk-;D|X2YpNn9_Npo?clhyqzI8JmIT(Q1JViH8CBNCKw&(+IVGYS>iq|LmS^=MyfV>b85CL|!Pd@eZ=E|yPo_+557hZhn!mxO-Wj^lyr03Jm z4u1Z{A)}w_wAUD<{l>6y-ndAQ(BsB99im6+G2<$mW;66F;}`lh{g$4j!^SOo#`xWs zH2yGV=qNpB%$oXG_9i`>y`25g)GuWxjqkJ9vscajOLQdrlQ}p>FVpMv2EAquj+=v5 z=mecK2M(J9C)iz+ot|Qc8m?MZ;aFI z1Uqi(Cr$m7sh>CX3#NY7)JKdd^URlQh@E1m8LX#GeTI#&VRnX%nfj=yf5$GeQFhMg zW#jCMF~sKB9d^w)X`Esc?7A_^Zm^r|SN0pbWn3`k=oGundf6tGj@99+#F<8hBUUV)fyzF4&&No(N6U UUG6J)m%A%m6`sN}?_J{l8|Jj23;+NC diff --git a/PythonHome/Lib/encodings/mac_croatian.py b/PythonHome/Lib/encodings/mac_croatian.py new file mode 100644 index 0000000000..f57f7b4b33 --- /dev/null +++ b/PythonHome/Lib/encodings/mac_croatian.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec mac_croatian generated from 'MAPPINGS/VENDORS/APPLE/CROATIAN.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-croatian', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> CONTROL CHARACTER + u'\x01' # 0x01 -> CONTROL CHARACTER + u'\x02' # 0x02 -> CONTROL CHARACTER + u'\x03' # 0x03 -> CONTROL CHARACTER + u'\x04' # 0x04 -> CONTROL CHARACTER + u'\x05' # 0x05 -> CONTROL CHARACTER + u'\x06' # 0x06 -> CONTROL CHARACTER + u'\x07' # 0x07 -> CONTROL CHARACTER + u'\x08' # 0x08 -> CONTROL CHARACTER + u'\t' # 0x09 -> CONTROL CHARACTER + u'\n' # 0x0A -> CONTROL CHARACTER + u'\x0b' # 0x0B -> CONTROL CHARACTER + u'\x0c' # 0x0C -> CONTROL CHARACTER + u'\r' # 0x0D -> CONTROL CHARACTER + u'\x0e' # 0x0E -> CONTROL CHARACTER + u'\x0f' # 0x0F -> CONTROL CHARACTER + u'\x10' # 0x10 -> CONTROL CHARACTER + u'\x11' # 0x11 -> CONTROL CHARACTER + u'\x12' # 0x12 -> CONTROL CHARACTER + u'\x13' # 0x13 -> CONTROL CHARACTER + u'\x14' # 0x14 -> CONTROL CHARACTER + u'\x15' # 0x15 -> CONTROL CHARACTER + u'\x16' # 0x16 -> CONTROL CHARACTER + u'\x17' # 0x17 -> CONTROL CHARACTER + u'\x18' # 0x18 -> CONTROL CHARACTER + u'\x19' # 0x19 -> CONTROL CHARACTER + u'\x1a' # 0x1A -> CONTROL CHARACTER + u'\x1b' # 0x1B -> CONTROL CHARACTER + u'\x1c' # 0x1C -> CONTROL CHARACTER + u'\x1d' # 0x1D -> CONTROL CHARACTER + u'\x1e' # 0x1E -> CONTROL CHARACTER + u'\x1f' # 0x1F -> CONTROL CHARACTER + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> CONTROL CHARACTER + u'\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0x81 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc7' # 0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xd1' # 0x84 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xe1' # 0x87 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe0' # 0x88 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe2' # 0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe3' # 0x8B -> LATIN SMALL LETTER A WITH TILDE + u'\xe5' # 0x8C -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe7' # 0x8D -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + u'\xe8' # 0x8F -> LATIN SMALL LETTER E WITH GRAVE + u'\xea' # 0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x91 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xed' # 0x92 -> LATIN SMALL LETTER I WITH ACUTE + u'\xec' # 0x93 -> LATIN SMALL LETTER I WITH GRAVE + u'\xee' # 0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0x95 -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xf1' # 0x96 -> LATIN SMALL LETTER N WITH TILDE + u'\xf3' # 0x97 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf2' # 0x98 -> LATIN SMALL LETTER O WITH GRAVE + u'\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf5' # 0x9B -> LATIN SMALL LETTER O WITH TILDE + u'\xfa' # 0x9C -> LATIN SMALL LETTER U WITH ACUTE + u'\xf9' # 0x9D -> LATIN SMALL LETTER U WITH GRAVE + u'\xfb' # 0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + u'\u2020' # 0xA0 -> DAGGER + u'\xb0' # 0xA1 -> DEGREE SIGN + u'\xa2' # 0xA2 -> CENT SIGN + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa7' # 0xA4 -> SECTION SIGN + u'\u2022' # 0xA5 -> BULLET + u'\xb6' # 0xA6 -> PILCROW SIGN + u'\xdf' # 0xA7 -> LATIN SMALL LETTER SHARP S + u'\xae' # 0xA8 -> REGISTERED SIGN + u'\u0160' # 0xA9 -> LATIN CAPITAL LETTER S WITH CARON + u'\u2122' # 0xAA -> TRADE MARK SIGN + u'\xb4' # 0xAB -> ACUTE ACCENT + u'\xa8' # 0xAC -> DIAERESIS + u'\u2260' # 0xAD -> NOT EQUAL TO + u'\u017d' # 0xAE -> LATIN CAPITAL LETTER Z WITH CARON + u'\xd8' # 0xAF -> LATIN CAPITAL LETTER O WITH STROKE + u'\u221e' # 0xB0 -> INFINITY + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + u'\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + u'\u2206' # 0xB4 -> INCREMENT + u'\xb5' # 0xB5 -> MICRO SIGN + u'\u2202' # 0xB6 -> PARTIAL DIFFERENTIAL + u'\u2211' # 0xB7 -> N-ARY SUMMATION + u'\u220f' # 0xB8 -> N-ARY PRODUCT + u'\u0161' # 0xB9 -> LATIN SMALL LETTER S WITH CARON + u'\u222b' # 0xBA -> INTEGRAL + u'\xaa' # 0xBB -> FEMININE ORDINAL INDICATOR + u'\xba' # 0xBC -> MASCULINE ORDINAL INDICATOR + u'\u03a9' # 0xBD -> GREEK CAPITAL LETTER OMEGA + u'\u017e' # 0xBE -> LATIN SMALL LETTER Z WITH CARON + u'\xf8' # 0xBF -> LATIN SMALL LETTER O WITH STROKE + u'\xbf' # 0xC0 -> INVERTED QUESTION MARK + u'\xa1' # 0xC1 -> INVERTED EXCLAMATION MARK + u'\xac' # 0xC2 -> NOT SIGN + u'\u221a' # 0xC3 -> SQUARE ROOT + u'\u0192' # 0xC4 -> LATIN SMALL LETTER F WITH HOOK + u'\u2248' # 0xC5 -> ALMOST EQUAL TO + u'\u0106' # 0xC6 -> LATIN CAPITAL LETTER C WITH ACUTE + u'\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u010c' # 0xC8 -> LATIN CAPITAL LETTER C WITH CARON + u'\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + u'\xa0' # 0xCA -> NO-BREAK SPACE + u'\xc0' # 0xCB -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc3' # 0xCC -> LATIN CAPITAL LETTER A WITH TILDE + u'\xd5' # 0xCD -> LATIN CAPITAL LETTER O WITH TILDE + u'\u0152' # 0xCE -> LATIN CAPITAL LIGATURE OE + u'\u0153' # 0xCF -> LATIN SMALL LIGATURE OE + u'\u0110' # 0xD0 -> LATIN CAPITAL LETTER D WITH STROKE + u'\u2014' # 0xD1 -> EM DASH + u'\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + u'\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + u'\xf7' # 0xD6 -> DIVISION SIGN + u'\u25ca' # 0xD7 -> LOZENGE + u'\uf8ff' # 0xD8 -> Apple logo + u'\xa9' # 0xD9 -> COPYRIGHT SIGN + u'\u2044' # 0xDA -> FRACTION SLASH + u'\u20ac' # 0xDB -> EURO SIGN + u'\u2039' # 0xDC -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + u'\u203a' # 0xDD -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + u'\xc6' # 0xDE -> LATIN CAPITAL LETTER AE + u'\xbb' # 0xDF -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2013' # 0xE0 -> EN DASH + u'\xb7' # 0xE1 -> MIDDLE DOT + u'\u201a' # 0xE2 -> SINGLE LOW-9 QUOTATION MARK + u'\u201e' # 0xE3 -> DOUBLE LOW-9 QUOTATION MARK + u'\u2030' # 0xE4 -> PER MILLE SIGN + u'\xc2' # 0xE5 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\u0107' # 0xE6 -> LATIN SMALL LETTER C WITH ACUTE + u'\xc1' # 0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\u010d' # 0xE8 -> LATIN SMALL LETTER C WITH CARON + u'\xc8' # 0xE9 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xcd' # 0xEA -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xEB -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0xEC -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\xcc' # 0xED -> LATIN CAPITAL LETTER I WITH GRAVE + u'\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\u0111' # 0xF0 -> LATIN SMALL LETTER D WITH STROKE + u'\xd2' # 0xF1 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xda' # 0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0xF3 -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xd9' # 0xF4 -> LATIN CAPITAL LETTER U WITH GRAVE + u'\u0131' # 0xF5 -> LATIN SMALL LETTER DOTLESS I + u'\u02c6' # 0xF6 -> MODIFIER LETTER CIRCUMFLEX ACCENT + u'\u02dc' # 0xF7 -> SMALL TILDE + u'\xaf' # 0xF8 -> MACRON + u'\u03c0' # 0xF9 -> GREEK SMALL LETTER PI + u'\xcb' # 0xFA -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\u02da' # 0xFB -> RING ABOVE + u'\xb8' # 0xFC -> CEDILLA + u'\xca' # 0xFD -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xe6' # 0xFE -> LATIN SMALL LETTER AE + u'\u02c7' # 0xFF -> CARON +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/mac_croatian.pyc b/PythonHome/Lib/encodings/mac_croatian.pyc deleted file mode 100644 index f306bac955a703ec2b6627fd8f105d532e1e1872..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2810 zcmc&$X?qk!5biy*SrTs0V3fs+^&s&+5eXq+6qYy}Ibw8~%*-Z(d&Jp^7)2RK3>yTI zLxqSK!hOi0+^9Uy)W$D)9{msf2mIgQtfEWsRd(m}70A(*D*~g@Klrmuk>FcJU zE2ctg8h#x0q@IS8$=Es%+kn4bW_nqV52N>>KIU#0p5@Gms8tY#wA`6++!ZPzA|MG< zZcAy-F1jJ7rII29J=57`3O_W%$QrpQ8kv}Kvr(#PU8c9S7Ej5wjz$#Wa5f5bCeWz_ z0rQL}7Kygr76k&1pbM1{Z;wJE{3XIqD#K|UZae1_ZnxZy5-?^6r$iznr?o`F42wlN zt9GSuDUnU0K;7$vG#02N+{Vgrwxf~)Y{1fb1sC9{h3_|Ysh&%YwtKv~QHm2jmM8E=giI^vVl*l{56Bl7Yl%$@K zQ*PX23YqYtAV&i%RnS$HIEiDI$f=wrfOXFvJEoMqDa8wdo;wj;EGYELaICHKirvaBHG@ zwp~Mqu!)*R_Z(d2h^ov}?g@G-@FysKx(*PvJYJta5G)IohbL52PMkD(%G7DoXUx3o z?y6b$RNs5w?8uz^A9(Pghv!BgdGxWz=hf6c@#IraKlAK!&%f~EOE1rVWx=Zp>lW27 zZdkJPwZ_-qShhU2qUlX3-u%|eRjb#uyxscFyNR`Oo1$vT_6~jBd#Q9L+xfncGrK-m z|6%t>A8+{N(~ZyzpTQRBhn?^>?1zIe2t#lf4#5#P1}ES+oP<;G1Du94a2C$PPw*pL zfJ<-@uEABf4nK2i&^~7m*@x_7+#0ek!T0u=;X&RzWM8n4^Zvo%UtllKAF$8!{=>Zg z2+#M~7kPd&&+p{<9m5BC{*-;vzV`cx;a}m3eZxLzpXT|2-*)l-e4)=iRoKR@qxK+J z&;wr$?;74+_>x|1u58bd&@J+pZ^J#8f<<>Rmv#)b&w|$vg z1Kc{mt#h!sumv_1wnHAa!xyjvw!v=LQ`iZ+U;w^_eTDNQeIxtrvwv9d`N)8M1-8P` zku6cmC9;_MqncH)A5trEc;m8#h~iL&`jAA$&!lQ!{O6>tOHZjzmqG0)PK~8Ri0(Y! f>BkFvxIIU`5u2&MDpcjK@>lz+1Lc!~H<|x$Q7)ts diff --git a/PythonHome/Lib/encodings/mac_cyrillic.py b/PythonHome/Lib/encodings/mac_cyrillic.py new file mode 100644 index 0000000000..63324a14b8 --- /dev/null +++ b/PythonHome/Lib/encodings/mac_cyrillic.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec mac_cyrillic generated from 'MAPPINGS/VENDORS/APPLE/CYRILLIC.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-cyrillic', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> CONTROL CHARACTER + u'\x01' # 0x01 -> CONTROL CHARACTER + u'\x02' # 0x02 -> CONTROL CHARACTER + u'\x03' # 0x03 -> CONTROL CHARACTER + u'\x04' # 0x04 -> CONTROL CHARACTER + u'\x05' # 0x05 -> CONTROL CHARACTER + u'\x06' # 0x06 -> CONTROL CHARACTER + u'\x07' # 0x07 -> CONTROL CHARACTER + u'\x08' # 0x08 -> CONTROL CHARACTER + u'\t' # 0x09 -> CONTROL CHARACTER + u'\n' # 0x0A -> CONTROL CHARACTER + u'\x0b' # 0x0B -> CONTROL CHARACTER + u'\x0c' # 0x0C -> CONTROL CHARACTER + u'\r' # 0x0D -> CONTROL CHARACTER + u'\x0e' # 0x0E -> CONTROL CHARACTER + u'\x0f' # 0x0F -> CONTROL CHARACTER + u'\x10' # 0x10 -> CONTROL CHARACTER + u'\x11' # 0x11 -> CONTROL CHARACTER + u'\x12' # 0x12 -> CONTROL CHARACTER + u'\x13' # 0x13 -> CONTROL CHARACTER + u'\x14' # 0x14 -> CONTROL CHARACTER + u'\x15' # 0x15 -> CONTROL CHARACTER + u'\x16' # 0x16 -> CONTROL CHARACTER + u'\x17' # 0x17 -> CONTROL CHARACTER + u'\x18' # 0x18 -> CONTROL CHARACTER + u'\x19' # 0x19 -> CONTROL CHARACTER + u'\x1a' # 0x1A -> CONTROL CHARACTER + u'\x1b' # 0x1B -> CONTROL CHARACTER + u'\x1c' # 0x1C -> CONTROL CHARACTER + u'\x1d' # 0x1D -> CONTROL CHARACTER + u'\x1e' # 0x1E -> CONTROL CHARACTER + u'\x1f' # 0x1F -> CONTROL CHARACTER + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> CONTROL CHARACTER + u'\u0410' # 0x80 -> CYRILLIC CAPITAL LETTER A + u'\u0411' # 0x81 -> CYRILLIC CAPITAL LETTER BE + u'\u0412' # 0x82 -> CYRILLIC CAPITAL LETTER VE + u'\u0413' # 0x83 -> CYRILLIC CAPITAL LETTER GHE + u'\u0414' # 0x84 -> CYRILLIC CAPITAL LETTER DE + u'\u0415' # 0x85 -> CYRILLIC CAPITAL LETTER IE + u'\u0416' # 0x86 -> CYRILLIC CAPITAL LETTER ZHE + u'\u0417' # 0x87 -> CYRILLIC CAPITAL LETTER ZE + u'\u0418' # 0x88 -> CYRILLIC CAPITAL LETTER I + u'\u0419' # 0x89 -> CYRILLIC CAPITAL LETTER SHORT I + u'\u041a' # 0x8A -> CYRILLIC CAPITAL LETTER KA + u'\u041b' # 0x8B -> CYRILLIC CAPITAL LETTER EL + u'\u041c' # 0x8C -> CYRILLIC CAPITAL LETTER EM + u'\u041d' # 0x8D -> CYRILLIC CAPITAL LETTER EN + u'\u041e' # 0x8E -> CYRILLIC CAPITAL LETTER O + u'\u041f' # 0x8F -> CYRILLIC CAPITAL LETTER PE + u'\u0420' # 0x90 -> CYRILLIC CAPITAL LETTER ER + u'\u0421' # 0x91 -> CYRILLIC CAPITAL LETTER ES + u'\u0422' # 0x92 -> CYRILLIC CAPITAL LETTER TE + u'\u0423' # 0x93 -> CYRILLIC CAPITAL LETTER U + u'\u0424' # 0x94 -> CYRILLIC CAPITAL LETTER EF + u'\u0425' # 0x95 -> CYRILLIC CAPITAL LETTER HA + u'\u0426' # 0x96 -> CYRILLIC CAPITAL LETTER TSE + u'\u0427' # 0x97 -> CYRILLIC CAPITAL LETTER CHE + u'\u0428' # 0x98 -> CYRILLIC CAPITAL LETTER SHA + u'\u0429' # 0x99 -> CYRILLIC CAPITAL LETTER SHCHA + u'\u042a' # 0x9A -> CYRILLIC CAPITAL LETTER HARD SIGN + u'\u042b' # 0x9B -> CYRILLIC CAPITAL LETTER YERU + u'\u042c' # 0x9C -> CYRILLIC CAPITAL LETTER SOFT SIGN + u'\u042d' # 0x9D -> CYRILLIC CAPITAL LETTER E + u'\u042e' # 0x9E -> CYRILLIC CAPITAL LETTER YU + u'\u042f' # 0x9F -> CYRILLIC CAPITAL LETTER YA + u'\u2020' # 0xA0 -> DAGGER + u'\xb0' # 0xA1 -> DEGREE SIGN + u'\u0490' # 0xA2 -> CYRILLIC CAPITAL LETTER GHE WITH UPTURN + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa7' # 0xA4 -> SECTION SIGN + u'\u2022' # 0xA5 -> BULLET + u'\xb6' # 0xA6 -> PILCROW SIGN + u'\u0406' # 0xA7 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + u'\xae' # 0xA8 -> REGISTERED SIGN + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\u2122' # 0xAA -> TRADE MARK SIGN + u'\u0402' # 0xAB -> CYRILLIC CAPITAL LETTER DJE + u'\u0452' # 0xAC -> CYRILLIC SMALL LETTER DJE + u'\u2260' # 0xAD -> NOT EQUAL TO + u'\u0403' # 0xAE -> CYRILLIC CAPITAL LETTER GJE + u'\u0453' # 0xAF -> CYRILLIC SMALL LETTER GJE + u'\u221e' # 0xB0 -> INFINITY + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + u'\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + u'\u0456' # 0xB4 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + u'\xb5' # 0xB5 -> MICRO SIGN + u'\u0491' # 0xB6 -> CYRILLIC SMALL LETTER GHE WITH UPTURN + u'\u0408' # 0xB7 -> CYRILLIC CAPITAL LETTER JE + u'\u0404' # 0xB8 -> CYRILLIC CAPITAL LETTER UKRAINIAN IE + u'\u0454' # 0xB9 -> CYRILLIC SMALL LETTER UKRAINIAN IE + u'\u0407' # 0xBA -> CYRILLIC CAPITAL LETTER YI + u'\u0457' # 0xBB -> CYRILLIC SMALL LETTER YI + u'\u0409' # 0xBC -> CYRILLIC CAPITAL LETTER LJE + u'\u0459' # 0xBD -> CYRILLIC SMALL LETTER LJE + u'\u040a' # 0xBE -> CYRILLIC CAPITAL LETTER NJE + u'\u045a' # 0xBF -> CYRILLIC SMALL LETTER NJE + u'\u0458' # 0xC0 -> CYRILLIC SMALL LETTER JE + u'\u0405' # 0xC1 -> CYRILLIC CAPITAL LETTER DZE + u'\xac' # 0xC2 -> NOT SIGN + u'\u221a' # 0xC3 -> SQUARE ROOT + u'\u0192' # 0xC4 -> LATIN SMALL LETTER F WITH HOOK + u'\u2248' # 0xC5 -> ALMOST EQUAL TO + u'\u2206' # 0xC6 -> INCREMENT + u'\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + u'\xa0' # 0xCA -> NO-BREAK SPACE + u'\u040b' # 0xCB -> CYRILLIC CAPITAL LETTER TSHE + u'\u045b' # 0xCC -> CYRILLIC SMALL LETTER TSHE + u'\u040c' # 0xCD -> CYRILLIC CAPITAL LETTER KJE + u'\u045c' # 0xCE -> CYRILLIC SMALL LETTER KJE + u'\u0455' # 0xCF -> CYRILLIC SMALL LETTER DZE + u'\u2013' # 0xD0 -> EN DASH + u'\u2014' # 0xD1 -> EM DASH + u'\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + u'\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + u'\xf7' # 0xD6 -> DIVISION SIGN + u'\u201e' # 0xD7 -> DOUBLE LOW-9 QUOTATION MARK + u'\u040e' # 0xD8 -> CYRILLIC CAPITAL LETTER SHORT U + u'\u045e' # 0xD9 -> CYRILLIC SMALL LETTER SHORT U + u'\u040f' # 0xDA -> CYRILLIC CAPITAL LETTER DZHE + u'\u045f' # 0xDB -> CYRILLIC SMALL LETTER DZHE + u'\u2116' # 0xDC -> NUMERO SIGN + u'\u0401' # 0xDD -> CYRILLIC CAPITAL LETTER IO + u'\u0451' # 0xDE -> CYRILLIC SMALL LETTER IO + u'\u044f' # 0xDF -> CYRILLIC SMALL LETTER YA + u'\u0430' # 0xE0 -> CYRILLIC SMALL LETTER A + u'\u0431' # 0xE1 -> CYRILLIC SMALL LETTER BE + u'\u0432' # 0xE2 -> CYRILLIC SMALL LETTER VE + u'\u0433' # 0xE3 -> CYRILLIC SMALL LETTER GHE + u'\u0434' # 0xE4 -> CYRILLIC SMALL LETTER DE + u'\u0435' # 0xE5 -> CYRILLIC SMALL LETTER IE + u'\u0436' # 0xE6 -> CYRILLIC SMALL LETTER ZHE + u'\u0437' # 0xE7 -> CYRILLIC SMALL LETTER ZE + u'\u0438' # 0xE8 -> CYRILLIC SMALL LETTER I + u'\u0439' # 0xE9 -> CYRILLIC SMALL LETTER SHORT I + u'\u043a' # 0xEA -> CYRILLIC SMALL LETTER KA + u'\u043b' # 0xEB -> CYRILLIC SMALL LETTER EL + u'\u043c' # 0xEC -> CYRILLIC SMALL LETTER EM + u'\u043d' # 0xED -> CYRILLIC SMALL LETTER EN + u'\u043e' # 0xEE -> CYRILLIC SMALL LETTER O + u'\u043f' # 0xEF -> CYRILLIC SMALL LETTER PE + u'\u0440' # 0xF0 -> CYRILLIC SMALL LETTER ER + u'\u0441' # 0xF1 -> CYRILLIC SMALL LETTER ES + u'\u0442' # 0xF2 -> CYRILLIC SMALL LETTER TE + u'\u0443' # 0xF3 -> CYRILLIC SMALL LETTER U + u'\u0444' # 0xF4 -> CYRILLIC SMALL LETTER EF + u'\u0445' # 0xF5 -> CYRILLIC SMALL LETTER HA + u'\u0446' # 0xF6 -> CYRILLIC SMALL LETTER TSE + u'\u0447' # 0xF7 -> CYRILLIC SMALL LETTER CHE + u'\u0448' # 0xF8 -> CYRILLIC SMALL LETTER SHA + u'\u0449' # 0xF9 -> CYRILLIC SMALL LETTER SHCHA + u'\u044a' # 0xFA -> CYRILLIC SMALL LETTER HARD SIGN + u'\u044b' # 0xFB -> CYRILLIC SMALL LETTER YERU + u'\u044c' # 0xFC -> CYRILLIC SMALL LETTER SOFT SIGN + u'\u044d' # 0xFD -> CYRILLIC SMALL LETTER E + u'\u044e' # 0xFE -> CYRILLIC SMALL LETTER YU + u'\u20ac' # 0xFF -> EURO SIGN +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/mac_cyrillic.pyc b/PythonHome/Lib/encodings/mac_cyrillic.pyc deleted file mode 100644 index 3dd71a389221cd1c1c5d7a06f04fd2ab3928ee5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2800 zcmc&$Yg<%R6y9@X7{I$0Mmct4x(MB`X6k@O;YeplgsAaw&KWp17dmsuD9ce0LCq`P z6$x*dWLk-pU7lxpo<6VbPdI;}A7E?kHto;9;7JZFI8)%3jvbSRZ4pZEmLegux>W{-VLd z)DmIv3PYf1@G`ZOX>MWju>>9vEZTfbEi2gk!d70i`I%Zli?$M`&R}f;aR8naV14Ld zkUWirXHoz?IE9*e&8|#36zP%;Sur&uv_|gk*3+G#NJiC^P)b(fO0S_Ole!Y>)Y6(E zo0=L*7@1V4dd-TariSS1Snay{Xx&;VR*UP#`r1gV)X>=25UFWi-&`Hqq?=u|Q=#)} zx_fJaLH!nfqNWe;7q=9#b)#k_xfa4n!x#`l0dGILjtHRaW+Z!<6bn-(Oh0|yG<3yO zXidY5BSPxAIGK!Xbg|9&>t?2#^?5LQ7wV(VcHvppoPk;eVMxi{aob&?5+VW;H|36` zX78dKvRX1BLeSIQJ*MzOGmMOp4Wp5XDZ2=zn)XJ$qrGrSwtX_92#38DZ`_6B7Xo;3Z<708%3F1Wz1<1yK@uT24A~ zPbp-=i-MdCuvAW0Rp2C!T_q>8ngG^0d+L}{_GT9@@Vo9tv`$dy|3Q>eZ6it~x(iW> zN|+Pyl)xn3Ex_^bU`n&lG;MAYhVu(&BaW1#m}zKos>RT;t`<2-j9W=xq}1A+#9D?j z6TEVg>jWpHDMd(Bsl*{7yu%Aglhyyq3#z+Sju*wyDP~qh*@Zw7^zw+wR*OtA$e8tL0UHz)n zZ#2C5R^yuJ+NQUqSo1sUTGqF=z1#lY`|%BOhoWkU&Mtl92gy`A)BT~5HG4kV^l|Se zpKku_^DVFs_QL@<2*Yp)4#N>R3di6$oPd*X3P#{GjKY^N24~!&^ zuie}agV4{1VFy0~L;M)*${qXTx|JJ&J$wZA^3zuTVc5#|^Sy8duEKZlJ^TRIU;?hgkMI-x z3^(8x_!WMG-+7L2<=c24@8{e30N=p}`4Hd9ck$i)3%^`$$ysOsesPe@Qxe^rUL{7Sv8+(o_nA=*dg%F1*Zx+q2XWv4wgo1C`!N PZ CONTROL CHARACTER + u'\x01' # 0x01 -> CONTROL CHARACTER + u'\x02' # 0x02 -> CONTROL CHARACTER + u'\x03' # 0x03 -> CONTROL CHARACTER + u'\x04' # 0x04 -> CONTROL CHARACTER + u'\x05' # 0x05 -> CONTROL CHARACTER + u'\x06' # 0x06 -> CONTROL CHARACTER + u'\x07' # 0x07 -> CONTROL CHARACTER + u'\x08' # 0x08 -> CONTROL CHARACTER + u'\t' # 0x09 -> CONTROL CHARACTER + u'\n' # 0x0A -> CONTROL CHARACTER + u'\x0b' # 0x0B -> CONTROL CHARACTER + u'\x0c' # 0x0C -> CONTROL CHARACTER + u'\r' # 0x0D -> CONTROL CHARACTER + u'\x0e' # 0x0E -> CONTROL CHARACTER + u'\x0f' # 0x0F -> CONTROL CHARACTER + u'\x10' # 0x10 -> CONTROL CHARACTER + u'\x11' # 0x11 -> CONTROL CHARACTER + u'\x12' # 0x12 -> CONTROL CHARACTER + u'\x13' # 0x13 -> CONTROL CHARACTER + u'\x14' # 0x14 -> CONTROL CHARACTER + u'\x15' # 0x15 -> CONTROL CHARACTER + u'\x16' # 0x16 -> CONTROL CHARACTER + u'\x17' # 0x17 -> CONTROL CHARACTER + u'\x18' # 0x18 -> CONTROL CHARACTER + u'\x19' # 0x19 -> CONTROL CHARACTER + u'\x1a' # 0x1A -> CONTROL CHARACTER + u'\x1b' # 0x1B -> CONTROL CHARACTER + u'\x1c' # 0x1C -> CONTROL CHARACTER + u'\x1d' # 0x1D -> CONTROL CHARACTER + u'\x1e' # 0x1E -> CONTROL CHARACTER + u'\x1f' # 0x1F -> CONTROL CHARACTER + u' ' # 0x20 -> SPACE, left-right + u'!' # 0x21 -> EXCLAMATION MARK, left-right + u'"' # 0x22 -> QUOTATION MARK, left-right + u'#' # 0x23 -> NUMBER SIGN, left-right + u'$' # 0x24 -> DOLLAR SIGN, left-right + u'%' # 0x25 -> PERCENT SIGN, left-right + u'&' # 0x26 -> AMPERSAND, left-right + u"'" # 0x27 -> APOSTROPHE, left-right + u'(' # 0x28 -> LEFT PARENTHESIS, left-right + u')' # 0x29 -> RIGHT PARENTHESIS, left-right + u'*' # 0x2A -> ASTERISK, left-right + u'+' # 0x2B -> PLUS SIGN, left-right + u',' # 0x2C -> COMMA, left-right; in Arabic-script context, displayed as 0x066C ARABIC THOUSANDS SEPARATOR + u'-' # 0x2D -> HYPHEN-MINUS, left-right + u'.' # 0x2E -> FULL STOP, left-right; in Arabic-script context, displayed as 0x066B ARABIC DECIMAL SEPARATOR + u'/' # 0x2F -> SOLIDUS, left-right + u'0' # 0x30 -> DIGIT ZERO; in Arabic-script context, displayed as 0x06F0 EXTENDED ARABIC-INDIC DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE; in Arabic-script context, displayed as 0x06F1 EXTENDED ARABIC-INDIC DIGIT ONE + u'2' # 0x32 -> DIGIT TWO; in Arabic-script context, displayed as 0x06F2 EXTENDED ARABIC-INDIC DIGIT TWO + u'3' # 0x33 -> DIGIT THREE; in Arabic-script context, displayed as 0x06F3 EXTENDED ARABIC-INDIC DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR; in Arabic-script context, displayed as 0x06F4 EXTENDED ARABIC-INDIC DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE; in Arabic-script context, displayed as 0x06F5 EXTENDED ARABIC-INDIC DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX; in Arabic-script context, displayed as 0x06F6 EXTENDED ARABIC-INDIC DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN; in Arabic-script context, displayed as 0x06F7 EXTENDED ARABIC-INDIC DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT; in Arabic-script context, displayed as 0x06F8 EXTENDED ARABIC-INDIC DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE; in Arabic-script context, displayed as 0x06F9 EXTENDED ARABIC-INDIC DIGIT NINE + u':' # 0x3A -> COLON, left-right + u';' # 0x3B -> SEMICOLON, left-right + u'<' # 0x3C -> LESS-THAN SIGN, left-right + u'=' # 0x3D -> EQUALS SIGN, left-right + u'>' # 0x3E -> GREATER-THAN SIGN, left-right + u'?' # 0x3F -> QUESTION MARK, left-right + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET, left-right + u'\\' # 0x5C -> REVERSE SOLIDUS, left-right + u']' # 0x5D -> RIGHT SQUARE BRACKET, left-right + u'^' # 0x5E -> CIRCUMFLEX ACCENT, left-right + u'_' # 0x5F -> LOW LINE, left-right + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET, left-right + u'|' # 0x7C -> VERTICAL LINE, left-right + u'}' # 0x7D -> RIGHT CURLY BRACKET, left-right + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> CONTROL CHARACTER + u'\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xa0' # 0x81 -> NO-BREAK SPACE, right-left + u'\xc7' # 0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xd1' # 0x84 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xe1' # 0x87 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe0' # 0x88 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe2' # 0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + u'\u06ba' # 0x8B -> ARABIC LETTER NOON GHUNNA + u'\xab' # 0x8C -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left + u'\xe7' # 0x8D -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + u'\xe8' # 0x8F -> LATIN SMALL LETTER E WITH GRAVE + u'\xea' # 0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x91 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xed' # 0x92 -> LATIN SMALL LETTER I WITH ACUTE + u'\u2026' # 0x93 -> HORIZONTAL ELLIPSIS, right-left + u'\xee' # 0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0x95 -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xf1' # 0x96 -> LATIN SMALL LETTER N WITH TILDE + u'\xf3' # 0x97 -> LATIN SMALL LETTER O WITH ACUTE + u'\xbb' # 0x98 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left + u'\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf7' # 0x9B -> DIVISION SIGN, right-left + u'\xfa' # 0x9C -> LATIN SMALL LETTER U WITH ACUTE + u'\xf9' # 0x9D -> LATIN SMALL LETTER U WITH GRAVE + u'\xfb' # 0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + u' ' # 0xA0 -> SPACE, right-left + u'!' # 0xA1 -> EXCLAMATION MARK, right-left + u'"' # 0xA2 -> QUOTATION MARK, right-left + u'#' # 0xA3 -> NUMBER SIGN, right-left + u'$' # 0xA4 -> DOLLAR SIGN, right-left + u'\u066a' # 0xA5 -> ARABIC PERCENT SIGN + u'&' # 0xA6 -> AMPERSAND, right-left + u"'" # 0xA7 -> APOSTROPHE, right-left + u'(' # 0xA8 -> LEFT PARENTHESIS, right-left + u')' # 0xA9 -> RIGHT PARENTHESIS, right-left + u'*' # 0xAA -> ASTERISK, right-left + u'+' # 0xAB -> PLUS SIGN, right-left + u'\u060c' # 0xAC -> ARABIC COMMA + u'-' # 0xAD -> HYPHEN-MINUS, right-left + u'.' # 0xAE -> FULL STOP, right-left + u'/' # 0xAF -> SOLIDUS, right-left + u'\u06f0' # 0xB0 -> EXTENDED ARABIC-INDIC DIGIT ZERO, right-left (need override) + u'\u06f1' # 0xB1 -> EXTENDED ARABIC-INDIC DIGIT ONE, right-left (need override) + u'\u06f2' # 0xB2 -> EXTENDED ARABIC-INDIC DIGIT TWO, right-left (need override) + u'\u06f3' # 0xB3 -> EXTENDED ARABIC-INDIC DIGIT THREE, right-left (need override) + u'\u06f4' # 0xB4 -> EXTENDED ARABIC-INDIC DIGIT FOUR, right-left (need override) + u'\u06f5' # 0xB5 -> EXTENDED ARABIC-INDIC DIGIT FIVE, right-left (need override) + u'\u06f6' # 0xB6 -> EXTENDED ARABIC-INDIC DIGIT SIX, right-left (need override) + u'\u06f7' # 0xB7 -> EXTENDED ARABIC-INDIC DIGIT SEVEN, right-left (need override) + u'\u06f8' # 0xB8 -> EXTENDED ARABIC-INDIC DIGIT EIGHT, right-left (need override) + u'\u06f9' # 0xB9 -> EXTENDED ARABIC-INDIC DIGIT NINE, right-left (need override) + u':' # 0xBA -> COLON, right-left + u'\u061b' # 0xBB -> ARABIC SEMICOLON + u'<' # 0xBC -> LESS-THAN SIGN, right-left + u'=' # 0xBD -> EQUALS SIGN, right-left + u'>' # 0xBE -> GREATER-THAN SIGN, right-left + u'\u061f' # 0xBF -> ARABIC QUESTION MARK + u'\u274a' # 0xC0 -> EIGHT TEARDROP-SPOKED PROPELLER ASTERISK, right-left + u'\u0621' # 0xC1 -> ARABIC LETTER HAMZA + u'\u0622' # 0xC2 -> ARABIC LETTER ALEF WITH MADDA ABOVE + u'\u0623' # 0xC3 -> ARABIC LETTER ALEF WITH HAMZA ABOVE + u'\u0624' # 0xC4 -> ARABIC LETTER WAW WITH HAMZA ABOVE + u'\u0625' # 0xC5 -> ARABIC LETTER ALEF WITH HAMZA BELOW + u'\u0626' # 0xC6 -> ARABIC LETTER YEH WITH HAMZA ABOVE + u'\u0627' # 0xC7 -> ARABIC LETTER ALEF + u'\u0628' # 0xC8 -> ARABIC LETTER BEH + u'\u0629' # 0xC9 -> ARABIC LETTER TEH MARBUTA + u'\u062a' # 0xCA -> ARABIC LETTER TEH + u'\u062b' # 0xCB -> ARABIC LETTER THEH + u'\u062c' # 0xCC -> ARABIC LETTER JEEM + u'\u062d' # 0xCD -> ARABIC LETTER HAH + u'\u062e' # 0xCE -> ARABIC LETTER KHAH + u'\u062f' # 0xCF -> ARABIC LETTER DAL + u'\u0630' # 0xD0 -> ARABIC LETTER THAL + u'\u0631' # 0xD1 -> ARABIC LETTER REH + u'\u0632' # 0xD2 -> ARABIC LETTER ZAIN + u'\u0633' # 0xD3 -> ARABIC LETTER SEEN + u'\u0634' # 0xD4 -> ARABIC LETTER SHEEN + u'\u0635' # 0xD5 -> ARABIC LETTER SAD + u'\u0636' # 0xD6 -> ARABIC LETTER DAD + u'\u0637' # 0xD7 -> ARABIC LETTER TAH + u'\u0638' # 0xD8 -> ARABIC LETTER ZAH + u'\u0639' # 0xD9 -> ARABIC LETTER AIN + u'\u063a' # 0xDA -> ARABIC LETTER GHAIN + u'[' # 0xDB -> LEFT SQUARE BRACKET, right-left + u'\\' # 0xDC -> REVERSE SOLIDUS, right-left + u']' # 0xDD -> RIGHT SQUARE BRACKET, right-left + u'^' # 0xDE -> CIRCUMFLEX ACCENT, right-left + u'_' # 0xDF -> LOW LINE, right-left + u'\u0640' # 0xE0 -> ARABIC TATWEEL + u'\u0641' # 0xE1 -> ARABIC LETTER FEH + u'\u0642' # 0xE2 -> ARABIC LETTER QAF + u'\u0643' # 0xE3 -> ARABIC LETTER KAF + u'\u0644' # 0xE4 -> ARABIC LETTER LAM + u'\u0645' # 0xE5 -> ARABIC LETTER MEEM + u'\u0646' # 0xE6 -> ARABIC LETTER NOON + u'\u0647' # 0xE7 -> ARABIC LETTER HEH + u'\u0648' # 0xE8 -> ARABIC LETTER WAW + u'\u0649' # 0xE9 -> ARABIC LETTER ALEF MAKSURA + u'\u064a' # 0xEA -> ARABIC LETTER YEH + u'\u064b' # 0xEB -> ARABIC FATHATAN + u'\u064c' # 0xEC -> ARABIC DAMMATAN + u'\u064d' # 0xED -> ARABIC KASRATAN + u'\u064e' # 0xEE -> ARABIC FATHA + u'\u064f' # 0xEF -> ARABIC DAMMA + u'\u0650' # 0xF0 -> ARABIC KASRA + u'\u0651' # 0xF1 -> ARABIC SHADDA + u'\u0652' # 0xF2 -> ARABIC SUKUN + u'\u067e' # 0xF3 -> ARABIC LETTER PEH + u'\u0679' # 0xF4 -> ARABIC LETTER TTEH + u'\u0686' # 0xF5 -> ARABIC LETTER TCHEH + u'\u06d5' # 0xF6 -> ARABIC LETTER AE + u'\u06a4' # 0xF7 -> ARABIC LETTER VEH + u'\u06af' # 0xF8 -> ARABIC LETTER GAF + u'\u0688' # 0xF9 -> ARABIC LETTER DDAL + u'\u0691' # 0xFA -> ARABIC LETTER RREH + u'{' # 0xFB -> LEFT CURLY BRACKET, right-left + u'|' # 0xFC -> VERTICAL LINE, right-left + u'}' # 0xFD -> RIGHT CURLY BRACKET, right-left + u'\u0698' # 0xFE -> ARABIC LETTER JEH + u'\u06d2' # 0xFF -> ARABIC LETTER YEH BARREE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/mac_farsi.pyc b/PythonHome/Lib/encodings/mac_farsi.pyc deleted file mode 100644 index 047159c4bf66a18e722a94a088e474bd5a391634..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2714 zcmc&$>sK2^6rW_15W=f(O+`(85g!HLk6J75ib9GTENw*7CA)#eJaBgr(W+IjFYAMz zqsMd9V_UHgu%#3Vg?jwJ{1da;Z~Yhi1M0oABn#*{*nZH!3^Vs;?%eykzquFT&$7U5 z=YeQ~EPVv{TMI*&n!W3#BGJ3O_P(!bzNeM&ILTyriznbX@HDqNa5lTymcv8}IHPoYI6iqS| zIh540=}=W$U3+^=WOuY?Z&Rdkj~K0ieQQ%qbDbD%sqWaELNF=dJ)p;d9Ra5yc38U!t_31S!cY&0+xVctSF9sDljn zJIq@_>hJ}K1C$YvGVrv6(J-2gs4x*8Er(o0!f^;i^p4ZR!ItwQsb-{<6ZG2gB2pOP za%ja;yr&E%ZnIfR=?aI`G5jyl#H6jyTlcwEW7)`Q^Z#IpNw%>>?ySO6#A@Y4yEcr- zwJk9I8Afp(sBVvsh~DPBVL%X56E!qNN_T216wd+=k!AJxMa-zpLnvFYCY(!7PMxs$ zYVFvN9zhs9wiPajiX{IhE?{xR`nKdkA!tlf1IlY*vR{+k8KEa)0fuJ<56Y8YLxb}o zr)3}3a_E8vbSyuXl3`L54I?EY20ksUDmreVfNtl_$SEnD#Hv#e?DDOx7TZ-z;|YVF z0SSWvXe|>A@(l88?UIT&@+Q@iNoIK|a;_EeEs0165z!DaE4P|T18Lf$fH%-14Q*%} zY<1)&aTU9Ku2T5%@t=WSq?5}nc)Y$Me{rCsw5+^h-TDn1H*MZ>$DP5gcU9hf&%L2- z_uc=%gAY}OAAaP~$F^73JpRO!Pd)w2v(G*M!j2brzO?J*+PeCN#-`@oue7}ST5DTm zPy6d)wBwDvo%{C3-t2no?f3zyJ0UB{o?f-@om4uL?SEI(je++D-yizm!-F4v{0SXd zJVlStV|0{$M}MTJ=_z`Kj^!2>C+InPfu5)1bb?;Iap)|)L?`JKonE|7XXq@QqYHGN zUZ=lv2hDNYLv{jOv@Tmy))i~onz620v(}t-&6?lAegJRT&o_QL&Q7y4>=!o1er0Fb zId-01VB>6p{l+e`OKg%|W>f46n`SfYDw}0<>>8VA3p^C_kol?knK^8Zn4g=6%_HVf z^O$+u{K7n8erbMXer CONTROL CHARACTER + u'\x01' # 0x01 -> CONTROL CHARACTER + u'\x02' # 0x02 -> CONTROL CHARACTER + u'\x03' # 0x03 -> CONTROL CHARACTER + u'\x04' # 0x04 -> CONTROL CHARACTER + u'\x05' # 0x05 -> CONTROL CHARACTER + u'\x06' # 0x06 -> CONTROL CHARACTER + u'\x07' # 0x07 -> CONTROL CHARACTER + u'\x08' # 0x08 -> CONTROL CHARACTER + u'\t' # 0x09 -> CONTROL CHARACTER + u'\n' # 0x0A -> CONTROL CHARACTER + u'\x0b' # 0x0B -> CONTROL CHARACTER + u'\x0c' # 0x0C -> CONTROL CHARACTER + u'\r' # 0x0D -> CONTROL CHARACTER + u'\x0e' # 0x0E -> CONTROL CHARACTER + u'\x0f' # 0x0F -> CONTROL CHARACTER + u'\x10' # 0x10 -> CONTROL CHARACTER + u'\x11' # 0x11 -> CONTROL CHARACTER + u'\x12' # 0x12 -> CONTROL CHARACTER + u'\x13' # 0x13 -> CONTROL CHARACTER + u'\x14' # 0x14 -> CONTROL CHARACTER + u'\x15' # 0x15 -> CONTROL CHARACTER + u'\x16' # 0x16 -> CONTROL CHARACTER + u'\x17' # 0x17 -> CONTROL CHARACTER + u'\x18' # 0x18 -> CONTROL CHARACTER + u'\x19' # 0x19 -> CONTROL CHARACTER + u'\x1a' # 0x1A -> CONTROL CHARACTER + u'\x1b' # 0x1B -> CONTROL CHARACTER + u'\x1c' # 0x1C -> CONTROL CHARACTER + u'\x1d' # 0x1D -> CONTROL CHARACTER + u'\x1e' # 0x1E -> CONTROL CHARACTER + u'\x1f' # 0x1F -> CONTROL CHARACTER + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> CONTROL CHARACTER + u'\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xb9' # 0x81 -> SUPERSCRIPT ONE + u'\xb2' # 0x82 -> SUPERSCRIPT TWO + u'\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xb3' # 0x84 -> SUPERSCRIPT THREE + u'\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\u0385' # 0x87 -> GREEK DIALYTIKA TONOS + u'\xe0' # 0x88 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe2' # 0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + u'\u0384' # 0x8B -> GREEK TONOS + u'\xa8' # 0x8C -> DIAERESIS + u'\xe7' # 0x8D -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + u'\xe8' # 0x8F -> LATIN SMALL LETTER E WITH GRAVE + u'\xea' # 0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x91 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xa3' # 0x92 -> POUND SIGN + u'\u2122' # 0x93 -> TRADE MARK SIGN + u'\xee' # 0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0x95 -> LATIN SMALL LETTER I WITH DIAERESIS + u'\u2022' # 0x96 -> BULLET + u'\xbd' # 0x97 -> VULGAR FRACTION ONE HALF + u'\u2030' # 0x98 -> PER MILLE SIGN + u'\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xa6' # 0x9B -> BROKEN BAR + u'\u20ac' # 0x9C -> EURO SIGN # before Mac OS 9.2.2, was SOFT HYPHEN + u'\xf9' # 0x9D -> LATIN SMALL LETTER U WITH GRAVE + u'\xfb' # 0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + u'\u2020' # 0xA0 -> DAGGER + u'\u0393' # 0xA1 -> GREEK CAPITAL LETTER GAMMA + u'\u0394' # 0xA2 -> GREEK CAPITAL LETTER DELTA + u'\u0398' # 0xA3 -> GREEK CAPITAL LETTER THETA + u'\u039b' # 0xA4 -> GREEK CAPITAL LETTER LAMDA + u'\u039e' # 0xA5 -> GREEK CAPITAL LETTER XI + u'\u03a0' # 0xA6 -> GREEK CAPITAL LETTER PI + u'\xdf' # 0xA7 -> LATIN SMALL LETTER SHARP S + u'\xae' # 0xA8 -> REGISTERED SIGN + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\u03a3' # 0xAA -> GREEK CAPITAL LETTER SIGMA + u'\u03aa' # 0xAB -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + u'\xa7' # 0xAC -> SECTION SIGN + u'\u2260' # 0xAD -> NOT EQUAL TO + u'\xb0' # 0xAE -> DEGREE SIGN + u'\xb7' # 0xAF -> MIDDLE DOT + u'\u0391' # 0xB0 -> GREEK CAPITAL LETTER ALPHA + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + u'\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + u'\xa5' # 0xB4 -> YEN SIGN + u'\u0392' # 0xB5 -> GREEK CAPITAL LETTER BETA + u'\u0395' # 0xB6 -> GREEK CAPITAL LETTER EPSILON + u'\u0396' # 0xB7 -> GREEK CAPITAL LETTER ZETA + u'\u0397' # 0xB8 -> GREEK CAPITAL LETTER ETA + u'\u0399' # 0xB9 -> GREEK CAPITAL LETTER IOTA + u'\u039a' # 0xBA -> GREEK CAPITAL LETTER KAPPA + u'\u039c' # 0xBB -> GREEK CAPITAL LETTER MU + u'\u03a6' # 0xBC -> GREEK CAPITAL LETTER PHI + u'\u03ab' # 0xBD -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + u'\u03a8' # 0xBE -> GREEK CAPITAL LETTER PSI + u'\u03a9' # 0xBF -> GREEK CAPITAL LETTER OMEGA + u'\u03ac' # 0xC0 -> GREEK SMALL LETTER ALPHA WITH TONOS + u'\u039d' # 0xC1 -> GREEK CAPITAL LETTER NU + u'\xac' # 0xC2 -> NOT SIGN + u'\u039f' # 0xC3 -> GREEK CAPITAL LETTER OMICRON + u'\u03a1' # 0xC4 -> GREEK CAPITAL LETTER RHO + u'\u2248' # 0xC5 -> ALMOST EQUAL TO + u'\u03a4' # 0xC6 -> GREEK CAPITAL LETTER TAU + u'\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + u'\xa0' # 0xCA -> NO-BREAK SPACE + u'\u03a5' # 0xCB -> GREEK CAPITAL LETTER UPSILON + u'\u03a7' # 0xCC -> GREEK CAPITAL LETTER CHI + u'\u0386' # 0xCD -> GREEK CAPITAL LETTER ALPHA WITH TONOS + u'\u0388' # 0xCE -> GREEK CAPITAL LETTER EPSILON WITH TONOS + u'\u0153' # 0xCF -> LATIN SMALL LIGATURE OE + u'\u2013' # 0xD0 -> EN DASH + u'\u2015' # 0xD1 -> HORIZONTAL BAR + u'\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + u'\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + u'\xf7' # 0xD6 -> DIVISION SIGN + u'\u0389' # 0xD7 -> GREEK CAPITAL LETTER ETA WITH TONOS + u'\u038a' # 0xD8 -> GREEK CAPITAL LETTER IOTA WITH TONOS + u'\u038c' # 0xD9 -> GREEK CAPITAL LETTER OMICRON WITH TONOS + u'\u038e' # 0xDA -> GREEK CAPITAL LETTER UPSILON WITH TONOS + u'\u03ad' # 0xDB -> GREEK SMALL LETTER EPSILON WITH TONOS + u'\u03ae' # 0xDC -> GREEK SMALL LETTER ETA WITH TONOS + u'\u03af' # 0xDD -> GREEK SMALL LETTER IOTA WITH TONOS + u'\u03cc' # 0xDE -> GREEK SMALL LETTER OMICRON WITH TONOS + u'\u038f' # 0xDF -> GREEK CAPITAL LETTER OMEGA WITH TONOS + u'\u03cd' # 0xE0 -> GREEK SMALL LETTER UPSILON WITH TONOS + u'\u03b1' # 0xE1 -> GREEK SMALL LETTER ALPHA + u'\u03b2' # 0xE2 -> GREEK SMALL LETTER BETA + u'\u03c8' # 0xE3 -> GREEK SMALL LETTER PSI + u'\u03b4' # 0xE4 -> GREEK SMALL LETTER DELTA + u'\u03b5' # 0xE5 -> GREEK SMALL LETTER EPSILON + u'\u03c6' # 0xE6 -> GREEK SMALL LETTER PHI + u'\u03b3' # 0xE7 -> GREEK SMALL LETTER GAMMA + u'\u03b7' # 0xE8 -> GREEK SMALL LETTER ETA + u'\u03b9' # 0xE9 -> GREEK SMALL LETTER IOTA + u'\u03be' # 0xEA -> GREEK SMALL LETTER XI + u'\u03ba' # 0xEB -> GREEK SMALL LETTER KAPPA + u'\u03bb' # 0xEC -> GREEK SMALL LETTER LAMDA + u'\u03bc' # 0xED -> GREEK SMALL LETTER MU + u'\u03bd' # 0xEE -> GREEK SMALL LETTER NU + u'\u03bf' # 0xEF -> GREEK SMALL LETTER OMICRON + u'\u03c0' # 0xF0 -> GREEK SMALL LETTER PI + u'\u03ce' # 0xF1 -> GREEK SMALL LETTER OMEGA WITH TONOS + u'\u03c1' # 0xF2 -> GREEK SMALL LETTER RHO + u'\u03c3' # 0xF3 -> GREEK SMALL LETTER SIGMA + u'\u03c4' # 0xF4 -> GREEK SMALL LETTER TAU + u'\u03b8' # 0xF5 -> GREEK SMALL LETTER THETA + u'\u03c9' # 0xF6 -> GREEK SMALL LETTER OMEGA + u'\u03c2' # 0xF7 -> GREEK SMALL LETTER FINAL SIGMA + u'\u03c7' # 0xF8 -> GREEK SMALL LETTER CHI + u'\u03c5' # 0xF9 -> GREEK SMALL LETTER UPSILON + u'\u03b6' # 0xFA -> GREEK SMALL LETTER ZETA + u'\u03ca' # 0xFB -> GREEK SMALL LETTER IOTA WITH DIALYTIKA + u'\u03cb' # 0xFC -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA + u'\u0390' # 0xFD -> GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + u'\u03b0' # 0xFE -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + u'\xad' # 0xFF -> SOFT HYPHEN # before Mac OS 9.2.2, was undefined +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/mac_greek.pyc b/PythonHome/Lib/encodings/mac_greek.pyc deleted file mode 100644 index ae631201fbae19866fb0cadc2d2a7cb7b03eb089..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2754 zcmc&$dv_C65WjggO&`3`V%6ZQ@j>hRiC8EFD-i0YQmECi&2HL29(A*|R#77@NDvW4 z5EP_BpR|Sou-Q?chJCmI|^PAtDsq4=Y|3u@? zaFk6yF8o`KBQuGU#8?x~4kkHS!oiww;bO9b?Q*ghuHCGMv2Mn8G&z~%;R+X5c=HMu zlM1-P%@w}9!p)>YCOf&#!(wQ_pVxVqR5YXWa$Rv==Vej}ZJG+0RLYus+yGkgv2JwG zPo9Q@3n+jzPJ#L^wJn_r)U=6;7*%B@utjWdkEdD#HEBtX29jbl(yGYv?m(-Yk`+;v zr9ezcCj%8**4Ee8g*Jw(w$+B#ZxzB-xZhk`wNa?8-Bj7Iy`dt|8CTorwJ2GtZ11Y{ z`{Ot938@}DncL5!>O{#paw>q6jNT)99M~Ro8e_+`lhNA6gm92@pnB=&suGW?QQFgR z$DITs z(5ttEfM_G)T*Q~Rh9D650)ZzK;B>n_TgC~oX`h1xiR!~C5=n_kITBI*e3MK|9SPhD zq!TDg`z*ei7bF4SVTCv{bcWYi>{1uwqAnFxG_HKY1E0#jQmnyh0MQ zsY49-JIpIkYV!q&gOqU*W$M*g?-9 zFCj${&W2VfrgKVg;x;#kiHyu4wGIDEG%0C|W~_T1bFo~{Y4iVJNlCV_B<{??QlM&O zM>{`^#I@x({uxGLA*$|-kA&W`8N-Mmr6#N@vY2dC;#fTMJS3K_qaRX6EgoXo!ZqVu zvU6&O#aHvkM)WAd!DG9{1wj_2|HK6gY7wpc({@n&R~6i(u}T@bADt;`i$ zRZHOs!=8Z&!+~hc5_Iwm@?))%N+4Jre7B5-4Z24Vxm#w&` z{NDTS53GFP!G|7xq$2p}V~;Gs3gZ)+v2-+Cz7dj`+G`8?RdZQgRT!h z+Vk-zpXxo@ly+IqX;<{)`YG6__v&Z$KIqYg^g(@CAJWh3BicE$=d3=aUo^94wHs!3 zT)(PMXanZnQGH6kre8O+y>Jx1g%j`t{0P1J8Es4(hI4RU8#Hsh+PF3eUu&1lT%Vci z*ZScbI0nbzJ2(m7!zmbm5g3AD7=_c?D4c{czxqqh=Pr z$IR?0Gke<1o-nf~^-0LVK{y15;R1}oMdJ{BWqb*j;IeT5uENj8ez*dYFa^KCuW${n z!wvY|$Qp-@&x~%P2YxYf#$MxdV;@Wy2aPY_2#jkNf|NaEEVVr;9mO_BO~RsyO%CFP z#SrQ+0u?uvO8Lxx8!a92gk<#(l+L2iyoG>w+|^c(UE{)cGt~01N4m>=W$rR}xvSh$ KxWIdpx&H!obd3N2 diff --git a/PythonHome/Lib/encodings/mac_iceland.py b/PythonHome/Lib/encodings/mac_iceland.py new file mode 100644 index 0000000000..c24add2ad0 --- /dev/null +++ b/PythonHome/Lib/encodings/mac_iceland.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec mac_iceland generated from 'MAPPINGS/VENDORS/APPLE/ICELAND.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-iceland', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> CONTROL CHARACTER + u'\x01' # 0x01 -> CONTROL CHARACTER + u'\x02' # 0x02 -> CONTROL CHARACTER + u'\x03' # 0x03 -> CONTROL CHARACTER + u'\x04' # 0x04 -> CONTROL CHARACTER + u'\x05' # 0x05 -> CONTROL CHARACTER + u'\x06' # 0x06 -> CONTROL CHARACTER + u'\x07' # 0x07 -> CONTROL CHARACTER + u'\x08' # 0x08 -> CONTROL CHARACTER + u'\t' # 0x09 -> CONTROL CHARACTER + u'\n' # 0x0A -> CONTROL CHARACTER + u'\x0b' # 0x0B -> CONTROL CHARACTER + u'\x0c' # 0x0C -> CONTROL CHARACTER + u'\r' # 0x0D -> CONTROL CHARACTER + u'\x0e' # 0x0E -> CONTROL CHARACTER + u'\x0f' # 0x0F -> CONTROL CHARACTER + u'\x10' # 0x10 -> CONTROL CHARACTER + u'\x11' # 0x11 -> CONTROL CHARACTER + u'\x12' # 0x12 -> CONTROL CHARACTER + u'\x13' # 0x13 -> CONTROL CHARACTER + u'\x14' # 0x14 -> CONTROL CHARACTER + u'\x15' # 0x15 -> CONTROL CHARACTER + u'\x16' # 0x16 -> CONTROL CHARACTER + u'\x17' # 0x17 -> CONTROL CHARACTER + u'\x18' # 0x18 -> CONTROL CHARACTER + u'\x19' # 0x19 -> CONTROL CHARACTER + u'\x1a' # 0x1A -> CONTROL CHARACTER + u'\x1b' # 0x1B -> CONTROL CHARACTER + u'\x1c' # 0x1C -> CONTROL CHARACTER + u'\x1d' # 0x1D -> CONTROL CHARACTER + u'\x1e' # 0x1E -> CONTROL CHARACTER + u'\x1f' # 0x1F -> CONTROL CHARACTER + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> CONTROL CHARACTER + u'\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0x81 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc7' # 0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xd1' # 0x84 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xe1' # 0x87 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe0' # 0x88 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe2' # 0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe3' # 0x8B -> LATIN SMALL LETTER A WITH TILDE + u'\xe5' # 0x8C -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe7' # 0x8D -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + u'\xe8' # 0x8F -> LATIN SMALL LETTER E WITH GRAVE + u'\xea' # 0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x91 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xed' # 0x92 -> LATIN SMALL LETTER I WITH ACUTE + u'\xec' # 0x93 -> LATIN SMALL LETTER I WITH GRAVE + u'\xee' # 0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0x95 -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xf1' # 0x96 -> LATIN SMALL LETTER N WITH TILDE + u'\xf3' # 0x97 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf2' # 0x98 -> LATIN SMALL LETTER O WITH GRAVE + u'\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf5' # 0x9B -> LATIN SMALL LETTER O WITH TILDE + u'\xfa' # 0x9C -> LATIN SMALL LETTER U WITH ACUTE + u'\xf9' # 0x9D -> LATIN SMALL LETTER U WITH GRAVE + u'\xfb' # 0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + u'\xdd' # 0xA0 -> LATIN CAPITAL LETTER Y WITH ACUTE + u'\xb0' # 0xA1 -> DEGREE SIGN + u'\xa2' # 0xA2 -> CENT SIGN + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa7' # 0xA4 -> SECTION SIGN + u'\u2022' # 0xA5 -> BULLET + u'\xb6' # 0xA6 -> PILCROW SIGN + u'\xdf' # 0xA7 -> LATIN SMALL LETTER SHARP S + u'\xae' # 0xA8 -> REGISTERED SIGN + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\u2122' # 0xAA -> TRADE MARK SIGN + u'\xb4' # 0xAB -> ACUTE ACCENT + u'\xa8' # 0xAC -> DIAERESIS + u'\u2260' # 0xAD -> NOT EQUAL TO + u'\xc6' # 0xAE -> LATIN CAPITAL LETTER AE + u'\xd8' # 0xAF -> LATIN CAPITAL LETTER O WITH STROKE + u'\u221e' # 0xB0 -> INFINITY + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + u'\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + u'\xa5' # 0xB4 -> YEN SIGN + u'\xb5' # 0xB5 -> MICRO SIGN + u'\u2202' # 0xB6 -> PARTIAL DIFFERENTIAL + u'\u2211' # 0xB7 -> N-ARY SUMMATION + u'\u220f' # 0xB8 -> N-ARY PRODUCT + u'\u03c0' # 0xB9 -> GREEK SMALL LETTER PI + u'\u222b' # 0xBA -> INTEGRAL + u'\xaa' # 0xBB -> FEMININE ORDINAL INDICATOR + u'\xba' # 0xBC -> MASCULINE ORDINAL INDICATOR + u'\u03a9' # 0xBD -> GREEK CAPITAL LETTER OMEGA + u'\xe6' # 0xBE -> LATIN SMALL LETTER AE + u'\xf8' # 0xBF -> LATIN SMALL LETTER O WITH STROKE + u'\xbf' # 0xC0 -> INVERTED QUESTION MARK + u'\xa1' # 0xC1 -> INVERTED EXCLAMATION MARK + u'\xac' # 0xC2 -> NOT SIGN + u'\u221a' # 0xC3 -> SQUARE ROOT + u'\u0192' # 0xC4 -> LATIN SMALL LETTER F WITH HOOK + u'\u2248' # 0xC5 -> ALMOST EQUAL TO + u'\u2206' # 0xC6 -> INCREMENT + u'\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + u'\xa0' # 0xCA -> NO-BREAK SPACE + u'\xc0' # 0xCB -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc3' # 0xCC -> LATIN CAPITAL LETTER A WITH TILDE + u'\xd5' # 0xCD -> LATIN CAPITAL LETTER O WITH TILDE + u'\u0152' # 0xCE -> LATIN CAPITAL LIGATURE OE + u'\u0153' # 0xCF -> LATIN SMALL LIGATURE OE + u'\u2013' # 0xD0 -> EN DASH + u'\u2014' # 0xD1 -> EM DASH + u'\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + u'\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + u'\xf7' # 0xD6 -> DIVISION SIGN + u'\u25ca' # 0xD7 -> LOZENGE + u'\xff' # 0xD8 -> LATIN SMALL LETTER Y WITH DIAERESIS + u'\u0178' # 0xD9 -> LATIN CAPITAL LETTER Y WITH DIAERESIS + u'\u2044' # 0xDA -> FRACTION SLASH + u'\u20ac' # 0xDB -> EURO SIGN + u'\xd0' # 0xDC -> LATIN CAPITAL LETTER ETH + u'\xf0' # 0xDD -> LATIN SMALL LETTER ETH + u'\xde' # 0xDE -> LATIN CAPITAL LETTER THORN + u'\xfe' # 0xDF -> LATIN SMALL LETTER THORN + u'\xfd' # 0xE0 -> LATIN SMALL LETTER Y WITH ACUTE + u'\xb7' # 0xE1 -> MIDDLE DOT + u'\u201a' # 0xE2 -> SINGLE LOW-9 QUOTATION MARK + u'\u201e' # 0xE3 -> DOUBLE LOW-9 QUOTATION MARK + u'\u2030' # 0xE4 -> PER MILLE SIGN + u'\xc2' # 0xE5 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xca' # 0xE6 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xc1' # 0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xcb' # 0xE8 -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xc8' # 0xE9 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xcd' # 0xEA -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xEB -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0xEC -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\xcc' # 0xED -> LATIN CAPITAL LETTER I WITH GRAVE + u'\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\uf8ff' # 0xF0 -> Apple logo + u'\xd2' # 0xF1 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xda' # 0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0xF3 -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xd9' # 0xF4 -> LATIN CAPITAL LETTER U WITH GRAVE + u'\u0131' # 0xF5 -> LATIN SMALL LETTER DOTLESS I + u'\u02c6' # 0xF6 -> MODIFIER LETTER CIRCUMFLEX ACCENT + u'\u02dc' # 0xF7 -> SMALL TILDE + u'\xaf' # 0xF8 -> MACRON + u'\u02d8' # 0xF9 -> BREVE + u'\u02d9' # 0xFA -> DOT ABOVE + u'\u02da' # 0xFB -> RING ABOVE + u'\xb8' # 0xFC -> CEDILLA + u'\u02dd' # 0xFD -> DOUBLE ACUTE ACCENT + u'\u02db' # 0xFE -> OGONEK + u'\u02c7' # 0xFF -> CARON +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/mac_iceland.pyc b/PythonHome/Lib/encodings/mac_iceland.pyc deleted file mode 100644 index 05d04b752593b4d1abfcfe6a7d530d9e81345d28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2793 zcmc&$X?qk!5biy*SrWpn!HA1j)`P_RL<}SWqhX1&NFYX+$;@mrxJR6sh*6Y2Es*MfT@$lbU~pjE9!zwEvHRe2~#JtwvaG@mO`u# z9SoDF@n{7FVB!>M>9xADnMi$?Y{-hG8Ih%OcekGDjMQgUO^KvsC7~-?O3tW}PA#Ju zvZbk!q>)WWs+TToX=#criPx@Zj5REi;F%uwhxKdt#H;|GF3u<->qW^Tax8+Ah7llw0^ELd9OK8em(kkCqJ>DIk=%oA$Yy^azrRtTp=A|t1@M8XP-O**Ug zq;M;dPNF#7)5K~5KuP!(E5%{bDM4?U&zgpdri@}}X)R;PsYZdKp`cVeMKaC6twScf zOe%8;L_GK>)U#3QvIgmc#PJbv@RC=?qhvOw{- z*b|AE(4rW}!z-21N#!^RtBd87sR>wJ(-TINQa5$Xe$aC>o(+ON{|}y&Xa`SX&`o$s zRJ+`GCjupLZWfMzhf#w&)G z%Rjcpwih6Ft3j&n*c&bEV<9RmeXJxNC2GVhx@J^kOv)^l)Opuilv`p1oprZ7I3?Y< zS?p9XL!=G+2&N4OA~sI2R^(9}>=apYK{T$WOfoA9lY6X0w@M;XNQ8$(nYs0ZS`=2N zhW=pZw2a=lxHXBT%v0(Kddlz<6rY~mL@STi=MMx+LZ#tJW#yAArc9kSea6gLcidSy z`>v|H=iC#Sd+&YsKk#66^r43zd30V)?PHHW@#IraKlAK!&%f~E{FfHIT(@vheM95o zC9gES`dahS*s_+_rTFqUR;%N>fUB|E$HHSeU-nQZsFhH3S@xAy(s z4?bM?(Z}ndA3lN2FaX=&YuE$(U<5|t0PKf@a2Srl5jY0N;X611C*c&Ffgj*|I1A_D z99)7Q;WGRLd+pQqsJ-7l%yXmmdHB{oX&>eNqxM<*2p<@MO|X;ahwU?b-~b;uXdkrC z@%%=f-^TM>|H$$Dar>Bk>Gz{>2rk-J?0xnLo*(*ckPqZ}ev^INzRYun>=DR8AAEIn z@alG+!|x8B+rx8vd2T1q?Sc#Zn=NqV>P5bxpKm+?U&3h^hF{=k`vT7m@!T-aoraCD z1vbE^kcZFV3)l*u!FJg3=l&}&2t%+NcKv#$u&J=eK2_LR*i{&^FBbL|b{95BDUnEE z>WOMr!5&Ec!{Lm}6e5X37ivBd)jW%8{Mf%E9X)zVby^Eb$MIWA1s{gt6gf2F_5R~0C&2wr3UzX9iqo2~!= diff --git a/PythonHome/Lib/encodings/mac_latin2.py b/PythonHome/Lib/encodings/mac_latin2.py new file mode 100644 index 0000000000..e322be236c --- /dev/null +++ b/PythonHome/Lib/encodings/mac_latin2.py @@ -0,0 +1,183 @@ +""" Python Character Mapping Codec generated from 'LATIN2.TXT' with gencodec.py. + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. +(c) Copyright 2000 Guido van Rossum. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_map) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_map)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-latin2', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x00c4, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x0081: 0x0100, # LATIN CAPITAL LETTER A WITH MACRON + 0x0082: 0x0101, # LATIN SMALL LETTER A WITH MACRON + 0x0083: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0084: 0x0104, # LATIN CAPITAL LETTER A WITH OGONEK + 0x0085: 0x00d6, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x0086: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x0087: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE + 0x0088: 0x0105, # LATIN SMALL LETTER A WITH OGONEK + 0x0089: 0x010c, # LATIN CAPITAL LETTER C WITH CARON + 0x008a: 0x00e4, # LATIN SMALL LETTER A WITH DIAERESIS + 0x008b: 0x010d, # LATIN SMALL LETTER C WITH CARON + 0x008c: 0x0106, # LATIN CAPITAL LETTER C WITH ACUTE + 0x008d: 0x0107, # LATIN SMALL LETTER C WITH ACUTE + 0x008e: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x008f: 0x0179, # LATIN CAPITAL LETTER Z WITH ACUTE + 0x0090: 0x017a, # LATIN SMALL LETTER Z WITH ACUTE + 0x0091: 0x010e, # LATIN CAPITAL LETTER D WITH CARON + 0x0092: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE + 0x0093: 0x010f, # LATIN SMALL LETTER D WITH CARON + 0x0094: 0x0112, # LATIN CAPITAL LETTER E WITH MACRON + 0x0095: 0x0113, # LATIN SMALL LETTER E WITH MACRON + 0x0096: 0x0116, # LATIN CAPITAL LETTER E WITH DOT ABOVE + 0x0097: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x0098: 0x0117, # LATIN SMALL LETTER E WITH DOT ABOVE + 0x0099: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x009a: 0x00f6, # LATIN SMALL LETTER O WITH DIAERESIS + 0x009b: 0x00f5, # LATIN SMALL LETTER O WITH TILDE + 0x009c: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x009d: 0x011a, # LATIN CAPITAL LETTER E WITH CARON + 0x009e: 0x011b, # LATIN SMALL LETTER E WITH CARON + 0x009f: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00a0: 0x2020, # DAGGER + 0x00a1: 0x00b0, # DEGREE SIGN + 0x00a2: 0x0118, # LATIN CAPITAL LETTER E WITH OGONEK + 0x00a4: 0x00a7, # SECTION SIGN + 0x00a5: 0x2022, # BULLET + 0x00a6: 0x00b6, # PILCROW SIGN + 0x00a7: 0x00df, # LATIN SMALL LETTER SHARP S + 0x00a8: 0x00ae, # REGISTERED SIGN + 0x00aa: 0x2122, # TRADE MARK SIGN + 0x00ab: 0x0119, # LATIN SMALL LETTER E WITH OGONEK + 0x00ac: 0x00a8, # DIAERESIS + 0x00ad: 0x2260, # NOT EQUAL TO + 0x00ae: 0x0123, # LATIN SMALL LETTER G WITH CEDILLA + 0x00af: 0x012e, # LATIN CAPITAL LETTER I WITH OGONEK + 0x00b0: 0x012f, # LATIN SMALL LETTER I WITH OGONEK + 0x00b1: 0x012a, # LATIN CAPITAL LETTER I WITH MACRON + 0x00b2: 0x2264, # LESS-THAN OR EQUAL TO + 0x00b3: 0x2265, # GREATER-THAN OR EQUAL TO + 0x00b4: 0x012b, # LATIN SMALL LETTER I WITH MACRON + 0x00b5: 0x0136, # LATIN CAPITAL LETTER K WITH CEDILLA + 0x00b6: 0x2202, # PARTIAL DIFFERENTIAL + 0x00b7: 0x2211, # N-ARY SUMMATION + 0x00b8: 0x0142, # LATIN SMALL LETTER L WITH STROKE + 0x00b9: 0x013b, # LATIN CAPITAL LETTER L WITH CEDILLA + 0x00ba: 0x013c, # LATIN SMALL LETTER L WITH CEDILLA + 0x00bb: 0x013d, # LATIN CAPITAL LETTER L WITH CARON + 0x00bc: 0x013e, # LATIN SMALL LETTER L WITH CARON + 0x00bd: 0x0139, # LATIN CAPITAL LETTER L WITH ACUTE + 0x00be: 0x013a, # LATIN SMALL LETTER L WITH ACUTE + 0x00bf: 0x0145, # LATIN CAPITAL LETTER N WITH CEDILLA + 0x00c0: 0x0146, # LATIN SMALL LETTER N WITH CEDILLA + 0x00c1: 0x0143, # LATIN CAPITAL LETTER N WITH ACUTE + 0x00c2: 0x00ac, # NOT SIGN + 0x00c3: 0x221a, # SQUARE ROOT + 0x00c4: 0x0144, # LATIN SMALL LETTER N WITH ACUTE + 0x00c5: 0x0147, # LATIN CAPITAL LETTER N WITH CARON + 0x00c6: 0x2206, # INCREMENT + 0x00c7: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00c8: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00c9: 0x2026, # HORIZONTAL ELLIPSIS + 0x00ca: 0x00a0, # NO-BREAK SPACE + 0x00cb: 0x0148, # LATIN SMALL LETTER N WITH CARON + 0x00cc: 0x0150, # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + 0x00cd: 0x00d5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00ce: 0x0151, # LATIN SMALL LETTER O WITH DOUBLE ACUTE + 0x00cf: 0x014c, # LATIN CAPITAL LETTER O WITH MACRON + 0x00d0: 0x2013, # EN DASH + 0x00d1: 0x2014, # EM DASH + 0x00d2: 0x201c, # LEFT DOUBLE QUOTATION MARK + 0x00d3: 0x201d, # RIGHT DOUBLE QUOTATION MARK + 0x00d4: 0x2018, # LEFT SINGLE QUOTATION MARK + 0x00d5: 0x2019, # RIGHT SINGLE QUOTATION MARK + 0x00d6: 0x00f7, # DIVISION SIGN + 0x00d7: 0x25ca, # LOZENGE + 0x00d8: 0x014d, # LATIN SMALL LETTER O WITH MACRON + 0x00d9: 0x0154, # LATIN CAPITAL LETTER R WITH ACUTE + 0x00da: 0x0155, # LATIN SMALL LETTER R WITH ACUTE + 0x00db: 0x0158, # LATIN CAPITAL LETTER R WITH CARON + 0x00dc: 0x2039, # SINGLE LEFT-POINTING ANGLE QUOTATION MARK + 0x00dd: 0x203a, # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + 0x00de: 0x0159, # LATIN SMALL LETTER R WITH CARON + 0x00df: 0x0156, # LATIN CAPITAL LETTER R WITH CEDILLA + 0x00e0: 0x0157, # LATIN SMALL LETTER R WITH CEDILLA + 0x00e1: 0x0160, # LATIN CAPITAL LETTER S WITH CARON + 0x00e2: 0x201a, # SINGLE LOW-9 QUOTATION MARK + 0x00e3: 0x201e, # DOUBLE LOW-9 QUOTATION MARK + 0x00e4: 0x0161, # LATIN SMALL LETTER S WITH CARON + 0x00e5: 0x015a, # LATIN CAPITAL LETTER S WITH ACUTE + 0x00e6: 0x015b, # LATIN SMALL LETTER S WITH ACUTE + 0x00e7: 0x00c1, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00e8: 0x0164, # LATIN CAPITAL LETTER T WITH CARON + 0x00e9: 0x0165, # LATIN SMALL LETTER T WITH CARON + 0x00ea: 0x00cd, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00eb: 0x017d, # LATIN CAPITAL LETTER Z WITH CARON + 0x00ec: 0x017e, # LATIN SMALL LETTER Z WITH CARON + 0x00ed: 0x016a, # LATIN CAPITAL LETTER U WITH MACRON + 0x00ee: 0x00d3, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00ef: 0x00d4, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00f0: 0x016b, # LATIN SMALL LETTER U WITH MACRON + 0x00f1: 0x016e, # LATIN CAPITAL LETTER U WITH RING ABOVE + 0x00f2: 0x00da, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00f3: 0x016f, # LATIN SMALL LETTER U WITH RING ABOVE + 0x00f4: 0x0170, # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + 0x00f5: 0x0171, # LATIN SMALL LETTER U WITH DOUBLE ACUTE + 0x00f6: 0x0172, # LATIN CAPITAL LETTER U WITH OGONEK + 0x00f7: 0x0173, # LATIN SMALL LETTER U WITH OGONEK + 0x00f8: 0x00dd, # LATIN CAPITAL LETTER Y WITH ACUTE + 0x00f9: 0x00fd, # LATIN SMALL LETTER Y WITH ACUTE + 0x00fa: 0x0137, # LATIN SMALL LETTER K WITH CEDILLA + 0x00fb: 0x017b, # LATIN CAPITAL LETTER Z WITH DOT ABOVE + 0x00fc: 0x0141, # LATIN CAPITAL LETTER L WITH STROKE + 0x00fd: 0x017c, # LATIN SMALL LETTER Z WITH DOT ABOVE + 0x00fe: 0x0122, # LATIN CAPITAL LETTER G WITH CEDILLA + 0x00ff: 0x02c7, # CARON +}) + +### Encoding Map + +encoding_map = codecs.make_encoding_map(decoding_map) diff --git a/PythonHome/Lib/encodings/mac_latin2.pyc b/PythonHome/Lib/encodings/mac_latin2.pyc deleted file mode 100644 index 53175dcb552dadf87fb01b3695b1658dfe5c600e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4772 zcmd^?d3+S*8ONX9Y&Hi8R}e@zI$(uGB~sds1(6cMVcHOJ5)H((VcBPr4D1nSC(tNT zHK=&s_ia6>x2SmE2a5N7;(hjR?S0wb?_HBkv7e9VANog=%^Tm=1#t7p;Je5ZwVbQgjq-v}h%)N^}fttmrt{c+qdbEYS(D ziK08gzA3sBY?A0?SWI*ZY-iD3V7rP=g;k602Ad}OE!cF?Z^OPL`dyeUx;yN9qBCGK zMfZTs65SIvTlD*|IifYNxuUhOd7|@S3q%*f_7bgw{Xq1GuzJx&um;h+VT(ogfjOd$ zuqM%cVf%?T!ST3lo$B7;fJ3;hB*fPHt zQ(>oxo(?-h^i0@UqG!X-5j_`np6L0o3q&u3T_k!j>}R5vz%CWN40gHb2H4L9m)d%T zAXjX?QuHd=)uPwHt`)rwcD?9E*bSmL!fq0zldYRXZ-(6>dMoTU!5Y|lyXYOTI|Zp` z>s_LE!|oBi7j~Z@)oi_A^a0p|q7T8=i*ANJEcys+iy-4{%tIfAJtq1%>7L)36Pq&%mA)eGc}#=nJroqA$W;5+t6jFAFlx)>j0nX6vhh#IyA^!AxyDxo(BM zF8T)SO+gyk`j+V1uy+LcXY0FyVO!r5eINFL=!atC1q`t`l<_6x+gQ%J(HQ%P#uUP+G^O_YOZmdnueyO)!SS(ecH5X z*1~R2GuEnj+Hx}4YyuA-=}Lx{qL!-fmQ zX^a)%q#(-E1K&#o3ATAeaMZH90uqR<2+11!g(V0}ZvmnlLVrX4aucU)Fc`fFggX`Q zYRd&LC_|S)1ilUZxodd;teb2%6Y$bq-GO-u*Y`7iHikhlk{t)CZmsv0xAxs5+nS0e z+LH0WOHaqbe30{ zO}XhHo}6zY=qJ!?e)_X$1e&=l!ndbNK697=pAB;rdh_Xmyg|kkFk_H_m5njpw!wpl znXU=B!+bMAbog{8Kl0Hv3DWMR4JDN>zbhE@4UV7 zWGqMa-98%HHk$KH;(R^PEa4=Xk`B{nn`k;i*oR|#UoVqyV{rce4y40(?n~z6FkH%X zF?U7`xjK!3@5WQCv~E6n%(S^Yk&BwkMN}@Zn0(4FYkp#ewj)jW7L3R7*=KOvxPCRy zz#1?i{|x=FAeYLN;5mTYJC)lSV^hp3jF$_qRiuw2+!G_QHOhjHZE#Q|TFi>lD@Bbl zrbR=*7mURv%iKU6otmqo`O;!C*~{03ToL!T?aoy%->ezFIk09p5U&9ptIZ;s&&^d< zK7skFs!O+LOhw9ntiu<|VMaI%hr@OG!mAmuHg>pp9DH#He$ON{vrJG4m4u?9GWqsw94yU|EIfC*Q^x?i5BEi(k9Afls72XP&QB|PJmoNs^kr>Bwa;WHW6|)X-5uJQ?6xmH`30O>)FIU zR=kZQmvjSZ7mnUYvPn0Q!Wneo+MRRkf%r^NKcc-lAa-rBRxwRO?r-0N%{+E%TACNNsD;Dmq<;dmr47Q zULh?Zy-J#4L1t36vbmH4uaov8HB;VXa~Y}1g1pVGz~RP%>{G4VaO+-*kA~%EO%_0NnnSD5pi(HfOPDo!cp4WI&bt{I5H+ qyPTEVPtGpJ#o3{l6}E$s%HqmMWn^r@*us+X9Z)Tc{%?N=75)br|E?(j diff --git a/PythonHome/Lib/encodings/mac_roman.py b/PythonHome/Lib/encodings/mac_roman.py new file mode 100644 index 0000000000..62605ec634 --- /dev/null +++ b/PythonHome/Lib/encodings/mac_roman.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec mac_roman generated from 'MAPPINGS/VENDORS/APPLE/ROMAN.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-roman', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> CONTROL CHARACTER + u'\x01' # 0x01 -> CONTROL CHARACTER + u'\x02' # 0x02 -> CONTROL CHARACTER + u'\x03' # 0x03 -> CONTROL CHARACTER + u'\x04' # 0x04 -> CONTROL CHARACTER + u'\x05' # 0x05 -> CONTROL CHARACTER + u'\x06' # 0x06 -> CONTROL CHARACTER + u'\x07' # 0x07 -> CONTROL CHARACTER + u'\x08' # 0x08 -> CONTROL CHARACTER + u'\t' # 0x09 -> CONTROL CHARACTER + u'\n' # 0x0A -> CONTROL CHARACTER + u'\x0b' # 0x0B -> CONTROL CHARACTER + u'\x0c' # 0x0C -> CONTROL CHARACTER + u'\r' # 0x0D -> CONTROL CHARACTER + u'\x0e' # 0x0E -> CONTROL CHARACTER + u'\x0f' # 0x0F -> CONTROL CHARACTER + u'\x10' # 0x10 -> CONTROL CHARACTER + u'\x11' # 0x11 -> CONTROL CHARACTER + u'\x12' # 0x12 -> CONTROL CHARACTER + u'\x13' # 0x13 -> CONTROL CHARACTER + u'\x14' # 0x14 -> CONTROL CHARACTER + u'\x15' # 0x15 -> CONTROL CHARACTER + u'\x16' # 0x16 -> CONTROL CHARACTER + u'\x17' # 0x17 -> CONTROL CHARACTER + u'\x18' # 0x18 -> CONTROL CHARACTER + u'\x19' # 0x19 -> CONTROL CHARACTER + u'\x1a' # 0x1A -> CONTROL CHARACTER + u'\x1b' # 0x1B -> CONTROL CHARACTER + u'\x1c' # 0x1C -> CONTROL CHARACTER + u'\x1d' # 0x1D -> CONTROL CHARACTER + u'\x1e' # 0x1E -> CONTROL CHARACTER + u'\x1f' # 0x1F -> CONTROL CHARACTER + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> CONTROL CHARACTER + u'\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0x81 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc7' # 0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xd1' # 0x84 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xe1' # 0x87 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe0' # 0x88 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe2' # 0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe3' # 0x8B -> LATIN SMALL LETTER A WITH TILDE + u'\xe5' # 0x8C -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe7' # 0x8D -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + u'\xe8' # 0x8F -> LATIN SMALL LETTER E WITH GRAVE + u'\xea' # 0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x91 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xed' # 0x92 -> LATIN SMALL LETTER I WITH ACUTE + u'\xec' # 0x93 -> LATIN SMALL LETTER I WITH GRAVE + u'\xee' # 0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0x95 -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xf1' # 0x96 -> LATIN SMALL LETTER N WITH TILDE + u'\xf3' # 0x97 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf2' # 0x98 -> LATIN SMALL LETTER O WITH GRAVE + u'\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf5' # 0x9B -> LATIN SMALL LETTER O WITH TILDE + u'\xfa' # 0x9C -> LATIN SMALL LETTER U WITH ACUTE + u'\xf9' # 0x9D -> LATIN SMALL LETTER U WITH GRAVE + u'\xfb' # 0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + u'\u2020' # 0xA0 -> DAGGER + u'\xb0' # 0xA1 -> DEGREE SIGN + u'\xa2' # 0xA2 -> CENT SIGN + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa7' # 0xA4 -> SECTION SIGN + u'\u2022' # 0xA5 -> BULLET + u'\xb6' # 0xA6 -> PILCROW SIGN + u'\xdf' # 0xA7 -> LATIN SMALL LETTER SHARP S + u'\xae' # 0xA8 -> REGISTERED SIGN + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\u2122' # 0xAA -> TRADE MARK SIGN + u'\xb4' # 0xAB -> ACUTE ACCENT + u'\xa8' # 0xAC -> DIAERESIS + u'\u2260' # 0xAD -> NOT EQUAL TO + u'\xc6' # 0xAE -> LATIN CAPITAL LETTER AE + u'\xd8' # 0xAF -> LATIN CAPITAL LETTER O WITH STROKE + u'\u221e' # 0xB0 -> INFINITY + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + u'\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + u'\xa5' # 0xB4 -> YEN SIGN + u'\xb5' # 0xB5 -> MICRO SIGN + u'\u2202' # 0xB6 -> PARTIAL DIFFERENTIAL + u'\u2211' # 0xB7 -> N-ARY SUMMATION + u'\u220f' # 0xB8 -> N-ARY PRODUCT + u'\u03c0' # 0xB9 -> GREEK SMALL LETTER PI + u'\u222b' # 0xBA -> INTEGRAL + u'\xaa' # 0xBB -> FEMININE ORDINAL INDICATOR + u'\xba' # 0xBC -> MASCULINE ORDINAL INDICATOR + u'\u03a9' # 0xBD -> GREEK CAPITAL LETTER OMEGA + u'\xe6' # 0xBE -> LATIN SMALL LETTER AE + u'\xf8' # 0xBF -> LATIN SMALL LETTER O WITH STROKE + u'\xbf' # 0xC0 -> INVERTED QUESTION MARK + u'\xa1' # 0xC1 -> INVERTED EXCLAMATION MARK + u'\xac' # 0xC2 -> NOT SIGN + u'\u221a' # 0xC3 -> SQUARE ROOT + u'\u0192' # 0xC4 -> LATIN SMALL LETTER F WITH HOOK + u'\u2248' # 0xC5 -> ALMOST EQUAL TO + u'\u2206' # 0xC6 -> INCREMENT + u'\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + u'\xa0' # 0xCA -> NO-BREAK SPACE + u'\xc0' # 0xCB -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc3' # 0xCC -> LATIN CAPITAL LETTER A WITH TILDE + u'\xd5' # 0xCD -> LATIN CAPITAL LETTER O WITH TILDE + u'\u0152' # 0xCE -> LATIN CAPITAL LIGATURE OE + u'\u0153' # 0xCF -> LATIN SMALL LIGATURE OE + u'\u2013' # 0xD0 -> EN DASH + u'\u2014' # 0xD1 -> EM DASH + u'\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + u'\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + u'\xf7' # 0xD6 -> DIVISION SIGN + u'\u25ca' # 0xD7 -> LOZENGE + u'\xff' # 0xD8 -> LATIN SMALL LETTER Y WITH DIAERESIS + u'\u0178' # 0xD9 -> LATIN CAPITAL LETTER Y WITH DIAERESIS + u'\u2044' # 0xDA -> FRACTION SLASH + u'\u20ac' # 0xDB -> EURO SIGN + u'\u2039' # 0xDC -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + u'\u203a' # 0xDD -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + u'\ufb01' # 0xDE -> LATIN SMALL LIGATURE FI + u'\ufb02' # 0xDF -> LATIN SMALL LIGATURE FL + u'\u2021' # 0xE0 -> DOUBLE DAGGER + u'\xb7' # 0xE1 -> MIDDLE DOT + u'\u201a' # 0xE2 -> SINGLE LOW-9 QUOTATION MARK + u'\u201e' # 0xE3 -> DOUBLE LOW-9 QUOTATION MARK + u'\u2030' # 0xE4 -> PER MILLE SIGN + u'\xc2' # 0xE5 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xca' # 0xE6 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xc1' # 0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xcb' # 0xE8 -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xc8' # 0xE9 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xcd' # 0xEA -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xEB -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0xEC -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\xcc' # 0xED -> LATIN CAPITAL LETTER I WITH GRAVE + u'\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\uf8ff' # 0xF0 -> Apple logo + u'\xd2' # 0xF1 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xda' # 0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0xF3 -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xd9' # 0xF4 -> LATIN CAPITAL LETTER U WITH GRAVE + u'\u0131' # 0xF5 -> LATIN SMALL LETTER DOTLESS I + u'\u02c6' # 0xF6 -> MODIFIER LETTER CIRCUMFLEX ACCENT + u'\u02dc' # 0xF7 -> SMALL TILDE + u'\xaf' # 0xF8 -> MACRON + u'\u02d8' # 0xF9 -> BREVE + u'\u02d9' # 0xFA -> DOT ABOVE + u'\u02da' # 0xFB -> RING ABOVE + u'\xb8' # 0xFC -> CEDILLA + u'\u02dd' # 0xFD -> DOUBLE ACUTE ACCENT + u'\u02db' # 0xFE -> OGONEK + u'\u02c7' # 0xFF -> CARON +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/mac_roman.pyc b/PythonHome/Lib/encodings/mac_roman.pyc deleted file mode 100644 index 9673a31cf89ee47754dbce2d8e19f2be331c442e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2771 zcmc&$>30-G5br&+SrWpn!KjND>p|juB9aS?CYv}L3B>3!*_lli_lUC-F^W1QF>LVQ z5l|rn%)u2BIg}gU~^QSYNxvDSHG@`>(65U z*_MsrD7*f+@b79InR7TPjJ4wIV2YC^9IO==E~YxzCMS#G+RgeI>tk#~tCJ}np>PR> zH?MFpr9dd$LgC9R+)OECs#EAZEQSXBd7XzTb7pj2p)1Pkyi6&kO=|&D=CW3wFo2eP ztPdUZlc(We2?dbGDbUoTccxQ;>P}gcqq?dE8sx67c&Z~%omSLnASp*9S~@AG0v&2f z)nr{&0x=W>mN!&3HPwaIhAY<9hH4t6a0Tw`Yb&J2hRRTR^ZMrHfz5HflU|FGrSh(x za=$-*4WE$i!IOpkJgQEVRFP8woK*B4(G$S-qth5WuAPk5E+&P8lmp#MKi9Q*RFBf0 zh8ssUi5KFeGq%aWw&2&vbSLX`VcZUshwRsdXBmAiN}~usQtpaa?h27uA`}r_ZcnJz zTXaH3O~gb9@l;p0F8ok6Ev;pOsAOWwl;Ntptv=q~He)5zmd6sYu-+2T%psE$KXcqk zAQHWLQwWGQA}&N?d2$7E?5WDVkkRZ{0I7K2UIjKe>x?gOPX{9@X zTZwcMMQNWURiDN1d=AaRf~E}{%x?b2|N%!cAPF%hkRTq42=2qp4P(8I=7@FNya$q75? z+2bXoD8d_|m5S(`Vw{A{HF6@O3P^3k{}N3~+WZ;oUdOFi)(G1CKUh+dEi8#Uw_qtz zwX&m~9Y*5X5*+^wqcjgycg9CTZ}E&_M37Pw)-_d5wrFuIo_QV;%c|&ylu?U^ShjG@ z1effb+F^;+?6DC&N^ywTZgN3VW#vC{fr=~Dx9cwCgQhf9lYBK!)@`ynBlbipz<90j zLb+$w*x)?GX~j#m9J`>79m_|hq>mMZgG7mtPFIVnN`|&rKv#%nWS0~{;<#N9tn#hh zDz>VYCK84{0~3Y=(YisfS!7TgYn4O|8H z6}`b8scSvUaGN1+GDo4q>nOsHSA4q1h)xct%kA+N_zL}Vii+o!%$vVp;iAP$?z+2l z={;rl-gkds*#i$g^zb9ggO5J;_!BG2E1rDn>1UpO?)ev9eCg#^R=&FGwbhkX)it$i z*1lf%#+&sGp~j}Sq;T`w>sr=tXnm*c-S;9J<@Tte#yUFVo8C_(Q|Yb`w2a>U;pUHe zKK^9Or=NWe{qO~BgF)B{-@yos!6=NwL70F;a0DjdC>(<+_z|YzIGlh}@H6}br{OG| zfs1efF2OI{7&T9tKZf6b$HtZ?6np z*~Ja~?&ih_H}-R54>$J0IsW~2xP0Y2-`dZ6r@3)~8yBxmZ@oI*%Z)Mf95;r!aex~q zp%=EpR`?RK@HKn`JK!tW1-q|KT!tYShJCR2*HgKH+=zK1w{C>CX?MM1Zy31T;p28CEHRk>c32T-6 diff --git a/PythonHome/Lib/encodings/mac_romanian.py b/PythonHome/Lib/encodings/mac_romanian.py new file mode 100644 index 0000000000..5bd5ae8625 --- /dev/null +++ b/PythonHome/Lib/encodings/mac_romanian.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec mac_romanian generated from 'MAPPINGS/VENDORS/APPLE/ROMANIAN.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-romanian', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> CONTROL CHARACTER + u'\x01' # 0x01 -> CONTROL CHARACTER + u'\x02' # 0x02 -> CONTROL CHARACTER + u'\x03' # 0x03 -> CONTROL CHARACTER + u'\x04' # 0x04 -> CONTROL CHARACTER + u'\x05' # 0x05 -> CONTROL CHARACTER + u'\x06' # 0x06 -> CONTROL CHARACTER + u'\x07' # 0x07 -> CONTROL CHARACTER + u'\x08' # 0x08 -> CONTROL CHARACTER + u'\t' # 0x09 -> CONTROL CHARACTER + u'\n' # 0x0A -> CONTROL CHARACTER + u'\x0b' # 0x0B -> CONTROL CHARACTER + u'\x0c' # 0x0C -> CONTROL CHARACTER + u'\r' # 0x0D -> CONTROL CHARACTER + u'\x0e' # 0x0E -> CONTROL CHARACTER + u'\x0f' # 0x0F -> CONTROL CHARACTER + u'\x10' # 0x10 -> CONTROL CHARACTER + u'\x11' # 0x11 -> CONTROL CHARACTER + u'\x12' # 0x12 -> CONTROL CHARACTER + u'\x13' # 0x13 -> CONTROL CHARACTER + u'\x14' # 0x14 -> CONTROL CHARACTER + u'\x15' # 0x15 -> CONTROL CHARACTER + u'\x16' # 0x16 -> CONTROL CHARACTER + u'\x17' # 0x17 -> CONTROL CHARACTER + u'\x18' # 0x18 -> CONTROL CHARACTER + u'\x19' # 0x19 -> CONTROL CHARACTER + u'\x1a' # 0x1A -> CONTROL CHARACTER + u'\x1b' # 0x1B -> CONTROL CHARACTER + u'\x1c' # 0x1C -> CONTROL CHARACTER + u'\x1d' # 0x1D -> CONTROL CHARACTER + u'\x1e' # 0x1E -> CONTROL CHARACTER + u'\x1f' # 0x1F -> CONTROL CHARACTER + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> CONTROL CHARACTER + u'\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0x81 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc7' # 0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xd1' # 0x84 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xe1' # 0x87 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe0' # 0x88 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe2' # 0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe3' # 0x8B -> LATIN SMALL LETTER A WITH TILDE + u'\xe5' # 0x8C -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe7' # 0x8D -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + u'\xe8' # 0x8F -> LATIN SMALL LETTER E WITH GRAVE + u'\xea' # 0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x91 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xed' # 0x92 -> LATIN SMALL LETTER I WITH ACUTE + u'\xec' # 0x93 -> LATIN SMALL LETTER I WITH GRAVE + u'\xee' # 0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0x95 -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xf1' # 0x96 -> LATIN SMALL LETTER N WITH TILDE + u'\xf3' # 0x97 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf2' # 0x98 -> LATIN SMALL LETTER O WITH GRAVE + u'\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf5' # 0x9B -> LATIN SMALL LETTER O WITH TILDE + u'\xfa' # 0x9C -> LATIN SMALL LETTER U WITH ACUTE + u'\xf9' # 0x9D -> LATIN SMALL LETTER U WITH GRAVE + u'\xfb' # 0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + u'\u2020' # 0xA0 -> DAGGER + u'\xb0' # 0xA1 -> DEGREE SIGN + u'\xa2' # 0xA2 -> CENT SIGN + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa7' # 0xA4 -> SECTION SIGN + u'\u2022' # 0xA5 -> BULLET + u'\xb6' # 0xA6 -> PILCROW SIGN + u'\xdf' # 0xA7 -> LATIN SMALL LETTER SHARP S + u'\xae' # 0xA8 -> REGISTERED SIGN + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\u2122' # 0xAA -> TRADE MARK SIGN + u'\xb4' # 0xAB -> ACUTE ACCENT + u'\xa8' # 0xAC -> DIAERESIS + u'\u2260' # 0xAD -> NOT EQUAL TO + u'\u0102' # 0xAE -> LATIN CAPITAL LETTER A WITH BREVE + u'\u0218' # 0xAF -> LATIN CAPITAL LETTER S WITH COMMA BELOW # for Unicode 3.0 and later + u'\u221e' # 0xB0 -> INFINITY + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + u'\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + u'\xa5' # 0xB4 -> YEN SIGN + u'\xb5' # 0xB5 -> MICRO SIGN + u'\u2202' # 0xB6 -> PARTIAL DIFFERENTIAL + u'\u2211' # 0xB7 -> N-ARY SUMMATION + u'\u220f' # 0xB8 -> N-ARY PRODUCT + u'\u03c0' # 0xB9 -> GREEK SMALL LETTER PI + u'\u222b' # 0xBA -> INTEGRAL + u'\xaa' # 0xBB -> FEMININE ORDINAL INDICATOR + u'\xba' # 0xBC -> MASCULINE ORDINAL INDICATOR + u'\u03a9' # 0xBD -> GREEK CAPITAL LETTER OMEGA + u'\u0103' # 0xBE -> LATIN SMALL LETTER A WITH BREVE + u'\u0219' # 0xBF -> LATIN SMALL LETTER S WITH COMMA BELOW # for Unicode 3.0 and later + u'\xbf' # 0xC0 -> INVERTED QUESTION MARK + u'\xa1' # 0xC1 -> INVERTED EXCLAMATION MARK + u'\xac' # 0xC2 -> NOT SIGN + u'\u221a' # 0xC3 -> SQUARE ROOT + u'\u0192' # 0xC4 -> LATIN SMALL LETTER F WITH HOOK + u'\u2248' # 0xC5 -> ALMOST EQUAL TO + u'\u2206' # 0xC6 -> INCREMENT + u'\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + u'\xa0' # 0xCA -> NO-BREAK SPACE + u'\xc0' # 0xCB -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc3' # 0xCC -> LATIN CAPITAL LETTER A WITH TILDE + u'\xd5' # 0xCD -> LATIN CAPITAL LETTER O WITH TILDE + u'\u0152' # 0xCE -> LATIN CAPITAL LIGATURE OE + u'\u0153' # 0xCF -> LATIN SMALL LIGATURE OE + u'\u2013' # 0xD0 -> EN DASH + u'\u2014' # 0xD1 -> EM DASH + u'\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + u'\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + u'\xf7' # 0xD6 -> DIVISION SIGN + u'\u25ca' # 0xD7 -> LOZENGE + u'\xff' # 0xD8 -> LATIN SMALL LETTER Y WITH DIAERESIS + u'\u0178' # 0xD9 -> LATIN CAPITAL LETTER Y WITH DIAERESIS + u'\u2044' # 0xDA -> FRACTION SLASH + u'\u20ac' # 0xDB -> EURO SIGN + u'\u2039' # 0xDC -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + u'\u203a' # 0xDD -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + u'\u021a' # 0xDE -> LATIN CAPITAL LETTER T WITH COMMA BELOW # for Unicode 3.0 and later + u'\u021b' # 0xDF -> LATIN SMALL LETTER T WITH COMMA BELOW # for Unicode 3.0 and later + u'\u2021' # 0xE0 -> DOUBLE DAGGER + u'\xb7' # 0xE1 -> MIDDLE DOT + u'\u201a' # 0xE2 -> SINGLE LOW-9 QUOTATION MARK + u'\u201e' # 0xE3 -> DOUBLE LOW-9 QUOTATION MARK + u'\u2030' # 0xE4 -> PER MILLE SIGN + u'\xc2' # 0xE5 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xca' # 0xE6 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xc1' # 0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xcb' # 0xE8 -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xc8' # 0xE9 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xcd' # 0xEA -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xEB -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0xEC -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\xcc' # 0xED -> LATIN CAPITAL LETTER I WITH GRAVE + u'\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\uf8ff' # 0xF0 -> Apple logo + u'\xd2' # 0xF1 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xda' # 0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0xF3 -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xd9' # 0xF4 -> LATIN CAPITAL LETTER U WITH GRAVE + u'\u0131' # 0xF5 -> LATIN SMALL LETTER DOTLESS I + u'\u02c6' # 0xF6 -> MODIFIER LETTER CIRCUMFLEX ACCENT + u'\u02dc' # 0xF7 -> SMALL TILDE + u'\xaf' # 0xF8 -> MACRON + u'\u02d8' # 0xF9 -> BREVE + u'\u02d9' # 0xFA -> DOT ABOVE + u'\u02da' # 0xFB -> RING ABOVE + u'\xb8' # 0xFC -> CEDILLA + u'\u02dd' # 0xFD -> DOUBLE ACUTE ACCENT + u'\u02db' # 0xFE -> OGONEK + u'\u02c7' # 0xFF -> CARON +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/mac_romanian.pyc b/PythonHome/Lib/encodings/mac_romanian.pyc deleted file mode 100644 index f80ccd2fddf7cde3263951705d39950af9b30fc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2811 zcmc&$>2nlS5Py4Svn1h0gHaYQ)`P_RL`(<)qhyJ*$PuHvXdO%3e0WSU+PMTHH+W34=!% z{6&L@DJ8<-6^203;AKiFQ{BSmV+q_KShV?=GOb|q3tL&y=4VPdEm}&LQo&jRVguYM z!1~d_AbA=MPp1I7aSAo}8XcK*sJ=ti<+!2hp(eSjOG~$h>NAQO52fUIOwXj`v?ixR z?P^-pWkXd$3DkuaHPtmYH%3-QYt}YImamqgHMm~YP$R8ws*5z%MXJ}VU$ZFGqZu9a zW}Nn`?&_@$2DRJxL<}FEFHR|9>qgBoaxH|DiZLLD0^R|19T7m;%}DkzDH^6s7=HS> zp=)s?PHP%o9QCB0jg!Gxr;BaEubUZe*6+dSU8s*ZuM5wzMg?l)2t!KlirMZ8l@Jk- zm?5_%Rr@VEA*&`6A_Ohn)olnrR9(;L*)STJn6e8{s%~ASwY3&@$+nJ16ydO66zEK& zT?qo_no2AZy?R#^2snZ+R6@Kv3W@NS2tTO=rzyB??@zehaXU=F7y+DOv9z30V=*Hr z7O9NVoy4U?Hi-gtjuX;kppx)4R*EA_$N1f49%B{?jp?|qrqr|{CmRHgdK|UlDe`F! zE^R*HjZ&DyA)>-R!Jdy=hd9U}+j@yc0Ze5Eev9 zXlXg=#678y2`>tAJit;J9aWB#*mi}S%&G!dXYa{lO4*xPIKc0ki0E=bq5lU_O0|tB zk!S*<5|uC~;7Nf=yqkyP-@%k-plQn7Bn;;k_C_2jM^Qsp<U>JD`s!uK20UW1BRvr3I+I^s|y^nCKBP=(16%$r9jLTNf9)l~Za2r!}Wa z*u`C+sJ5$_E;5H51v7^OF&n4o5vdd>+trqQ5G|}Royds#Icye)d%~MZ5^XzlazwqKqFTe8YlGm2LUR$@U zetE-+m2Wh@`PQnY$m-^|rRbV>)~;K>q2=Ay_uh|fl-uHpnrQFPIzLFJ(wVLg^{mnT zQP0P{pM1LMv(LYP0r(QO!XWH`?_nPtf)N;nBXAgw!ZA1j$KfQLf}h|toPo1&9)5wJ z;R0NOi*OCD!gctSnyP4GXG&4+_-gxZyw-%r@48Ro7cvM$M$mbkad}x z!`wW;&2!KP+h8+%1v&TzzJ=}ZHSB`je;&R8J7F01!qCn0`7QZ<*4g}?{7`<_x{}|Y z-<#hWreq?GsX;24I5tG;B{p#!x)4)r&QK$gsQMXH?hF5&v~_Dq#cngG9Y?Ck)Ckd@ hm)H$?sRv)rQgg&^>a7e^dMmwEo+@AIbpLJU{TqDlr6m9W diff --git a/PythonHome/Lib/encodings/mac_turkish.py b/PythonHome/Lib/encodings/mac_turkish.py new file mode 100644 index 0000000000..0787f4990b --- /dev/null +++ b/PythonHome/Lib/encodings/mac_turkish.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec mac_turkish generated from 'MAPPINGS/VENDORS/APPLE/TURKISH.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-turkish', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> CONTROL CHARACTER + u'\x01' # 0x01 -> CONTROL CHARACTER + u'\x02' # 0x02 -> CONTROL CHARACTER + u'\x03' # 0x03 -> CONTROL CHARACTER + u'\x04' # 0x04 -> CONTROL CHARACTER + u'\x05' # 0x05 -> CONTROL CHARACTER + u'\x06' # 0x06 -> CONTROL CHARACTER + u'\x07' # 0x07 -> CONTROL CHARACTER + u'\x08' # 0x08 -> CONTROL CHARACTER + u'\t' # 0x09 -> CONTROL CHARACTER + u'\n' # 0x0A -> CONTROL CHARACTER + u'\x0b' # 0x0B -> CONTROL CHARACTER + u'\x0c' # 0x0C -> CONTROL CHARACTER + u'\r' # 0x0D -> CONTROL CHARACTER + u'\x0e' # 0x0E -> CONTROL CHARACTER + u'\x0f' # 0x0F -> CONTROL CHARACTER + u'\x10' # 0x10 -> CONTROL CHARACTER + u'\x11' # 0x11 -> CONTROL CHARACTER + u'\x12' # 0x12 -> CONTROL CHARACTER + u'\x13' # 0x13 -> CONTROL CHARACTER + u'\x14' # 0x14 -> CONTROL CHARACTER + u'\x15' # 0x15 -> CONTROL CHARACTER + u'\x16' # 0x16 -> CONTROL CHARACTER + u'\x17' # 0x17 -> CONTROL CHARACTER + u'\x18' # 0x18 -> CONTROL CHARACTER + u'\x19' # 0x19 -> CONTROL CHARACTER + u'\x1a' # 0x1A -> CONTROL CHARACTER + u'\x1b' # 0x1B -> CONTROL CHARACTER + u'\x1c' # 0x1C -> CONTROL CHARACTER + u'\x1d' # 0x1D -> CONTROL CHARACTER + u'\x1e' # 0x1E -> CONTROL CHARACTER + u'\x1f' # 0x1F -> CONTROL CHARACTER + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> CONTROL CHARACTER + u'\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + u'\xc5' # 0x81 -> LATIN CAPITAL LETTER A WITH RING ABOVE + u'\xc7' # 0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA + u'\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + u'\xd1' # 0x84 -> LATIN CAPITAL LETTER N WITH TILDE + u'\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + u'\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + u'\xe1' # 0x87 -> LATIN SMALL LETTER A WITH ACUTE + u'\xe0' # 0x88 -> LATIN SMALL LETTER A WITH GRAVE + u'\xe2' # 0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + u'\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + u'\xe3' # 0x8B -> LATIN SMALL LETTER A WITH TILDE + u'\xe5' # 0x8C -> LATIN SMALL LETTER A WITH RING ABOVE + u'\xe7' # 0x8D -> LATIN SMALL LETTER C WITH CEDILLA + u'\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + u'\xe8' # 0x8F -> LATIN SMALL LETTER E WITH GRAVE + u'\xea' # 0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + u'\xeb' # 0x91 -> LATIN SMALL LETTER E WITH DIAERESIS + u'\xed' # 0x92 -> LATIN SMALL LETTER I WITH ACUTE + u'\xec' # 0x93 -> LATIN SMALL LETTER I WITH GRAVE + u'\xee' # 0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + u'\xef' # 0x95 -> LATIN SMALL LETTER I WITH DIAERESIS + u'\xf1' # 0x96 -> LATIN SMALL LETTER N WITH TILDE + u'\xf3' # 0x97 -> LATIN SMALL LETTER O WITH ACUTE + u'\xf2' # 0x98 -> LATIN SMALL LETTER O WITH GRAVE + u'\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + u'\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + u'\xf5' # 0x9B -> LATIN SMALL LETTER O WITH TILDE + u'\xfa' # 0x9C -> LATIN SMALL LETTER U WITH ACUTE + u'\xf9' # 0x9D -> LATIN SMALL LETTER U WITH GRAVE + u'\xfb' # 0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX + u'\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + u'\u2020' # 0xA0 -> DAGGER + u'\xb0' # 0xA1 -> DEGREE SIGN + u'\xa2' # 0xA2 -> CENT SIGN + u'\xa3' # 0xA3 -> POUND SIGN + u'\xa7' # 0xA4 -> SECTION SIGN + u'\u2022' # 0xA5 -> BULLET + u'\xb6' # 0xA6 -> PILCROW SIGN + u'\xdf' # 0xA7 -> LATIN SMALL LETTER SHARP S + u'\xae' # 0xA8 -> REGISTERED SIGN + u'\xa9' # 0xA9 -> COPYRIGHT SIGN + u'\u2122' # 0xAA -> TRADE MARK SIGN + u'\xb4' # 0xAB -> ACUTE ACCENT + u'\xa8' # 0xAC -> DIAERESIS + u'\u2260' # 0xAD -> NOT EQUAL TO + u'\xc6' # 0xAE -> LATIN CAPITAL LETTER AE + u'\xd8' # 0xAF -> LATIN CAPITAL LETTER O WITH STROKE + u'\u221e' # 0xB0 -> INFINITY + u'\xb1' # 0xB1 -> PLUS-MINUS SIGN + u'\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + u'\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + u'\xa5' # 0xB4 -> YEN SIGN + u'\xb5' # 0xB5 -> MICRO SIGN + u'\u2202' # 0xB6 -> PARTIAL DIFFERENTIAL + u'\u2211' # 0xB7 -> N-ARY SUMMATION + u'\u220f' # 0xB8 -> N-ARY PRODUCT + u'\u03c0' # 0xB9 -> GREEK SMALL LETTER PI + u'\u222b' # 0xBA -> INTEGRAL + u'\xaa' # 0xBB -> FEMININE ORDINAL INDICATOR + u'\xba' # 0xBC -> MASCULINE ORDINAL INDICATOR + u'\u03a9' # 0xBD -> GREEK CAPITAL LETTER OMEGA + u'\xe6' # 0xBE -> LATIN SMALL LETTER AE + u'\xf8' # 0xBF -> LATIN SMALL LETTER O WITH STROKE + u'\xbf' # 0xC0 -> INVERTED QUESTION MARK + u'\xa1' # 0xC1 -> INVERTED EXCLAMATION MARK + u'\xac' # 0xC2 -> NOT SIGN + u'\u221a' # 0xC3 -> SQUARE ROOT + u'\u0192' # 0xC4 -> LATIN SMALL LETTER F WITH HOOK + u'\u2248' # 0xC5 -> ALMOST EQUAL TO + u'\u2206' # 0xC6 -> INCREMENT + u'\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\xbb' # 0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + u'\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + u'\xa0' # 0xCA -> NO-BREAK SPACE + u'\xc0' # 0xCB -> LATIN CAPITAL LETTER A WITH GRAVE + u'\xc3' # 0xCC -> LATIN CAPITAL LETTER A WITH TILDE + u'\xd5' # 0xCD -> LATIN CAPITAL LETTER O WITH TILDE + u'\u0152' # 0xCE -> LATIN CAPITAL LIGATURE OE + u'\u0153' # 0xCF -> LATIN SMALL LIGATURE OE + u'\u2013' # 0xD0 -> EN DASH + u'\u2014' # 0xD1 -> EM DASH + u'\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + u'\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + u'\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + u'\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + u'\xf7' # 0xD6 -> DIVISION SIGN + u'\u25ca' # 0xD7 -> LOZENGE + u'\xff' # 0xD8 -> LATIN SMALL LETTER Y WITH DIAERESIS + u'\u0178' # 0xD9 -> LATIN CAPITAL LETTER Y WITH DIAERESIS + u'\u011e' # 0xDA -> LATIN CAPITAL LETTER G WITH BREVE + u'\u011f' # 0xDB -> LATIN SMALL LETTER G WITH BREVE + u'\u0130' # 0xDC -> LATIN CAPITAL LETTER I WITH DOT ABOVE + u'\u0131' # 0xDD -> LATIN SMALL LETTER DOTLESS I + u'\u015e' # 0xDE -> LATIN CAPITAL LETTER S WITH CEDILLA + u'\u015f' # 0xDF -> LATIN SMALL LETTER S WITH CEDILLA + u'\u2021' # 0xE0 -> DOUBLE DAGGER + u'\xb7' # 0xE1 -> MIDDLE DOT + u'\u201a' # 0xE2 -> SINGLE LOW-9 QUOTATION MARK + u'\u201e' # 0xE3 -> DOUBLE LOW-9 QUOTATION MARK + u'\u2030' # 0xE4 -> PER MILLE SIGN + u'\xc2' # 0xE5 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + u'\xca' # 0xE6 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + u'\xc1' # 0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE + u'\xcb' # 0xE8 -> LATIN CAPITAL LETTER E WITH DIAERESIS + u'\xc8' # 0xE9 -> LATIN CAPITAL LETTER E WITH GRAVE + u'\xcd' # 0xEA -> LATIN CAPITAL LETTER I WITH ACUTE + u'\xce' # 0xEB -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + u'\xcf' # 0xEC -> LATIN CAPITAL LETTER I WITH DIAERESIS + u'\xcc' # 0xED -> LATIN CAPITAL LETTER I WITH GRAVE + u'\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + u'\xd4' # 0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + u'\uf8ff' # 0xF0 -> Apple logo + u'\xd2' # 0xF1 -> LATIN CAPITAL LETTER O WITH GRAVE + u'\xda' # 0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE + u'\xdb' # 0xF3 -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + u'\xd9' # 0xF4 -> LATIN CAPITAL LETTER U WITH GRAVE + u'\uf8a0' # 0xF5 -> undefined1 + u'\u02c6' # 0xF6 -> MODIFIER LETTER CIRCUMFLEX ACCENT + u'\u02dc' # 0xF7 -> SMALL TILDE + u'\xaf' # 0xF8 -> MACRON + u'\u02d8' # 0xF9 -> BREVE + u'\u02d9' # 0xFA -> DOT ABOVE + u'\u02da' # 0xFB -> RING ABOVE + u'\xb8' # 0xFC -> CEDILLA + u'\u02dd' # 0xFD -> DOUBLE ACUTE ACCENT + u'\u02db' # 0xFE -> OGONEK + u'\u02c7' # 0xFF -> CARON +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/mac_turkish.pyc b/PythonHome/Lib/encodings/mac_turkish.pyc deleted file mode 100644 index 7c1fe88895f071cd3a4f6869b56e1b9a71214b5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2794 zcmc&$S$7mw5Wcf!G9>Jv!H9z!<3i%TA_5^m1culXwiq2c(>+PUEU~*IMp0W5VS)>X zMTHPT2>T+7vI(BUIbDe_bB_Lp`v-XN2Vm80W;&n`fd}oGdvkBqbls}2zFQUFUzOp@ zYu3k;?Dpfszw>bzS8!4oYsT5b6faAASTinsO!cr0UY5eOpY<@-&DgqTFH-_S;S-8r zN#SEknNawJB2-fNnNrSFuh0cp3Jruyx&Twg6?H+Ot0?J$OsS+za~V^{v*wU6fR;k6 z8yyUjr}5|n3c$cA(%5CT=dzKyc3GE`rm9C)$Q>P8wk=YZQ`BT6BPSDPr@m1$+9Pdh zR@G%wRU#=pmx;_?v7oWBA+{u5yShHMXr&ad#r^X7+NM>~vWEE5nx?f)vm=`{Q@ofY zYc(BRHQ}&!3!j)7z|+MUC1kxQSxAmWa8fY>L{Na+gN|eTxb`wy`LU&WNd?nZN{&cnO@fI!`MA2kGZc4&kS=sN|OjeM(#+cSrQ77SRxz= zQ*KSG&RcYXp{7$J1TEXqX$n77UC-%86qQU&#!Ot*v@F+JTZ&eUmQi>j8qRy-v~gsV z5MZAB2}Pn;?+60%E(Rf%cLpI5{1U+@mEm;nUOVOqwcB1t2^KSiQzDU-GioAXhQ%h6 zQ##YQl}IO1obG92H3pz0e2bOiFzA$^x58&m#zjLmsjC?^Ys%?*fuf#7sd!3cnu=S8 zOn8|T<`Rf_@K2~`pwwjz(g%s-BjVsCuZl;>Y)r$6iFgI<646e;D3N!9Brd*!B`GZ{ zr`@o}5;37gF^+~;s-Tl9aS~P+%V|Ruu)3zlj3}jUQqg|Ub2pxg1bzM=JSou*p2VQL z@RX=_x$%w#O5)sf9RCibG!a$z%S%FVTG2G3NC}FYx+-VZ=o*&O5+8|e3+acHSBH;S z#Bj|7r`*iCp^4R4;v$H}=_PQS!XNhKMt z7+x-aagA*+K!Io?4U9)g&5KEb-+!ORv;3p_Po&7{BkJsl91j|C@;c*p}<0njXn9gK#9Utn3+4<3? zkGnqkbn|DQe*r!46>NiE*a<&CKOBNV7=j~k7>>emI0+}<6r6^i;0&CFb8rEEfuG?b zT!u?<4St2|@Ef-V?eq4Keb_$Ets(m|9JJ5cCwb41ebGL_dk0}F?B)3Z`vUJh!h4U} zN9{{IzlG;_^8AiJEuKGZpR%w0aT1QfRr`j0$UejKeZTMGy?LJBYM-{RbL*Hr2o`k1 z_anPTc5@5Ad$`rltpnWJ%dLHIh5xu6Zj4+V9vD72e17=C$iT=!ZXL3(aI2471Kc_f zTVOkU3134VzJ>2#2Yds&Vb9IOH((d^!G73xb7-)zwa{;$E9@=oEA-h{3kM4O3)`ZU zNn|iJMJ1QSCP)p$A&pBFVu`~S>OK+`J(G%j@&A$5PA#oCy#=MC2sMV{AUg6~rw7mT c;oAl^MC_pcs!)}`%3tlP4wO#_-eUg00R*g{k^lez diff --git a/PythonHome/Lib/encodings/mbcs.py b/PythonHome/Lib/encodings/mbcs.py new file mode 100644 index 0000000000..baf46cbd48 --- /dev/null +++ b/PythonHome/Lib/encodings/mbcs.py @@ -0,0 +1,47 @@ +""" Python 'mbcs' Codec for Windows + + +Cloned by Mark Hammond (mhammond@skippinet.com.au) from ascii.py, +which was written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +# Import them explicitly to cause an ImportError +# on non-Windows systems +from codecs import mbcs_encode, mbcs_decode +# for IncrementalDecoder, IncrementalEncoder, ... +import codecs + +### Codec APIs + +encode = mbcs_encode + +def decode(input, errors='strict'): + return mbcs_decode(input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return mbcs_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + _buffer_decode = mbcs_decode + +class StreamWriter(codecs.StreamWriter): + encode = mbcs_encode + +class StreamReader(codecs.StreamReader): + decode = mbcs_decode + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mbcs', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/mbcs.pyc b/PythonHome/Lib/encodings/mbcs.pyc deleted file mode 100644 index 35153404c0bdb0843a3423d2e10d8370e4becde8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2003 zcmbtU+m0JW5Uufe?e**?T!erH2{kWdRtkPVNJt2w-53xnfkEv^t5_=ybcSe( zJ|NSfBA~KE(+-s(O+yOU8nSg7kcFd52EQYE0m~7Y9@&7N_Gpe}eR@Ikoao84N9I@@ zeQ^wSj$<;BI0oW4**OMePQ?+4Oncnng?oB z8=I+l?bLN%nfkVgqG(jql{IR%Q9q~dnffs;%epcuE|=}-qIs6DR(WOpFssX9x;|HP zSC=YnvOFKIHV>oQWu7h7ZQ7_?mwRuk?P1yHmz8l={bbA8+AVNoT3i(EgwHx3Mp2xd z1J!Ed^2O4t(O6$SRF_4eG|wBQZDZZ<)(qA77j=E9_2u~S6Ku=>#V76{LVtpeqf2a+ zA-w$@p<+JvJto7uJo6cE;MPSOvH5Lup6Cz!0`dVpXZ8XZ$8xylq36|)-P*SI9buMN ztF@Pdt#h?&V%SK!=2MJDU*EL6fAQ5#kJ*;mS69xWV^jB5p zY-uZ>7T-%iZYM`x^$4xuJr=JmVlyN%3rV-gGgj@(CPDIY4l>|4pCZT(%lK>}@r-kL zsg0ILn&XRkzr@|xVy>A0&-Qs0Z6u^?H`94!yb-P#1ts0!?mqZ1^OQM0XI|i~#2zqzEF=GcWoTjGEl0QTk7rx&)?e;pS;aT@A#P{ew DJJgn$ diff --git a/PythonHome/Lib/encodings/palmos.py b/PythonHome/Lib/encodings/palmos.py new file mode 100644 index 0000000000..4b77e2ba91 --- /dev/null +++ b/PythonHome/Lib/encodings/palmos.py @@ -0,0 +1,83 @@ +""" Python Character Mapping Codec for PalmOS 3.5. + +Written by Sjoerd Mullender (sjoerd@acm.org); based on iso8859_15.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_map) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_map)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='palmos', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) + +# The PalmOS character set is mostly iso-8859-1 with some differences. +decoding_map.update({ + 0x0080: 0x20ac, # EURO SIGN + 0x0082: 0x201a, # SINGLE LOW-9 QUOTATION MARK + 0x0083: 0x0192, # LATIN SMALL LETTER F WITH HOOK + 0x0084: 0x201e, # DOUBLE LOW-9 QUOTATION MARK + 0x0085: 0x2026, # HORIZONTAL ELLIPSIS + 0x0086: 0x2020, # DAGGER + 0x0087: 0x2021, # DOUBLE DAGGER + 0x0088: 0x02c6, # MODIFIER LETTER CIRCUMFLEX ACCENT + 0x0089: 0x2030, # PER MILLE SIGN + 0x008a: 0x0160, # LATIN CAPITAL LETTER S WITH CARON + 0x008b: 0x2039, # SINGLE LEFT-POINTING ANGLE QUOTATION MARK + 0x008c: 0x0152, # LATIN CAPITAL LIGATURE OE + 0x008d: 0x2666, # BLACK DIAMOND SUIT + 0x008e: 0x2663, # BLACK CLUB SUIT + 0x008f: 0x2665, # BLACK HEART SUIT + 0x0090: 0x2660, # BLACK SPADE SUIT + 0x0091: 0x2018, # LEFT SINGLE QUOTATION MARK + 0x0092: 0x2019, # RIGHT SINGLE QUOTATION MARK + 0x0093: 0x201c, # LEFT DOUBLE QUOTATION MARK + 0x0094: 0x201d, # RIGHT DOUBLE QUOTATION MARK + 0x0095: 0x2022, # BULLET + 0x0096: 0x2013, # EN DASH + 0x0097: 0x2014, # EM DASH + 0x0098: 0x02dc, # SMALL TILDE + 0x0099: 0x2122, # TRADE MARK SIGN + 0x009a: 0x0161, # LATIN SMALL LETTER S WITH CARON + 0x009c: 0x0153, # LATIN SMALL LIGATURE OE + 0x009f: 0x0178, # LATIN CAPITAL LETTER Y WITH DIAERESIS +}) + +### Encoding Map + +encoding_map = codecs.make_encoding_map(decoding_map) diff --git a/PythonHome/Lib/encodings/palmos.pyc b/PythonHome/Lib/encodings/palmos.pyc deleted file mode 100644 index 07203bf5fe2a555fa4e311b0ab3b0827e51407d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2931 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 diff --git a/PythonHome/Lib/encodings/punycode.py b/PythonHome/Lib/encodings/punycode.py new file mode 100644 index 0000000000..d97200fd35 --- /dev/null +++ b/PythonHome/Lib/encodings/punycode.py @@ -0,0 +1,238 @@ +# -*- coding: iso-8859-1 -*- +""" Codec for the Punicode encoding, as specified in RFC 3492 + +Written by Martin v. Lwis. +""" + +import codecs + +##################### Encoding ##################################### + +def segregate(str): + """3.1 Basic code point segregation""" + base = [] + extended = {} + for c in str: + if ord(c) < 128: + base.append(c) + else: + extended[c] = 1 + extended = extended.keys() + extended.sort() + return "".join(base).encode("ascii"),extended + +def selective_len(str, max): + """Return the length of str, considering only characters below max.""" + res = 0 + for c in str: + if ord(c) < max: + res += 1 + return res + +def selective_find(str, char, index, pos): + """Return a pair (index, pos), indicating the next occurrence of + char in str. index is the position of the character considering + only ordinals up to and including char, and pos is the position in + the full string. index/pos is the starting position in the full + string.""" + + l = len(str) + while 1: + pos += 1 + if pos == l: + return (-1, -1) + c = str[pos] + if c == char: + return index+1, pos + elif c < char: + index += 1 + +def insertion_unsort(str, extended): + """3.2 Insertion unsort coding""" + oldchar = 0x80 + result = [] + oldindex = -1 + for c in extended: + index = pos = -1 + char = ord(c) + curlen = selective_len(str, char) + delta = (curlen+1) * (char - oldchar) + while 1: + index,pos = selective_find(str,c,index,pos) + if index == -1: + break + delta += index - oldindex + result.append(delta-1) + oldindex = index + delta = 0 + oldchar = char + + return result + +def T(j, bias): + # Punycode parameters: tmin = 1, tmax = 26, base = 36 + res = 36 * (j + 1) - bias + if res < 1: return 1 + if res > 26: return 26 + return res + +digits = "abcdefghijklmnopqrstuvwxyz0123456789" +def generate_generalized_integer(N, bias): + """3.3 Generalized variable-length integers""" + result = [] + j = 0 + while 1: + t = T(j, bias) + if N < t: + result.append(digits[N]) + return result + result.append(digits[t + ((N - t) % (36 - t))]) + N = (N - t) // (36 - t) + j += 1 + +def adapt(delta, first, numchars): + if first: + delta //= 700 + else: + delta //= 2 + delta += delta // numchars + # ((base - tmin) * tmax) // 2 == 455 + divisions = 0 + while delta > 455: + delta = delta // 35 # base - tmin + divisions += 36 + bias = divisions + (36 * delta // (delta + 38)) + return bias + + +def generate_integers(baselen, deltas): + """3.4 Bias adaptation""" + # Punycode parameters: initial bias = 72, damp = 700, skew = 38 + result = [] + bias = 72 + for points, delta in enumerate(deltas): + s = generate_generalized_integer(delta, bias) + result.extend(s) + bias = adapt(delta, points==0, baselen+points+1) + return "".join(result) + +def punycode_encode(text): + base, extended = segregate(text) + base = base.encode("ascii") + deltas = insertion_unsort(text, extended) + extended = generate_integers(len(base), deltas) + if base: + return base + "-" + extended + return extended + +##################### Decoding ##################################### + +def decode_generalized_number(extended, extpos, bias, errors): + """3.3 Generalized variable-length integers""" + result = 0 + w = 1 + j = 0 + while 1: + try: + char = ord(extended[extpos]) + except IndexError: + if errors == "strict": + raise UnicodeError, "incomplete punicode string" + return extpos + 1, None + extpos += 1 + if 0x41 <= char <= 0x5A: # A-Z + digit = char - 0x41 + elif 0x30 <= char <= 0x39: + digit = char - 22 # 0x30-26 + elif errors == "strict": + raise UnicodeError("Invalid extended code point '%s'" + % extended[extpos]) + else: + return extpos, None + t = T(j, bias) + result += digit * w + if digit < t: + return extpos, result + w = w * (36 - t) + j += 1 + + +def insertion_sort(base, extended, errors): + """3.2 Insertion unsort coding""" + char = 0x80 + pos = -1 + bias = 72 + extpos = 0 + while extpos < len(extended): + newpos, delta = decode_generalized_number(extended, extpos, + bias, errors) + if delta is None: + # There was an error in decoding. We can't continue because + # synchronization is lost. + return base + pos += delta+1 + char += pos // (len(base) + 1) + if char > 0x10FFFF: + if errors == "strict": + raise UnicodeError, ("Invalid character U+%x" % char) + char = ord('?') + pos = pos % (len(base) + 1) + base = base[:pos] + unichr(char) + base[pos:] + bias = adapt(delta, (extpos == 0), len(base)) + extpos = newpos + return base + +def punycode_decode(text, errors): + pos = text.rfind("-") + if pos == -1: + base = "" + extended = text + else: + base = text[:pos] + extended = text[pos+1:] + base = unicode(base, "ascii", errors) + extended = extended.upper() + return insertion_sort(base, extended, errors) + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + res = punycode_encode(input) + return res, len(input) + + def decode(self,input,errors='strict'): + if errors not in ('strict', 'replace', 'ignore'): + raise UnicodeError, "Unsupported error handling "+errors + res = punycode_decode(input, errors) + return res, len(input) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return punycode_encode(input) + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + if self.errors not in ('strict', 'replace', 'ignore'): + raise UnicodeError, "Unsupported error handling "+self.errors + return punycode_decode(input, self.errors) + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='punycode', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/PythonHome/Lib/encodings/punycode.pyc b/PythonHome/Lib/encodings/punycode.pyc deleted file mode 100644 index e60aa60f58e32cee0e45f9b30970e3a890838b26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7685 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 KmY0f4BmV-ts=9#y diff --git a/PythonHome/Lib/encodings/quopri_codec.py b/PythonHome/Lib/encodings/quopri_codec.py new file mode 100644 index 0000000000..d8683fd56d --- /dev/null +++ b/PythonHome/Lib/encodings/quopri_codec.py @@ -0,0 +1,75 @@ +"""Codec for quoted-printable encoding. + +Like base64 and rot13, this returns Python strings, not Unicode. +""" + +import codecs, quopri +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + +def quopri_encode(input, errors='strict'): + """Encode the input, returning a tuple (output object, length consumed). + + errors defines the error handling to apply. It defaults to + 'strict' handling which is the only currently supported + error handling for this codec. + + """ + assert errors == 'strict' + # using str() because of cStringIO's Unicode undesired Unicode behavior. + f = StringIO(str(input)) + g = StringIO() + quopri.encode(f, g, 1) + output = g.getvalue() + return (output, len(input)) + +def quopri_decode(input, errors='strict'): + """Decode the input, returning a tuple (output object, length consumed). + + errors defines the error handling to apply. It defaults to + 'strict' handling which is the only currently supported + error handling for this codec. + + """ + assert errors == 'strict' + f = StringIO(str(input)) + g = StringIO() + quopri.decode(f, g) + output = g.getvalue() + return (output, len(input)) + +class Codec(codecs.Codec): + + def encode(self, input,errors='strict'): + return quopri_encode(input,errors) + def decode(self, input,errors='strict'): + return quopri_decode(input,errors) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return quopri_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return quopri_decode(input, self.errors)[0] + +class StreamWriter(Codec, codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +# encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='quopri', + encode=quopri_encode, + decode=quopri_decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/PythonHome/Lib/encodings/quopri_codec.pyc b/PythonHome/Lib/encodings/quopri_codec.pyc deleted file mode 100644 index 86db8adcc6c2508348e43a3bf9253a92dad61a1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3430 zcmd^B-)|d55S~3dw&OTWng(c4B(_gIL>dIGii7|Gp-7Rc6s=XIwIZ3z-P*b2d}r>~ zRFTpb(!Ys6idWu&Z{}=YNGp-%p)Xu~lewM!G4sv0vs?Rfx&8b8&)txw&jS8`i?{d- zA|mQRDvCTx6!oB#x<@^aPS@qLMoEoEb?Vhg?WcFBZWrjJP5Dz&N^yU5sLwj2ik?Mv ziWcY<=4%k^4bhtvHOVSEZqWdPTJ(zOoalM4MbV-d7RAt>8x|>A5<^=Iow=b+(K6YV z*p_JEQFLQ&TcT)XX6uM;b#CiWbdx`N%N%gmUt=7G5Ib39Lp{iH{mUeCHo7;?C_!%sV*EQ7#3SP z&76Lk#+buyx8uL@?D+~Sx)wxNdhI@O4R!<{p$k2zoTED49d15=IFrPjcvP&BBl=B| z!_T8LK&bfl(&HAu`Laf?M#ptJgSEzCp4Ui0J6;eo40XbKBs$P;G6o!eHgPcN?C{uz=#kiT=#F%lrNv}qqmKcT#$)q5%L^UZL7dt` zrj#aq1mF^$&}BLpkCW4Fz3aGNFi9LbW-|P43C7*3`-`JEJkkJ~z01<%RELv1x2c0x zOvd9ZN7|~TtAU(U$q>gDPTez{f|!Nhgm5gjHKj6@&jgo6`~3! ztfX*g-LFA1vC{KSq!kMNVE@a zhK*8L9K%uAWKaeEc99z1O!s&a_MFsPI;)uBk?b=Roh4>Wj)Cpgb%&F}6(_m!# zeaG4C_eWVYN$@FN8y;0fE810dxmm@yPw*DJOvCGVj*qI{G|cS?H7`iYQk}n^)OGYL zlWHZGoK#69SD)9Rj;=EFboYnhy zF9K>fN^=WBru{KU3M)WXb6*`p4(;>V0u6N;!Lm}lLj;+KZ$i+#2SXL$mB3?OeKCuT zl(4Y^&%Dn|U6*?wVDQ7)+`x@%6D}$?813WuvlU{@C@CZ@C?)4mFrZHK7fM#gPntIgSv^kFs@}0u2{HxEf9(y zZoeQiuD&=DaOrhTT*I1OpAUdNsf}Dd&h23D;v#?`bK@Twz=>RhYz)* diff --git a/PythonHome/Lib/encodings/raw_unicode_escape.py b/PythonHome/Lib/encodings/raw_unicode_escape.py new file mode 100644 index 0000000000..2b919b40d3 --- /dev/null +++ b/PythonHome/Lib/encodings/raw_unicode_escape.py @@ -0,0 +1,45 @@ +""" Python 'raw-unicode-escape' Codec + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + # Note: Binding these as C functions will result in the class not + # converting them to methods. This is intended. + encode = codecs.raw_unicode_escape_encode + decode = codecs.raw_unicode_escape_decode + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.raw_unicode_escape_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.raw_unicode_escape_decode(input, self.errors)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='raw-unicode-escape', + encode=Codec.encode, + decode=Codec.decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/PythonHome/Lib/encodings/raw_unicode_escape.pyc b/PythonHome/Lib/encodings/raw_unicode_escape.pyc deleted file mode 100644 index 7cfb6c6ef5b1ef1b9285f36b8e90df89c2f740b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2093 zcmc&#!EVz)5FN*klejG)1cIPS_yDRa(R=_xs3Cw5X zL1w`a6&s`lr!^R%?!X1WIl$qt21%U_HXGd1U_;VigTsbqX>cHEfvmBu4kL8nm9{!0 zYfGEUw)N8HLb5@VVS|Di1h**GuPFQv3v)8f{Vf%p?acEuo+fff>NuLoEx(78*z>#t zl^P>+|9IiQi&VVR%@Za4eK|RvtFa$UqHH%SCY^XX+3t8=5O3q#vxQ2>C&usf#ojZ& zn`OSBx%P$BQhk<5$M3)Q54u8h`yUVSwe%-GeN)H4`0Ns23s+uI%#Tn=%)_EgPi+`F ztkhxXf*1s7g`k1LG*N_M9!+Ez8jmNFX)@1f>f)3VjkRf`im8W}sfR`Cq0Gt78!y$r zY(yu^jfGl-fL?(${S>v%(SCY-#E#N@tdFi9*qJQ^y|aNsJ1AVIWtqFE?B%hN6PcSR zd&5Dg5|kR68I*gdl%QbuU0~DM1P8$uQ*SOu4|V+jg#kFV;0yktQiF5sBn#SufPD5- z6cErmf&~RsV4>7hX|@{1)JjyB%R>+^KexICD3}6LxfS?QnEwJ;q zQKqG!jnxUO!ra8S2{1m!y#n%UF6e&%nVM3xC^g2MT2`!)Sf@1{D>oF~18Upr0TtA1 zg7#F-SH+TO4Ut85m^T2 z#N?%wlVubNVso;dmnOZ87h_yesAu%zI+0Fq32tzzg;O zykHN&3-$oKU=P3x_5i$K55Nod0K8xizzg;OykHN&3-$oKU=Pe`F=t@j7xMwkSury( zvtmAknG^F7%)FR$FdvHvU_KG^Da>bL&cl2z<^s$YVlKjbDP{rYl9;ZVe9)K6@0eHb4fEVlmc)=ck7wiFe!5)AY>;YV#qb$bhe#T)!%%VnV zk66UvifrU1N%GrDnv~^9v1po<^?iy{vXz%y46Ws*R=rC7{SK(y-t=poxU#qwB~ioM zq;fOrc3r$$S?n0ws5CoCCA@WKZhmHTw1Q8~+RB>u-Se}vy++zwnQ3%dog^}y8Ebm8 zzio8dF18!9NypF4&uVXDedJo{cK^GH^WMgll}!wkG|pa%O=2rIYS}664t5({K=R3cb~Y1 zZ}6Q@5ziv4_XE7hdQKkUmlvOxtpZ$?L;cdAdxLIC{T|dd;Inqrt=pKDejHU=g!k&G z&-#!*wXLQuz{TC3*IC#k=_F|tjiQiFqcn5>hFiJ6!;#*H7whnRcQfmv!%UKoOPAd1 ztRZCAf6N}s*_pi-ch5eg*F$h(Bk+j`xP>Px$0dM&($ zYzxN#gMqa4eCLGdAdE-K0m}LDf}cX+dfZ5C+r~a>T~*H|4b>6sqC)w9yg0%IQi35R^Mn_}y{yCY zGFwUYbrk=7wgW@%uh-DvK6Ilzloh^XL~1^t1&d1UKdcv_6{}+&LCWKm|?MruziXs~khr|psYi!9-tx6dzd2S>okd%oDIr8k>{2+CxYTaP(XUREvvO3F7iN*;h z0^;;g@D<^E!q970aj`O>ghdY)tfd#MdKgR>vZMVX%jshPPUqtE@N{vy Zc&u=&G%|4z;vV`>zGJ1m#gPKH(cg(WVyOTC diff --git a/PythonHome/Lib/encodings/shift_jis.py b/PythonHome/Lib/encodings/shift_jis.py new file mode 100644 index 0000000000..8338117276 --- /dev/null +++ b/PythonHome/Lib/encodings/shift_jis.py @@ -0,0 +1,39 @@ +# +# shift_jis.py: Python Unicode Codec for SHIFT_JIS +# +# Written by Hye-Shik Chang +# + +import _codecs_jp, codecs +import _multibytecodec as mbc + +codec = _codecs_jp.getcodec('shift_jis') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='shift_jis', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/shift_jis.pyc b/PythonHome/Lib/encodings/shift_jis.pyc deleted file mode 100644 index 65d6022bf944b5b187989d0bcf67e445f25887c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1705 zcmcgs&2G~`5FY=;`Kgm21gQLo1E-w&1PE0G4wayX&7s1IWD@Tt*ovLX-U{^`o{5*? zF?ay@X52VY3x{0d^{!`UX4l`$&bQw0e(&ei*GWQmkB{#;di4u~#_Q0EC~9PfB4?|2 zDe}k=Wj<+_HZZkFL*q~u&;o8g{UF*9eTf3nEixWuZ83Lf;gSv-bB8nxFn7h=6LY6A z_ejGKh{uU|gtYKT_Zp9oGz_&zUpxll5jGwJ(tVypLyl=O8X&&(51vcg<#@lP3ma!? zWm}ky*V-gaP8?|7v(F0*h!+_!E@hsC55cF%Cp8(tN+VuwI~d})nB^vpZBHioTHmaA z$_@$dZv#lCU|B?{AlAFULLybKAe~J=rSqw{rp2!09^nF@%dE zDNSw)J6nB}Uz88S;S@CCL~av;2fcE65Q+Ca7*!jK9-&vfPvG9i^g&`hGA2HiCwrJU zYZF_VS+2}Xn> ztCG{h3F7qj6yGI*@;70Y(5(`lkC}NF#bPbI+5KE`!78p0#UK^uFpav^cv~qT_VO`OV6v^IIz%Ni35vpC@vuV0T%eIENB~ z +# + +import _codecs_jp, codecs +import _multibytecodec as mbc + +codec = _codecs_jp.getcodec('shift_jis_2004') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='shift_jis_2004', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/shift_jis_2004.pyc b/PythonHome/Lib/encodings/shift_jis_2004.pyc deleted file mode 100644 index 51385fe31f235c27f2146fd05be693d1e83e4252..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmc&!&2G~`5FY=;`Kgm21gL<71gD&;s^W-HMc_~gde|H)tVkyDI>A=#RQ6UV=kQFt z43EJBz&GQ@2`yZ5iS1p_&dl!4-#5;$Zs*6{4vYoPJ63##2~Hynu}!HXF#zFG;F1~*Af*9sH!VzIm`}1e3{6KC z*;3yuc*zP8pKm-+an7`mV1cYofrNxAUxGRre@v!hQBCrBIsV(?lk1gY6Mc-5ljvD( z%RB^ekw-YnXO4zMPd$O5?Al@tx0tO^}!o5{~VJ+CjjX2 z0ox84v;=SfQ+Gq7Pc#U%59FiR0eRCT-D0GysW}?3 zW{SJ)3O|Jet&}_>m&oG|eihe>Vl~C_*b4~e z2s`I744VUy#p(r?B?E&1SI_eCdh!mKS#^!dzA(L3!sD2S+0DWv)0Gk2M269sO(SVJ zI9+xq4y5>DICY;kJMQ-b@$SD$x7ZZ#&EwsZc5xzc`Ioq=S&5k9cC=sEIP`C-?)jE; VQ8H$aE#L0jPu;fl#NqJ@?;mAYPrLvC diff --git a/PythonHome/Lib/encodings/shift_jisx0213.py b/PythonHome/Lib/encodings/shift_jisx0213.py new file mode 100644 index 0000000000..cb653f5305 --- /dev/null +++ b/PythonHome/Lib/encodings/shift_jisx0213.py @@ -0,0 +1,39 @@ +# +# shift_jisx0213.py: Python Unicode Codec for SHIFT_JISX0213 +# +# Written by Hye-Shik Chang +# + +import _codecs_jp, codecs +import _multibytecodec as mbc + +codec = _codecs_jp.getcodec('shift_jisx0213') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='shift_jisx0213', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/shift_jisx0213.pyc b/PythonHome/Lib/encodings/shift_jisx0213.pyc deleted file mode 100644 index 9740271c58dcd709669cbea84a8dbec4750b249d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmc&!OK;Oa5FS6`JnAF}0V*IN!6~PT#}%Q9z@ZZKusKv%kxb%sg00x8?5!Z@@SFHE z{0x2od^2vG(848`*xvQ*%MWl%Ac4tK8qGaK}}l}SR1}g zfkQD->XNo;4N-$MI2NTI&7kJeccL}Xr@$lKpxB|bDdHB*Y|>sWZjpun;~uibhW~{92<&y3328&pwR?J@}XW#&d3%EWac(6Q)V| z?fJ_WuS^51;Zny@9T*Fox2*UG6P!jEVw+M&VgSOWz$G;rKuQDNZd#baFrQ>`7@CeO zvZcOS@RAiGKHqqt;+$zA!2(&G0tpFKJ_U6${*X+^qMGFMa{RZ&CzmV5Ci)m9C(*Oo zmbnY!ERTvfi*qwsyq9~5+dgpwYM%nT_QL^R**pow=k8}(6FcuVr3A{wXGdP5{v3 z1GXJ9XbIo|rtXGDpJ)(jAIL|s1M;Rxy2VIYQ*$(6$IlHH8G}aQPl|z}7$Z_L$+ng& z%oI1-6@Cf{S}A!%E|JF_##f1=+$N9{9F~S}A2KA*^4U_bw7pz${VJ{%#cGPO9lo3uAb%N_2eBev+5d^ePMd3gvT)tv#W(krYj@3i43DNn?}-d zaJuYJ97yrQaOys8cHHg<;@y9huCXcJoBO*b?czk@@-J~!vl21I?P$NSap+%H-SZ9S VqGZe-TfW`5AG&Spfy3h&-ah~^P=o*g diff --git a/PythonHome/Lib/encodings/string_escape.py b/PythonHome/Lib/encodings/string_escape.py new file mode 100644 index 0000000000..e329a2607d --- /dev/null +++ b/PythonHome/Lib/encodings/string_escape.py @@ -0,0 +1,38 @@ +# -*- coding: iso-8859-1 -*- +""" Python 'escape' Codec + + +Written by Martin v. Lwis (martin@v.loewis.de). + +""" +import codecs + +class Codec(codecs.Codec): + + encode = codecs.escape_encode + decode = codecs.escape_decode + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.escape_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.escape_decode(input, self.errors)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +def getregentry(): + return codecs.CodecInfo( + name='string-escape', + encode=Codec.encode, + decode=Codec.decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/PythonHome/Lib/encodings/string_escape.pyc b/PythonHome/Lib/encodings/string_escape.pyc deleted file mode 100644 index 4ff4ad65b30c927d121164211849bbe678213af8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1952 zcmc&#&2G~`5FY=;N!%6?Afccl`Brlv4}cJ=C?Hjo3T+M*Q6=Nro8l^QD(|*cByR1K z@DRKh5?7dS+}IWLKzjfuJDJ^C&wlf>U%c;Y;kUg{ql_*ekAF9Ln6E5yqA^Q{a+jtK zjal(XJ9OmIgms@Th|Y;Vj$O(-V(`QeGzO3It{8kV^csUtd7rc^whm3$LD<+jl&>sp zf!J0XTR{05CgUzZjp94N`i@2PVPQYd%VCiYJHHz6vahHYdu}G3Ko#`a8p-g7;{A7x0z|#yMja_54#+~RAYht`quNZmr(panY zQT#TEW+K*x`#Z(KzPwzNhi2c{ihq;Z|L}OBupL;8&mwU9j=j&yc9~Urrc0Yn-w1}P ziQ8qf#Ql(!CT{MI3vLPz5hF7hdS^MdST~PYSfV3`zVMe7m(ID;4h=>zeC`%3D8@TV z1OU~cSJk{SVzF2>dODGU6y@=W6>U9mdi??OjS@4+9ACntt)1@H-+}E?eU9udB_RDAE|vU75opWMYpLwqLNIb{%Qqc6>B_h(n08L^uqONROncRJ+0px zWDr;S!O}Tr5CBKE(&-FWS+}`st|M|@x8?Hkp_*-7Zv_KIL<27i*}_md&Hot;bSvoQ z5=O?VJb<^w!#rnEU$UC0nWC+bQtpewOxr)C_yd34TlaneYCvun diff --git a/PythonHome/Lib/encodings/tis_620.py b/PythonHome/Lib/encodings/tis_620.py new file mode 100644 index 0000000000..b2cd22b23d --- /dev/null +++ b/PythonHome/Lib/encodings/tis_620.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec tis_620 generated from 'python-mappings/TIS-620.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='tis-620', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + u'\x00' # 0x00 -> NULL + u'\x01' # 0x01 -> START OF HEADING + u'\x02' # 0x02 -> START OF TEXT + u'\x03' # 0x03 -> END OF TEXT + u'\x04' # 0x04 -> END OF TRANSMISSION + u'\x05' # 0x05 -> ENQUIRY + u'\x06' # 0x06 -> ACKNOWLEDGE + u'\x07' # 0x07 -> BELL + u'\x08' # 0x08 -> BACKSPACE + u'\t' # 0x09 -> HORIZONTAL TABULATION + u'\n' # 0x0A -> LINE FEED + u'\x0b' # 0x0B -> VERTICAL TABULATION + u'\x0c' # 0x0C -> FORM FEED + u'\r' # 0x0D -> CARRIAGE RETURN + u'\x0e' # 0x0E -> SHIFT OUT + u'\x0f' # 0x0F -> SHIFT IN + u'\x10' # 0x10 -> DATA LINK ESCAPE + u'\x11' # 0x11 -> DEVICE CONTROL ONE + u'\x12' # 0x12 -> DEVICE CONTROL TWO + u'\x13' # 0x13 -> DEVICE CONTROL THREE + u'\x14' # 0x14 -> DEVICE CONTROL FOUR + u'\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + u'\x16' # 0x16 -> SYNCHRONOUS IDLE + u'\x17' # 0x17 -> END OF TRANSMISSION BLOCK + u'\x18' # 0x18 -> CANCEL + u'\x19' # 0x19 -> END OF MEDIUM + u'\x1a' # 0x1A -> SUBSTITUTE + u'\x1b' # 0x1B -> ESCAPE + u'\x1c' # 0x1C -> FILE SEPARATOR + u'\x1d' # 0x1D -> GROUP SEPARATOR + u'\x1e' # 0x1E -> RECORD SEPARATOR + u'\x1f' # 0x1F -> UNIT SEPARATOR + u' ' # 0x20 -> SPACE + u'!' # 0x21 -> EXCLAMATION MARK + u'"' # 0x22 -> QUOTATION MARK + u'#' # 0x23 -> NUMBER SIGN + u'$' # 0x24 -> DOLLAR SIGN + u'%' # 0x25 -> PERCENT SIGN + u'&' # 0x26 -> AMPERSAND + u"'" # 0x27 -> APOSTROPHE + u'(' # 0x28 -> LEFT PARENTHESIS + u')' # 0x29 -> RIGHT PARENTHESIS + u'*' # 0x2A -> ASTERISK + u'+' # 0x2B -> PLUS SIGN + u',' # 0x2C -> COMMA + u'-' # 0x2D -> HYPHEN-MINUS + u'.' # 0x2E -> FULL STOP + u'/' # 0x2F -> SOLIDUS + u'0' # 0x30 -> DIGIT ZERO + u'1' # 0x31 -> DIGIT ONE + u'2' # 0x32 -> DIGIT TWO + u'3' # 0x33 -> DIGIT THREE + u'4' # 0x34 -> DIGIT FOUR + u'5' # 0x35 -> DIGIT FIVE + u'6' # 0x36 -> DIGIT SIX + u'7' # 0x37 -> DIGIT SEVEN + u'8' # 0x38 -> DIGIT EIGHT + u'9' # 0x39 -> DIGIT NINE + u':' # 0x3A -> COLON + u';' # 0x3B -> SEMICOLON + u'<' # 0x3C -> LESS-THAN SIGN + u'=' # 0x3D -> EQUALS SIGN + u'>' # 0x3E -> GREATER-THAN SIGN + u'?' # 0x3F -> QUESTION MARK + u'@' # 0x40 -> COMMERCIAL AT + u'A' # 0x41 -> LATIN CAPITAL LETTER A + u'B' # 0x42 -> LATIN CAPITAL LETTER B + u'C' # 0x43 -> LATIN CAPITAL LETTER C + u'D' # 0x44 -> LATIN CAPITAL LETTER D + u'E' # 0x45 -> LATIN CAPITAL LETTER E + u'F' # 0x46 -> LATIN CAPITAL LETTER F + u'G' # 0x47 -> LATIN CAPITAL LETTER G + u'H' # 0x48 -> LATIN CAPITAL LETTER H + u'I' # 0x49 -> LATIN CAPITAL LETTER I + u'J' # 0x4A -> LATIN CAPITAL LETTER J + u'K' # 0x4B -> LATIN CAPITAL LETTER K + u'L' # 0x4C -> LATIN CAPITAL LETTER L + u'M' # 0x4D -> LATIN CAPITAL LETTER M + u'N' # 0x4E -> LATIN CAPITAL LETTER N + u'O' # 0x4F -> LATIN CAPITAL LETTER O + u'P' # 0x50 -> LATIN CAPITAL LETTER P + u'Q' # 0x51 -> LATIN CAPITAL LETTER Q + u'R' # 0x52 -> LATIN CAPITAL LETTER R + u'S' # 0x53 -> LATIN CAPITAL LETTER S + u'T' # 0x54 -> LATIN CAPITAL LETTER T + u'U' # 0x55 -> LATIN CAPITAL LETTER U + u'V' # 0x56 -> LATIN CAPITAL LETTER V + u'W' # 0x57 -> LATIN CAPITAL LETTER W + u'X' # 0x58 -> LATIN CAPITAL LETTER X + u'Y' # 0x59 -> LATIN CAPITAL LETTER Y + u'Z' # 0x5A -> LATIN CAPITAL LETTER Z + u'[' # 0x5B -> LEFT SQUARE BRACKET + u'\\' # 0x5C -> REVERSE SOLIDUS + u']' # 0x5D -> RIGHT SQUARE BRACKET + u'^' # 0x5E -> CIRCUMFLEX ACCENT + u'_' # 0x5F -> LOW LINE + u'`' # 0x60 -> GRAVE ACCENT + u'a' # 0x61 -> LATIN SMALL LETTER A + u'b' # 0x62 -> LATIN SMALL LETTER B + u'c' # 0x63 -> LATIN SMALL LETTER C + u'd' # 0x64 -> LATIN SMALL LETTER D + u'e' # 0x65 -> LATIN SMALL LETTER E + u'f' # 0x66 -> LATIN SMALL LETTER F + u'g' # 0x67 -> LATIN SMALL LETTER G + u'h' # 0x68 -> LATIN SMALL LETTER H + u'i' # 0x69 -> LATIN SMALL LETTER I + u'j' # 0x6A -> LATIN SMALL LETTER J + u'k' # 0x6B -> LATIN SMALL LETTER K + u'l' # 0x6C -> LATIN SMALL LETTER L + u'm' # 0x6D -> LATIN SMALL LETTER M + u'n' # 0x6E -> LATIN SMALL LETTER N + u'o' # 0x6F -> LATIN SMALL LETTER O + u'p' # 0x70 -> LATIN SMALL LETTER P + u'q' # 0x71 -> LATIN SMALL LETTER Q + u'r' # 0x72 -> LATIN SMALL LETTER R + u's' # 0x73 -> LATIN SMALL LETTER S + u't' # 0x74 -> LATIN SMALL LETTER T + u'u' # 0x75 -> LATIN SMALL LETTER U + u'v' # 0x76 -> LATIN SMALL LETTER V + u'w' # 0x77 -> LATIN SMALL LETTER W + u'x' # 0x78 -> LATIN SMALL LETTER X + u'y' # 0x79 -> LATIN SMALL LETTER Y + u'z' # 0x7A -> LATIN SMALL LETTER Z + u'{' # 0x7B -> LEFT CURLY BRACKET + u'|' # 0x7C -> VERTICAL LINE + u'}' # 0x7D -> RIGHT CURLY BRACKET + u'~' # 0x7E -> TILDE + u'\x7f' # 0x7F -> DELETE + u'\x80' # 0x80 -> + u'\x81' # 0x81 -> + u'\x82' # 0x82 -> + u'\x83' # 0x83 -> + u'\x84' # 0x84 -> + u'\x85' # 0x85 -> + u'\x86' # 0x86 -> + u'\x87' # 0x87 -> + u'\x88' # 0x88 -> + u'\x89' # 0x89 -> + u'\x8a' # 0x8A -> + u'\x8b' # 0x8B -> + u'\x8c' # 0x8C -> + u'\x8d' # 0x8D -> + u'\x8e' # 0x8E -> + u'\x8f' # 0x8F -> + u'\x90' # 0x90 -> + u'\x91' # 0x91 -> + u'\x92' # 0x92 -> + u'\x93' # 0x93 -> + u'\x94' # 0x94 -> + u'\x95' # 0x95 -> + u'\x96' # 0x96 -> + u'\x97' # 0x97 -> + u'\x98' # 0x98 -> + u'\x99' # 0x99 -> + u'\x9a' # 0x9A -> + u'\x9b' # 0x9B -> + u'\x9c' # 0x9C -> + u'\x9d' # 0x9D -> + u'\x9e' # 0x9E -> + u'\x9f' # 0x9F -> + u'\ufffe' + u'\u0e01' # 0xA1 -> THAI CHARACTER KO KAI + u'\u0e02' # 0xA2 -> THAI CHARACTER KHO KHAI + u'\u0e03' # 0xA3 -> THAI CHARACTER KHO KHUAT + u'\u0e04' # 0xA4 -> THAI CHARACTER KHO KHWAI + u'\u0e05' # 0xA5 -> THAI CHARACTER KHO KHON + u'\u0e06' # 0xA6 -> THAI CHARACTER KHO RAKHANG + u'\u0e07' # 0xA7 -> THAI CHARACTER NGO NGU + u'\u0e08' # 0xA8 -> THAI CHARACTER CHO CHAN + u'\u0e09' # 0xA9 -> THAI CHARACTER CHO CHING + u'\u0e0a' # 0xAA -> THAI CHARACTER CHO CHANG + u'\u0e0b' # 0xAB -> THAI CHARACTER SO SO + u'\u0e0c' # 0xAC -> THAI CHARACTER CHO CHOE + u'\u0e0d' # 0xAD -> THAI CHARACTER YO YING + u'\u0e0e' # 0xAE -> THAI CHARACTER DO CHADA + u'\u0e0f' # 0xAF -> THAI CHARACTER TO PATAK + u'\u0e10' # 0xB0 -> THAI CHARACTER THO THAN + u'\u0e11' # 0xB1 -> THAI CHARACTER THO NANGMONTHO + u'\u0e12' # 0xB2 -> THAI CHARACTER THO PHUTHAO + u'\u0e13' # 0xB3 -> THAI CHARACTER NO NEN + u'\u0e14' # 0xB4 -> THAI CHARACTER DO DEK + u'\u0e15' # 0xB5 -> THAI CHARACTER TO TAO + u'\u0e16' # 0xB6 -> THAI CHARACTER THO THUNG + u'\u0e17' # 0xB7 -> THAI CHARACTER THO THAHAN + u'\u0e18' # 0xB8 -> THAI CHARACTER THO THONG + u'\u0e19' # 0xB9 -> THAI CHARACTER NO NU + u'\u0e1a' # 0xBA -> THAI CHARACTER BO BAIMAI + u'\u0e1b' # 0xBB -> THAI CHARACTER PO PLA + u'\u0e1c' # 0xBC -> THAI CHARACTER PHO PHUNG + u'\u0e1d' # 0xBD -> THAI CHARACTER FO FA + u'\u0e1e' # 0xBE -> THAI CHARACTER PHO PHAN + u'\u0e1f' # 0xBF -> THAI CHARACTER FO FAN + u'\u0e20' # 0xC0 -> THAI CHARACTER PHO SAMPHAO + u'\u0e21' # 0xC1 -> THAI CHARACTER MO MA + u'\u0e22' # 0xC2 -> THAI CHARACTER YO YAK + u'\u0e23' # 0xC3 -> THAI CHARACTER RO RUA + u'\u0e24' # 0xC4 -> THAI CHARACTER RU + u'\u0e25' # 0xC5 -> THAI CHARACTER LO LING + u'\u0e26' # 0xC6 -> THAI CHARACTER LU + u'\u0e27' # 0xC7 -> THAI CHARACTER WO WAEN + u'\u0e28' # 0xC8 -> THAI CHARACTER SO SALA + u'\u0e29' # 0xC9 -> THAI CHARACTER SO RUSI + u'\u0e2a' # 0xCA -> THAI CHARACTER SO SUA + u'\u0e2b' # 0xCB -> THAI CHARACTER HO HIP + u'\u0e2c' # 0xCC -> THAI CHARACTER LO CHULA + u'\u0e2d' # 0xCD -> THAI CHARACTER O ANG + u'\u0e2e' # 0xCE -> THAI CHARACTER HO NOKHUK + u'\u0e2f' # 0xCF -> THAI CHARACTER PAIYANNOI + u'\u0e30' # 0xD0 -> THAI CHARACTER SARA A + u'\u0e31' # 0xD1 -> THAI CHARACTER MAI HAN-AKAT + u'\u0e32' # 0xD2 -> THAI CHARACTER SARA AA + u'\u0e33' # 0xD3 -> THAI CHARACTER SARA AM + u'\u0e34' # 0xD4 -> THAI CHARACTER SARA I + u'\u0e35' # 0xD5 -> THAI CHARACTER SARA II + u'\u0e36' # 0xD6 -> THAI CHARACTER SARA UE + u'\u0e37' # 0xD7 -> THAI CHARACTER SARA UEE + u'\u0e38' # 0xD8 -> THAI CHARACTER SARA U + u'\u0e39' # 0xD9 -> THAI CHARACTER SARA UU + u'\u0e3a' # 0xDA -> THAI CHARACTER PHINTHU + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\u0e3f' # 0xDF -> THAI CURRENCY SYMBOL BAHT + u'\u0e40' # 0xE0 -> THAI CHARACTER SARA E + u'\u0e41' # 0xE1 -> THAI CHARACTER SARA AE + u'\u0e42' # 0xE2 -> THAI CHARACTER SARA O + u'\u0e43' # 0xE3 -> THAI CHARACTER SARA AI MAIMUAN + u'\u0e44' # 0xE4 -> THAI CHARACTER SARA AI MAIMALAI + u'\u0e45' # 0xE5 -> THAI CHARACTER LAKKHANGYAO + u'\u0e46' # 0xE6 -> THAI CHARACTER MAIYAMOK + u'\u0e47' # 0xE7 -> THAI CHARACTER MAITAIKHU + u'\u0e48' # 0xE8 -> THAI CHARACTER MAI EK + u'\u0e49' # 0xE9 -> THAI CHARACTER MAI THO + u'\u0e4a' # 0xEA -> THAI CHARACTER MAI TRI + u'\u0e4b' # 0xEB -> THAI CHARACTER MAI CHATTAWA + u'\u0e4c' # 0xEC -> THAI CHARACTER THANTHAKHAT + u'\u0e4d' # 0xED -> THAI CHARACTER NIKHAHIT + u'\u0e4e' # 0xEE -> THAI CHARACTER YAMAKKAN + u'\u0e4f' # 0xEF -> THAI CHARACTER FONGMAN + u'\u0e50' # 0xF0 -> THAI DIGIT ZERO + u'\u0e51' # 0xF1 -> THAI DIGIT ONE + u'\u0e52' # 0xF2 -> THAI DIGIT TWO + u'\u0e53' # 0xF3 -> THAI DIGIT THREE + u'\u0e54' # 0xF4 -> THAI DIGIT FOUR + u'\u0e55' # 0xF5 -> THAI DIGIT FIVE + u'\u0e56' # 0xF6 -> THAI DIGIT SIX + u'\u0e57' # 0xF7 -> THAI DIGIT SEVEN + u'\u0e58' # 0xF8 -> THAI DIGIT EIGHT + u'\u0e59' # 0xF9 -> THAI DIGIT NINE + u'\u0e5a' # 0xFA -> THAI CHARACTER ANGKHANKHU + u'\u0e5b' # 0xFB -> THAI CHARACTER KHOMUT + u'\ufffe' + u'\ufffe' + u'\ufffe' + u'\ufffe' +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/PythonHome/Lib/encodings/tis_620.pyc b/PythonHome/Lib/encodings/tis_620.pyc deleted file mode 100644 index d83d896c75d0000bac322ccc06bb11b574165e3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2803 zcmc&$X?qk!5biy*SrTs0VAREn^&lWBUWiBljY7oPXdp(H&CYBxagR7N5u+%_2Eu*c zr}upyQ0)hKp8h5E5B%T{z^Wdy6Qa)(;e+mOcWSz(tE=96yDE`C8L)^f zm(g%9(PRqIMRQ1)VNnc;E)pWb3W@%(D3BZ#!$MSrSl<;EW=tz0S`n`)BEqcGil|m3 zYKo{Z>xC88x|k@Cfn-e=6Xv8*U0mxLYPz^E8~LHDPMDKLS3(;gO9@dW2b1h+COw4% z=%XpMcF60ilvAyJIVYF*EGM-lH!xtAdsD3y)5@nj+s!Usv@q3cl`SXdS!Sx>R7$CN z1A5#1lK-;1prb7_pWbWfSl2NxwbAzact@U1v;Cpd?-E-``m*;05Q5vnhJcA}ri2jh+M8B}`!lD|X zfJ3z29&Fd1x!z=2%~RwQM%H&%FKLl5$a=Y+qUG=66I`oU&>`66fk99EVL494anqy} zdUEHG)Y84$?&%)2;&xvJk&y8BXkaF>L5^O8ZX^tYw_XzfVNH1JB`sbXfWgok44qL& z)Af1mn`X4GdYooByaY|zY&lo5vRN;wA4(N-ut<*v>kN)DI7v$r0A$b(QBT9=6XM~9 zh&P>twsPLFN>Cq<;-5OH_q~YBE9b!&Yz!ahkktM=pq1)V) zNwe8@ne3H4UG^-f3b4xN2q;>~gLcggjBSj1tE;7FMHyPidq{TU?bZx|W7B zF#E5NqHPT$7a*`X9$g{q`DCvGIFy< z%@TT?l#J(Cxl*TNQ=P2wkJ+`HU*uf+{G&oevd|m~vKfS=rHSHVS~Stnab4qpVdc#K zzyU6$&4B~8fH^&_yuOSk{|5ODkXj#?Te?bgiK3%2^|2T;*^G1Lre^0+V@h!GsEWEw znyJw4@pa-l;&N@Ga>>0UC?T49?5p`wdVaIC>M$Y3HEjD^7&xxOTNOwL}5e4%dWIYV>l(Pc)8P<<#KYM^gie+Q9i z6beV8v3OmgJ~^qOaq^U@)27duIcxS!H#g0>rTNy|Zcoj<_>_ga(Z~);T!Xbpi2uBc(A{;|Fj&K6uB*H0#(+Fn}&LW&c zIFE1v;RA#Z5k5lr7~vCyPZ2&t_#EL2gf9`kLiift8-#BWzC-vP;Rl2t5q?7W8Q~X% zUlA@MTtWZ@iSQdaT>BwhM!5y$R+QUNR#6V4+>UYw$`O=1QSL&y8|5C9dr|H~xgX^L zlm}5BLU|bF5tK(!9z%H?I7_gLcvM`wy*-A>;%FMR)5Zet%vXp`9)_OzN=FrbJV;DcT%qj@3_z IUlGy206g@&O8@`> diff --git a/PythonHome/Lib/encodings/undefined.py b/PythonHome/Lib/encodings/undefined.py new file mode 100644 index 0000000000..4690288355 --- /dev/null +++ b/PythonHome/Lib/encodings/undefined.py @@ -0,0 +1,49 @@ +""" Python 'undefined' Codec + + This codec will always raise a ValueError exception when being + used. It is intended for use by the site.py file to switch off + automatic string to Unicode coercion. + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + raise UnicodeError("undefined encoding") + + def decode(self,input,errors='strict'): + raise UnicodeError("undefined encoding") + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + raise UnicodeError("undefined encoding") + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + raise UnicodeError("undefined encoding") + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='undefined', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/PythonHome/Lib/encodings/undefined.pyc b/PythonHome/Lib/encodings/undefined.pyc deleted file mode 100644 index 334120a285fd1f846927ab9fe8793977e5b39358..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2454 zcmd5-QE%f!5MIZLo90?T2oRNuv=R^JleoO`hERLqkSZMkZ4RodDiznePPTIFYIj4( zE4^RBkKm8-1K^u+W21u9D*}X5Pj`2`Gv9nOI~)JHKlI zkcZKP(ZXgO6 z7`3{A(2usdgmrtZE)ja4CTBYYYL>o5SU-(~kl$>=qORoQRi#Z~E2AIFNv%yj8c94a z7uL(1=5lSzQfB2k+j!|R>y6ChcUieI&z-BCG(YC%I#`%mFH9vbjjiTvV&#n<%ab5s z$yUL@kCp{?Kp`(TGAxYrHkk4CMi#a-GSt$qZO9k0E($i0twO!bg3YB54tD92Z!1f< z0M57^ZpWk1sj~t0$>>*^%by-s+8O!6EH77XF4JXJ9+k~xoY%`I*pcQ>5bgEG+4&;K z$yA+uB99TKqPdsKc;kK`_|vcD>9JDB)0eNX&HjdG8U`SdxoXRxhm~hUt%NY38|mgs zc#SeZvM}xm8plG-QYxB|(C3IM4>`^0B`XtJeg`7({+mer#I|NBX{Y{O$TnrtRNw-{ zq{yfUdl0wuaBdn$eXM#@77W`~*Q>z34Q0=#Pzo0Q5To(=3wwFKwd&7XPe@X;iyRsP z;R%n3{weT^%rRg^R478Ni0FqRM9Bi-``CGlFeOuA2yt;yWlM8$5k@>&)_PT9swfp| z2cq-!W|S!G5tJ-XK9b&E9Eh5eDtBgSs*sh>nJ<@Pl^=@o8D9S$L{lg@)mn7LL7DtF zN#!!YfzQe=+Iw@)6de%mChN?pB2LvV1l#;FE4|?lJHu~CBjw}6t@R|jOX3%t(*F~Q z>JiX(VcyRlRo6$`2t{;fGRnN0sD5Z;FSk2?r$(6m0G^&<#$)GPE-{NcpKBJ}7o zzQUE;-;Qz14yc%QLj4(6alo}Xq~>uWc4jG+`ZUl{r#=#B+BV3piE#DWt_5&6HSX?m z)2AFK4EF#Mw&sNWVF8PvkKJ zfN72%<~FpSuOt!eMoF}XU&6n12n{Hr&Z_Gio%92Y8$^GBL(vg`Fc|XjS<|XNCt#l9 R0*d~@@SuOtKa39tzXMGr>45+M diff --git a/PythonHome/Lib/encodings/unicode_escape.py b/PythonHome/Lib/encodings/unicode_escape.py new file mode 100644 index 0000000000..817f93265a --- /dev/null +++ b/PythonHome/Lib/encodings/unicode_escape.py @@ -0,0 +1,45 @@ +""" Python 'unicode-escape' Codec + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + # Note: Binding these as C functions will result in the class not + # converting them to methods. This is intended. + encode = codecs.unicode_escape_encode + decode = codecs.unicode_escape_decode + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.unicode_escape_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.unicode_escape_decode(input, self.errors)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='unicode-escape', + encode=Codec.encode, + decode=Codec.decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/PythonHome/Lib/encodings/unicode_escape.pyc b/PythonHome/Lib/encodings/unicode_escape.pyc deleted file mode 100644 index e3985181014b6a436cac8898db67a01b55f97f99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2041 zcmc&#;c62>5T46jF3Gi35k(^fPY`+qn+Fh)#;8!JQ8q$pD4f^3O?u&S3A-C5;J@~l zkKsf3Vm^S*%r$pb`@{B!Uc1xTo!yz)Z)U&R-#5H(2OkD8oPRd{-Nm85qDTOSC@n~8 zkXbN9#Rh4?qy{6@9XJCx1vnhmAgQy#W`kQAY)BexaM;i+4GttNkTtf|VT2C6(pHCL zZDn)WwqDv?NH%CPY*12z;0ERT1%>}^X-;OjzqQEIc$UZ=spDuaxBMPXV$bsqRBDXO z{o|$oCQ|WEH&2xG_vQ3>p~ikNjk4XWm~`UVbi3nuLA;Hp=S!82PmJH|i@hg)H_LoM zbL|VMrTQq7j^BUlA9RK2_TL}kvGfOieN)GzIChDxg)1*8-v=lp-oc_f)3x8f$YG)$?nI#kE73lZ`i>tCwuT!>dh& zT7*V#z?y!9TIXm#Jw9S5X+G9R7Xx+XOF{cLaA*gG>$EI$8cOD^Jn0GAq2wCGxlHMOT$Be70vIIh%0)bDK^mjfxNzXa{69A5=P zqKW$}?}#C#I50{^Q=$b~p;x|9LcM6s)r+KpR;9gO9yig)CXQ7tt2~5^l7E-SEzIFz zl}C&!f0SPjhklBpcxnaxBk>#Ns>ERh`MXZ-ow)SCkmL;#a+4VA6dHqo+M>@djmS$A z{18kXvQ>Eg%wm_ zL5T^vv>-&TRZ~MfKbDx%7|Bj8ALCS$H?Ufki-RQn1QZcrB1%tYaTpdHMLRD`MiARw cFCz-{toTRqoOH(Dwbq?>qwTbvO?$Kc6Fkj})&Kwi diff --git a/PythonHome/Lib/encodings/unicode_internal.py b/PythonHome/Lib/encodings/unicode_internal.py new file mode 100644 index 0000000000..df3e7752d2 --- /dev/null +++ b/PythonHome/Lib/encodings/unicode_internal.py @@ -0,0 +1,45 @@ +""" Python 'unicode-internal' Codec + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + # Note: Binding these as C functions will result in the class not + # converting them to methods. This is intended. + encode = codecs.unicode_internal_encode + decode = codecs.unicode_internal_decode + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.unicode_internal_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.unicode_internal_decode(input, self.errors)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='unicode-internal', + encode=Codec.encode, + decode=Codec.decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/PythonHome/Lib/encodings/unicode_internal.pyc b/PythonHome/Lib/encodings/unicode_internal.pyc deleted file mode 100644 index 68daa8c5969b6b683ca724e11059566b0e055b6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2067 zcmc&#?`qUQ5T9Ifxx2Jg5k*f51{6%e-UEn8&#F+Ur|b!(M5Z{aZCP)L9gN(W>E zatB7JxS$+3Zon9I56%Ei0rp1?kWDtYZ15|C3$n!qj}7h0;DPLbYOt*dV{{NywkF7x zrOjvCYGw05uF+)FB2dHV24Ve*B7DEFN3$Y)GB2`pCe>zESfz_3e-duvG!24aPiNMu zB0OA#Zxfwv_6w<1xT~gzb3F;8X_9Z{<)oL+rW?H=h|&#w`(&ZB$&n4W2V&=G*w6D& z(AZ*TI#Sg!lmpg;6*Z=dlYTkCi5j zd=SG3tq`?P*fxqdE|RH=V;k^fI+OF9ran$7)YRB}sGbKNF9VNNK~~;&u3owg9W1w% zYI!_*1lG(W)OrWI+2H}Z$%=_NxOiCaWFhE{H5|r6;d>p&-bQ7oNVS@(!Y27^2BfQW zG|cqPbC98ch~5z_ z2vC^^t!LV>#nPft`IzgJ6(@7c+Bn0esZ;RR(NneWl1oAWPDJhn;TN>PuHPiNQGzzs z{;!teHoi;A;zRsD68wrw`5zKYttdJa80VWBRjiO$r8OK^Y$fXbE{@BSDX7Z??WtW~ zEssPS_m}=Lj|6jQwMwQ$5~|K%bz>>>Ws5HFCzZ7>@O6>gL@(<&mKCj$2$jfxiR2cd zcvvGzQRRmaZsRb|P?XoM{3PJVz%qMDj}_$fCN;YB>9Qg5TO{c=ao8!eh7q;LfNveq znW5t@ay8!#E-X_=R#QhwVEW>6Nm!ceXSjZ!xqiPbU{NuRd^(eXB^*r4JH>d$q*Wg) zsLX=8Lr~a)Kwh)5mim995Yz<8PcI(hl!FGR6@Pb-i_Wz4;5GsF&;j diff --git a/PythonHome/Lib/encodings/utf_16.py b/PythonHome/Lib/encodings/utf_16.py new file mode 100644 index 0000000000..f3fadff615 --- /dev/null +++ b/PythonHome/Lib/encodings/utf_16.py @@ -0,0 +1,126 @@ +""" Python 'utf-16' Codec + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs, sys + +### Codec APIs + +encode = codecs.utf_16_encode + +def decode(input, errors='strict'): + return codecs.utf_16_decode(input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def __init__(self, errors='strict'): + codecs.IncrementalEncoder.__init__(self, errors) + self.encoder = None + + def encode(self, input, final=False): + if self.encoder is None: + result = codecs.utf_16_encode(input, self.errors)[0] + if sys.byteorder == 'little': + self.encoder = codecs.utf_16_le_encode + else: + self.encoder = codecs.utf_16_be_encode + return result + return self.encoder(input, self.errors)[0] + + def reset(self): + codecs.IncrementalEncoder.reset(self) + self.encoder = None + + def getstate(self): + # state info we return to the caller: + # 0: stream is in natural order for this platform + # 2: endianness hasn't been determined yet + # (we're never writing in unnatural order) + return (2 if self.encoder is None else 0) + + def setstate(self, state): + if state: + self.encoder = None + else: + if sys.byteorder == 'little': + self.encoder = codecs.utf_16_le_encode + else: + self.encoder = codecs.utf_16_be_encode + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + def __init__(self, errors='strict'): + codecs.BufferedIncrementalDecoder.__init__(self, errors) + self.decoder = None + + def _buffer_decode(self, input, errors, final): + if self.decoder is None: + (output, consumed, byteorder) = \ + codecs.utf_16_ex_decode(input, errors, 0, final) + if byteorder == -1: + self.decoder = codecs.utf_16_le_decode + elif byteorder == 1: + self.decoder = codecs.utf_16_be_decode + elif consumed >= 2: + raise UnicodeError("UTF-16 stream does not start with BOM") + return (output, consumed) + return self.decoder(input, self.errors, final) + + def reset(self): + codecs.BufferedIncrementalDecoder.reset(self) + self.decoder = None + +class StreamWriter(codecs.StreamWriter): + def __init__(self, stream, errors='strict'): + codecs.StreamWriter.__init__(self, stream, errors) + self.encoder = None + + def reset(self): + codecs.StreamWriter.reset(self) + self.encoder = None + + def encode(self, input, errors='strict'): + if self.encoder is None: + result = codecs.utf_16_encode(input, errors) + if sys.byteorder == 'little': + self.encoder = codecs.utf_16_le_encode + else: + self.encoder = codecs.utf_16_be_encode + return result + else: + return self.encoder(input, errors) + +class StreamReader(codecs.StreamReader): + + def reset(self): + codecs.StreamReader.reset(self) + try: + del self.decode + except AttributeError: + pass + + def decode(self, input, errors='strict'): + (object, consumed, byteorder) = \ + codecs.utf_16_ex_decode(input, errors, 0, False) + if byteorder == -1: + self.decode = codecs.utf_16_le_decode + elif byteorder == 1: + self.decode = codecs.utf_16_be_decode + elif consumed>=2: + raise UnicodeError,"UTF-16 stream does not start with BOM" + return (object, consumed) + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='utf-16', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/utf_16.pyc b/PythonHome/Lib/encodings/utf_16.pyc deleted file mode 100644 index 14579d22916f0837440ca267a680899f82d32fb1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4908 zcmb_gZF3V<6h6Dzv`t9m)k=L`L?JlP5nuSAj#5w@Mhwgrtag}*Y4)Z~NjA*xjhGqu zAmy9C!Wn;qf6O1C&vWi}H?19L9m?FxecyA>dCqgrP37#J$sT9bt9lkoda+P$=##Hk5ync@04-3Xh*&fx06b(XrL;f1Aoz1h8h z-47>ee`C{z*IUuei{bKM5Jv20VPrCs{$k>#uys3JU5=vV*4>}5t^W`HT6TsK*|gua zT^~)B0OdM|PolCSTb?`?dF+YxWxIk~co=UrseRqvrRbTRM<2IoU%t{tA7hpW-A%`) z$y03=RX=$+wz|or=_t*b7!$3sMYNXg-|Da5Hwkw4la1`YJ8tRWM7Ow8k78ZM1I4o^ zP~S|tsTrEYb_U;Yqe;7*r!HN3dx7)K*lX~odhhZdhyXuK_`#Fq!Yq&IZktX@zgX=ryY?>+`V+^KtySy9Ba`uMEF%>YOrm}U+A zsLo1TRM0e*oHF$Gma=D)%yQxS#F|kGbK7I+<-i-5wp%|vxV|&kyd^(F_EH+mJ@&Y`yvQy@oTU9%l)0$-R-ac<11dI4s~uh*h5v@JneABf zKIP)sQY}2J(ArfD154=%`Vz!zdy;&RLlxo?ksk^iXsfz23q+zjlXtOeMa6AJ4II^^ zhn1R)Xt;=^;#`wpijJdlHzZgTCo1Pbm93Y9!F1C_9Ffsz;>~yspYUkXJ#zv`Izs~j z;DUC0IEu%>a9jOXzk8!I$V_w!vueR;fvwZ1N?Ek^eEw9%AzP{-5F=>RYe8*xFN1!q z#JvxLp2J@A9|k3TVh}u9(MCYBq-(uIvb3+`yldlL&!i@vBKura)s&i3snf*>N1e{o z4^5j_s3u-QX_E~ihR3KA|AEFXC;5GfHkB|zf!l%HugH@?o>b)tfLL(nce*%GXo5Sh z=u|~P+|wxsVobduk2M-Ss7m@92@?Scgz*&UhX6RCDm|nWySNsdjBhhUGh#Wa)i~cL z52^QN^tF3;Zy@Oi5%*1J7{()$g~`aG-$`xwsBbsJYq!5wkVbD~`4llvajp4vC(cg| z0=&)ydk8omqyyed`V7V z!a<+*)TO0D4nhcTV%w)E8IeLlsLfkiXGJl=EOfs_>H=1n=g=)pp7 zQZG7-#&jrTvY^@J3o5XOdcaf9%|5P+B11XJOW?jy`nVXh?eZB{4^t+1%Cv_U~=ZdT* z$0dNt9@HhhB%bFbp8TjrAd$D+t=WutF-J9&TFGwN;yt%MwvJ-|C+0dhEzeqxc@?kj z&3i7W^EUicaghnX>t2cK#K0IIiY@}~1VP3!_j>q37vq%yRt_ZjSi_u)fU7#?A|R$t zGt9+M0wUljkAP2o4S(1kX!v_6fllL(YV#f3C3=HZ$cp!j&aiqHm3s#6j#Dl~t#6sG zjo#xzW|AfBUI1*KzloC3S!7ozYIrV@D%oC9%^l_O+Iqn^xTcMw+&1IaW=R+NM^P1u zpP=C^2;0F-;BZ(Fn#Y3+SqE^4Uq_IQ;%5=&A#;LMYg=Yl^y${ZG&lrVton`nJ;Noe z6jn3Le)&ev-?n>)^Sn*{%`rGq6F%-3lia`~jY%#mp|SK8c%8pJ+)R3-@{5}5MvQOH zInJSVD3w{77*CVbY~W{wbTUTQS;(s)g)jd#DV(OA?RGrsB5hX?>5D?y@D%19h!kR) q7N}s9$w_w^t;0z-haF$Ihr*X^t7tRc>7eE}DvM_q7Zy(~F8m9z2swQK diff --git a/PythonHome/Lib/encodings/utf_16_be.py b/PythonHome/Lib/encodings/utf_16_be.py new file mode 100644 index 0000000000..86b458eb9b --- /dev/null +++ b/PythonHome/Lib/encodings/utf_16_be.py @@ -0,0 +1,42 @@ +""" Python 'utf-16-be' Codec + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs + +### Codec APIs + +encode = codecs.utf_16_be_encode + +def decode(input, errors='strict'): + return codecs.utf_16_be_decode(input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.utf_16_be_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + _buffer_decode = codecs.utf_16_be_decode + +class StreamWriter(codecs.StreamWriter): + encode = codecs.utf_16_be_encode + +class StreamReader(codecs.StreamReader): + decode = codecs.utf_16_be_decode + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='utf-16-be', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/utf_16_be.pyc b/PythonHome/Lib/encodings/utf_16_be.pyc deleted file mode 100644 index 0f60b753fe561e13563dc67faf9a14465cb1fb8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1894 zcmbVM-AWrl6h52(tlEECEWOxXxk3#H#j8?`X$yi)%R~@^uuXO+ab>fS*-1;lJMBC4 zN%~@afc86QV+^(zjT`4Ub7s!WcfRve{I%x(Jo?fJY4#QIe-|VB0TB^(AsvbelsMFN zNIP^^pl*>O{FUem$`VCo(U)m}lNGumx+FU8mMN;rMnyJi^NlJ+b=j!NhCAP=QM4i( zb=g>*Z`3JT<3-nHC>{SEBm55GeV*FWaq4YM>|kqqXREI_yw*6n4#y7ddY5*FB;)^wApZ7Kiq`%`P9V2Q|q=fGLj>MvK*tAuQ3ELl;CB4%q@-7U75k zecNZ!#XMx_nSFpY916B~g1!!*g4*(3hi0OEzSx!_;`DrC#ZDVDHkl6{iO61H);Kwc z`zJbub({{fllhH}^QlO0dm|kL)|JI*98D5lGKLSmB-3gIvzrJ1k9Adr z5pyi>RsQ1pokaSEZ{|Yyeu&AO@3SHo9ms}~d`6^JS*)>O6UA||Tq8k$G8kwxOQEIV za%w!qxQ5Hmbga?65!cp2V%!yI4Hw>xNoHjIpU{-fSvnMS9@3imG zC+Umz0ore7V-jpH8aJNtoS8FoX1@6;{#tc^9)0PAH2sSBzk`+i0EvjYpbkX^N*wAs zq#ZghP`5}C{z`NWW{IM*@XOT4%?e!;T@f93%M?{bP!U0GCa6+W7eP$~?o3dlXhj5d z5j19kIz_8|=(_Am$G^uOeh2YBPwd$!_14F>zqz%&ndo(|HHviTy6%yQt<|Y_I`KaC zOt`t5Mn-!FdU!fE1J57!lARTVbcHi9;I}u;o?4YBBpUh$T9A=#uEtAzPrUA_8&1 zZ~F|osE6!&W*^{;fP$^U|Y6zXvW%S!?p|(rx#-@dfJ$g$$aogNcIA|=E*^P zdZJTk$LSzDnOSUJOhhX;d>>acwn>hC1iGJwMh|srd&zs&)h1*ie|&2XD|-T>kq#6@ zfvbe;phzl@C**K$R*SDc1DQrI0HB1fpy$w9N1|!RxIhAfVnl8MAR%bQA?Hvr6q!!? ziZ=p9KTdnevhnA3IW^PxeX&;qBM8#oPzQl^Z%GQ z##r8~{Dt>B$@Cm=#zOFZh|LV|^CCALzy_0iMnyH4tTJI0#d)&aBf;so-`8eZLQA{L zrSTN&#$A4L>5D}Oz3n>QIs0SC;Bw1k*#8)Ry%$jiftJLT%8#oXLC^X@m6lZvs0q+$WN1;#hYvM*U;94)`t;u*D{_DAy= 4: + raise UnicodeError("UTF-32 stream does not start with BOM") + return (output, consumed) + return self.decoder(input, self.errors, final) + + def reset(self): + codecs.BufferedIncrementalDecoder.reset(self) + self.decoder = None + + def getstate(self): + # additonal state info from the base class must be None here, + # as it isn't passed along to the caller + state = codecs.BufferedIncrementalDecoder.getstate(self)[0] + # additional state info we pass to the caller: + # 0: stream is in natural order for this platform + # 1: stream is in unnatural order + # 2: endianness hasn't been determined yet + if self.decoder is None: + return (state, 2) + addstate = int((sys.byteorder == "big") != + (self.decoder is codecs.utf_32_be_decode)) + return (state, addstate) + + def setstate(self, state): + # state[1] will be ignored by BufferedIncrementalDecoder.setstate() + codecs.BufferedIncrementalDecoder.setstate(self, state) + state = state[1] + if state == 0: + self.decoder = (codecs.utf_32_be_decode + if sys.byteorder == "big" + else codecs.utf_32_le_decode) + elif state == 1: + self.decoder = (codecs.utf_32_le_decode + if sys.byteorder == "big" + else codecs.utf_32_be_decode) + else: + self.decoder = None + +class StreamWriter(codecs.StreamWriter): + def __init__(self, stream, errors='strict'): + self.encoder = None + codecs.StreamWriter.__init__(self, stream, errors) + + def reset(self): + codecs.StreamWriter.reset(self) + self.encoder = None + + def encode(self, input, errors='strict'): + if self.encoder is None: + result = codecs.utf_32_encode(input, errors) + if sys.byteorder == 'little': + self.encoder = codecs.utf_32_le_encode + else: + self.encoder = codecs.utf_32_be_encode + return result + else: + return self.encoder(input, errors) + +class StreamReader(codecs.StreamReader): + + def reset(self): + codecs.StreamReader.reset(self) + try: + del self.decode + except AttributeError: + pass + + def decode(self, input, errors='strict'): + (object, consumed, byteorder) = \ + codecs.utf_32_ex_decode(input, errors, 0, False) + if byteorder == -1: + self.decode = codecs.utf_32_le_decode + elif byteorder == 1: + self.decode = codecs.utf_32_be_decode + elif consumed>=4: + raise UnicodeError,"UTF-32 stream does not start with BOM" + return (object, consumed) + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='utf-32', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/utf_32.pyc b/PythonHome/Lib/encodings/utf_32.pyc deleted file mode 100644 index b99fb81dcd2d6154e9933ed576f8ff644f42a6b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5446 zcmcIoe~%ki6}>Ya+iS<$q)7<7G=M{a7*I<|03i`Uo3xQCTDO`_NxO>V?AqgGcD>_j z=B>g?SqZxN4*`#tyFd+xdSP3_<7?SDOdyfw7) zSHu6e@f80=F*4gm8Q3VaNnqQk_?7^bdD)8efjl@#N#N=H1rbks$~>u4`5)pQbC zfcHRW18i)S!l;0lx{I4!w1#3ZNVC)p22xdjnk9}yQb3Y>wMFPClF2yc@>TT}b8{hp z%PqJP3@I@imE;F#K*l}cd4J9FKhnT}E-cOd$Z!w>+&{RLQFr!YdvlzsdJO0*Frm{Rb$ntphYZsW$5&dvKL2%mt@r7A!X=zANHBgF%0Twg1bYq)(6~c(kSp=+4up0v?AN z{|EYX-+?f9569yqPeu#$UkWeX$-p90A2mFgdfz`ck^X{;i%^J2Ss{kFjokVlsGM?} zzb+7|C={f464|4g9Y=Otw_`xFV$(lpawM>VO@FPSnqWQFkcTyfUbE+lPy2Pt|3V5y zhysOt0e^r1*r9G?M1C(y$-ZD|yqiIrG0c;%B7aJ>r#wsXBNU%JxR2bRi%cNdIp~h2 zNzu)w4(*-Xb)Ti~Y4`3&9}2ed_b`2dsu$Qd`O_@&FLVOV-ULgOTz1kWKgm)C?)R7y z_%J6Qt%zEEF=vwSf{E55|(iNzLpK7$2ju6k`;_eN2a^nlaY@oRkXp zC1Aia(Cc24UJN!Reh~3du5s!<@DtcE`mu#ypg3A$i8QUayqiAppNRN;h5l7jw@%A$gBEGBGJ z2Xh@9Qi@?%`Isj|9_00szoT_^%NnZq_|mlOj+XdHbaHx$D`%EVyene~vUnfMpmc^O zny>F&5;co|jAB`vB>g4b#a;GQ8lH!&n5taW9~4d=U_n6_v+xRZ*9kZ111v)yF`1vo zWM0p&B#o~Xk*;HdxA0UEskM%X^opYew?sn^^VFS{&Hn^562z9%+59{fA)!S$LW&dDL?m zrmS+s(KdM9EYh^T5#Eu2O#SAPe?{JTIu{MRGt(pgOP51b$Q;#e;-gbR5H7}RgtD|U zY5Tn1zb;o!}|if_zgZatr|T6x640%yAZ+gmK7ca}jGx5ry~Lm7U}& zCQtBGnf~QjrXThMjU@+>(z$5<2Gw33n_?P_x-1y4nW(j*1(%4Eoii`Eq}$3RUcfh$ zcF-l@1~s|?4OQJpD6gz`3zbDO@)BIb^;TbVjv3TmLG^kXNg~9(PhDN#y42}0EPb+aT>@zE85*lhA#dgC-OQohuxPTj{E-^PeEs~Q`t`^ z@bo!{wouI#^X*qbH39MrkFw}S*lH5u`cYIt@t3H03&M6V6F3|egys>0k>~=4_-=+& z1s}|C-qD&NyFan!mcnEo!{88HrQ|pMOP9YjQCMAb()ov?@&n6qcX?Hizj+2nHq0*! zj7h%ZnPQSpglQ~&inzxQVDD$+>HLklaK+a#BbIZ}t83LnjHW}}9R(s?YsH3FG44Smh$%CZV2TZrj=DdebZb~~$KO_eM{1F1 UjbI~cg`L{w>zlVXuWnxZFI!-4^Z)<= diff --git a/PythonHome/Lib/encodings/utf_32_be.py b/PythonHome/Lib/encodings/utf_32_be.py new file mode 100644 index 0000000000..fe272b5faf --- /dev/null +++ b/PythonHome/Lib/encodings/utf_32_be.py @@ -0,0 +1,37 @@ +""" +Python 'utf-32-be' Codec +""" +import codecs + +### Codec APIs + +encode = codecs.utf_32_be_encode + +def decode(input, errors='strict'): + return codecs.utf_32_be_decode(input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.utf_32_be_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + _buffer_decode = codecs.utf_32_be_decode + +class StreamWriter(codecs.StreamWriter): + encode = codecs.utf_32_be_encode + +class StreamReader(codecs.StreamReader): + decode = codecs.utf_32_be_decode + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='utf-32-be', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/utf_32_be.pyc b/PythonHome/Lib/encodings/utf_32_be.pyc deleted file mode 100644 index 863ab3810efd123b1b615ab4a88ee0786bc40e0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1787 zcmbVM%WB&|6uq+ij?*_3moBo4HpwFCvXm0Hg+MVyE`*wZYHP-+f-MJWObKL{d_=#b zKh_Uu&$)7BlWgipp7H43nLFp6`|$s4w|}2}AH=eJeEh%1$bVrnB16ocn2Jn28G2$p zIj_jj7lU6_ZXm3Rsj0js6YQ+ZjmWjgw_#08Llt#ZG)qN8OiL9_RkTY*Q_PksTB_)j zik6sdehk}$G6)_K;VVq-FPHAeJl)w{xXIq(!QR;J?)2uy#_i-Up1!Mdr^}Mq#T6_$ zsu(?rpJQ?&=bl`NTzTRua_z&q2YEjr6M8(Rz1%&)H*Sdz52CS+AcEM@*4J!d0~&TU zOi6mNaC**W**wbw$V8|7HCFqlpOf*aO>sI&&+^mK;{L^@o+=Etu{Ebn@!T`a$7!6| znN8hj`jKaC7E{TGyN)pO7nm$KLX;{D9fRXbSojmuo!iml_LrEJ-YWr!>ov}K(jBNb z{RA6CX$Z;49Rkz^8`9;1DpHZ#=_KSrshA|`Xu7HYg1bx7$dR2W zn$68(%1>hWG@9l%+`?*g;s3E7HgISgL;0@Xx0VhAn9jy(ihMtBx zHBE61w7JG0XyIUA8v(O3=V#fBltu-tRh+Dx!m|GM4)F=lU zC9O-|*kg}6PABu#jhfdX{R`=Q$lz>Bn`1$pSpYdh@5wIN!E!c2@mgMe?G3mQjIb`v zJdUCw=gU-54iu4N+dk3?ux72TEz7I`Osoa!E>;_(=CyB&_VA89Pa)U6PPJ9(_}yyP H$6NaceP>81 diff --git a/PythonHome/Lib/encodings/utf_32_le.py b/PythonHome/Lib/encodings/utf_32_le.py new file mode 100644 index 0000000000..9e48210928 --- /dev/null +++ b/PythonHome/Lib/encodings/utf_32_le.py @@ -0,0 +1,37 @@ +""" +Python 'utf-32-le' Codec +""" +import codecs + +### Codec APIs + +encode = codecs.utf_32_le_encode + +def decode(input, errors='strict'): + return codecs.utf_32_le_decode(input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.utf_32_le_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + _buffer_decode = codecs.utf_32_le_decode + +class StreamWriter(codecs.StreamWriter): + encode = codecs.utf_32_le_encode + +class StreamReader(codecs.StreamReader): + decode = codecs.utf_32_le_decode + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='utf-32-le', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/utf_32_le.pyc b/PythonHome/Lib/encodings/utf_32_le.pyc deleted file mode 100644 index bc56ccc15052d9e71846eacd307f3e823615c4bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1787 zcmbVM%WB(D5FJ^5$LSl2OBdNin`Du6SxSl9LZFx;7eY-yb)>6QMwWwgO$lU|d_=#b zKh_Uu&lx$gNj7yP-|^MVow+k-9`2v*?(dWDqfnNQi~sjn#V?RZWDM#^RFl+^u_MNj zX-&qiMEKR^2F$ud4dpi^#>uAKh+K<&8#g3ssi3KXb|q*@)KNiO1>H)}mS{@_9ToH{ zK}Vu(evG?xW#m1ghp#}oUoP#BdA75=u<_pE!Cq>1cLwvwgx%yXo}q2>q|KAihBa)t z>R1D^pMzMDsUue+SB}`4T)VLDfIswzgsO+MSJ)@`#x23&L6DjNEU+zYea#ofqhZ?s zNwSNDRXvmE^StoD6D7rK?DkJTCugT7gLaag7pIlQ{fkT0Dh+pWw4hCK>@(2gEX>W! zWOkB%q^`+B3i~C}39^h{0YF}_q31|{q|po$ z91w-UCn9$M&=8EzkV~itMPbs|=SHE3lWdZ18h>e56I{mcsl7Ig20=ENnIN!4CkSTq zXn{-wde^5(S{Q!|g4Kophq~W_(l(aj-MokQ2hH>fZ(^Z%KgFiPd+M?i05+K75f#5j zLc;3eFaBZ1QCZZS3x2nBdj7?(&+E&CO(Xk|%bpFdph?8wMYSB;8^a-gnJ6 zll7W?sB6T~XG?F48k>j}zjUqY9-^u3@CKW*9m;u!0f%`I)x~1cH3XfG(S}mPOhcbW zZLuwkxz@<*Kyj#pfYn*>vl>PUqdKfzoUFRIEc5&>yX^klGN~9_NGcYPTVwpxEPI+I z?MvP`;EX!X;`!=Et!tn0`3&A?ayEs{vZ2lm9687A$uBv<3JyYXI!<%#^>`47urH%| z7zAa_SEZyFs7ID#`$#*$L~CPh*=D7~^tJT5kKM*z^V+xNczDN|r!F_0UcFQ6x&3OCzL?%+K2E- zd@&zDzi&1sK?O;ZoXI&eXXea&^W*;5ZGJ!bGKggPaq)kEm45??MTVe`#3dO!GIYc^ za#50@D=~g$xdF2*aYgwR8R2GCZbYs{J`XDr*HlndL475tN!(CDT?NgRpf2%_3K}YC ztpp8;cX=2#>B_*nLl2KYIv*DH>oo1`&F$#r{$8gyjZM^So@9x&CheRpI)_;jrk#)T zBpu`5JLB;nzcj{%vspKqPF{4I$xnRxwo0ouOClSUu;nUa^~in*Vnr?-xe~c@#FpgR zg(nX9eUGTAdc^m0+rk+h1^WSxU|HJvl+BGtqqYK)q_eqI9g}6#Ecd_@CHYhAx~K1x zvs05oJ4w&;Q?=HeEmWg0x`S&u?TKR_fF7q&W+o=J;rJc(Ocqhd4{se}<&QuNa6~3c zOfM7YieJPLF^u1<$Lmi(mQicq$o)0+9BB_Ul74~-a;CtT~t{*Sa@gMtUwF@mtO88e_(<7~jWch4F>U4gtVmibrpJ7Kgt}LKUCZE#C>w=A)6xmL;>5tAvCl zps>JIJ~6PF2`B7?jY7DslXV!}9zi1U_@8e1Cfuyg+qy;Ue75aYXb~y)*b=Q(mk>oQ z`&ZZ$Wnaub3_J9DTo#L|R}pkG#vDou^9}tN*TvQ_@@fOG0mZ&HJF78gx^*xqbn2*f zYO?OsqNKAw*+qwEnn;W!BoYgVZ7?o1vz}&#_*p*Qa@y@Qp;_Z+b+J9UymzEd;kCd diff --git a/PythonHome/Lib/encodings/utf_8.py b/PythonHome/Lib/encodings/utf_8.py new file mode 100644 index 0000000000..1bf6336571 --- /dev/null +++ b/PythonHome/Lib/encodings/utf_8.py @@ -0,0 +1,42 @@ +""" Python 'utf-8' Codec + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs + +### Codec APIs + +encode = codecs.utf_8_encode + +def decode(input, errors='strict'): + return codecs.utf_8_decode(input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.utf_8_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + _buffer_decode = codecs.utf_8_decode + +class StreamWriter(codecs.StreamWriter): + encode = codecs.utf_8_encode + +class StreamReader(codecs.StreamReader): + decode = codecs.utf_8_decode + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='utf-8', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/utf_8.pyc b/PythonHome/Lib/encodings/utf_8.pyc index 25fd323f06f04de54a1aa50205cd86c14afb470b..c0be188f0184cebb5edd85b74429d7387840038c 100644 GIT binary patch delta 468 zcmZqUpC-8B0;8b|0|P^On82Uo>#EHUr>N^jDKlKL1{^hOKMVSdQ3oN zNk)F2M}BVV try again on the next call + return (u"", 0) + else: + self.first = None + else: + self.first = None + if input[:3] == codecs.BOM_UTF8: + (output, consumed) = codecs.utf_8_decode(input[3:], errors, final) + return (output, consumed+3) + return codecs.utf_8_decode(input, errors, final) + + def reset(self): + codecs.BufferedIncrementalDecoder.reset(self) + self.first = True + +class StreamWriter(codecs.StreamWriter): + def reset(self): + codecs.StreamWriter.reset(self) + try: + del self.encode + except AttributeError: + pass + + def encode(self, input, errors='strict'): + self.encode = codecs.utf_8_encode + return encode(input, errors) + +class StreamReader(codecs.StreamReader): + def reset(self): + codecs.StreamReader.reset(self) + try: + del self.decode + except AttributeError: + pass + + def decode(self, input, errors='strict'): + if len(input) < 3: + if codecs.BOM_UTF8.startswith(input): + # not enough data to decide if this is a BOM + # => try again on the next call + return (u"", 0) + elif input[:3] == codecs.BOM_UTF8: + self.decode = codecs.utf_8_decode + (output, consumed) = codecs.utf_8_decode(input[3:],errors) + return (output, consumed+3) + # (else) no BOM present + self.decode = codecs.utf_8_decode + return codecs.utf_8_decode(input, errors) + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='utf-8-sig', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/PythonHome/Lib/encodings/utf_8_sig.pyc b/PythonHome/Lib/encodings/utf_8_sig.pyc deleted file mode 100644 index dd0160d89b9bb8a9b17fad17387549848e41ba4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4725 zcmd5=TW=Fb6h31+acmqKpaKGvY#&S_jdhNXGGwlTDm;x;s`H zi9CfD-umADj{dR!fcE>&*lRb02Ir|kGtAD;GMWg27g8T{|#F9 zJGw~Z8G0j8LApksVNjH)Brh>8=y*!Un4A`CWV0k4tSQS&kpq#RpOqw<(HB$tqLROu zmZ+*P%KG9|{-P{VO<&CDi`o3ej6|pT@T@{<8ufQ5p^>?m8{$B z^J?|u;87CTq}_`!e``059pASGTlIyFg1e7?#4+7&ux5ju)b7|MvXQQKHVIl8kFN$n zCr&emacXU_w&!eib8rD9^cSSI#fyTt<0U%0A!w!csN1h|dB!{R++3J!E8f|$(amc7 zH~yC0G%e-Qxb4~n4B1L(OPs!j&WUUq?F;fkMh1y|(6fsqa^&W+14I;nHN zo(mOhJ99I5hCP}v?xL&V0lsK1Hod8Eib&TcdVrh4L!9jNo$j}3+Do%K=0v;f3Pv|q ze~8yshYrYA{b6wI&7D2Ji@vd^u{5JlVpK7noGbPO571#>RRUlFujN)j((6CN+z{@C;7K=mRm+=A5aTin(muSv)^X+Ns^P ziEDN5s|C|Gm+_CH-$l#5KxYwU2xB#%4|R(OFKDPEqKg`aQ%VF_iBJX$U{IE@QKxDl zn&eock(SW10G;>3=Frjrnt_+#k0x%A9Aq@-m|^K@wM?@aC$Vcb6-63Z9#ph(X1kq` z*H2)!kSubEn|Xr3Ty2WW#t9Ysdki4prbv35kfN{<2W(f+9_Y|Xkl!$F8hrcud}B;Q z94a0Wa~O^A6Y_4ahK}e>1o{c~Nu53$z&>ehTfn}G znPzjl7xlY%RP^eV4_e*KhBQ$~Q-<%dJCAN8hK`P<*N~w$kCySOX;UlJ%9T>3c$h!# zF?rb|_~S!td!0W>9$*N>xF?Sise%zU8CCdv)C32SD!dm6KMfzpIKJEObZly)F{&Gg zs>TW{T&f0@#%`GZMZ&P+fe3N z*8J6nsN%CaO)~bVaH6e3>NTP$MIpeNx{PI%Cb;EZVngE9CxD!_)VLv&Pk4$Q^U?^D z$HLJOj?Fc7YSX8;JDACcZ?f50bGBG2)Cv_a_kuYyqK!Owk7Bm}gi&}INBbxmf#t-c zc8}81d}8K|=lcsh{~|jkpOEaV*Nx2bmZ3_#-$Kg>J%(y!POFcGLq)m$6lLpC0ZN19 z0s0a_skPo9yB8Uk%sV;%GQ1ShpJ8w~MeJ3H(&t5anw*gmfUs4S^oAH?5+grFM+9lO zfMdLM2`}~Uw+_YWTHo3GECx@WKpx^ir7haJh{9*qczU5i!=}2B;JhvjGNf??5rVY9 z1U}>yZt$4b5v5hjD9?||xRKY61+((=W1KSpM9p{#905YPTW`XuN#aD!`rYv8X;UeW zAtA)~#s3fq??YUV1SZ%pKzDNAv)q59?}=eLQGNd#2JpRS-T@{q zc=ToDzgg46(?0p68dmt22Ep>P-HuQ2hXR{w)#eKl-nhgMf;Zv0UQlR#dO4UB~xay4S^H#$3&;I6d~S&N>bjVci(@+9(<|mvKV9?1j;srxGbY jt5_6dVzFkh=}TXqeoggNCM_e2wVCY5>&%8lWU^Id?ldJ3I5tvwQV_Zg#(Z z`o&R9^G^f+4{+Ikph<|1(FT;%C=2Kqf|qM_T%)8;NrRF#N}BYlPRF>#uSKt*iRW$7 z0iCYV5JNijis&n%KO955D;-VgSYLKDDcO*YmUL_`J6e=nBfTblZ5m?UHEO12h# z9qD^>+1H_Dn{ST0?EX>jEnd|h10wZ!;znhmcB`r%mx+#d)jt2Jd+Ny(6_LtyAStxsg^S8iR2#Vb#k~8jqBV%!zhTPWka&sHN6x zh>@3RmMNoMWr~F}))~y9%E76QomIoqr~wT7*|my_M8Q6c?Rh_*n$*EhHJGT+BNN~I zxJZmvk90n$%!%sdQT8D7H+ylJ-`P_~Wv*euMQH{vwb9~9ltg2v6E!qtuBvKpJejZH zWdyC&9FL+R*6LxF!O2lsS@B3L7d6Id@6%HoGf-q+ zG$^Z6-k{kU1=9w(HJSo*0sm%A!V}XPMb7q)3imWEt+*`3Zy_8*lp5-X^mm@ z0}KkLKvzqKcj^3nns&+jm6fMZ?#?Y=PUDTkZHD1P z29~xSLy~uu7URlE=sY^Cij=FynO42Ba_EzgGY&ma?y5`|Cx8i1YpYx*cjoY56>Usu zEOI_fi}^J2NR5yiPNZ_BipJw?vZoFl>qS)t?74C|%dSt;?rMm~H_$A|FS3b>D`QYF zkZd&`mj-ZJj=wY?qk2^eb5}zIgajEqM1@=%&5=~Y!EgK%2Fc)l)UPVL!Ju`Eg~DIX;|ZNbu?JE zV+a}@B>)l;mx318P}eV_tkR-~==T_|q9e%@aQn!M`Y?q~lxs1ETG2ACpNZF%7Ode~ z5RqY)LzY91f>@15RdLqC9Z6$<1ZnTtqjd0WK}`19g2+(5vPRrXr+x#<_9hSRZUr&vlGOj~A(87LnBUz^h*nX~K(jO+9^!99h zZe_Yo%3CS|`aMb-_07fo{4Z?5{ybo>uPwaB;?||&H@;c%l7x2=Wc6!d@c&)Kd-}*L z>`em=8kw`ioYKdpe332)XE5vo$&BwoHC)y!WZv>@R=T~5JCnVu=ADZziU~f~d1)rg z;W^lZHxr;3%!U0(pGP^^%koya80Xy(`r%zs=JI>m{}E}itB0l2zm&ytfeUN%%5gSG zG?*M@mq*M!kcBOMc6hT>sa?h_Jt<0TliyB;LKZ6$jP4JZ1aF~6KToaY7~T>#yrsbB zJSl#>gYYCNm$Oias95GRX2%r&lqzn1#SK4Ch4ijN`mL#oIN~G0%2IC=9U-fPtn3+# zt%rQ33Yo@)>ljV!hbJ#4;omV+dhTU?FR`K0Bq6hL$XY!npOASp6p4x1o95C9x43zm z8zDvRwL+)7O2@Y^gmsI-#A*BbRO!!EciHSO(9oMgmBE54>mbS|=yEG))md&qZUlAQ zZ`a-nuGcoXw8% zu6@Xs!;f~*8H+qaZL0G@frPl9*z=`^OR9cncHdMF`e~Mhl~Do#IrAK>_U?_1NH{ z)TD@#Pbq^-kraU8Bo}3?HD0+q1>Hab>|yE15uqkOS03N8gLe4nTJE?C>ez-(a`@nWvSVN^#s zzs%`Xq!>Y;uwomH#~26#GI@wB6S!KGNLQ|mwZ^yv4i`KKLEYbn2X}b(l?ThRVxr&Y z=O3U!ouEQc9{gHYCx;gAb9g^nBaj@Wcdg3DqwnTc9dC@U*cjb=WgNu1MK|1iUp8d zB_XFiW+$B@BW-7!+uo6Cfe0|{LvRRzv-yR#-*_~!7P(wMv@=4S{l!-JWcKz zofX#UVx--X(FM8^OR(PRdq+uhq}`xAG!By!e!hTdiS;vt$-N{^b!ptB%;&OLS7Hxc z43ACZtR5Am9)hvo-RMCcYw!oNu9xF>nK);1J)G*V2W52eavqmP-!$29QXc9~Hb^g} z{-q0L&SO>bH=cc0rxmbSzksMH zSDn4W8NCkK*k%B`UZbgu^;Qv0bdrxJPQ>^6T0PKiGER-|6cdLrF$gW|RllH9lOICy zsL1UkGciTyFdtKvMQLG(QIgNLkx%*v_DN|!SLnfboKCy?hU2`!B!x9yv0$<5b>Ces z@g9SJ#Fu$G)zPFZP3}P1$#`6p&cuuLC-$SCmd>4t8p0r|vxd%Xpu23XDIK76jp93g zC&*kA#2jd_s8Z0p!(UfJCx#Pmd98)?ChK5WNoU^$)xC2w8Qz)0)ZSU5x;vh_Q8@XTruzmF>qB-`rAAKK?5v5nbio($DUXwPcXAs2O_#-fx3E~qKmF@TQL1y}W zadN+(74am+Ye*}FOdLzCg?e)K37LJmXqG0dSK1Y~1>!~?l_o=q9i+Zwl#jdiJmx*_ zT7v_IcP$PWRjKYZ1s{{Wq+Lm9v@o0anA<;I)aY_(jOtcV$5kFp_zLc7R?+r_oo6iY z7i^QOq||u?AmXI}hT;~^SsLld_K_OU?z$a=6U98btKbvT4x0x95BPIhi`D;O%9;>?kPOYg!mQOb3!;p{C@}!iBx8* z{{VOR7Uxi8nY~o>X>q-crPsIzBWH$dhGLKBtBki1vqUsQT%xTB!Y6U$Xwb^%%0=L< zF2_4yatlp#tp{!?Lx^+U%aLIR`+vKXAp$86)!IX|AEWbG&0myJsZeI(HC~)>KgJaR zmt!O*T#Iq6$9>o}kpCLJ4k5ZPHw0E&HQJ(zl3w$Y-!DR>D;RzTw z5Sq$=xF_!F&^vOi;H@pPj=Rf2>qb5*7P_si+` zU}Bkj6-r(Gk-rX)46p}}BXJSo`0*ZSZwd int + cmpfiles(a, b, common) -> ([], [], []) + +""" + +import os +import stat +from itertools import ifilter, ifilterfalse, imap, izip + +__all__ = ["cmp","dircmp","cmpfiles"] + +_cache = {} +BUFSIZE=8*1024 + +def cmp(f1, f2, shallow=1): + """Compare two files. + + Arguments: + + f1 -- First file name + + f2 -- Second file name + + shallow -- Just check stat signature (do not read the files). + defaults to 1. + + Return value: + + True if the files are the same, False otherwise. + + This function uses a cache for past comparisons and the results, + with a cache invalidation mechanism relying on stale signatures. + + """ + + s1 = _sig(os.stat(f1)) + s2 = _sig(os.stat(f2)) + if s1[0] != stat.S_IFREG or s2[0] != stat.S_IFREG: + return False + if shallow and s1 == s2: + return True + if s1[1] != s2[1]: + return False + + outcome = _cache.get((f1, f2, s1, s2)) + if outcome is None: + outcome = _do_cmp(f1, f2) + if len(_cache) > 100: # limit the maximum size of the cache + _cache.clear() + _cache[f1, f2, s1, s2] = outcome + return outcome + +def _sig(st): + return (stat.S_IFMT(st.st_mode), + st.st_size, + st.st_mtime) + +def _do_cmp(f1, f2): + bufsize = BUFSIZE + with open(f1, 'rb') as fp1, open(f2, 'rb') as fp2: + while True: + b1 = fp1.read(bufsize) + b2 = fp2.read(bufsize) + if b1 != b2: + return False + if not b1: + return True + +# Directory comparison class. +# +class dircmp: + """A class that manages the comparison of 2 directories. + + dircmp(a,b,ignore=None,hide=None) + A and B are directories. + IGNORE is a list of names to ignore, + defaults to ['RCS', 'CVS', 'tags']. + HIDE is a list of names to hide, + defaults to [os.curdir, os.pardir]. + + High level usage: + x = dircmp(dir1, dir2) + x.report() -> prints a report on the differences between dir1 and dir2 + or + x.report_partial_closure() -> prints report on differences between dir1 + and dir2, and reports on common immediate subdirectories. + x.report_full_closure() -> like report_partial_closure, + but fully recursive. + + Attributes: + left_list, right_list: The files in dir1 and dir2, + filtered by hide and ignore. + common: a list of names in both dir1 and dir2. + left_only, right_only: names only in dir1, dir2. + common_dirs: subdirectories in both dir1 and dir2. + common_files: files in both dir1 and dir2. + common_funny: names in both dir1 and dir2 where the type differs between + dir1 and dir2, or the name is not stat-able. + same_files: list of identical files. + diff_files: list of filenames which differ. + funny_files: list of files which could not be compared. + subdirs: a dictionary of dircmp objects, keyed by names in common_dirs. + """ + + def __init__(self, a, b, ignore=None, hide=None): # Initialize + self.left = a + self.right = b + if hide is None: + self.hide = [os.curdir, os.pardir] # Names never to be shown + else: + self.hide = hide + if ignore is None: + self.ignore = ['RCS', 'CVS', 'tags'] # Names ignored in comparison + else: + self.ignore = ignore + + def phase0(self): # Compare everything except common subdirectories + self.left_list = _filter(os.listdir(self.left), + self.hide+self.ignore) + self.right_list = _filter(os.listdir(self.right), + self.hide+self.ignore) + self.left_list.sort() + self.right_list.sort() + + def phase1(self): # Compute common names + a = dict(izip(imap(os.path.normcase, self.left_list), self.left_list)) + b = dict(izip(imap(os.path.normcase, self.right_list), self.right_list)) + self.common = map(a.__getitem__, ifilter(b.__contains__, a)) + self.left_only = map(a.__getitem__, ifilterfalse(b.__contains__, a)) + self.right_only = map(b.__getitem__, ifilterfalse(a.__contains__, b)) + + def phase2(self): # Distinguish files, directories, funnies + self.common_dirs = [] + self.common_files = [] + self.common_funny = [] + + for x in self.common: + a_path = os.path.join(self.left, x) + b_path = os.path.join(self.right, x) + + ok = 1 + try: + a_stat = os.stat(a_path) + except os.error, why: + # print 'Can\'t stat', a_path, ':', why[1] + ok = 0 + try: + b_stat = os.stat(b_path) + except os.error, why: + # print 'Can\'t stat', b_path, ':', why[1] + ok = 0 + + if ok: + a_type = stat.S_IFMT(a_stat.st_mode) + b_type = stat.S_IFMT(b_stat.st_mode) + if a_type != b_type: + self.common_funny.append(x) + elif stat.S_ISDIR(a_type): + self.common_dirs.append(x) + elif stat.S_ISREG(a_type): + self.common_files.append(x) + else: + self.common_funny.append(x) + else: + self.common_funny.append(x) + + def phase3(self): # Find out differences between common files + xx = cmpfiles(self.left, self.right, self.common_files) + self.same_files, self.diff_files, self.funny_files = xx + + def phase4(self): # Find out differences between common subdirectories + # A new dircmp object is created for each common subdirectory, + # these are stored in a dictionary indexed by filename. + # The hide and ignore properties are inherited from the parent + self.subdirs = {} + for x in self.common_dirs: + a_x = os.path.join(self.left, x) + b_x = os.path.join(self.right, x) + self.subdirs[x] = dircmp(a_x, b_x, self.ignore, self.hide) + + def phase4_closure(self): # Recursively call phase4() on subdirectories + self.phase4() + for sd in self.subdirs.itervalues(): + sd.phase4_closure() + + def report(self): # Print a report on the differences between a and b + # Output format is purposely lousy + print 'diff', self.left, self.right + if self.left_only: + self.left_only.sort() + print 'Only in', self.left, ':', self.left_only + if self.right_only: + self.right_only.sort() + print 'Only in', self.right, ':', self.right_only + if self.same_files: + self.same_files.sort() + print 'Identical files :', self.same_files + if self.diff_files: + self.diff_files.sort() + print 'Differing files :', self.diff_files + if self.funny_files: + self.funny_files.sort() + print 'Trouble with common files :', self.funny_files + if self.common_dirs: + self.common_dirs.sort() + print 'Common subdirectories :', self.common_dirs + if self.common_funny: + self.common_funny.sort() + print 'Common funny cases :', self.common_funny + + def report_partial_closure(self): # Print reports on self and on subdirs + self.report() + for sd in self.subdirs.itervalues(): + print + sd.report() + + def report_full_closure(self): # Report on self and subdirs recursively + self.report() + for sd in self.subdirs.itervalues(): + print + sd.report_full_closure() + + methodmap = dict(subdirs=phase4, + same_files=phase3, diff_files=phase3, funny_files=phase3, + common_dirs = phase2, common_files=phase2, common_funny=phase2, + common=phase1, left_only=phase1, right_only=phase1, + left_list=phase0, right_list=phase0) + + def __getattr__(self, attr): + if attr not in self.methodmap: + raise AttributeError, attr + self.methodmap[attr](self) + return getattr(self, attr) + +def cmpfiles(a, b, common, shallow=1): + """Compare common files in two directories. + + a, b -- directory names + common -- list of file names found in both directories + shallow -- if true, do comparison based solely on stat() information + + Returns a tuple of three lists: + files that compare equal + files that are different + filenames that aren't regular files. + + """ + res = ([], [], []) + for x in common: + ax = os.path.join(a, x) + bx = os.path.join(b, x) + res[_cmp(ax, bx, shallow)].append(x) + return res + + +# Compare two files. +# Return: +# 0 for equal +# 1 for different +# 2 for funny cases (can't stat, etc.) +# +def _cmp(a, b, sh, abs=abs, cmp=cmp): + try: + return not abs(cmp(a, b, sh)) + except (os.error, IOError): + return 2 + + +# Return a copy with items that occur in skip removed. +# +def _filter(flist, skip): + return list(ifilterfalse(skip.__contains__, flist)) + + +# Demonstration and testing. +# +def demo(): + import sys + import getopt + options, args = getopt.getopt(sys.argv[1:], 'r') + if len(args) != 2: + raise getopt.GetoptError('need exactly two args', None) + dd = dircmp(args[0], args[1]) + if ('-r', '') in options: + dd.report_full_closure() + else: + dd.report() + +if __name__ == '__main__': + demo() diff --git a/PythonHome/Lib/filecmp.pyc b/PythonHome/Lib/filecmp.pyc deleted file mode 100644 index e1584518cb8ea9edc1af96e750c099e9b641344b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9322 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 diff --git a/PythonHome/Lib/fileinput.py b/PythonHome/Lib/fileinput.py new file mode 100644 index 0000000000..21c2d1f9bb --- /dev/null +++ b/PythonHome/Lib/fileinput.py @@ -0,0 +1,413 @@ +"""Helper class to quickly write a loop over all standard input files. + +Typical use is: + + import fileinput + for line in fileinput.input(): + process(line) + +This iterates over the lines of all files listed in sys.argv[1:], +defaulting to sys.stdin if the list is empty. If a filename is '-' it +is also replaced by sys.stdin. To specify an alternative list of +filenames, pass it as the argument to input(). A single file name is +also allowed. + +Functions filename(), lineno() return the filename and cumulative line +number of the line that has just been read; filelineno() returns its +line number in the current file; isfirstline() returns true iff the +line just read is the first line of its file; isstdin() returns true +iff the line was read from sys.stdin. Function nextfile() closes the +current file so that the next iteration will read the first line from +the next file (if any); lines not read from the file will not count +towards the cumulative line count; the filename is not changed until +after the first line of the next file has been read. Function close() +closes the sequence. + +Before any lines have been read, filename() returns None and both line +numbers are zero; nextfile() has no effect. After all lines have been +read, filename() and the line number functions return the values +pertaining to the last line read; nextfile() has no effect. + +All files are opened in text mode by default, you can override this by +setting the mode parameter to input() or FileInput.__init__(). +If an I/O error occurs during opening or reading a file, the IOError +exception is raised. + +If sys.stdin is used more than once, the second and further use will +return no lines, except perhaps for interactive use, or if it has been +explicitly reset (e.g. using sys.stdin.seek(0)). + +Empty files are opened and immediately closed; the only time their +presence in the list of filenames is noticeable at all is when the +last file opened is empty. + +It is possible that the last line of a file doesn't end in a newline +character; otherwise lines are returned including the trailing +newline. + +Class FileInput is the implementation; its methods filename(), +lineno(), fileline(), isfirstline(), isstdin(), nextfile() and close() +correspond to the functions in the module. In addition it has a +readline() method which returns the next input line, and a +__getitem__() method which implements the sequence behavior. The +sequence must be accessed in strictly sequential order; sequence +access and readline() cannot be mixed. + +Optional in-place filtering: if the keyword argument inplace=1 is +passed to input() or to the FileInput constructor, the file is moved +to a backup file and standard output is directed to the input file. +This makes it possible to write a filter that rewrites its input file +in place. If the keyword argument backup="." is also +given, it specifies the extension for the backup file, and the backup +file remains around; by default, the extension is ".bak" and it is +deleted when the output file is closed. In-place filtering is +disabled when standard input is read. XXX The current implementation +does not work for MS-DOS 8+3 filesystems. + +Performance: this module is unfortunately one of the slower ways of +processing large numbers of input lines. Nevertheless, a significant +speed-up has been obtained by using readlines(bufsize) instead of +readline(). A new keyword argument, bufsize=N, is present on the +input() function and the FileInput() class to override the default +buffer size. + +XXX Possible additions: + +- optional getopt argument processing +- isatty() +- read(), read(size), even readlines() + +""" + +import sys, os + +__all__ = ["input","close","nextfile","filename","lineno","filelineno", + "isfirstline","isstdin","FileInput"] + +_state = None + +DEFAULT_BUFSIZE = 8*1024 + +def input(files=None, inplace=0, backup="", bufsize=0, + mode="r", openhook=None): + """Return an instance of the FileInput class, which can be iterated. + + The parameters are passed to the constructor of the FileInput class. + The returned instance, in addition to being an iterator, + keeps global state for the functions of this module,. + """ + global _state + if _state and _state._file: + raise RuntimeError, "input() already active" + _state = FileInput(files, inplace, backup, bufsize, mode, openhook) + return _state + +def close(): + """Close the sequence.""" + global _state + state = _state + _state = None + if state: + state.close() + +def nextfile(): + """ + Close the current file so that the next iteration will read the first + line from the next file (if any); lines not read from the file will + not count towards the cumulative line count. The filename is not + changed until after the first line of the next file has been read. + Before the first line has been read, this function has no effect; + it cannot be used to skip the first file. After the last line of the + last file has been read, this function has no effect. + """ + if not _state: + raise RuntimeError, "no active input()" + return _state.nextfile() + +def filename(): + """ + Return the name of the file currently being read. + Before the first line has been read, returns None. + """ + if not _state: + raise RuntimeError, "no active input()" + return _state.filename() + +def lineno(): + """ + Return the cumulative line number of the line that has just been read. + Before the first line has been read, returns 0. After the last line + of the last file has been read, returns the line number of that line. + """ + if not _state: + raise RuntimeError, "no active input()" + return _state.lineno() + +def filelineno(): + """ + Return the line number in the current file. Before the first line + has been read, returns 0. After the last line of the last file has + been read, returns the line number of that line within the file. + """ + if not _state: + raise RuntimeError, "no active input()" + return _state.filelineno() + +def fileno(): + """ + Return the file number of the current file. When no file is currently + opened, returns -1. + """ + if not _state: + raise RuntimeError, "no active input()" + return _state.fileno() + +def isfirstline(): + """ + Returns true the line just read is the first line of its file, + otherwise returns false. + """ + if not _state: + raise RuntimeError, "no active input()" + return _state.isfirstline() + +def isstdin(): + """ + Returns true if the last line was read from sys.stdin, + otherwise returns false. + """ + if not _state: + raise RuntimeError, "no active input()" + return _state.isstdin() + +class FileInput: + """FileInput([files[, inplace[, backup[, bufsize[, mode[, openhook]]]]]]) + + Class FileInput is the implementation of the module; its methods + filename(), lineno(), fileline(), isfirstline(), isstdin(), fileno(), + nextfile() and close() correspond to the functions of the same name + in the module. + In addition it has a readline() method which returns the next + input line, and a __getitem__() method which implements the + sequence behavior. The sequence must be accessed in strictly + sequential order; random access and readline() cannot be mixed. + """ + + def __init__(self, files=None, inplace=0, backup="", bufsize=0, + mode="r", openhook=None): + if isinstance(files, basestring): + files = (files,) + else: + if files is None: + files = sys.argv[1:] + if not files: + files = ('-',) + else: + files = tuple(files) + self._files = files + self._inplace = inplace + self._backup = backup + self._bufsize = bufsize or DEFAULT_BUFSIZE + self._savestdout = None + self._output = None + self._filename = None + self._lineno = 0 + self._filelineno = 0 + self._file = None + self._isstdin = False + self._backupfilename = None + self._buffer = [] + self._bufindex = 0 + # restrict mode argument to reading modes + if mode not in ('r', 'rU', 'U', 'rb'): + raise ValueError("FileInput opening mode must be one of " + "'r', 'rU', 'U' and 'rb'") + self._mode = mode + if inplace and openhook: + raise ValueError("FileInput cannot use an opening hook in inplace mode") + elif openhook and not hasattr(openhook, '__call__'): + raise ValueError("FileInput openhook must be callable") + self._openhook = openhook + + def __del__(self): + self.close() + + def close(self): + self.nextfile() + self._files = () + + def __iter__(self): + return self + + def next(self): + try: + line = self._buffer[self._bufindex] + except IndexError: + pass + else: + self._bufindex += 1 + self._lineno += 1 + self._filelineno += 1 + return line + line = self.readline() + if not line: + raise StopIteration + return line + + def __getitem__(self, i): + if i != self._lineno: + raise RuntimeError, "accessing lines out of order" + try: + return self.next() + except StopIteration: + raise IndexError, "end of input reached" + + def nextfile(self): + savestdout = self._savestdout + self._savestdout = 0 + if savestdout: + sys.stdout = savestdout + + output = self._output + self._output = 0 + if output: + output.close() + + file = self._file + self._file = 0 + if file and not self._isstdin: + file.close() + + backupfilename = self._backupfilename + self._backupfilename = 0 + if backupfilename and not self._backup: + try: os.unlink(backupfilename) + except OSError: pass + + self._isstdin = False + self._buffer = [] + self._bufindex = 0 + + def readline(self): + try: + line = self._buffer[self._bufindex] + except IndexError: + pass + else: + self._bufindex += 1 + self._lineno += 1 + self._filelineno += 1 + return line + if not self._file: + if not self._files: + return "" + self._filename = self._files[0] + self._files = self._files[1:] + self._filelineno = 0 + self._file = None + self._isstdin = False + self._backupfilename = 0 + if self._filename == '-': + self._filename = '' + self._file = sys.stdin + self._isstdin = True + else: + if self._inplace: + self._backupfilename = ( + self._filename + (self._backup or os.extsep+"bak")) + try: os.unlink(self._backupfilename) + except os.error: pass + # The next few lines may raise IOError + os.rename(self._filename, self._backupfilename) + self._file = open(self._backupfilename, self._mode) + try: + perm = os.fstat(self._file.fileno()).st_mode + except OSError: + self._output = open(self._filename, "w") + else: + fd = os.open(self._filename, + os.O_CREAT | os.O_WRONLY | os.O_TRUNC, + perm) + self._output = os.fdopen(fd, "w") + try: + if hasattr(os, 'chmod'): + os.chmod(self._filename, perm) + except OSError: + pass + self._savestdout = sys.stdout + sys.stdout = self._output + else: + # This may raise IOError + if self._openhook: + self._file = self._openhook(self._filename, self._mode) + else: + self._file = open(self._filename, self._mode) + self._buffer = self._file.readlines(self._bufsize) + self._bufindex = 0 + if not self._buffer: + self.nextfile() + # Recursive call + return self.readline() + + def filename(self): + return self._filename + + def lineno(self): + return self._lineno + + def filelineno(self): + return self._filelineno + + def fileno(self): + if self._file: + try: + return self._file.fileno() + except ValueError: + return -1 + else: + return -1 + + def isfirstline(self): + return self._filelineno == 1 + + def isstdin(self): + return self._isstdin + + +def hook_compressed(filename, mode): + ext = os.path.splitext(filename)[1] + if ext == '.gz': + import gzip + return gzip.open(filename, mode) + elif ext == '.bz2': + import bz2 + return bz2.BZ2File(filename, mode) + else: + return open(filename, mode) + + +def hook_encoded(encoding): + import io + def openhook(filename, mode): + mode = mode.replace('U', '').replace('b', '') or 'r' + return io.open(filename, mode, encoding=encoding, newline='') + return openhook + + +def _test(): + import getopt + inplace = 0 + backup = 0 + opts, args = getopt.getopt(sys.argv[1:], "ib:") + for o, a in opts: + if o == '-i': inplace = 1 + if o == '-b': backup = a + for line in input(args, inplace=inplace, backup=backup): + if line[-1:] == '\n': line = line[:-1] + if line[-1:] == '\r': line = line[:-1] + print "%d: %s[%d]%s %s" % (lineno(), filename(), filelineno(), + isfirstline() and "*" or "", line) + print "%d: %s[%d]" % (lineno(), filename(), filelineno()) + +if __name__ == '__main__': + _test() diff --git a/PythonHome/Lib/fileinput.pyc b/PythonHome/Lib/fileinput.pyc deleted file mode 100644 index 7e70114d95fcc598334c3c97dd2da2f833bfb17b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14415 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 rcI5-~vsckf)Sj= _MAXCACHE: + _cache.clear() + _cache[pat] = re.compile(res) + match=_cache[pat].match + if os.path is posixpath: + # normcase on posix is NOP. Optimize it away from the loop. + for name in names: + if match(name): + result.append(name) + else: + for name in names: + if match(os.path.normcase(name)): + result.append(name) + return result + +def fnmatchcase(name, pat): + """Test whether FILENAME matches PATTERN, including case. + + This is a version of fnmatch() which doesn't case-normalize + its arguments. + """ + + if not pat in _cache: + res = translate(pat) + if len(_cache) >= _MAXCACHE: + _cache.clear() + _cache[pat] = re.compile(res) + return _cache[pat].match(name) is not None + +def translate(pat): + """Translate a shell PATTERN to a regular expression. + + There is no way to quote meta-characters. + """ + + i, n = 0, len(pat) + res = '' + while i < n: + c = pat[i] + i = i+1 + if c == '*': + res = res + '.*' + elif c == '?': + res = res + '.' + elif c == '[': + j = i + if j < n and pat[j] == '!': + j = j+1 + if j < n and pat[j] == ']': + j = j+1 + while j < n and pat[j] != ']': + j = j+1 + if j >= n: + res = res + '\\[' + else: + stuff = pat[i:j].replace('\\','\\\\') + i = j+1 + if stuff[0] == '!': + stuff = '^' + stuff[1:] + elif stuff[0] == '^': + stuff = '\\' + stuff + res = '%s[%s]' % (res, stuff) + else: + res = res + re.escape(c) + return res + '\Z(?ms)' diff --git a/PythonHome/Lib/fnmatch.pyc b/PythonHome/Lib/fnmatch.pyc deleted file mode 100644 index e6db6c7f467a1e65900b313b7ee6da57e2a8ef9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3504 zcma)8TW=dh6h6C7oY=WGy(B?JomQ%FqSg<6pimV`D5R3ociKy)+7B*}^XS16Gtjnmhqch)X^`xh4<|iiht?UhsEd$yG(H*PlK=t-lnw%+OGDmvY4SD%BR;f=`+_^(tH zvGD_RiU=S&cIn7vd-u>FdhXCM4UOO&7;(s!c=iZg#yG1pzv0ju+F13hrQzpH^#MG9 zZQljes>0`C0eR(TT0Kgl!y*)n?Zx_5F0;&n_((*+WBRGia9E&ERNTpD2h)DiQwEbU zP}cG@KY$BGaLed}?IArZIFMlIV?GzWoJ;mM>dKqpx)+>!PM$Bo9K4JJT~(w-G)E z-3S-NVeJ0=8BF+NHN3XB892<`n*%67TCH!k6s;NTV7tJ2Y^NI@*yL*#7!AuJXcVjDiq3NAri7KiZN?yHz=R6j?j$*EG%Uy8F zfYBtrbIz1=0cFOWLT?`Rf^#kh7@v=e04zj<0Yd_q2V|W-U|c>a#u+g1H~@1~_#6-d zpEEQ@X-_c05~4)_Bdx_fAVSsxvHO)i_kWMwPDPa0z$ro8l?=v#hn&cSw}Gfu`1uNK z$T^l>-+whMfqtW)B?*ps;8jM+3B_V)_-VC>9xnlPq z9EjG^L<6NyZW4Nr{A#CNRy z7!-nEzQ@mO1-grP1hP)_@gOW==_mmbCxU+r1gj#5{;=TT@{sJ`!?GpH&>zSi{E6_- zw+8|j96rKCZs`xjc`Q(WQCFC2tP|rp3&j z12tG9lc3%iz8dtKE?p?Dt;BJ`d@Ed9T;^l8YnJBMYm5@pM72@87d6nDzjTX70KZ%Z z@5P~q+W_MluL4PMf}+OT8^ZjV;3~8hNK7GhZ6!rmJS_s@XP-#l~jsPTMR=dX(@G?#py1_5&>eB5bBj z;CFP5S4d2VvPkO0{do9=PMT~)Bgg?(+$f2 diff --git a/PythonHome/Lib/formatter.py b/PythonHome/Lib/formatter.py new file mode 100644 index 0000000000..e0a8fe10b2 --- /dev/null +++ b/PythonHome/Lib/formatter.py @@ -0,0 +1,445 @@ +"""Generic output formatting. + +Formatter objects transform an abstract flow of formatting events into +specific output events on writer objects. Formatters manage several stack +structures to allow various properties of a writer object to be changed and +restored; writers need not be able to handle relative changes nor any sort +of ``change back'' operation. Specific writer properties which may be +controlled via formatter objects are horizontal alignment, font, and left +margin indentations. A mechanism is provided which supports providing +arbitrary, non-exclusive style settings to a writer as well. Additional +interfaces facilitate formatting events which are not reversible, such as +paragraph separation. + +Writer objects encapsulate device interfaces. Abstract devices, such as +file formats, are supported as well as physical devices. The provided +implementations all work with abstract devices. The interface makes +available mechanisms for setting the properties which formatter objects +manage and inserting data into the output. +""" + +import sys + + +AS_IS = None + + +class NullFormatter: + """A formatter which does nothing. + + If the writer parameter is omitted, a NullWriter instance is created. + No methods of the writer are called by NullFormatter instances. + + Implementations should inherit from this class if implementing a writer + interface but don't need to inherit any implementation. + + """ + + def __init__(self, writer=None): + if writer is None: + writer = NullWriter() + self.writer = writer + def end_paragraph(self, blankline): pass + def add_line_break(self): pass + def add_hor_rule(self, *args, **kw): pass + def add_label_data(self, format, counter, blankline=None): pass + def add_flowing_data(self, data): pass + def add_literal_data(self, data): pass + def flush_softspace(self): pass + def push_alignment(self, align): pass + def pop_alignment(self): pass + def push_font(self, x): pass + def pop_font(self): pass + def push_margin(self, margin): pass + def pop_margin(self): pass + def set_spacing(self, spacing): pass + def push_style(self, *styles): pass + def pop_style(self, n=1): pass + def assert_line_data(self, flag=1): pass + + +class AbstractFormatter: + """The standard formatter. + + This implementation has demonstrated wide applicability to many writers, + and may be used directly in most circumstances. It has been used to + implement a full-featured World Wide Web browser. + + """ + + # Space handling policy: blank spaces at the boundary between elements + # are handled by the outermost context. "Literal" data is not checked + # to determine context, so spaces in literal data are handled directly + # in all circumstances. + + def __init__(self, writer): + self.writer = writer # Output device + self.align = None # Current alignment + self.align_stack = [] # Alignment stack + self.font_stack = [] # Font state + self.margin_stack = [] # Margin state + self.spacing = None # Vertical spacing state + self.style_stack = [] # Other state, e.g. color + self.nospace = 1 # Should leading space be suppressed + self.softspace = 0 # Should a space be inserted + self.para_end = 1 # Just ended a paragraph + self.parskip = 0 # Skipped space between paragraphs? + self.hard_break = 1 # Have a hard break + self.have_label = 0 + + def end_paragraph(self, blankline): + if not self.hard_break: + self.writer.send_line_break() + self.have_label = 0 + if self.parskip < blankline and not self.have_label: + self.writer.send_paragraph(blankline - self.parskip) + self.parskip = blankline + self.have_label = 0 + self.hard_break = self.nospace = self.para_end = 1 + self.softspace = 0 + + def add_line_break(self): + if not (self.hard_break or self.para_end): + self.writer.send_line_break() + self.have_label = self.parskip = 0 + self.hard_break = self.nospace = 1 + self.softspace = 0 + + def add_hor_rule(self, *args, **kw): + if not self.hard_break: + self.writer.send_line_break() + self.writer.send_hor_rule(*args, **kw) + self.hard_break = self.nospace = 1 + self.have_label = self.para_end = self.softspace = self.parskip = 0 + + def add_label_data(self, format, counter, blankline = None): + if self.have_label or not self.hard_break: + self.writer.send_line_break() + if not self.para_end: + self.writer.send_paragraph((blankline and 1) or 0) + if isinstance(format, str): + self.writer.send_label_data(self.format_counter(format, counter)) + else: + self.writer.send_label_data(format) + self.nospace = self.have_label = self.hard_break = self.para_end = 1 + self.softspace = self.parskip = 0 + + def format_counter(self, format, counter): + label = '' + for c in format: + if c == '1': + label = label + ('%d' % counter) + elif c in 'aA': + if counter > 0: + label = label + self.format_letter(c, counter) + elif c in 'iI': + if counter > 0: + label = label + self.format_roman(c, counter) + else: + label = label + c + return label + + def format_letter(self, case, counter): + label = '' + while counter > 0: + counter, x = divmod(counter-1, 26) + # This makes a strong assumption that lowercase letters + # and uppercase letters form two contiguous blocks, with + # letters in order! + s = chr(ord(case) + x) + label = s + label + return label + + def format_roman(self, case, counter): + ones = ['i', 'x', 'c', 'm'] + fives = ['v', 'l', 'd'] + label, index = '', 0 + # This will die of IndexError when counter is too big + while counter > 0: + counter, x = divmod(counter, 10) + if x == 9: + label = ones[index] + ones[index+1] + label + elif x == 4: + label = ones[index] + fives[index] + label + else: + if x >= 5: + s = fives[index] + x = x-5 + else: + s = '' + s = s + ones[index]*x + label = s + label + index = index + 1 + if case == 'I': + return label.upper() + return label + + def add_flowing_data(self, data): + if not data: return + prespace = data[:1].isspace() + postspace = data[-1:].isspace() + data = " ".join(data.split()) + if self.nospace and not data: + return + elif prespace or self.softspace: + if not data: + if not self.nospace: + self.softspace = 1 + self.parskip = 0 + return + if not self.nospace: + data = ' ' + data + self.hard_break = self.nospace = self.para_end = \ + self.parskip = self.have_label = 0 + self.softspace = postspace + self.writer.send_flowing_data(data) + + def add_literal_data(self, data): + if not data: return + if self.softspace: + self.writer.send_flowing_data(" ") + self.hard_break = data[-1:] == '\n' + self.nospace = self.para_end = self.softspace = \ + self.parskip = self.have_label = 0 + self.writer.send_literal_data(data) + + def flush_softspace(self): + if self.softspace: + self.hard_break = self.para_end = self.parskip = \ + self.have_label = self.softspace = 0 + self.nospace = 1 + self.writer.send_flowing_data(' ') + + def push_alignment(self, align): + if align and align != self.align: + self.writer.new_alignment(align) + self.align = align + self.align_stack.append(align) + else: + self.align_stack.append(self.align) + + def pop_alignment(self): + if self.align_stack: + del self.align_stack[-1] + if self.align_stack: + self.align = align = self.align_stack[-1] + self.writer.new_alignment(align) + else: + self.align = None + self.writer.new_alignment(None) + + def push_font(self, font): + size, i, b, tt = font + if self.softspace: + self.hard_break = self.para_end = self.softspace = 0 + self.nospace = 1 + self.writer.send_flowing_data(' ') + if self.font_stack: + csize, ci, cb, ctt = self.font_stack[-1] + if size is AS_IS: size = csize + if i is AS_IS: i = ci + if b is AS_IS: b = cb + if tt is AS_IS: tt = ctt + font = (size, i, b, tt) + self.font_stack.append(font) + self.writer.new_font(font) + + def pop_font(self): + if self.font_stack: + del self.font_stack[-1] + if self.font_stack: + font = self.font_stack[-1] + else: + font = None + self.writer.new_font(font) + + def push_margin(self, margin): + self.margin_stack.append(margin) + fstack = filter(None, self.margin_stack) + if not margin and fstack: + margin = fstack[-1] + self.writer.new_margin(margin, len(fstack)) + + def pop_margin(self): + if self.margin_stack: + del self.margin_stack[-1] + fstack = filter(None, self.margin_stack) + if fstack: + margin = fstack[-1] + else: + margin = None + self.writer.new_margin(margin, len(fstack)) + + def set_spacing(self, spacing): + self.spacing = spacing + self.writer.new_spacing(spacing) + + def push_style(self, *styles): + if self.softspace: + self.hard_break = self.para_end = self.softspace = 0 + self.nospace = 1 + self.writer.send_flowing_data(' ') + for style in styles: + self.style_stack.append(style) + self.writer.new_styles(tuple(self.style_stack)) + + def pop_style(self, n=1): + del self.style_stack[-n:] + self.writer.new_styles(tuple(self.style_stack)) + + def assert_line_data(self, flag=1): + self.nospace = self.hard_break = not flag + self.para_end = self.parskip = self.have_label = 0 + + +class NullWriter: + """Minimal writer interface to use in testing & inheritance. + + A writer which only provides the interface definition; no actions are + taken on any methods. This should be the base class for all writers + which do not need to inherit any implementation methods. + + """ + def __init__(self): pass + def flush(self): pass + def new_alignment(self, align): pass + def new_font(self, font): pass + def new_margin(self, margin, level): pass + def new_spacing(self, spacing): pass + def new_styles(self, styles): pass + def send_paragraph(self, blankline): pass + def send_line_break(self): pass + def send_hor_rule(self, *args, **kw): pass + def send_label_data(self, data): pass + def send_flowing_data(self, data): pass + def send_literal_data(self, data): pass + + +class AbstractWriter(NullWriter): + """A writer which can be used in debugging formatters, but not much else. + + Each method simply announces itself by printing its name and + arguments on standard output. + + """ + + def new_alignment(self, align): + print "new_alignment(%r)" % (align,) + + def new_font(self, font): + print "new_font(%r)" % (font,) + + def new_margin(self, margin, level): + print "new_margin(%r, %d)" % (margin, level) + + def new_spacing(self, spacing): + print "new_spacing(%r)" % (spacing,) + + def new_styles(self, styles): + print "new_styles(%r)" % (styles,) + + def send_paragraph(self, blankline): + print "send_paragraph(%r)" % (blankline,) + + def send_line_break(self): + print "send_line_break()" + + def send_hor_rule(self, *args, **kw): + print "send_hor_rule()" + + def send_label_data(self, data): + print "send_label_data(%r)" % (data,) + + def send_flowing_data(self, data): + print "send_flowing_data(%r)" % (data,) + + def send_literal_data(self, data): + print "send_literal_data(%r)" % (data,) + + +class DumbWriter(NullWriter): + """Simple writer class which writes output on the file object passed in + as the file parameter or, if file is omitted, on standard output. The + output is simply word-wrapped to the number of columns specified by + the maxcol parameter. This class is suitable for reflowing a sequence + of paragraphs. + + """ + + def __init__(self, file=None, maxcol=72): + self.file = file or sys.stdout + self.maxcol = maxcol + NullWriter.__init__(self) + self.reset() + + def reset(self): + self.col = 0 + self.atbreak = 0 + + def send_paragraph(self, blankline): + self.file.write('\n'*blankline) + self.col = 0 + self.atbreak = 0 + + def send_line_break(self): + self.file.write('\n') + self.col = 0 + self.atbreak = 0 + + def send_hor_rule(self, *args, **kw): + self.file.write('\n') + self.file.write('-'*self.maxcol) + self.file.write('\n') + self.col = 0 + self.atbreak = 0 + + def send_literal_data(self, data): + self.file.write(data) + i = data.rfind('\n') + if i >= 0: + self.col = 0 + data = data[i+1:] + data = data.expandtabs() + self.col = self.col + len(data) + self.atbreak = 0 + + def send_flowing_data(self, data): + if not data: return + atbreak = self.atbreak or data[0].isspace() + col = self.col + maxcol = self.maxcol + write = self.file.write + for word in data.split(): + if atbreak: + if col + len(word) >= maxcol: + write('\n') + col = 0 + else: + write(' ') + col = col + 1 + write(word) + col = col + len(word) + atbreak = 1 + self.col = col + self.atbreak = data[-1].isspace() + + +def test(file = None): + w = DumbWriter() + f = AbstractFormatter(w) + if file is not None: + fp = open(file) + elif sys.argv[1:]: + fp = open(sys.argv[1]) + else: + fp = sys.stdin + for line in fp: + if line == '\n': + f.end_paragraph(1) + else: + f.add_flowing_data(line) + f.end_paragraph(0) + + +if __name__ == '__main__': + test() diff --git a/PythonHome/Lib/formatter.pyc b/PythonHome/Lib/formatter.pyc deleted file mode 100644 index 29813be42d8c1b177aa5fa7064616cc025e36a1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18023 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 diff --git a/PythonHome/Lib/fpformat.py b/PythonHome/Lib/fpformat.py new file mode 100644 index 0000000000..71cbb25f3c --- /dev/null +++ b/PythonHome/Lib/fpformat.py @@ -0,0 +1,145 @@ +"""General floating point formatting functions. + +Functions: +fix(x, digits_behind) +sci(x, digits_behind) + +Each takes a number or a string and a number of digits as arguments. + +Parameters: +x: number to be formatted; or a string resembling a number +digits_behind: number of digits behind the decimal point +""" +from warnings import warnpy3k +warnpy3k("the fpformat module has been removed in Python 3.0", stacklevel=2) +del warnpy3k + +import re + +__all__ = ["fix","sci","NotANumber"] + +# Compiled regular expression to "decode" a number +decoder = re.compile(r'^([-+]?)0*(\d*)((?:\.\d*)?)(([eE][-+]?\d+)?)$') +# \0 the whole thing +# \1 leading sign or empty +# \2 digits left of decimal point +# \3 fraction (empty or begins with point) +# \4 exponent part (empty or begins with 'e' or 'E') + +try: + class NotANumber(ValueError): + pass +except TypeError: + NotANumber = 'fpformat.NotANumber' + +def extract(s): + """Return (sign, intpart, fraction, expo) or raise an exception: + sign is '+' or '-' + intpart is 0 or more digits beginning with a nonzero + fraction is 0 or more digits + expo is an integer""" + res = decoder.match(s) + if res is None: raise NotANumber, s + sign, intpart, fraction, exppart = res.group(1,2,3,4) + if sign == '+': sign = '' + if fraction: fraction = fraction[1:] + if exppart: expo = int(exppart[1:]) + else: expo = 0 + return sign, intpart, fraction, expo + +def unexpo(intpart, fraction, expo): + """Remove the exponent by changing intpart and fraction.""" + if expo > 0: # Move the point left + f = len(fraction) + intpart, fraction = intpart + fraction[:expo], fraction[expo:] + if expo > f: + intpart = intpart + '0'*(expo-f) + elif expo < 0: # Move the point right + i = len(intpart) + intpart, fraction = intpart[:expo], intpart[expo:] + fraction + if expo < -i: + fraction = '0'*(-expo-i) + fraction + return intpart, fraction + +def roundfrac(intpart, fraction, digs): + """Round or extend the fraction to size digs.""" + f = len(fraction) + if f <= digs: + return intpart, fraction + '0'*(digs-f) + i = len(intpart) + if i+digs < 0: + return '0'*-digs, '' + total = intpart + fraction + nextdigit = total[i+digs] + if nextdigit >= '5': # Hard case: increment last digit, may have carry! + n = i + digs - 1 + while n >= 0: + if total[n] != '9': break + n = n-1 + else: + total = '0' + total + i = i+1 + n = 0 + total = total[:n] + chr(ord(total[n]) + 1) + '0'*(len(total)-n-1) + intpart, fraction = total[:i], total[i:] + if digs >= 0: + return intpart, fraction[:digs] + else: + return intpart[:digs] + '0'*-digs, '' + +def fix(x, digs): + """Format x as [-]ddd.ddd with 'digs' digits after the point + and at least one digit before. + If digs <= 0, the point is suppressed.""" + if type(x) != type(''): x = repr(x) + try: + sign, intpart, fraction, expo = extract(x) + except NotANumber: + return x + intpart, fraction = unexpo(intpart, fraction, expo) + intpart, fraction = roundfrac(intpart, fraction, digs) + while intpart and intpart[0] == '0': intpart = intpart[1:] + if intpart == '': intpart = '0' + if digs > 0: return sign + intpart + '.' + fraction + else: return sign + intpart + +def sci(x, digs): + """Format x as [-]d.dddE[+-]ddd with 'digs' digits after the point + and exactly one digit before. + If digs is <= 0, one digit is kept and the point is suppressed.""" + if type(x) != type(''): x = repr(x) + sign, intpart, fraction, expo = extract(x) + if not intpart: + while fraction and fraction[0] == '0': + fraction = fraction[1:] + expo = expo - 1 + if fraction: + intpart, fraction = fraction[0], fraction[1:] + expo = expo - 1 + else: + intpart = '0' + else: + expo = expo + len(intpart) - 1 + intpart, fraction = intpart[0], intpart[1:] + fraction + digs = max(0, digs) + intpart, fraction = roundfrac(intpart, fraction, digs) + if len(intpart) > 1: + intpart, fraction, expo = \ + intpart[0], intpart[1:] + fraction[:-1], \ + expo + len(intpart) - 1 + s = sign + intpart + if digs > 0: s = s + '.' + fraction + e = repr(abs(expo)) + e = '0'*(3-len(e)) + e + if expo < 0: e = '-' + e + else: e = '+' + e + return s + 'e' + e + +def test(): + """Interactive test run.""" + try: + while 1: + x, digs = input('Enter (x, digs): ') + print x, fix(x, digs), sci(x, digs) + except (EOFError, KeyboardInterrupt): + pass diff --git a/PythonHome/Lib/fpformat.pyc b/PythonHome/Lib/fpformat.pyc deleted file mode 100644 index 046091a736044e7bc089bdab2df89ec8c05dd066..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4551 zcmb7HUvC@75uZI$lt}%xteBD!)C;MHC_2)_v4)=<-alf-^F9Ugb0cDAQgokbrf|y+Ve;mkHP|lMGD90g;HuC?@%dG zr$Boc7^iT8!ZID%xFrtpe1W+4Wr*@T(^0p#+-^3;j zI=a8)VYa>c`D2N@82DRPGPko0V2Hs14S17#&5KZ5*28C=ORD zwi&&ox3U#9k98Kbjn#pU``ts6>Lf+mW+^Wk#NoMtR&G@XP*0EgT@z=#`oka%x+XKJ z-K-2Y_4!|JGfVWL8E)Q$?_5|UHP&j>^O<_ zoAr&X!uOE{&34B;Go8r8>vmRvgq!6bjuoZtB>UmEIMA+R_~*6#_0`9BRyJVh~ex;Lso4x z+%XyrrzNT^>=lUm!H=WEgW-wmy%WEP-f!?Qn=2{Ha2t)E9ihn^8OOuXbq|mIBSc2@ zMA36ZfTB}05D*j8o}hG@;0pBr!lRhD{|RDEg3!g?iy|Eq>C~gs0-d5UM$Zv~W7PI2 z{g`o&A)Z*I)Uw3f8_?sfF-m_&873ek(aS5BC@yi(q5(6{v2u}~m#9@l_>_6Ce}nK% z)=y(yv(Zt!hC9uAL7J`URvJjmtZ6goB`XZWG>EJL(9zR0Jr1bN3L}_j>d5Nl)n!&& zUSF2(+!T*&aDO*R0YM2i;OHodW5)3(QFhFMlf<8zG?9tJrC&Bv6nIBGh^=4|b7azp zuR$;uG2|k?y^Q--aTR!Hv0W=cW_(!)gd{X6yhQ|(XdY)gVLOS9+`IH2rAfahz{MIh zo+SpYbRiIB3Ljl8=7$yB4fiht*eg3!w0YlW=zBTv@<|!H{|zi^7a^!LtEOm5-GnTw z5>4Z|s!FQKhvh@?_V3}bUqCQq6t#hopE44GG6sX-4sDF;s{6m;os!^Fz`+wfXK*4V zIJhh>RH5+nbBcF|Mu~OUsKYk!B5$w}aEae;LZ6l_-P;JxJm zk$e{W7KAVSB8=`axKn=md)npQjkzU2HQd4_ z4RK%UKRw_QY=8Z67>0E`F5fKky)6%uQP4s`CYW)B5$7~1=Q7-`5*!XVW<`*?zBw6k$zR7nnJ~3G_HA2_EWsK9W>*(ldgm)bvvSHK<4) z@~?C24G5RIc<#Wz!JTs~F0$HX`0^PXDEi5AT|>o1npFk$I=E{L@L5z#1ZW|>OwpVY zAaQ_<)Wde`?4J4+7m!SxkWK>H6v zZMN&tYDbX?g_cNHJxX9GJOg6M$q;5&py>K)475P#*7MoR5Vp zIu0{J#7vx=WEE=6yf?-NReAWr)+?}%2|Kk(zW+Z#d_6okIJWjzB~bpKATa|JDxH%{ zVgxba!sINJ(A7p2DUrr}?Y`PB4<7k!@o(Y?QtC-8t^1?;%t)!`e-q>WEfx|@BR=m2 z0|_X2k|;Q|j?|Y~@l|o<&+zC9#HA6&MxWrZ--U1ywg`G&651}Q*VMFE_7?Cyi+G#& zuBjUsnW8Ido(UXfT}3r{=8(qkp=}>QoV-JW?=X=&{${Fml^Z^P9gRB#zwcr%e|hk< z. + +"""Rational, infinite-precision, real numbers.""" + +from __future__ import division +from decimal import Decimal +import math +import numbers +import operator +import re + +__all__ = ['Fraction', 'gcd'] + +Rational = numbers.Rational + + +def gcd(a, b): + """Calculate the Greatest Common Divisor of a and b. + + Unless b==0, the result will have the same sign as b (so that when + b is divided by it, the result comes out positive). + """ + while b: + a, b = b, a%b + return a + + +_RATIONAL_FORMAT = re.compile(r""" + \A\s* # optional whitespace at the start, then + (?P[-+]?) # an optional sign, then + (?=\d|\.\d) # lookahead for digit or .digit + (?P\d*) # numerator (possibly empty) + (?: # followed by + (?:/(?P\d+))? # an optional denominator + | # or + (?:\.(?P\d*))? # an optional fractional part + (?:E(?P[-+]?\d+))? # and optional exponent + ) + \s*\Z # and optional whitespace to finish +""", re.VERBOSE | re.IGNORECASE) + + +class Fraction(Rational): + """This class implements rational numbers. + + In the two-argument form of the constructor, Fraction(8, 6) will + produce a rational number equivalent to 4/3. Both arguments must + be Rational. The numerator defaults to 0 and the denominator + defaults to 1 so that Fraction(3) == 3 and Fraction() == 0. + + Fractions can also be constructed from: + + - numeric strings similar to those accepted by the + float constructor (for example, '-2.3' or '1e10') + + - strings of the form '123/456' + + - float and Decimal instances + + - other Rational instances (including integers) + + """ + + __slots__ = ('_numerator', '_denominator') + + # We're immutable, so use __new__ not __init__ + def __new__(cls, numerator=0, denominator=None): + """Constructs a Fraction. + + Takes a string like '3/2' or '1.5', another Rational instance, a + numerator/denominator pair, or a float. + + Examples + -------- + + >>> Fraction(10, -8) + Fraction(-5, 4) + >>> Fraction(Fraction(1, 7), 5) + Fraction(1, 35) + >>> Fraction(Fraction(1, 7), Fraction(2, 3)) + Fraction(3, 14) + >>> Fraction('314') + Fraction(314, 1) + >>> Fraction('-35/4') + Fraction(-35, 4) + >>> Fraction('3.1415') # conversion from numeric string + Fraction(6283, 2000) + >>> Fraction('-47e-2') # string may include a decimal exponent + Fraction(-47, 100) + >>> Fraction(1.47) # direct construction from float (exact conversion) + Fraction(6620291452234629, 4503599627370496) + >>> Fraction(2.25) + Fraction(9, 4) + >>> Fraction(Decimal('1.47')) + Fraction(147, 100) + + """ + self = super(Fraction, cls).__new__(cls) + + if denominator is None: + if isinstance(numerator, Rational): + self._numerator = numerator.numerator + self._denominator = numerator.denominator + return self + + elif isinstance(numerator, float): + # Exact conversion from float + value = Fraction.from_float(numerator) + self._numerator = value._numerator + self._denominator = value._denominator + return self + + elif isinstance(numerator, Decimal): + value = Fraction.from_decimal(numerator) + self._numerator = value._numerator + self._denominator = value._denominator + return self + + elif isinstance(numerator, basestring): + # Handle construction from strings. + m = _RATIONAL_FORMAT.match(numerator) + if m is None: + raise ValueError('Invalid literal for Fraction: %r' % + numerator) + numerator = int(m.group('num') or '0') + denom = m.group('denom') + if denom: + denominator = int(denom) + else: + denominator = 1 + decimal = m.group('decimal') + if decimal: + scale = 10**len(decimal) + numerator = numerator * scale + int(decimal) + denominator *= scale + exp = m.group('exp') + if exp: + exp = int(exp) + if exp >= 0: + numerator *= 10**exp + else: + denominator *= 10**-exp + if m.group('sign') == '-': + numerator = -numerator + + else: + raise TypeError("argument should be a string " + "or a Rational instance") + + elif (isinstance(numerator, Rational) and + isinstance(denominator, Rational)): + numerator, denominator = ( + numerator.numerator * denominator.denominator, + denominator.numerator * numerator.denominator + ) + else: + raise TypeError("both arguments should be " + "Rational instances") + + if denominator == 0: + raise ZeroDivisionError('Fraction(%s, 0)' % numerator) + g = gcd(numerator, denominator) + self._numerator = numerator // g + self._denominator = denominator // g + return self + + @classmethod + def from_float(cls, f): + """Converts a finite float to a rational number, exactly. + + Beware that Fraction.from_float(0.3) != Fraction(3, 10). + + """ + if isinstance(f, numbers.Integral): + return cls(f) + elif not isinstance(f, float): + raise TypeError("%s.from_float() only takes floats, not %r (%s)" % + (cls.__name__, f, type(f).__name__)) + if math.isnan(f) or math.isinf(f): + raise TypeError("Cannot convert %r to %s." % (f, cls.__name__)) + return cls(*f.as_integer_ratio()) + + @classmethod + def from_decimal(cls, dec): + """Converts a finite Decimal instance to a rational number, exactly.""" + from decimal import Decimal + if isinstance(dec, numbers.Integral): + dec = Decimal(int(dec)) + elif not isinstance(dec, Decimal): + raise TypeError( + "%s.from_decimal() only takes Decimals, not %r (%s)" % + (cls.__name__, dec, type(dec).__name__)) + if not dec.is_finite(): + # Catches infinities and nans. + raise TypeError("Cannot convert %s to %s." % (dec, cls.__name__)) + sign, digits, exp = dec.as_tuple() + digits = int(''.join(map(str, digits))) + if sign: + digits = -digits + if exp >= 0: + return cls(digits * 10 ** exp) + else: + return cls(digits, 10 ** -exp) + + def limit_denominator(self, max_denominator=1000000): + """Closest Fraction to self with denominator at most max_denominator. + + >>> Fraction('3.141592653589793').limit_denominator(10) + Fraction(22, 7) + >>> Fraction('3.141592653589793').limit_denominator(100) + Fraction(311, 99) + >>> Fraction(4321, 8765).limit_denominator(10000) + Fraction(4321, 8765) + + """ + # Algorithm notes: For any real number x, define a *best upper + # approximation* to x to be a rational number p/q such that: + # + # (1) p/q >= x, and + # (2) if p/q > r/s >= x then s > q, for any rational r/s. + # + # Define *best lower approximation* similarly. Then it can be + # proved that a rational number is a best upper or lower + # approximation to x if, and only if, it is a convergent or + # semiconvergent of the (unique shortest) continued fraction + # associated to x. + # + # To find a best rational approximation with denominator <= M, + # we find the best upper and lower approximations with + # denominator <= M and take whichever of these is closer to x. + # In the event of a tie, the bound with smaller denominator is + # chosen. If both denominators are equal (which can happen + # only when max_denominator == 1 and self is midway between + # two integers) the lower bound---i.e., the floor of self, is + # taken. + + if max_denominator < 1: + raise ValueError("max_denominator should be at least 1") + if self._denominator <= max_denominator: + return Fraction(self) + + p0, q0, p1, q1 = 0, 1, 1, 0 + n, d = self._numerator, self._denominator + while True: + a = n//d + q2 = q0+a*q1 + if q2 > max_denominator: + break + p0, q0, p1, q1 = p1, q1, p0+a*p1, q2 + n, d = d, n-a*d + + k = (max_denominator-q0)//q1 + bound1 = Fraction(p0+k*p1, q0+k*q1) + bound2 = Fraction(p1, q1) + if abs(bound2 - self) <= abs(bound1-self): + return bound2 + else: + return bound1 + + @property + def numerator(a): + return a._numerator + + @property + def denominator(a): + return a._denominator + + def __repr__(self): + """repr(self)""" + return ('Fraction(%s, %s)' % (self._numerator, self._denominator)) + + def __str__(self): + """str(self)""" + if self._denominator == 1: + return str(self._numerator) + else: + return '%s/%s' % (self._numerator, self._denominator) + + def _operator_fallbacks(monomorphic_operator, fallback_operator): + """Generates forward and reverse operators given a purely-rational + operator and a function from the operator module. + + Use this like: + __op__, __rop__ = _operator_fallbacks(just_rational_op, operator.op) + + In general, we want to implement the arithmetic operations so + that mixed-mode operations either call an implementation whose + author knew about the types of both arguments, or convert both + to the nearest built in type and do the operation there. In + Fraction, that means that we define __add__ and __radd__ as: + + def __add__(self, other): + # Both types have numerators/denominator attributes, + # so do the operation directly + if isinstance(other, (int, long, Fraction)): + return Fraction(self.numerator * other.denominator + + other.numerator * self.denominator, + self.denominator * other.denominator) + # float and complex don't have those operations, but we + # know about those types, so special case them. + elif isinstance(other, float): + return float(self) + other + elif isinstance(other, complex): + return complex(self) + other + # Let the other type take over. + return NotImplemented + + def __radd__(self, other): + # radd handles more types than add because there's + # nothing left to fall back to. + if isinstance(other, Rational): + return Fraction(self.numerator * other.denominator + + other.numerator * self.denominator, + self.denominator * other.denominator) + elif isinstance(other, Real): + return float(other) + float(self) + elif isinstance(other, Complex): + return complex(other) + complex(self) + return NotImplemented + + + There are 5 different cases for a mixed-type addition on + Fraction. I'll refer to all of the above code that doesn't + refer to Fraction, float, or complex as "boilerplate". 'r' + will be an instance of Fraction, which is a subtype of + Rational (r : Fraction <: Rational), and b : B <: + Complex. The first three involve 'r + b': + + 1. If B <: Fraction, int, float, or complex, we handle + that specially, and all is well. + 2. If Fraction falls back to the boilerplate code, and it + were to return a value from __add__, we'd miss the + possibility that B defines a more intelligent __radd__, + so the boilerplate should return NotImplemented from + __add__. In particular, we don't handle Rational + here, even though we could get an exact answer, in case + the other type wants to do something special. + 3. If B <: Fraction, Python tries B.__radd__ before + Fraction.__add__. This is ok, because it was + implemented with knowledge of Fraction, so it can + handle those instances before delegating to Real or + Complex. + + The next two situations describe 'b + r'. We assume that b + didn't know about Fraction in its implementation, and that it + uses similar boilerplate code: + + 4. If B <: Rational, then __radd_ converts both to the + builtin rational type (hey look, that's us) and + proceeds. + 5. Otherwise, __radd__ tries to find the nearest common + base ABC, and fall back to its builtin type. Since this + class doesn't subclass a concrete type, there's no + implementation to fall back to, so we need to try as + hard as possible to return an actual value, or the user + will get a TypeError. + + """ + def forward(a, b): + if isinstance(b, (int, long, Fraction)): + return monomorphic_operator(a, b) + elif isinstance(b, float): + return fallback_operator(float(a), b) + elif isinstance(b, complex): + return fallback_operator(complex(a), b) + else: + return NotImplemented + forward.__name__ = '__' + fallback_operator.__name__ + '__' + forward.__doc__ = monomorphic_operator.__doc__ + + def reverse(b, a): + if isinstance(a, Rational): + # Includes ints. + return monomorphic_operator(a, b) + elif isinstance(a, numbers.Real): + return fallback_operator(float(a), float(b)) + elif isinstance(a, numbers.Complex): + return fallback_operator(complex(a), complex(b)) + else: + return NotImplemented + reverse.__name__ = '__r' + fallback_operator.__name__ + '__' + reverse.__doc__ = monomorphic_operator.__doc__ + + return forward, reverse + + def _add(a, b): + """a + b""" + return Fraction(a.numerator * b.denominator + + b.numerator * a.denominator, + a.denominator * b.denominator) + + __add__, __radd__ = _operator_fallbacks(_add, operator.add) + + def _sub(a, b): + """a - b""" + return Fraction(a.numerator * b.denominator - + b.numerator * a.denominator, + a.denominator * b.denominator) + + __sub__, __rsub__ = _operator_fallbacks(_sub, operator.sub) + + def _mul(a, b): + """a * b""" + return Fraction(a.numerator * b.numerator, a.denominator * b.denominator) + + __mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul) + + def _div(a, b): + """a / b""" + return Fraction(a.numerator * b.denominator, + a.denominator * b.numerator) + + __truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv) + __div__, __rdiv__ = _operator_fallbacks(_div, operator.div) + + def __floordiv__(a, b): + """a // b""" + # Will be math.floor(a / b) in 3.0. + div = a / b + if isinstance(div, Rational): + # trunc(math.floor(div)) doesn't work if the rational is + # more precise than a float because the intermediate + # rounding may cross an integer boundary. + return div.numerator // div.denominator + else: + return math.floor(div) + + def __rfloordiv__(b, a): + """a // b""" + # Will be math.floor(a / b) in 3.0. + div = a / b + if isinstance(div, Rational): + # trunc(math.floor(div)) doesn't work if the rational is + # more precise than a float because the intermediate + # rounding may cross an integer boundary. + return div.numerator // div.denominator + else: + return math.floor(div) + + def __mod__(a, b): + """a % b""" + div = a // b + return a - b * div + + def __rmod__(b, a): + """a % b""" + div = a // b + return a - b * div + + def __pow__(a, b): + """a ** b + + If b is not an integer, the result will be a float or complex + since roots are generally irrational. If b is an integer, the + result will be rational. + + """ + if isinstance(b, Rational): + if b.denominator == 1: + power = b.numerator + if power >= 0: + return Fraction(a._numerator ** power, + a._denominator ** power) + else: + return Fraction(a._denominator ** -power, + a._numerator ** -power) + else: + # A fractional power will generally produce an + # irrational number. + return float(a) ** float(b) + else: + return float(a) ** b + + def __rpow__(b, a): + """a ** b""" + if b._denominator == 1 and b._numerator >= 0: + # If a is an int, keep it that way if possible. + return a ** b._numerator + + if isinstance(a, Rational): + return Fraction(a.numerator, a.denominator) ** b + + if b._denominator == 1: + return a ** b._numerator + + return a ** float(b) + + def __pos__(a): + """+a: Coerces a subclass instance to Fraction""" + return Fraction(a._numerator, a._denominator) + + def __neg__(a): + """-a""" + return Fraction(-a._numerator, a._denominator) + + def __abs__(a): + """abs(a)""" + return Fraction(abs(a._numerator), a._denominator) + + def __trunc__(a): + """trunc(a)""" + if a._numerator < 0: + return -(-a._numerator // a._denominator) + else: + return a._numerator // a._denominator + + def __hash__(self): + """hash(self) + + Tricky because values that are exactly representable as a + float must have the same hash as that float. + + """ + # XXX since this method is expensive, consider caching the result + if self._denominator == 1: + # Get integers right. + return hash(self._numerator) + # Expensive check, but definitely correct. + if self == float(self): + return hash(float(self)) + else: + # Use tuple's hash to avoid a high collision rate on + # simple fractions. + return hash((self._numerator, self._denominator)) + + def __eq__(a, b): + """a == b""" + if isinstance(b, Rational): + return (a._numerator == b.numerator and + a._denominator == b.denominator) + if isinstance(b, numbers.Complex) and b.imag == 0: + b = b.real + if isinstance(b, float): + if math.isnan(b) or math.isinf(b): + # comparisons with an infinity or nan should behave in + # the same way for any finite a, so treat a as zero. + return 0.0 == b + else: + return a == a.from_float(b) + else: + # Since a doesn't know how to compare with b, let's give b + # a chance to compare itself with a. + return NotImplemented + + def _richcmp(self, other, op): + """Helper for comparison operators, for internal use only. + + Implement comparison between a Rational instance `self`, and + either another Rational instance or a float `other`. If + `other` is not a Rational instance or a float, return + NotImplemented. `op` should be one of the six standard + comparison operators. + + """ + # convert other to a Rational instance where reasonable. + if isinstance(other, Rational): + return op(self._numerator * other.denominator, + self._denominator * other.numerator) + # comparisons with complex should raise a TypeError, for consistency + # with int<->complex, float<->complex, and complex<->complex comparisons. + if isinstance(other, complex): + raise TypeError("no ordering relation is defined for complex numbers") + if isinstance(other, float): + if math.isnan(other) or math.isinf(other): + return op(0.0, other) + else: + return op(self, self.from_float(other)) + else: + return NotImplemented + + def __lt__(a, b): + """a < b""" + return a._richcmp(b, operator.lt) + + def __gt__(a, b): + """a > b""" + return a._richcmp(b, operator.gt) + + def __le__(a, b): + """a <= b""" + return a._richcmp(b, operator.le) + + def __ge__(a, b): + """a >= b""" + return a._richcmp(b, operator.ge) + + def __nonzero__(a): + """a != 0""" + return a._numerator != 0 + + # support for pickling, copy, and deepcopy + + def __reduce__(self): + return (self.__class__, (str(self),)) + + def __copy__(self): + if type(self) == Fraction: + return self # I'm immutable; therefore I am my own clone + return self.__class__(self._numerator, self._denominator) + + def __deepcopy__(self, memo): + if type(self) == Fraction: + return self # My components are also immutable + return self.__class__(self._numerator, self._denominator) diff --git a/PythonHome/Lib/fractions.pyc b/PythonHome/Lib/fractions.pyc deleted file mode 100644 index 0b31d4bd129f3917718195db445ea34d9847ed28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19148 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 diff --git a/PythonHome/Lib/ftplib.py b/PythonHome/Lib/ftplib.py new file mode 100644 index 0000000000..c98290ce85 --- /dev/null +++ b/PythonHome/Lib/ftplib.py @@ -0,0 +1,1061 @@ +"""An FTP client class and some helper functions. + +Based on RFC 959: File Transfer Protocol (FTP), by J. Postel and J. Reynolds + +Example: + +>>> from ftplib import FTP +>>> ftp = FTP('ftp.python.org') # connect to host, default port +>>> ftp.login() # default, i.e.: user anonymous, passwd anonymous@ +'230 Guest login ok, access restrictions apply.' +>>> ftp.retrlines('LIST') # list directory contents +total 9 +drwxr-xr-x 8 root wheel 1024 Jan 3 1994 . +drwxr-xr-x 8 root wheel 1024 Jan 3 1994 .. +drwxr-xr-x 2 root wheel 1024 Jan 3 1994 bin +drwxr-xr-x 2 root wheel 1024 Jan 3 1994 etc +d-wxrwxr-x 2 ftp wheel 1024 Sep 5 13:43 incoming +drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib +drwxr-xr-x 6 1094 wheel 1024 Sep 13 19:07 pub +drwxr-xr-x 3 root wheel 1024 Jan 3 1994 usr +-rw-r--r-- 1 root root 312 Aug 1 1994 welcome.msg +'226 Transfer complete.' +>>> ftp.quit() +'221 Goodbye.' +>>> + +A nice test that reveals some of the network dialogue would be: +python ftplib.py -d localhost -l -p -l +""" + +# +# Changes and improvements suggested by Steve Majewski. +# Modified by Jack to work on the mac. +# Modified by Siebren to support docstrings and PASV. +# Modified by Phil Schwartz to add storbinary and storlines callbacks. +# Modified by Giampaolo Rodola' to add TLS support. +# + +import os +import sys + +# Import SOCKS module if it exists, else standard socket module socket +try: + import SOCKS; socket = SOCKS; del SOCKS # import SOCKS as socket + from socket import getfqdn; socket.getfqdn = getfqdn; del getfqdn +except ImportError: + import socket +from socket import _GLOBAL_DEFAULT_TIMEOUT + +__all__ = ["FTP","Netrc"] + +# Magic number from +MSG_OOB = 0x1 # Process data out of band + + +# The standard FTP server control port +FTP_PORT = 21 +# The sizehint parameter passed to readline() calls +MAXLINE = 8192 + + +# Exception raised when an error or invalid response is received +class Error(Exception): pass +class error_reply(Error): pass # unexpected [123]xx reply +class error_temp(Error): pass # 4xx errors +class error_perm(Error): pass # 5xx errors +class error_proto(Error): pass # response does not begin with [1-5] + + +# All exceptions (hopefully) that may be raised here and that aren't +# (always) programming errors on our side +all_errors = (Error, IOError, EOFError) + + +# Line terminators (we always output CRLF, but accept any of CRLF, CR, LF) +CRLF = '\r\n' + +# The class itself +class FTP: + + '''An FTP client class. + + To create a connection, call the class using these arguments: + host, user, passwd, acct, timeout + + The first four arguments are all strings, and have default value ''. + timeout must be numeric and defaults to None if not passed, + meaning that no timeout will be set on any ftp socket(s) + If a timeout is passed, then this is now the default timeout for all ftp + socket operations for this instance. + + Then use self.connect() with optional host and port argument. + + To download a file, use ftp.retrlines('RETR ' + filename), + or ftp.retrbinary() with slightly different arguments. + To upload a file, use ftp.storlines() or ftp.storbinary(), + which have an open file as argument (see their definitions + below for details). + The download/upload functions first issue appropriate TYPE + and PORT or PASV commands. +''' + + debugging = 0 + host = '' + port = FTP_PORT + maxline = MAXLINE + sock = None + file = None + welcome = None + passiveserver = 1 + + # Initialization method (called by class instantiation). + # Initialize host to localhost, port to standard ftp port + # Optional arguments are host (for connect()), + # and user, passwd, acct (for login()) + def __init__(self, host='', user='', passwd='', acct='', + timeout=_GLOBAL_DEFAULT_TIMEOUT): + self.timeout = timeout + if host: + self.connect(host) + if user: + self.login(user, passwd, acct) + + def connect(self, host='', port=0, timeout=-999): + '''Connect to host. Arguments are: + - host: hostname to connect to (string, default previous host) + - port: port to connect to (integer, default previous port) + ''' + if host != '': + self.host = host + if port > 0: + self.port = port + if timeout != -999: + self.timeout = timeout + self.sock = socket.create_connection((self.host, self.port), self.timeout) + self.af = self.sock.family + self.file = self.sock.makefile('rb') + self.welcome = self.getresp() + return self.welcome + + def getwelcome(self): + '''Get the welcome message from the server. + (this is read and squirreled away by connect())''' + if self.debugging: + print '*welcome*', self.sanitize(self.welcome) + return self.welcome + + def set_debuglevel(self, level): + '''Set the debugging level. + The required argument level means: + 0: no debugging output (default) + 1: print commands and responses but not body text etc. + 2: also print raw lines read and sent before stripping CR/LF''' + self.debugging = level + debug = set_debuglevel + + def set_pasv(self, val): + '''Use passive or active mode for data transfers. + With a false argument, use the normal PORT mode, + With a true argument, use the PASV command.''' + self.passiveserver = val + + # Internal: "sanitize" a string for printing + def sanitize(self, s): + if s[:5] == 'pass ' or s[:5] == 'PASS ': + i = len(s) + while i > 5 and s[i-1] in '\r\n': + i = i-1 + s = s[:5] + '*'*(i-5) + s[i:] + return repr(s) + + # Internal: send one line to the server, appending CRLF + def putline(self, line): + line = line + CRLF + if self.debugging > 1: print '*put*', self.sanitize(line) + self.sock.sendall(line) + + # Internal: send one command to the server (through putline()) + def putcmd(self, line): + if self.debugging: print '*cmd*', self.sanitize(line) + self.putline(line) + + # Internal: return one line from the server, stripping CRLF. + # Raise EOFError if the connection is closed + def getline(self): + line = self.file.readline(self.maxline + 1) + if len(line) > self.maxline: + raise Error("got more than %d bytes" % self.maxline) + if self.debugging > 1: + print '*get*', self.sanitize(line) + if not line: raise EOFError + if line[-2:] == CRLF: line = line[:-2] + elif line[-1:] in CRLF: line = line[:-1] + return line + + # Internal: get a response from the server, which may possibly + # consist of multiple lines. Return a single string with no + # trailing CRLF. If the response consists of multiple lines, + # these are separated by '\n' characters in the string + def getmultiline(self): + line = self.getline() + if line[3:4] == '-': + code = line[:3] + while 1: + nextline = self.getline() + line = line + ('\n' + nextline) + if nextline[:3] == code and \ + nextline[3:4] != '-': + break + return line + + # Internal: get a response from the server. + # Raise various errors if the response indicates an error + def getresp(self): + resp = self.getmultiline() + if self.debugging: print '*resp*', self.sanitize(resp) + self.lastresp = resp[:3] + c = resp[:1] + if c in ('1', '2', '3'): + return resp + if c == '4': + raise error_temp, resp + if c == '5': + raise error_perm, resp + raise error_proto, resp + + def voidresp(self): + """Expect a response beginning with '2'.""" + resp = self.getresp() + if resp[:1] != '2': + raise error_reply, resp + return resp + + def abort(self): + '''Abort a file transfer. Uses out-of-band data. + This does not follow the procedure from the RFC to send Telnet + IP and Synch; that doesn't seem to work with the servers I've + tried. Instead, just send the ABOR command as OOB data.''' + line = 'ABOR' + CRLF + if self.debugging > 1: print '*put urgent*', self.sanitize(line) + self.sock.sendall(line, MSG_OOB) + resp = self.getmultiline() + if resp[:3] not in ('426', '225', '226'): + raise error_proto, resp + + def sendcmd(self, cmd): + '''Send a command and return the response.''' + self.putcmd(cmd) + return self.getresp() + + def voidcmd(self, cmd): + """Send a command and expect a response beginning with '2'.""" + self.putcmd(cmd) + return self.voidresp() + + def sendport(self, host, port): + '''Send a PORT command with the current host and the given + port number. + ''' + hbytes = host.split('.') + pbytes = [repr(port//256), repr(port%256)] + bytes = hbytes + pbytes + cmd = 'PORT ' + ','.join(bytes) + return self.voidcmd(cmd) + + def sendeprt(self, host, port): + '''Send a EPRT command with the current host and the given port number.''' + af = 0 + if self.af == socket.AF_INET: + af = 1 + if self.af == socket.AF_INET6: + af = 2 + if af == 0: + raise error_proto, 'unsupported address family' + fields = ['', repr(af), host, repr(port), ''] + cmd = 'EPRT ' + '|'.join(fields) + return self.voidcmd(cmd) + + def makeport(self): + '''Create a new socket and send a PORT command for it.''' + err = None + sock = None + for res in socket.getaddrinfo(None, 0, self.af, socket.SOCK_STREAM, 0, socket.AI_PASSIVE): + af, socktype, proto, canonname, sa = res + try: + sock = socket.socket(af, socktype, proto) + sock.bind(sa) + except socket.error, err: + if sock: + sock.close() + sock = None + continue + break + if sock is None: + if err is not None: + raise err + else: + raise socket.error("getaddrinfo returns an empty list") + sock.listen(1) + port = sock.getsockname()[1] # Get proper port + host = self.sock.getsockname()[0] # Get proper host + if self.af == socket.AF_INET: + resp = self.sendport(host, port) + else: + resp = self.sendeprt(host, port) + if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT: + sock.settimeout(self.timeout) + return sock + + def makepasv(self): + if self.af == socket.AF_INET: + host, port = parse227(self.sendcmd('PASV')) + else: + host, port = parse229(self.sendcmd('EPSV'), self.sock.getpeername()) + return host, port + + def ntransfercmd(self, cmd, rest=None): + """Initiate a transfer over the data connection. + + If the transfer is active, send a port command and the + transfer command, and accept the connection. If the server is + passive, send a pasv command, connect to it, and start the + transfer command. Either way, return the socket for the + connection and the expected size of the transfer. The + expected size may be None if it could not be determined. + + Optional `rest' argument can be a string that is sent as the + argument to a REST command. This is essentially a server + marker used to tell the server to skip over any data up to the + given marker. + """ + size = None + if self.passiveserver: + host, port = self.makepasv() + conn = socket.create_connection((host, port), self.timeout) + try: + if rest is not None: + self.sendcmd("REST %s" % rest) + resp = self.sendcmd(cmd) + # Some servers apparently send a 200 reply to + # a LIST or STOR command, before the 150 reply + # (and way before the 226 reply). This seems to + # be in violation of the protocol (which only allows + # 1xx or error messages for LIST), so we just discard + # this response. + if resp[0] == '2': + resp = self.getresp() + if resp[0] != '1': + raise error_reply, resp + except: + conn.close() + raise + else: + sock = self.makeport() + try: + if rest is not None: + self.sendcmd("REST %s" % rest) + resp = self.sendcmd(cmd) + # See above. + if resp[0] == '2': + resp = self.getresp() + if resp[0] != '1': + raise error_reply, resp + conn, sockaddr = sock.accept() + if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT: + conn.settimeout(self.timeout) + finally: + sock.close() + if resp[:3] == '150': + # this is conditional in case we received a 125 + size = parse150(resp) + return conn, size + + def transfercmd(self, cmd, rest=None): + """Like ntransfercmd() but returns only the socket.""" + return self.ntransfercmd(cmd, rest)[0] + + def login(self, user = '', passwd = '', acct = ''): + '''Login, default anonymous.''' + if not user: user = 'anonymous' + if not passwd: passwd = '' + if not acct: acct = '' + if user == 'anonymous' and passwd in ('', '-'): + # If there is no anonymous ftp password specified + # then we'll just use anonymous@ + # We don't send any other thing because: + # - We want to remain anonymous + # - We want to stop SPAM + # - We don't want to let ftp sites to discriminate by the user, + # host or country. + passwd = passwd + 'anonymous@' + resp = self.sendcmd('USER ' + user) + if resp[0] == '3': resp = self.sendcmd('PASS ' + passwd) + if resp[0] == '3': resp = self.sendcmd('ACCT ' + acct) + if resp[0] != '2': + raise error_reply, resp + return resp + + def retrbinary(self, cmd, callback, blocksize=8192, rest=None): + """Retrieve data in binary mode. A new port is created for you. + + Args: + cmd: A RETR command. + callback: A single parameter callable to be called on each + block of data read. + blocksize: The maximum number of bytes to read from the + socket at one time. [default: 8192] + rest: Passed to transfercmd(). [default: None] + + Returns: + The response code. + """ + self.voidcmd('TYPE I') + conn = self.transfercmd(cmd, rest) + while 1: + data = conn.recv(blocksize) + if not data: + break + callback(data) + conn.close() + return self.voidresp() + + def retrlines(self, cmd, callback = None): + """Retrieve data in line mode. A new port is created for you. + + Args: + cmd: A RETR, LIST, NLST, or MLSD command. + callback: An optional single parameter callable that is called + for each line with the trailing CRLF stripped. + [default: print_line()] + + Returns: + The response code. + """ + if callback is None: callback = print_line + resp = self.sendcmd('TYPE A') + conn = self.transfercmd(cmd) + fp = conn.makefile('rb') + while 1: + line = fp.readline(self.maxline + 1) + if len(line) > self.maxline: + raise Error("got more than %d bytes" % self.maxline) + if self.debugging > 2: print '*retr*', repr(line) + if not line: + break + if line[-2:] == CRLF: + line = line[:-2] + elif line[-1:] == '\n': + line = line[:-1] + callback(line) + fp.close() + conn.close() + return self.voidresp() + + def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None): + """Store a file in binary mode. A new port is created for you. + + Args: + cmd: A STOR command. + fp: A file-like object with a read(num_bytes) method. + blocksize: The maximum data size to read from fp and send over + the connection at once. [default: 8192] + callback: An optional single parameter callable that is called on + each block of data after it is sent. [default: None] + rest: Passed to transfercmd(). [default: None] + + Returns: + The response code. + """ + self.voidcmd('TYPE I') + conn = self.transfercmd(cmd, rest) + while 1: + buf = fp.read(blocksize) + if not buf: break + conn.sendall(buf) + if callback: callback(buf) + conn.close() + return self.voidresp() + + def storlines(self, cmd, fp, callback=None): + """Store a file in line mode. A new port is created for you. + + Args: + cmd: A STOR command. + fp: A file-like object with a readline() method. + callback: An optional single parameter callable that is called on + each line after it is sent. [default: None] + + Returns: + The response code. + """ + self.voidcmd('TYPE A') + conn = self.transfercmd(cmd) + while 1: + buf = fp.readline(self.maxline + 1) + if len(buf) > self.maxline: + raise Error("got more than %d bytes" % self.maxline) + if not buf: break + if buf[-2:] != CRLF: + if buf[-1] in CRLF: buf = buf[:-1] + buf = buf + CRLF + conn.sendall(buf) + if callback: callback(buf) + conn.close() + return self.voidresp() + + def acct(self, password): + '''Send new account name.''' + cmd = 'ACCT ' + password + return self.voidcmd(cmd) + + def nlst(self, *args): + '''Return a list of files in a given directory (default the current).''' + cmd = 'NLST' + for arg in args: + cmd = cmd + (' ' + arg) + files = [] + self.retrlines(cmd, files.append) + return files + + def dir(self, *args): + '''List a directory in long form. + By default list current directory to stdout. + Optional last argument is callback function; all + non-empty arguments before it are concatenated to the + LIST command. (This *should* only be used for a pathname.)''' + cmd = 'LIST' + func = None + if args[-1:] and type(args[-1]) != type(''): + args, func = args[:-1], args[-1] + for arg in args: + if arg: + cmd = cmd + (' ' + arg) + self.retrlines(cmd, func) + + def rename(self, fromname, toname): + '''Rename a file.''' + resp = self.sendcmd('RNFR ' + fromname) + if resp[0] != '3': + raise error_reply, resp + return self.voidcmd('RNTO ' + toname) + + def delete(self, filename): + '''Delete a file.''' + resp = self.sendcmd('DELE ' + filename) + if resp[:3] in ('250', '200'): + return resp + else: + raise error_reply, resp + + def cwd(self, dirname): + '''Change to a directory.''' + if dirname == '..': + try: + return self.voidcmd('CDUP') + except error_perm, msg: + if msg.args[0][:3] != '500': + raise + elif dirname == '': + dirname = '.' # does nothing, but could return error + cmd = 'CWD ' + dirname + return self.voidcmd(cmd) + + def size(self, filename): + '''Retrieve the size of a file.''' + # The SIZE command is defined in RFC-3659 + resp = self.sendcmd('SIZE ' + filename) + if resp[:3] == '213': + s = resp[3:].strip() + try: + return int(s) + except (OverflowError, ValueError): + return long(s) + + def mkd(self, dirname): + '''Make a directory, return its full pathname.''' + resp = self.sendcmd('MKD ' + dirname) + return parse257(resp) + + def rmd(self, dirname): + '''Remove a directory.''' + return self.voidcmd('RMD ' + dirname) + + def pwd(self): + '''Return current working directory.''' + resp = self.sendcmd('PWD') + return parse257(resp) + + def quit(self): + '''Quit, and close the connection.''' + resp = self.voidcmd('QUIT') + self.close() + return resp + + def close(self): + '''Close the connection without assuming anything about it.''' + if self.file is not None: + self.file.close() + if self.sock is not None: + self.sock.close() + self.file = self.sock = None + +try: + import ssl +except ImportError: + pass +else: + class FTP_TLS(FTP): + '''A FTP subclass which adds TLS support to FTP as described + in RFC-4217. + + Connect as usual to port 21 implicitly securing the FTP control + connection before authenticating. + + Securing the data connection requires user to explicitly ask + for it by calling prot_p() method. + + Usage example: + >>> from ftplib import FTP_TLS + >>> ftps = FTP_TLS('ftp.python.org') + >>> ftps.login() # login anonymously previously securing control channel + '230 Guest login ok, access restrictions apply.' + >>> ftps.prot_p() # switch to secure data connection + '200 Protection level set to P' + >>> ftps.retrlines('LIST') # list directory content securely + total 9 + drwxr-xr-x 8 root wheel 1024 Jan 3 1994 . + drwxr-xr-x 8 root wheel 1024 Jan 3 1994 .. + drwxr-xr-x 2 root wheel 1024 Jan 3 1994 bin + drwxr-xr-x 2 root wheel 1024 Jan 3 1994 etc + d-wxrwxr-x 2 ftp wheel 1024 Sep 5 13:43 incoming + drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib + drwxr-xr-x 6 1094 wheel 1024 Sep 13 19:07 pub + drwxr-xr-x 3 root wheel 1024 Jan 3 1994 usr + -rw-r--r-- 1 root root 312 Aug 1 1994 welcome.msg + '226 Transfer complete.' + >>> ftps.quit() + '221 Goodbye.' + >>> + ''' + ssl_version = ssl.PROTOCOL_TLSv1 + + def __init__(self, host='', user='', passwd='', acct='', keyfile=None, + certfile=None, timeout=_GLOBAL_DEFAULT_TIMEOUT): + self.keyfile = keyfile + self.certfile = certfile + self._prot_p = False + FTP.__init__(self, host, user, passwd, acct, timeout) + + def login(self, user='', passwd='', acct='', secure=True): + if secure and not isinstance(self.sock, ssl.SSLSocket): + self.auth() + return FTP.login(self, user, passwd, acct) + + def auth(self): + '''Set up secure control connection by using TLS/SSL.''' + if isinstance(self.sock, ssl.SSLSocket): + raise ValueError("Already using TLS") + if self.ssl_version == ssl.PROTOCOL_TLSv1: + resp = self.voidcmd('AUTH TLS') + else: + resp = self.voidcmd('AUTH SSL') + self.sock = ssl.wrap_socket(self.sock, self.keyfile, self.certfile, + ssl_version=self.ssl_version) + self.file = self.sock.makefile(mode='rb') + return resp + + def prot_p(self): + '''Set up secure data connection.''' + # PROT defines whether or not the data channel is to be protected. + # Though RFC-2228 defines four possible protection levels, + # RFC-4217 only recommends two, Clear and Private. + # Clear (PROT C) means that no security is to be used on the + # data-channel, Private (PROT P) means that the data-channel + # should be protected by TLS. + # PBSZ command MUST still be issued, but must have a parameter of + # '0' to indicate that no buffering is taking place and the data + # connection should not be encapsulated. + self.voidcmd('PBSZ 0') + resp = self.voidcmd('PROT P') + self._prot_p = True + return resp + + def prot_c(self): + '''Set up clear text data connection.''' + resp = self.voidcmd('PROT C') + self._prot_p = False + return resp + + # --- Overridden FTP methods + + def ntransfercmd(self, cmd, rest=None): + conn, size = FTP.ntransfercmd(self, cmd, rest) + if self._prot_p: + conn = ssl.wrap_socket(conn, self.keyfile, self.certfile, + ssl_version=self.ssl_version) + return conn, size + + def retrbinary(self, cmd, callback, blocksize=8192, rest=None): + self.voidcmd('TYPE I') + conn = self.transfercmd(cmd, rest) + try: + while 1: + data = conn.recv(blocksize) + if not data: + break + callback(data) + # shutdown ssl layer + if isinstance(conn, ssl.SSLSocket): + conn.unwrap() + finally: + conn.close() + return self.voidresp() + + def retrlines(self, cmd, callback = None): + if callback is None: callback = print_line + resp = self.sendcmd('TYPE A') + conn = self.transfercmd(cmd) + fp = conn.makefile('rb') + try: + while 1: + line = fp.readline(self.maxline + 1) + if len(line) > self.maxline: + raise Error("got more than %d bytes" % self.maxline) + if self.debugging > 2: print '*retr*', repr(line) + if not line: + break + if line[-2:] == CRLF: + line = line[:-2] + elif line[-1:] == '\n': + line = line[:-1] + callback(line) + # shutdown ssl layer + if isinstance(conn, ssl.SSLSocket): + conn.unwrap() + finally: + fp.close() + conn.close() + return self.voidresp() + + def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None): + self.voidcmd('TYPE I') + conn = self.transfercmd(cmd, rest) + try: + while 1: + buf = fp.read(blocksize) + if not buf: break + conn.sendall(buf) + if callback: callback(buf) + # shutdown ssl layer + if isinstance(conn, ssl.SSLSocket): + conn.unwrap() + finally: + conn.close() + return self.voidresp() + + def storlines(self, cmd, fp, callback=None): + self.voidcmd('TYPE A') + conn = self.transfercmd(cmd) + try: + while 1: + buf = fp.readline(self.maxline + 1) + if len(buf) > self.maxline: + raise Error("got more than %d bytes" % self.maxline) + if not buf: break + if buf[-2:] != CRLF: + if buf[-1] in CRLF: buf = buf[:-1] + buf = buf + CRLF + conn.sendall(buf) + if callback: callback(buf) + # shutdown ssl layer + if isinstance(conn, ssl.SSLSocket): + conn.unwrap() + finally: + conn.close() + return self.voidresp() + + __all__.append('FTP_TLS') + all_errors = (Error, IOError, EOFError, ssl.SSLError) + + +_150_re = None + +def parse150(resp): + '''Parse the '150' response for a RETR request. + Returns the expected transfer size or None; size is not guaranteed to + be present in the 150 message. + ''' + if resp[:3] != '150': + raise error_reply, resp + global _150_re + if _150_re is None: + import re + _150_re = re.compile("150 .* \((\d+) bytes\)", re.IGNORECASE) + m = _150_re.match(resp) + if not m: + return None + s = m.group(1) + try: + return int(s) + except (OverflowError, ValueError): + return long(s) + + +_227_re = None + +def parse227(resp): + '''Parse the '227' response for a PASV request. + Raises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)' + Return ('host.addr.as.numbers', port#) tuple.''' + + if resp[:3] != '227': + raise error_reply, resp + global _227_re + if _227_re is None: + import re + _227_re = re.compile(r'(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)') + m = _227_re.search(resp) + if not m: + raise error_proto, resp + numbers = m.groups() + host = '.'.join(numbers[:4]) + port = (int(numbers[4]) << 8) + int(numbers[5]) + return host, port + + +def parse229(resp, peer): + '''Parse the '229' response for a EPSV request. + Raises error_proto if it does not contain '(|||port|)' + Return ('host.addr.as.numbers', port#) tuple.''' + + if resp[:3] != '229': + raise error_reply, resp + left = resp.find('(') + if left < 0: raise error_proto, resp + right = resp.find(')', left + 1) + if right < 0: + raise error_proto, resp # should contain '(|||port|)' + if resp[left + 1] != resp[right - 1]: + raise error_proto, resp + parts = resp[left + 1:right].split(resp[left+1]) + if len(parts) != 5: + raise error_proto, resp + host = peer[0] + port = int(parts[3]) + return host, port + + +def parse257(resp): + '''Parse the '257' response for a MKD or PWD request. + This is a response to a MKD or PWD request: a directory name. + Returns the directoryname in the 257 reply.''' + + if resp[:3] != '257': + raise error_reply, resp + if resp[3:5] != ' "': + return '' # Not compliant to RFC 959, but UNIX ftpd does this + dirname = '' + i = 5 + n = len(resp) + while i < n: + c = resp[i] + i = i+1 + if c == '"': + if i >= n or resp[i] != '"': + break + i = i+1 + dirname = dirname + c + return dirname + + +def print_line(line): + '''Default retrlines callback to print a line.''' + print line + + +def ftpcp(source, sourcename, target, targetname = '', type = 'I'): + '''Copy file from one FTP-instance to another.''' + if not targetname: targetname = sourcename + type = 'TYPE ' + type + source.voidcmd(type) + target.voidcmd(type) + sourcehost, sourceport = parse227(source.sendcmd('PASV')) + target.sendport(sourcehost, sourceport) + # RFC 959: the user must "listen" [...] BEFORE sending the + # transfer request. + # So: STOR before RETR, because here the target is a "user". + treply = target.sendcmd('STOR ' + targetname) + if treply[:3] not in ('125', '150'): raise error_proto # RFC 959 + sreply = source.sendcmd('RETR ' + sourcename) + if sreply[:3] not in ('125', '150'): raise error_proto # RFC 959 + source.voidresp() + target.voidresp() + + +class Netrc: + """Class to parse & provide access to 'netrc' format files. + + See the netrc(4) man page for information on the file format. + + WARNING: This class is obsolete -- use module netrc instead. + + """ + __defuser = None + __defpasswd = None + __defacct = None + + def __init__(self, filename=None): + if filename is None: + if "HOME" in os.environ: + filename = os.path.join(os.environ["HOME"], + ".netrc") + else: + raise IOError, \ + "specify file to load or set $HOME" + self.__hosts = {} + self.__macros = {} + fp = open(filename, "r") + in_macro = 0 + while 1: + line = fp.readline(self.maxline + 1) + if len(line) > self.maxline: + raise Error("got more than %d bytes" % self.maxline) + if not line: break + if in_macro and line.strip(): + macro_lines.append(line) + continue + elif in_macro: + self.__macros[macro_name] = tuple(macro_lines) + in_macro = 0 + words = line.split() + host = user = passwd = acct = None + default = 0 + i = 0 + while i < len(words): + w1 = words[i] + if i+1 < len(words): + w2 = words[i + 1] + else: + w2 = None + if w1 == 'default': + default = 1 + elif w1 == 'machine' and w2: + host = w2.lower() + i = i + 1 + elif w1 == 'login' and w2: + user = w2 + i = i + 1 + elif w1 == 'password' and w2: + passwd = w2 + i = i + 1 + elif w1 == 'account' and w2: + acct = w2 + i = i + 1 + elif w1 == 'macdef' and w2: + macro_name = w2 + macro_lines = [] + in_macro = 1 + break + i = i + 1 + if default: + self.__defuser = user or self.__defuser + self.__defpasswd = passwd or self.__defpasswd + self.__defacct = acct or self.__defacct + if host: + if host in self.__hosts: + ouser, opasswd, oacct = \ + self.__hosts[host] + user = user or ouser + passwd = passwd or opasswd + acct = acct or oacct + self.__hosts[host] = user, passwd, acct + fp.close() + + def get_hosts(self): + """Return a list of hosts mentioned in the .netrc file.""" + return self.__hosts.keys() + + def get_account(self, host): + """Returns login information for the named host. + + The return value is a triple containing userid, + password, and the accounting field. + + """ + host = host.lower() + user = passwd = acct = None + if host in self.__hosts: + user, passwd, acct = self.__hosts[host] + user = user or self.__defuser + passwd = passwd or self.__defpasswd + acct = acct or self.__defacct + return user, passwd, acct + + def get_macros(self): + """Return a list of all defined macro names.""" + return self.__macros.keys() + + def get_macro(self, macro): + """Return a sequence of lines which define a named macro.""" + return self.__macros[macro] + + + +def test(): + '''Test program. + Usage: ftp [-d] [-r[file]] host [-l[dir]] [-d[dir]] [-p] [file] ... + + -d dir + -l list + -p password + ''' + + if len(sys.argv) < 2: + print test.__doc__ + sys.exit(0) + + debugging = 0 + rcfile = None + while sys.argv[1] == '-d': + debugging = debugging+1 + del sys.argv[1] + if sys.argv[1][:2] == '-r': + # get name of alternate ~/.netrc file: + rcfile = sys.argv[1][2:] + del sys.argv[1] + host = sys.argv[1] + ftp = FTP(host) + ftp.set_debuglevel(debugging) + userid = passwd = acct = '' + try: + netrc = Netrc(rcfile) + except IOError: + if rcfile is not None: + sys.stderr.write("Could not open account file" + " -- using anonymous login.") + else: + try: + userid, passwd, acct = netrc.get_account(host) + except KeyError: + # no account for host + sys.stderr.write( + "No account -- using anonymous login.") + ftp.login(userid, passwd, acct) + for file in sys.argv[2:]: + if file[:2] == '-l': + ftp.dir(file[2:]) + elif file[:2] == '-d': + cmd = 'CWD' + if file[2:]: cmd = cmd + ' ' + file[2:] + resp = ftp.sendcmd(cmd) + elif file == '-p': + ftp.set_pasv(not ftp.passiveserver) + else: + ftp.retrbinary('RETR ' + file, \ + sys.stdout.write, 1024) + ftp.quit() + + +if __name__ == '__main__': + test() diff --git a/PythonHome/Lib/ftplib.pyc b/PythonHome/Lib/ftplib.pyc deleted file mode 100644 index b68200ee3cf1a7213a7765eaf16c5552b8f382ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33147 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 UJ-d2#_jC +# Copyright (C) 2006 Python Software Foundation. +# See C source code for _functools credits/copyright + +from _functools import partial, reduce + +# update_wrapper() and wraps() are tools to help write +# wrapper functions that can handle naive introspection + +WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__') +WRAPPER_UPDATES = ('__dict__',) +def update_wrapper(wrapper, + wrapped, + assigned = WRAPPER_ASSIGNMENTS, + updated = WRAPPER_UPDATES): + """Update a wrapper function to look like the wrapped function + + wrapper is the function to be updated + wrapped is the original function + assigned is a tuple naming the attributes assigned directly + from the wrapped function to the wrapper function (defaults to + functools.WRAPPER_ASSIGNMENTS) + updated is a tuple naming the attributes of the wrapper that + are updated with the corresponding attribute from the wrapped + function (defaults to functools.WRAPPER_UPDATES) + """ + for attr in assigned: + setattr(wrapper, attr, getattr(wrapped, attr)) + for attr in updated: + getattr(wrapper, attr).update(getattr(wrapped, attr, {})) + # Return the wrapper so this can be used as a decorator via partial() + return wrapper + +def wraps(wrapped, + assigned = WRAPPER_ASSIGNMENTS, + updated = WRAPPER_UPDATES): + """Decorator factory to apply update_wrapper() to a wrapper function + + Returns a decorator that invokes update_wrapper() with the decorated + function as the wrapper argument and the arguments to wraps() as the + remaining arguments. Default arguments are as for update_wrapper(). + This is a convenience function to simplify applying partial() to + update_wrapper(). + """ + return partial(update_wrapper, wrapped=wrapped, + assigned=assigned, updated=updated) + +def total_ordering(cls): + """Class decorator that fills in missing ordering methods""" + convert = { + '__lt__': [('__gt__', lambda self, other: not (self < other or self == other)), + ('__le__', lambda self, other: self < other or self == other), + ('__ge__', lambda self, other: not self < other)], + '__le__': [('__ge__', lambda self, other: not self <= other or self == other), + ('__lt__', lambda self, other: self <= other and not self == other), + ('__gt__', lambda self, other: not self <= other)], + '__gt__': [('__lt__', lambda self, other: not (self > other or self == other)), + ('__ge__', lambda self, other: self > other or self == other), + ('__le__', lambda self, other: not self > other)], + '__ge__': [('__le__', lambda self, other: (not self >= other) or self == other), + ('__gt__', lambda self, other: self >= other and not self == other), + ('__lt__', lambda self, other: not self >= other)] + } + roots = set(dir(cls)) & set(convert) + if not roots: + raise ValueError('must define at least one ordering operation: < > <= >=') + root = max(roots) # prefer __lt__ to __le__ to __gt__ to __ge__ + for opname, opfunc in convert[root]: + if opname not in roots: + opfunc.__name__ = opname + opfunc.__doc__ = getattr(int, opname).__doc__ + setattr(cls, opname, opfunc) + return cls + +def cmp_to_key(mycmp): + """Convert a cmp= function into a key= function""" + class K(object): + __slots__ = ['obj'] + def __init__(self, obj, *args): + self.obj = obj + def __lt__(self, other): + return mycmp(self.obj, other.obj) < 0 + def __gt__(self, other): + return mycmp(self.obj, other.obj) > 0 + def __eq__(self, other): + return mycmp(self.obj, other.obj) == 0 + def __le__(self, other): + return mycmp(self.obj, other.obj) <= 0 + def __ge__(self, other): + return mycmp(self.obj, other.obj) >= 0 + def __ne__(self, other): + return mycmp(self.obj, other.obj) != 0 + def __hash__(self): + raise TypeError('hash not implemented') + return K diff --git a/PythonHome/Lib/functools.pyc b/PythonHome/Lib/functools.pyc index 118bab5ab1239ae6a4b8feddc20ac287ff885d9e..6c64a1bc9b444ccca1c94fff76cb7adfa7e38422 100644 GIT binary patch delta 1532 zcmX@Ex7&1s1dE{^0|SGrRZMzjNk(Z>On82Uo>#EHUr>N^jDKlKL1{^hOKMVSdQ3oN zNk)F2M}BVVW_1>8CNi`YvfX85WS;EL5lFh`$?G|+fqGwaxRasRk+Xm-U1F23amoU1 z{le)%o_=9#VAvJ|F+(yFkN{!k$t7H5nl||%mp^&#m>kM21oTG+H@P-n1?zvoOL*T^lfah)w1ZtR_R} zG{F`!bZH8aqic^)7a4Yi3X@~k3$k?W5t5iZS)_&xSAt@|L^PKSof||G$j~J(_J9ms M>p8?HtBNZD0Nwot)Bpeg delta 652 zcmdmOdR%XV1Pi|m0|SGzRZKu-Nk)F2k@;p%7HcL9!L4j}87KeY zOlLO_Hk}$Eb2)`4>++gl)xUxlySa9J5OY1S>Usc`6`jn%Z;Vw%6F+uyB?NAwtKY07 zc$g7gaI%hs#AH3;N(}KE!YvqLy&{-mPNH2H>i&vis@o)nDV8oi1w*fnL^Foi1BnC- Nu|mlQ7-CIQmH?!hx6A+l diff --git a/PythonHome/Lib/genericpath.py b/PythonHome/Lib/genericpath.py new file mode 100644 index 0000000000..7ddb94c08b --- /dev/null +++ b/PythonHome/Lib/genericpath.py @@ -0,0 +1,105 @@ +""" +Path operations common to more than one OS +Do not use directly. The OS specific modules import the appropriate +functions from this module themselves. +""" +import os +import stat + +__all__ = ['commonprefix', 'exists', 'getatime', 'getctime', 'getmtime', + 'getsize', 'isdir', 'isfile'] + + +# Does a path exist? +# This is false for dangling symbolic links on systems that support them. +def exists(path): + """Test whether a path exists. Returns False for broken symbolic links""" + try: + os.stat(path) + except os.error: + return False + return True + + +# This follows symbolic links, so both islink() and isdir() can be true +# for the same path on systems that support symlinks +def isfile(path): + """Test whether a path is a regular file""" + try: + st = os.stat(path) + except os.error: + return False + return stat.S_ISREG(st.st_mode) + + +# Is a path a directory? +# This follows symbolic links, so both islink() and isdir() +# can be true for the same path on systems that support symlinks +def isdir(s): + """Return true if the pathname refers to an existing directory.""" + try: + st = os.stat(s) + except os.error: + return False + return stat.S_ISDIR(st.st_mode) + + +def getsize(filename): + """Return the size of a file, reported by os.stat().""" + return os.stat(filename).st_size + + +def getmtime(filename): + """Return the last modification time of a file, reported by os.stat().""" + return os.stat(filename).st_mtime + + +def getatime(filename): + """Return the last access time of a file, reported by os.stat().""" + return os.stat(filename).st_atime + + +def getctime(filename): + """Return the metadata change time of a file, reported by os.stat().""" + return os.stat(filename).st_ctime + + +# Return the longest prefix of all list elements. +def commonprefix(m): + "Given a list of pathnames, returns the longest common leading component" + if not m: return '' + s1 = min(m) + s2 = max(m) + for i, c in enumerate(s1): + if c != s2[i]: + return s1[:i] + return s1 + +# Split a path in root and extension. +# The extension is everything starting at the last dot in the last +# pathname component; the root is everything before that. +# It is always true that root + ext == p. + +# Generic implementation of splitext, to be parametrized with +# the separators +def _splitext(p, sep, altsep, extsep): + """Split the extension from a pathname. + + Extension is everything from the last dot to the end, ignoring + leading dots. Returns "(root, ext)"; ext may be empty.""" + + sepIndex = p.rfind(sep) + if altsep: + altsepIndex = p.rfind(altsep) + sepIndex = max(sepIndex, altsepIndex) + + dotIndex = p.rfind(extsep) + if dotIndex > sepIndex: + # skip all leading dots + filenameIndex = sepIndex + 1 + while filenameIndex < dotIndex: + if p[filenameIndex] != extsep: + return p[:dotIndex], p[dotIndex:] + filenameIndex += 1 + + return p, '' diff --git a/PythonHome/Lib/genericpath.pyc b/PythonHome/Lib/genericpath.pyc index 8cad3dcebc00365a6167d6ef57739af99219af82..311bf12b231f1115ae802391189b3914cd8df960 100644 GIT binary patch delta 577 zcmeB`d?>wPI+LLT0|SGrRZMzjNk(Z>On82Uo>#EHUr>N^jDKlKL1{^hOKMVSdQ3oN zNk)F2M}BVVWC0G5$-9`Ikg4+^^Jg-3UT4`rrp{HYo5|GKz_yl5odN6{N!PhqfWwxN YbZww0*<8RWMow%_. +# +# Gerrit Holl moved the string-based exceptions +# to class-based exceptions. +# +# Peter Astrand added gnu_getopt(). +# +# TODO for gnu_getopt(): +# +# - GNU getopt_long_only mechanism +# - allow the caller to specify ordering +# - RETURN_IN_ORDER option +# - GNU extension with '-' as first character of option string +# - optional arguments, specified by double colons +# - a option string with a W followed by semicolon should +# treat "-W foo" as "--foo" + +__all__ = ["GetoptError","error","getopt","gnu_getopt"] + +import os + +class GetoptError(Exception): + opt = '' + msg = '' + def __init__(self, msg, opt=''): + self.msg = msg + self.opt = opt + Exception.__init__(self, msg, opt) + + def __str__(self): + return self.msg + +error = GetoptError # backward compatibility + +def getopt(args, shortopts, longopts = []): + """getopt(args, options[, long_options]) -> opts, args + + Parses command line options and parameter list. args is the + argument list to be parsed, without the leading reference to the + running program. Typically, this means "sys.argv[1:]". shortopts + is the string of option letters that the script wants to + recognize, with options that require an argument followed by a + colon (i.e., the same format that Unix getopt() uses). If + specified, longopts is a list of strings with the names of the + long options which should be supported. The leading '--' + characters should not be included in the option name. Options + which require an argument should be followed by an equal sign + ('='). + + The return value consists of two elements: the first is a list of + (option, value) pairs; the second is the list of program arguments + left after the option list was stripped (this is a trailing slice + of the first argument). Each option-and-value pair returned has + the option as its first element, prefixed with a hyphen (e.g., + '-x'), and the option argument as its second element, or an empty + string if the option has no argument. The options occur in the + list in the same order in which they were found, thus allowing + multiple occurrences. Long and short options may be mixed. + + """ + + opts = [] + if type(longopts) == type(""): + longopts = [longopts] + else: + longopts = list(longopts) + while args and args[0].startswith('-') and args[0] != '-': + if args[0] == '--': + args = args[1:] + break + if args[0].startswith('--'): + opts, args = do_longs(opts, args[0][2:], longopts, args[1:]) + else: + opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:]) + + return opts, args + +def gnu_getopt(args, shortopts, longopts = []): + """getopt(args, options[, long_options]) -> opts, args + + This function works like getopt(), except that GNU style scanning + mode is used by default. This means that option and non-option + arguments may be intermixed. The getopt() function stops + processing options as soon as a non-option argument is + encountered. + + If the first character of the option string is `+', or if the + environment variable POSIXLY_CORRECT is set, then option + processing stops as soon as a non-option argument is encountered. + + """ + + opts = [] + prog_args = [] + if isinstance(longopts, str): + longopts = [longopts] + else: + longopts = list(longopts) + + # Allow options after non-option arguments? + if shortopts.startswith('+'): + shortopts = shortopts[1:] + all_options_first = True + elif os.environ.get("POSIXLY_CORRECT"): + all_options_first = True + else: + all_options_first = False + + while args: + if args[0] == '--': + prog_args += args[1:] + break + + if args[0][:2] == '--': + opts, args = do_longs(opts, args[0][2:], longopts, args[1:]) + elif args[0][:1] == '-' and args[0] != '-': + opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:]) + else: + if all_options_first: + prog_args += args + break + else: + prog_args.append(args[0]) + args = args[1:] + + return opts, prog_args + +def do_longs(opts, opt, longopts, args): + try: + i = opt.index('=') + except ValueError: + optarg = None + else: + opt, optarg = opt[:i], opt[i+1:] + + has_arg, opt = long_has_args(opt, longopts) + if has_arg: + if optarg is None: + if not args: + raise GetoptError('option --%s requires argument' % opt, opt) + optarg, args = args[0], args[1:] + elif optarg is not None: + raise GetoptError('option --%s must not have an argument' % opt, opt) + opts.append(('--' + opt, optarg or '')) + return opts, args + +# Return: +# has_arg? +# full option name +def long_has_args(opt, longopts): + possibilities = [o for o in longopts if o.startswith(opt)] + if not possibilities: + raise GetoptError('option --%s not recognized' % opt, opt) + # Is there an exact match? + if opt in possibilities: + return False, opt + elif opt + '=' in possibilities: + return True, opt + # No exact match, so better be unique. + if len(possibilities) > 1: + # XXX since possibilities contains all valid continuations, might be + # nice to work them into the error msg + raise GetoptError('option --%s not a unique prefix' % opt, opt) + assert len(possibilities) == 1 + unique_match = possibilities[0] + has_arg = unique_match.endswith('=') + if has_arg: + unique_match = unique_match[:-1] + return has_arg, unique_match + +def do_shorts(opts, optstring, shortopts, args): + while optstring != '': + opt, optstring = optstring[0], optstring[1:] + if short_has_arg(opt, shortopts): + if optstring == '': + if not args: + raise GetoptError('option -%s requires argument' % opt, + opt) + optstring, args = args[0], args[1:] + optarg, optstring = optstring, '' + else: + optarg = '' + opts.append(('-' + opt, optarg)) + return opts, args + +def short_has_arg(opt, shortopts): + for i in range(len(shortopts)): + if opt == shortopts[i] != ':': + return shortopts.startswith(':', i+1) + raise GetoptError('option -%s not recognized' % opt, opt) + +if __name__ == '__main__': + import sys + print getopt(sys.argv[1:], "a:b", ["alpha=", "beta"]) diff --git a/PythonHome/Lib/getopt.pyc b/PythonHome/Lib/getopt.pyc deleted file mode 100644 index 24607cd840b00997e3b62e30ff00e570e98f4707..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6604 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 diff --git a/PythonHome/Lib/getpass.py b/PythonHome/Lib/getpass.py new file mode 100644 index 0000000000..2ac6fd7f38 --- /dev/null +++ b/PythonHome/Lib/getpass.py @@ -0,0 +1,179 @@ +"""Utilities to get a password and/or the current user name. + +getpass(prompt[, stream]) - Prompt for a password, with echo turned off. +getuser() - Get the user name from the environment or password database. + +GetPassWarning - This UserWarning is issued when getpass() cannot prevent + echoing of the password contents while reading. + +On Windows, the msvcrt module will be used. +On the Mac EasyDialogs.AskPassword is used, if available. + +""" + +# Authors: Piers Lauder (original) +# Guido van Rossum (Windows support and cleanup) +# Gregory P. Smith (tty support & GetPassWarning) + +import os, sys, warnings + +__all__ = ["getpass","getuser","GetPassWarning"] + + +class GetPassWarning(UserWarning): pass + + +def unix_getpass(prompt='Password: ', stream=None): + """Prompt for a password, with echo turned off. + + Args: + prompt: Written on stream to ask for the input. Default: 'Password: ' + stream: A writable file object to display the prompt. Defaults to + the tty. If no tty is available defaults to sys.stderr. + Returns: + The seKr3t input. + Raises: + EOFError: If our input tty or stdin was closed. + GetPassWarning: When we were unable to turn echo off on the input. + + Always restores terminal settings before returning. + """ + fd = None + tty = None + try: + # Always try reading and writing directly on the tty first. + fd = os.open('/dev/tty', os.O_RDWR|os.O_NOCTTY) + tty = os.fdopen(fd, 'w+', 1) + input = tty + if not stream: + stream = tty + except EnvironmentError, e: + # If that fails, see if stdin can be controlled. + try: + fd = sys.stdin.fileno() + except (AttributeError, ValueError): + passwd = fallback_getpass(prompt, stream) + input = sys.stdin + if not stream: + stream = sys.stderr + + if fd is not None: + passwd = None + try: + old = termios.tcgetattr(fd) # a copy to save + new = old[:] + new[3] &= ~termios.ECHO # 3 == 'lflags' + tcsetattr_flags = termios.TCSAFLUSH + if hasattr(termios, 'TCSASOFT'): + tcsetattr_flags |= termios.TCSASOFT + try: + termios.tcsetattr(fd, tcsetattr_flags, new) + passwd = _raw_input(prompt, stream, input=input) + finally: + termios.tcsetattr(fd, tcsetattr_flags, old) + stream.flush() # issue7208 + except termios.error, e: + if passwd is not None: + # _raw_input succeeded. The final tcsetattr failed. Reraise + # instead of leaving the terminal in an unknown state. + raise + # We can't control the tty or stdin. Give up and use normal IO. + # fallback_getpass() raises an appropriate warning. + del input, tty # clean up unused file objects before blocking + passwd = fallback_getpass(prompt, stream) + + stream.write('\n') + return passwd + + +def win_getpass(prompt='Password: ', stream=None): + """Prompt for password with echo off, using Windows getch().""" + if sys.stdin is not sys.__stdin__: + return fallback_getpass(prompt, stream) + import msvcrt + for c in prompt: + msvcrt.putch(c) + pw = "" + while 1: + c = msvcrt.getch() + if c == '\r' or c == '\n': + break + if c == '\003': + raise KeyboardInterrupt + if c == '\b': + pw = pw[:-1] + else: + pw = pw + c + msvcrt.putch('\r') + msvcrt.putch('\n') + return pw + + +def fallback_getpass(prompt='Password: ', stream=None): + warnings.warn("Can not control echo on the terminal.", GetPassWarning, + stacklevel=2) + if not stream: + stream = sys.stderr + print >>stream, "Warning: Password input may be echoed." + return _raw_input(prompt, stream) + + +def _raw_input(prompt="", stream=None, input=None): + # A raw_input() replacement that doesn't save the string in the + # GNU readline history. + if not stream: + stream = sys.stderr + if not input: + input = sys.stdin + prompt = str(prompt) + if prompt: + stream.write(prompt) + stream.flush() + # NOTE: The Python C API calls flockfile() (and unlock) during readline. + line = input.readline() + if not line: + raise EOFError + if line[-1] == '\n': + line = line[:-1] + return line + + +def getuser(): + """Get the username from the environment or password database. + + First try various environment variables, then the password + database. This works on Windows as long as USERNAME is set. + + """ + + import os + + for name in ('LOGNAME', 'USER', 'LNAME', 'USERNAME'): + user = os.environ.get(name) + if user: + return user + + # If this fails, the exception will "explain" why + import pwd + return pwd.getpwuid(os.getuid())[0] + +# Bind the name getpass to the appropriate function +try: + import termios + # it's possible there is an incompatible termios from the + # McMillan Installer, make sure we have a UNIX-compatible termios + termios.tcgetattr, termios.tcsetattr +except (ImportError, AttributeError): + try: + import msvcrt + except ImportError: + try: + from EasyDialogs import AskPassword + except ImportError: + getpass = fallback_getpass + else: + getpass = AskPassword + else: + getpass = win_getpass +else: + getpass = unix_getpass diff --git a/PythonHome/Lib/getpass.pyc b/PythonHome/Lib/getpass.pyc deleted file mode 100644 index 6d70489b664f3fbfffb9315b08fb996eda30ece6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4708 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 0: + modifier = locale[pos:] + locale = locale[:pos] + mask |= COMPONENT_MODIFIER + else: + modifier = '' + pos = locale.find('.') + if pos >= 0: + codeset = locale[pos:] + locale = locale[:pos] + mask |= COMPONENT_CODESET + else: + codeset = '' + pos = locale.find('_') + if pos >= 0: + territory = locale[pos:] + locale = locale[:pos] + mask |= COMPONENT_TERRITORY + else: + territory = '' + language = locale + ret = [] + for i in range(mask+1): + if not (i & ~mask): # if all components for this combo exist ... + val = language + if i & COMPONENT_TERRITORY: val += territory + if i & COMPONENT_CODESET: val += codeset + if i & COMPONENT_MODIFIER: val += modifier + ret.append(val) + ret.reverse() + return ret + + + +class NullTranslations: + def __init__(self, fp=None): + self._info = {} + self._charset = None + self._output_charset = None + self._fallback = None + if fp is not None: + self._parse(fp) + + def _parse(self, fp): + pass + + def add_fallback(self, fallback): + if self._fallback: + self._fallback.add_fallback(fallback) + else: + self._fallback = fallback + + def gettext(self, message): + if self._fallback: + return self._fallback.gettext(message) + return message + + def lgettext(self, message): + if self._fallback: + return self._fallback.lgettext(message) + return message + + def ngettext(self, msgid1, msgid2, n): + if self._fallback: + return self._fallback.ngettext(msgid1, msgid2, n) + if n == 1: + return msgid1 + else: + return msgid2 + + def lngettext(self, msgid1, msgid2, n): + if self._fallback: + return self._fallback.lngettext(msgid1, msgid2, n) + if n == 1: + return msgid1 + else: + return msgid2 + + def ugettext(self, message): + if self._fallback: + return self._fallback.ugettext(message) + return unicode(message) + + def ungettext(self, msgid1, msgid2, n): + if self._fallback: + return self._fallback.ungettext(msgid1, msgid2, n) + if n == 1: + return unicode(msgid1) + else: + return unicode(msgid2) + + def info(self): + return self._info + + def charset(self): + return self._charset + + def output_charset(self): + return self._output_charset + + def set_output_charset(self, charset): + self._output_charset = charset + + def install(self, unicode=False, names=None): + import __builtin__ + __builtin__.__dict__['_'] = unicode and self.ugettext or self.gettext + if hasattr(names, "__contains__"): + if "gettext" in names: + __builtin__.__dict__['gettext'] = __builtin__.__dict__['_'] + if "ngettext" in names: + __builtin__.__dict__['ngettext'] = (unicode and self.ungettext + or self.ngettext) + if "lgettext" in names: + __builtin__.__dict__['lgettext'] = self.lgettext + if "lngettext" in names: + __builtin__.__dict__['lngettext'] = self.lngettext + + +class GNUTranslations(NullTranslations): + # Magic number of .mo files + LE_MAGIC = 0x950412deL + BE_MAGIC = 0xde120495L + + def _parse(self, fp): + """Override this method to support alternative .mo formats.""" + unpack = struct.unpack + filename = getattr(fp, 'name', '') + # Parse the .mo file header, which consists of 5 little endian 32 + # bit words. + self._catalog = catalog = {} + self.plural = lambda n: int(n != 1) # germanic plural by default + buf = fp.read() + buflen = len(buf) + # Are we big endian or little endian? + magic = unpack('4I', buf[4:20]) + ii = '>II' + else: + raise IOError(0, 'Bad magic number', filename) + # Now put all messages from the .mo file buffer into the catalog + # dictionary. + for i in xrange(0, msgcount): + mlen, moff = unpack(ii, buf[masteridx:masteridx+8]) + mend = moff + mlen + tlen, toff = unpack(ii, buf[transidx:transidx+8]) + tend = toff + tlen + if mend < buflen and tend < buflen: + msg = buf[moff:mend] + tmsg = buf[toff:tend] + else: + raise IOError(0, 'File is corrupt', filename) + # See if we're looking at GNU .mo conventions for metadata + if mlen == 0: + # Catalog description + lastk = k = None + for item in tmsg.splitlines(): + item = item.strip() + if not item: + continue + if ':' in item: + k, v = item.split(':', 1) + k = k.strip().lower() + v = v.strip() + self._info[k] = v + lastk = k + elif lastk: + self._info[lastk] += '\n' + item + if k == 'content-type': + self._charset = v.split('charset=')[1] + elif k == 'plural-forms': + v = v.split(';') + plural = v[1].split('plural=')[1] + self.plural = c2py(plural) + # Note: we unconditionally convert both msgids and msgstrs to + # Unicode using the character encoding specified in the charset + # parameter of the Content-Type header. The gettext documentation + # strongly encourages msgids to be us-ascii, but some applications + # require alternative encodings (e.g. Zope's ZCML and ZPT). For + # traditional gettext applications, the msgid conversion will + # cause no problems since us-ascii should always be a subset of + # the charset encoding. We may want to fall back to 8-bit msgids + # if the Unicode conversion fails. + if '\x00' in msg: + # Plural forms + msgid1, msgid2 = msg.split('\x00') + tmsg = tmsg.split('\x00') + if self._charset: + msgid1 = unicode(msgid1, self._charset) + tmsg = [unicode(x, self._charset) for x in tmsg] + for i in range(len(tmsg)): + catalog[(msgid1, i)] = tmsg[i] + else: + if self._charset: + msg = unicode(msg, self._charset) + tmsg = unicode(tmsg, self._charset) + catalog[msg] = tmsg + # advance to next entry in the seek tables + masteridx += 8 + transidx += 8 + + def gettext(self, message): + missing = object() + tmsg = self._catalog.get(message, missing) + if tmsg is missing: + if self._fallback: + return self._fallback.gettext(message) + return message + # Encode the Unicode tmsg back to an 8-bit string, if possible + if self._output_charset: + return tmsg.encode(self._output_charset) + elif self._charset: + return tmsg.encode(self._charset) + return tmsg + + def lgettext(self, message): + missing = object() + tmsg = self._catalog.get(message, missing) + if tmsg is missing: + if self._fallback: + return self._fallback.lgettext(message) + return message + if self._output_charset: + return tmsg.encode(self._output_charset) + return tmsg.encode(locale.getpreferredencoding()) + + def ngettext(self, msgid1, msgid2, n): + try: + tmsg = self._catalog[(msgid1, self.plural(n))] + if self._output_charset: + return tmsg.encode(self._output_charset) + elif self._charset: + return tmsg.encode(self._charset) + return tmsg + except KeyError: + if self._fallback: + return self._fallback.ngettext(msgid1, msgid2, n) + if n == 1: + return msgid1 + else: + return msgid2 + + def lngettext(self, msgid1, msgid2, n): + try: + tmsg = self._catalog[(msgid1, self.plural(n))] + if self._output_charset: + return tmsg.encode(self._output_charset) + return tmsg.encode(locale.getpreferredencoding()) + except KeyError: + if self._fallback: + return self._fallback.lngettext(msgid1, msgid2, n) + if n == 1: + return msgid1 + else: + return msgid2 + + def ugettext(self, message): + missing = object() + tmsg = self._catalog.get(message, missing) + if tmsg is missing: + if self._fallback: + return self._fallback.ugettext(message) + return unicode(message) + return tmsg + + def ungettext(self, msgid1, msgid2, n): + try: + tmsg = self._catalog[(msgid1, self.plural(n))] + except KeyError: + if self._fallback: + return self._fallback.ungettext(msgid1, msgid2, n) + if n == 1: + tmsg = unicode(msgid1) + else: + tmsg = unicode(msgid2) + return tmsg + + +# Locate a .mo file using the gettext strategy +def find(domain, localedir=None, languages=None, all=0): + # Get some reasonable defaults for arguments that were not supplied + if localedir is None: + localedir = _default_localedir + if languages is None: + languages = [] + for envar in ('LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG'): + val = os.environ.get(envar) + if val: + languages = val.split(':') + break + if 'C' not in languages: + languages.append('C') + # now normalize and expand the languages + nelangs = [] + for lang in languages: + for nelang in _expand_lang(lang): + if nelang not in nelangs: + nelangs.append(nelang) + # select a language + if all: + result = [] + else: + result = None + for lang in nelangs: + if lang == 'C': + break + mofile = os.path.join(localedir, lang, 'LC_MESSAGES', '%s.mo' % domain) + if os.path.exists(mofile): + if all: + result.append(mofile) + else: + return mofile + return result + + + +# a mapping between absolute .mo file path and Translation object +_translations = {} + +def translation(domain, localedir=None, languages=None, + class_=None, fallback=False, codeset=None): + if class_ is None: + class_ = GNUTranslations + mofiles = find(domain, localedir, languages, all=1) + if not mofiles: + if fallback: + return NullTranslations() + raise IOError(ENOENT, 'No translation file found for domain', domain) + # Avoid opening, reading, and parsing the .mo file after it's been done + # once. + result = None + for mofile in mofiles: + key = (class_, os.path.abspath(mofile)) + t = _translations.get(key) + if t is None: + with open(mofile, 'rb') as fp: + t = _translations.setdefault(key, class_(fp)) + # Copy the translation object to allow setting fallbacks and + # output charset. All other instance data is shared with the + # cached object. + t = copy.copy(t) + if codeset: + t.set_output_charset(codeset) + if result is None: + result = t + else: + result.add_fallback(t) + return result + + +def install(domain, localedir=None, unicode=False, codeset=None, names=None): + t = translation(domain, localedir, fallback=True, codeset=codeset) + t.install(unicode, names) + + + +# a mapping b/w domains and locale directories +_localedirs = {} +# a mapping b/w domains and codesets +_localecodesets = {} +# current global domain, `messages' used for compatibility w/ GNU gettext +_current_domain = 'messages' + + +def textdomain(domain=None): + global _current_domain + if domain is not None: + _current_domain = domain + return _current_domain + + +def bindtextdomain(domain, localedir=None): + global _localedirs + if localedir is not None: + _localedirs[domain] = localedir + return _localedirs.get(domain, _default_localedir) + + +def bind_textdomain_codeset(domain, codeset=None): + global _localecodesets + if codeset is not None: + _localecodesets[domain] = codeset + return _localecodesets.get(domain) + + +def dgettext(domain, message): + try: + t = translation(domain, _localedirs.get(domain, None), + codeset=_localecodesets.get(domain)) + except IOError: + return message + return t.gettext(message) + +def ldgettext(domain, message): + try: + t = translation(domain, _localedirs.get(domain, None), + codeset=_localecodesets.get(domain)) + except IOError: + return message + return t.lgettext(message) + +def dngettext(domain, msgid1, msgid2, n): + try: + t = translation(domain, _localedirs.get(domain, None), + codeset=_localecodesets.get(domain)) + except IOError: + if n == 1: + return msgid1 + else: + return msgid2 + return t.ngettext(msgid1, msgid2, n) + +def ldngettext(domain, msgid1, msgid2, n): + try: + t = translation(domain, _localedirs.get(domain, None), + codeset=_localecodesets.get(domain)) + except IOError: + if n == 1: + return msgid1 + else: + return msgid2 + return t.lngettext(msgid1, msgid2, n) + +def gettext(message): + return dgettext(_current_domain, message) + +def lgettext(message): + return ldgettext(_current_domain, message) + +def ngettext(msgid1, msgid2, n): + return dngettext(_current_domain, msgid1, msgid2, n) + +def lngettext(msgid1, msgid2, n): + return ldngettext(_current_domain, msgid1, msgid2, n) + +# dcgettext() has been deemed unnecessary and is not implemented. + +# James Henstridge's Catalog constructor from GNOME gettext. Documented usage +# was: +# +# import gettext +# cat = gettext.Catalog(PACKAGE, localedir=LOCALEDIR) +# _ = cat.gettext +# print _('Hello World') + +# The resulting catalog object currently don't support access through a +# dictionary API, which was supported (but apparently unused) in GNOME +# gettext. + +Catalog = translation diff --git a/PythonHome/Lib/gettext.pyc b/PythonHome/Lib/gettext.pyc deleted file mode 100644 index 1dd946812634b40e93433084494070092adc8217..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15309 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 OeVovZID>hdF!2A>welVS diff --git a/PythonHome/Lib/glob.py b/PythonHome/Lib/glob.py new file mode 100644 index 0000000000..f34534b53c --- /dev/null +++ b/PythonHome/Lib/glob.py @@ -0,0 +1,95 @@ +"""Filename globbing utility.""" + +import sys +import os +import re +import fnmatch + +try: + _unicode = unicode +except NameError: + # If Python is built without Unicode support, the unicode type + # will not exist. Fake one. + class _unicode(object): + pass + +__all__ = ["glob", "iglob"] + +def glob(pathname): + """Return a list of paths matching a pathname pattern. + + The pattern may contain simple shell-style wildcards a la + fnmatch. However, unlike fnmatch, filenames starting with a + dot are special cases that are not matched by '*' and '?' + patterns. + + """ + return list(iglob(pathname)) + +def iglob(pathname): + """Return an iterator which yields the paths matching a pathname pattern. + + The pattern may contain simple shell-style wildcards a la + fnmatch. However, unlike fnmatch, filenames starting with a + dot are special cases that are not matched by '*' and '?' + patterns. + + """ + if not has_magic(pathname): + if os.path.lexists(pathname): + yield pathname + return + dirname, basename = os.path.split(pathname) + if not dirname: + for name in glob1(os.curdir, basename): + yield name + return + # `os.path.split()` returns the argument itself as a dirname if it is a + # drive or UNC path. Prevent an infinite recursion if a drive or UNC path + # contains magic characters (i.e. r'\\?\C:'). + if dirname != pathname and has_magic(dirname): + dirs = iglob(dirname) + else: + dirs = [dirname] + if has_magic(basename): + glob_in_dir = glob1 + else: + glob_in_dir = glob0 + for dirname in dirs: + for name in glob_in_dir(dirname, basename): + yield os.path.join(dirname, name) + +# These 2 helper functions non-recursively glob inside a literal directory. +# They return a list of basenames. `glob1` accepts a pattern while `glob0` +# takes a literal basename (so it only has to check for its existence). + +def glob1(dirname, pattern): + if not dirname: + dirname = os.curdir + if isinstance(pattern, _unicode) and not isinstance(dirname, unicode): + dirname = unicode(dirname, sys.getfilesystemencoding() or + sys.getdefaultencoding()) + try: + names = os.listdir(dirname) + except os.error: + return [] + if pattern[0] != '.': + names = filter(lambda x: x[0] != '.', names) + return fnmatch.filter(names, pattern) + +def glob0(dirname, basename): + if basename == '': + # `os.path.split()` returns an empty basename for paths ending with a + # directory separator. 'q*x/' should match only directories. + if os.path.isdir(dirname): + return [basename] + else: + if os.path.lexists(os.path.join(dirname, basename)): + return [basename] + return [] + + +magic_check = re.compile('[*?[]') + +def has_magic(s): + return magic_check.search(s) is not None diff --git a/PythonHome/Lib/glob.pyc b/PythonHome/Lib/glob.pyc deleted file mode 100644 index 6ca6f81690ec541c2cae9456f3c04a81aa6e2115..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2857 zcmd^BUvC>l5TCtsoSfq{B~|Gk3A#v>SfxaOkdRQ-q6QET5LM?wikotr?>6>1=R5ay zO=2k#59wFnBk&0jedbf}MR-Mm-^^W8c&YNv**l)wot>ROznQiF=UV6a?hpNhnr8{W zpJLeOASuxRR8i_tu4n+J<~2hDsVmG#W8oOl7&c`w#0l|thRk79SXgm+chL?B-(hHrGg^RO7+iW_^jkaTx=kHm! z0DqX}X%bhdxithnXAedVg9v z9alJJW|Azv$SLzgTEI9}vGZG-l z8png(f0?FNX2{3p4Gu16hyqDR8yqJn!LWaUARTos>@CjA#G{Gd%vA3%^Q|hRhWgEF zt6AOi=tR+pN5_h6K}R)obsCfFAc2RqM$U^0TPu0(IvOs|O zWmW??oV2J2m>&tx)Q`2OvP4Cj5e(+&4js2}$VY6((YtiK#M@pReVvbPEEat* z12(~uKWO*q@3l1&YZ-tNt2OnyO4wg6B`%w74Eq}hP;56C!V};WmcewX1Sc@7zL8fEGE{VpKrovELyTxT{@hO4aLO<~>G$QIh0@P7Y*Kl8OG5tblslMa^z*B0L_?EFp!!lgm9B`twD_OXv)FMzsj9LPWI_ijUQTKHy*M1oRmIzy1})nd zfcAV2hwR#Y40{!X0I#mP0kCZ-UtLlc)e^?#8eANF&dfH3eF#z~_rN27x`r6qGP1&b z@IliY`^DKB8lB*9A`q){{U1?AjP$x42qNl?TlXG6`48g6;Y(Pm?XNvdaX$pGml3ujxsXbi z-V-HblN?Citcj~+EG=ZGEKGe#@}BeNhjaTq%d@MbdhDmbAd1p5iK3AIfk~94<5ecq zJaLT)M%@*60Eo}euv88wCUK3DIM1Pk5i4y^@DOr@WIZXTGoUxT$?I&&%Mc6qsyNrR lRR3qYD=xnY1#Pbjh~eY;s-xEY>web@R)d?tg`m6c{R3?5P2>Oo diff --git a/PythonHome/Lib/gzip.py b/PythonHome/Lib/gzip.py new file mode 100644 index 0000000000..a613bae876 --- /dev/null +++ b/PythonHome/Lib/gzip.py @@ -0,0 +1,518 @@ +"""Functions that read and write gzipped files. + +The user of the file doesn't have to worry about the compression, +but random access is not allowed.""" + +# based on Andrew Kuchling's minigzip.py distributed with the zlib module + +import struct, sys, time, os +import zlib +import io +import __builtin__ + +__all__ = ["GzipFile","open"] + +FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16 + +READ, WRITE = 1, 2 + +def write32u(output, value): + # The L format writes the bit pattern correctly whether signed + # or unsigned. + output.write(struct.pack("' + + def _check_closed(self): + """Raises a ValueError if the underlying file object has been closed. + + """ + if self.closed: + raise ValueError('I/O operation on closed file.') + + def _init_write(self, filename): + self.name = filename + self.crc = zlib.crc32("") & 0xffffffffL + self.size = 0 + self.writebuf = [] + self.bufsize = 0 + + def _write_gzip_header(self): + self.fileobj.write('\037\213') # magic header + self.fileobj.write('\010') # compression method + fname = os.path.basename(self.name) + if fname.endswith(".gz"): + fname = fname[:-3] + flags = 0 + if fname: + flags = FNAME + self.fileobj.write(chr(flags)) + mtime = self.mtime + if mtime is None: + mtime = time.time() + write32u(self.fileobj, long(mtime)) + self.fileobj.write('\002') + self.fileobj.write('\377') + if fname: + self.fileobj.write(fname + '\000') + + def _init_read(self): + self.crc = zlib.crc32("") & 0xffffffffL + self.size = 0 + + def _read_gzip_header(self): + magic = self.fileobj.read(2) + if magic != '\037\213': + raise IOError, 'Not a gzipped file' + method = ord( self.fileobj.read(1) ) + if method != 8: + raise IOError, 'Unknown compression method' + flag = ord( self.fileobj.read(1) ) + self.mtime = read32(self.fileobj) + # extraflag = self.fileobj.read(1) + # os = self.fileobj.read(1) + self.fileobj.read(2) + + if flag & FEXTRA: + # Read & discard the extra field, if present + xlen = ord(self.fileobj.read(1)) + xlen = xlen + 256*ord(self.fileobj.read(1)) + self.fileobj.read(xlen) + if flag & FNAME: + # Read and discard a null-terminated string containing the filename + while True: + s = self.fileobj.read(1) + if not s or s=='\000': + break + if flag & FCOMMENT: + # Read and discard a null-terminated string containing a comment + while True: + s = self.fileobj.read(1) + if not s or s=='\000': + break + if flag & FHCRC: + self.fileobj.read(2) # Read & discard the 16-bit header CRC + + def write(self,data): + self._check_closed() + if self.mode != WRITE: + import errno + raise IOError(errno.EBADF, "write() on read-only GzipFile object") + + if self.fileobj is None: + raise ValueError, "write() on closed GzipFile object" + + # Convert data type if called by io.BufferedWriter. + if isinstance(data, memoryview): + data = data.tobytes() + + if len(data) > 0: + self.size = self.size + len(data) + self.crc = zlib.crc32(data, self.crc) & 0xffffffffL + self.fileobj.write( self.compress.compress(data) ) + self.offset += len(data) + + return len(data) + + def read(self, size=-1): + self._check_closed() + if self.mode != READ: + import errno + raise IOError(errno.EBADF, "read() on write-only GzipFile object") + + if self.extrasize <= 0 and self.fileobj is None: + return '' + + readsize = 1024 + if size < 0: # get the whole thing + try: + while True: + self._read(readsize) + readsize = min(self.max_read_chunk, readsize * 2) + except EOFError: + size = self.extrasize + else: # just get some more of it + try: + while size > self.extrasize: + self._read(readsize) + readsize = min(self.max_read_chunk, readsize * 2) + except EOFError: + if size > self.extrasize: + size = self.extrasize + + offset = self.offset - self.extrastart + chunk = self.extrabuf[offset: offset + size] + self.extrasize = self.extrasize - size + + self.offset += size + return chunk + + def _unread(self, buf): + self.extrasize = len(buf) + self.extrasize + self.offset -= len(buf) + + def _read(self, size=1024): + if self.fileobj is None: + raise EOFError, "Reached EOF" + + if self._new_member: + # If the _new_member flag is set, we have to + # jump to the next member, if there is one. + # + # First, check if we're at the end of the file; + # if so, it's time to stop; no more members to read. + pos = self.fileobj.tell() # Save current position + self.fileobj.seek(0, 2) # Seek to end of file + if pos == self.fileobj.tell(): + raise EOFError, "Reached EOF" + else: + self.fileobj.seek( pos ) # Return to original position + + self._init_read() + self._read_gzip_header() + self.decompress = zlib.decompressobj(-zlib.MAX_WBITS) + self._new_member = False + + # Read a chunk of data from the file + buf = self.fileobj.read(size) + + # If the EOF has been reached, flush the decompression object + # and mark this object as finished. + + if buf == "": + uncompress = self.decompress.flush() + self._read_eof() + self._add_read_data( uncompress ) + raise EOFError, 'Reached EOF' + + uncompress = self.decompress.decompress(buf) + self._add_read_data( uncompress ) + + if self.decompress.unused_data != "": + # Ending case: we've come to the end of a member in the file, + # so seek back to the start of the unused data, finish up + # this member, and read a new gzip header. + # (The number of bytes to seek back is the length of the unused + # data, minus 8 because _read_eof() will rewind a further 8 bytes) + self.fileobj.seek( -len(self.decompress.unused_data)+8, 1) + + # Check the CRC and file size, and set the flag so we read + # a new member on the next call + self._read_eof() + self._new_member = True + + def _add_read_data(self, data): + self.crc = zlib.crc32(data, self.crc) & 0xffffffffL + offset = self.offset - self.extrastart + self.extrabuf = self.extrabuf[offset:] + data + self.extrasize = self.extrasize + len(data) + self.extrastart = self.offset + self.size = self.size + len(data) + + def _read_eof(self): + # We've read to the end of the file, so we have to rewind in order + # to reread the 8 bytes containing the CRC and the file size. + # We check the that the computed CRC and size of the + # uncompressed data matches the stored values. Note that the size + # stored is the true file size mod 2**32. + self.fileobj.seek(-8, 1) + crc32 = read32(self.fileobj) + isize = read32(self.fileobj) # may exceed 2GB + if crc32 != self.crc: + raise IOError("CRC check failed %s != %s" % (hex(crc32), + hex(self.crc))) + elif isize != (self.size & 0xffffffffL): + raise IOError, "Incorrect length of data produced" + + # Gzip files can be padded with zeroes and still have archives. + # Consume all zero bytes and set the file position to the first + # non-zero byte. See http://www.gzip.org/#faq8 + c = "\x00" + while c == "\x00": + c = self.fileobj.read(1) + if c: + self.fileobj.seek(-1, 1) + + @property + def closed(self): + return self.fileobj is None + + def close(self): + if self.fileobj is None: + return + if self.mode == WRITE: + self.fileobj.write(self.compress.flush()) + write32u(self.fileobj, self.crc) + # self.size may exceed 2GB, or even 4GB + write32u(self.fileobj, self.size & 0xffffffffL) + self.fileobj = None + elif self.mode == READ: + self.fileobj = None + if self.myfileobj: + self.myfileobj.close() + self.myfileobj = None + + def flush(self,zlib_mode=zlib.Z_SYNC_FLUSH): + self._check_closed() + if self.mode == WRITE: + # Ensure the compressor's buffer is flushed + self.fileobj.write(self.compress.flush(zlib_mode)) + self.fileobj.flush() + + def fileno(self): + """Invoke the underlying file object's fileno() method. + + This will raise AttributeError if the underlying file object + doesn't support fileno(). + """ + return self.fileobj.fileno() + + def rewind(self): + '''Return the uncompressed stream file position indicator to the + beginning of the file''' + if self.mode != READ: + raise IOError("Can't rewind in write mode") + self.fileobj.seek(0) + self._new_member = True + self.extrabuf = "" + self.extrasize = 0 + self.extrastart = 0 + self.offset = 0 + + def readable(self): + return self.mode == READ + + def writable(self): + return self.mode == WRITE + + def seekable(self): + return True + + def seek(self, offset, whence=0): + if whence: + if whence == 1: + offset = self.offset + offset + else: + raise ValueError('Seek from end not supported') + if self.mode == WRITE: + if offset < self.offset: + raise IOError('Negative seek in write mode') + count = offset - self.offset + for i in xrange(count // 1024): + self.write(1024 * '\0') + self.write((count % 1024) * '\0') + elif self.mode == READ: + if offset < self.offset: + # for negative seek, rewind and do positive seek + self.rewind() + count = offset - self.offset + for i in xrange(count // 1024): + self.read(1024) + self.read(count % 1024) + + return self.offset + + def readline(self, size=-1): + if size < 0: + # Shortcut common case - newline found in buffer. + offset = self.offset - self.extrastart + i = self.extrabuf.find('\n', offset) + 1 + if i > 0: + self.extrasize -= i - offset + self.offset += i - offset + return self.extrabuf[offset: i] + + size = sys.maxint + readsize = self.min_readsize + else: + readsize = size + bufs = [] + while size != 0: + c = self.read(readsize) + i = c.find('\n') + + # We set i=size to break out of the loop under two + # conditions: 1) there's no newline, and the chunk is + # larger than size, or 2) there is a newline, but the + # resulting line would be longer than 'size'. + if (size <= i) or (i == -1 and len(c) > size): + i = size - 1 + + if i >= 0 or c == '': + bufs.append(c[:i + 1]) # Add portion of last chunk + self._unread(c[i + 1:]) # Push back rest of chunk + break + + # Append chunk to list, decrease 'size', + bufs.append(c) + size = size - len(c) + readsize = min(size, readsize * 2) + if readsize > self.min_readsize: + self.min_readsize = min(readsize, self.min_readsize * 2, 512) + return ''.join(bufs) # Return resulting line + + +def _test(): + # Act like gzip; with -d, act like gunzip. + # The input file is not deleted, however, nor are any other gzip + # options or features supported. + args = sys.argv[1:] + decompress = args and args[0] == "-d" + if decompress: + args = args[1:] + if not args: + args = ["-"] + for arg in args: + if decompress: + if arg == "-": + f = GzipFile(filename="", mode="rb", fileobj=sys.stdin) + g = sys.stdout + else: + if arg[-3:] != ".gz": + print "filename doesn't end in .gz:", repr(arg) + continue + f = open(arg, "rb") + g = __builtin__.open(arg[:-3], "wb") + else: + if arg == "-": + f = sys.stdin + g = GzipFile(filename="", mode="wb", fileobj=sys.stdout) + else: + f = __builtin__.open(arg, "rb") + g = open(arg + ".gz", "wb") + while True: + chunk = f.read(1024) + if not chunk: + break + g.write(chunk) + if g is not sys.stdout: + g.close() + if f is not sys.stdin: + f.close() + +if __name__ == '__main__': + _test() diff --git a/PythonHome/Lib/gzip.pyc b/PythonHome/Lib/gzip.pyc deleted file mode 100644 index 402a1fdb459955ec2acc05ee6dd11d4a0df977fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14921 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
-jvplK0#q#Pdh8qrS?kH)lGM9x8rT| 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 o^*Zu7(L6gvFeSeYx82{5eQ+}PKSm~&@Bjb+ diff --git a/PythonHome/Lib/hashlib.py b/PythonHome/Lib/hashlib.py new file mode 100644 index 0000000000..6d69ad2c84 --- /dev/null +++ b/PythonHome/Lib/hashlib.py @@ -0,0 +1,213 @@ +# $Id$ +# +# Copyright (C) 2005 Gregory P. Smith (greg@krypto.org) +# Licensed to PSF under a Contributor Agreement. +# + +__doc__ = """hashlib module - A common interface to many hash functions. + +new(name, string='') - returns a new hash object implementing the + given hash function; initializing the hash + using the given string data. + +Named constructor functions are also available, these are much faster +than using new(): + +md5(), sha1(), sha224(), sha256(), sha384(), and sha512() + +More algorithms may be available on your platform but the above are +guaranteed to exist. + +NOTE: If you want the adler32 or crc32 hash functions they are available in +the zlib module. + +Choose your hash function wisely. Some have known collision weaknesses. +sha384 and sha512 will be slow on 32 bit platforms. + +Hash objects have these methods: + - update(arg): Update the hash object with the string arg. Repeated calls + are equivalent to a single call with the concatenation of all + the arguments. + - digest(): Return the digest of the strings passed to the update() method + so far. This may contain non-ASCII characters, including + NUL bytes. + - hexdigest(): Like digest() except the digest is returned as a string of + double length, containing only hexadecimal digits. + - copy(): Return a copy (clone) of the hash object. This can be used to + efficiently compute the digests of strings that share a common + initial substring. + +For example, to obtain the digest of the string 'Nobody inspects the +spammish repetition': + + >>> import hashlib + >>> m = hashlib.md5() + >>> m.update("Nobody inspects") + >>> m.update(" the spammish repetition") + >>> m.digest() + '\\xbbd\\x9c\\x83\\xdd\\x1e\\xa5\\xc9\\xd9\\xde\\xc9\\xa1\\x8d\\xf0\\xff\\xe9' + +More condensed: + + >>> hashlib.sha224("Nobody inspects the spammish repetition").hexdigest() + 'a4337bc45a8fc544c03f52dc550cd6e1e87021bc896588bd79e901e2' + +""" + +# This tuple and __get_builtin_constructor() must be modified if a new +# always available algorithm is added. +__always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512') + +algorithms = __always_supported + +__all__ = __always_supported + ('new', 'algorithms', 'pbkdf2_hmac') + + +def __get_builtin_constructor(name): + try: + if name in ('SHA1', 'sha1'): + import _sha + return _sha.new + elif name in ('MD5', 'md5'): + import _md5 + return _md5.new + elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'): + import _sha256 + bs = name[3:] + if bs == '256': + return _sha256.sha256 + elif bs == '224': + return _sha256.sha224 + elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'): + import _sha512 + bs = name[3:] + if bs == '512': + return _sha512.sha512 + elif bs == '384': + return _sha512.sha384 + except ImportError: + pass # no extension module, this hash is unsupported. + + raise ValueError('unsupported hash type ' + name) + + +def __get_openssl_constructor(name): + try: + f = getattr(_hashlib, 'openssl_' + name) + # Allow the C module to raise ValueError. The function will be + # defined but the hash not actually available thanks to OpenSSL. + f() + # Use the C function directly (very fast) + return f + except (AttributeError, ValueError): + return __get_builtin_constructor(name) + + +def __py_new(name, string=''): + """new(name, string='') - Return a new hashing object using the named algorithm; + optionally initialized with a string. + """ + return __get_builtin_constructor(name)(string) + + +def __hash_new(name, string=''): + """new(name, string='') - Return a new hashing object using the named algorithm; + optionally initialized with a string. + """ + try: + return _hashlib.new(name, string) + except ValueError: + # If the _hashlib module (OpenSSL) doesn't support the named + # hash, try using our builtin implementations. + # This allows for SHA224/256 and SHA384/512 support even though + # the OpenSSL library prior to 0.9.8 doesn't provide them. + return __get_builtin_constructor(name)(string) + + +try: + import _hashlib + new = __hash_new + __get_hash = __get_openssl_constructor +except ImportError: + new = __py_new + __get_hash = __get_builtin_constructor + +for __func_name in __always_supported: + # try them all, some may not work due to the OpenSSL + # version not supporting that algorithm. + try: + globals()[__func_name] = __get_hash(__func_name) + except ValueError: + import logging + logging.exception('code for hash %s was not found.', __func_name) + + +try: + # OpenSSL's PKCS5_PBKDF2_HMAC requires OpenSSL 1.0+ with HMAC and SHA + from _hashlib import pbkdf2_hmac +except ImportError: + import binascii + import struct + + _trans_5C = b"".join(chr(x ^ 0x5C) for x in range(256)) + _trans_36 = b"".join(chr(x ^ 0x36) for x in range(256)) + + def pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None): + """Password based key derivation function 2 (PKCS #5 v2.0) + + This Python implementations based on the hmac module about as fast + as OpenSSL's PKCS5_PBKDF2_HMAC for short passwords and much faster + for long passwords. + """ + if not isinstance(hash_name, str): + raise TypeError(hash_name) + + if not isinstance(password, (bytes, bytearray)): + password = bytes(buffer(password)) + if not isinstance(salt, (bytes, bytearray)): + salt = bytes(buffer(salt)) + + # Fast inline HMAC implementation + inner = new(hash_name) + outer = new(hash_name) + blocksize = getattr(inner, 'block_size', 64) + if len(password) > blocksize: + password = new(hash_name, password).digest() + password = password + b'\x00' * (blocksize - len(password)) + inner.update(password.translate(_trans_36)) + outer.update(password.translate(_trans_5C)) + + def prf(msg, inner=inner, outer=outer): + # PBKDF2_HMAC uses the password as key. We can re-use the same + # digest objects and and just update copies to skip initialization. + icpy = inner.copy() + ocpy = outer.copy() + icpy.update(msg) + ocpy.update(icpy.digest()) + return ocpy.digest() + + if iterations < 1: + raise ValueError(iterations) + if dklen is None: + dklen = outer.digest_size + if dklen < 1: + raise ValueError(dklen) + + hex_format_string = "%%0%ix" % (new(hash_name).digest_size * 2) + + dkey = b'' + loop = 1 + while len(dkey) < dklen: + prev = prf(salt + struct.pack(b'>I', loop)) + rkey = int(binascii.hexlify(prev), 16) + for i in xrange(iterations - 1): + prev = prf(prev) + rkey ^= int(binascii.hexlify(prev), 16) + loop += 1 + dkey += binascii.unhexlify(hex_format_string % rkey) + + return dkey[:dklen] + +# Cleanup locals() +del __always_supported, __func_name, __get_hash +del __py_new, __hash_new, __get_openssl_constructor diff --git a/PythonHome/Lib/hashlib.pyc b/PythonHome/Lib/hashlib.pyc index c81eee727cfeb1891d9b634703cc158b42213ce6..bc842302f90d46c28cb486fcd73555df72bd00f7 100644 GIT binary patch delta 503 zcmexmyvA&UDUYEI0|P^On82Uo>#EHUr>N^jDKlKL1{^hOKMVSdQ3oN zNk)F2M}BVV292SOkg7Ex;Cc?MzD~f W?X2i8GJLlAn)ntnv`wBVnFs(CY_WL& delta 201 zcmZ2u_RDyKDG$FC0|SGzRZKu-Nk)F2k@@B{9vwyu!Na_=n1X`*1{i{qiv-T1>z-U7 mI1!7O>}G! heap[0]: + item = heapreplace(heap, item) + """ + returnitem = heap[0] # raises appropriate IndexError if heap is empty + heap[0] = item + _siftup(heap, 0) + return returnitem + +def heappushpop(heap, item): + """Fast version of a heappush followed by a heappop.""" + if heap and cmp_lt(heap[0], item): + item, heap[0] = heap[0], item + _siftup(heap, 0) + return item + +def heapify(x): + """Transform list into a heap, in-place, in O(len(x)) time.""" + n = len(x) + # Transform bottom-up. The largest index there's any point to looking at + # is the largest with a child index in-range, so must have 2*i + 1 < n, + # or i < (n-1)/2. If n is even = 2*j, this is (2*j-1)/2 = j-1/2 so + # j-1 is the largest, which is n//2 - 1. If n is odd = 2*j+1, this is + # (2*j+1-1)/2 = j so j-1 is the largest, and that's again n//2-1. + for i in reversed(xrange(n//2)): + _siftup(x, i) + +def _heappushpop_max(heap, item): + """Maxheap version of a heappush followed by a heappop.""" + if heap and cmp_lt(item, heap[0]): + item, heap[0] = heap[0], item + _siftup_max(heap, 0) + return item + +def _heapify_max(x): + """Transform list into a maxheap, in-place, in O(len(x)) time.""" + n = len(x) + for i in reversed(range(n//2)): + _siftup_max(x, i) + +def nlargest(n, iterable): + """Find the n largest elements in a dataset. + + Equivalent to: sorted(iterable, reverse=True)[:n] + """ + if n < 0: + return [] + it = iter(iterable) + result = list(islice(it, n)) + if not result: + return result + heapify(result) + _heappushpop = heappushpop + for elem in it: + _heappushpop(result, elem) + result.sort(reverse=True) + return result + +def nsmallest(n, iterable): + """Find the n smallest elements in a dataset. + + Equivalent to: sorted(iterable)[:n] + """ + if n < 0: + return [] + it = iter(iterable) + result = list(islice(it, n)) + if not result: + return result + _heapify_max(result) + _heappushpop = _heappushpop_max + for elem in it: + _heappushpop(result, elem) + result.sort() + return result + +# 'heap' is a heap at all indices >= startpos, except possibly for pos. pos +# is the index of a leaf with a possibly out-of-order value. Restore the +# heap invariant. +def _siftdown(heap, startpos, pos): + newitem = heap[pos] + # Follow the path to the root, moving parents down until finding a place + # newitem fits. + while pos > startpos: + parentpos = (pos - 1) >> 1 + parent = heap[parentpos] + if cmp_lt(newitem, parent): + heap[pos] = parent + pos = parentpos + continue + break + heap[pos] = newitem + +# The child indices of heap index pos are already heaps, and we want to make +# a heap at index pos too. We do this by bubbling the smaller child of +# pos up (and so on with that child's children, etc) until hitting a leaf, +# then using _siftdown to move the oddball originally at index pos into place. +# +# We *could* break out of the loop as soon as we find a pos where newitem <= +# both its children, but turns out that's not a good idea, and despite that +# many books write the algorithm that way. During a heap pop, the last array +# element is sifted in, and that tends to be large, so that comparing it +# against values starting from the root usually doesn't pay (= usually doesn't +# get us out of the loop early). See Knuth, Volume 3, where this is +# explained and quantified in an exercise. +# +# Cutting the # of comparisons is important, since these routines have no +# way to extract "the priority" from an array element, so that intelligence +# is likely to be hiding in custom __cmp__ methods, or in array elements +# storing (priority, record) tuples. Comparisons are thus potentially +# expensive. +# +# On random arrays of length 1000, making this change cut the number of +# comparisons made by heapify() a little, and those made by exhaustive +# heappop() a lot, in accord with theory. Here are typical results from 3 +# runs (3 just to demonstrate how small the variance is): +# +# Compares needed by heapify Compares needed by 1000 heappops +# -------------------------- -------------------------------- +# 1837 cut to 1663 14996 cut to 8680 +# 1855 cut to 1659 14966 cut to 8678 +# 1847 cut to 1660 15024 cut to 8703 +# +# Building the heap by using heappush() 1000 times instead required +# 2198, 2148, and 2219 compares: heapify() is more efficient, when +# you can use it. +# +# The total compares needed by list.sort() on the same lists were 8627, +# 8627, and 8632 (this should be compared to the sum of heapify() and +# heappop() compares): list.sort() is (unsurprisingly!) more efficient +# for sorting. + +def _siftup(heap, pos): + endpos = len(heap) + startpos = pos + newitem = heap[pos] + # Bubble up the smaller child until hitting a leaf. + childpos = 2*pos + 1 # leftmost child position + while childpos < endpos: + # Set childpos to index of smaller child. + rightpos = childpos + 1 + if rightpos < endpos and not cmp_lt(heap[childpos], heap[rightpos]): + childpos = rightpos + # Move the smaller child up. + heap[pos] = heap[childpos] + pos = childpos + childpos = 2*pos + 1 + # The leaf at pos is empty now. Put newitem there, and bubble it up + # to its final resting place (by sifting its parents down). + heap[pos] = newitem + _siftdown(heap, startpos, pos) + +def _siftdown_max(heap, startpos, pos): + 'Maxheap variant of _siftdown' + newitem = heap[pos] + # Follow the path to the root, moving parents down until finding a place + # newitem fits. + while pos > startpos: + parentpos = (pos - 1) >> 1 + parent = heap[parentpos] + if cmp_lt(parent, newitem): + heap[pos] = parent + pos = parentpos + continue + break + heap[pos] = newitem + +def _siftup_max(heap, pos): + 'Maxheap variant of _siftup' + endpos = len(heap) + startpos = pos + newitem = heap[pos] + # Bubble up the larger child until hitting a leaf. + childpos = 2*pos + 1 # leftmost child position + while childpos < endpos: + # Set childpos to index of larger child. + rightpos = childpos + 1 + if rightpos < endpos and not cmp_lt(heap[rightpos], heap[childpos]): + childpos = rightpos + # Move the larger child up. + heap[pos] = heap[childpos] + pos = childpos + childpos = 2*pos + 1 + # The leaf at pos is empty now. Put newitem there, and bubble it up + # to its final resting place (by sifting its parents down). + heap[pos] = newitem + _siftdown_max(heap, startpos, pos) + +# If available, use C implementation +try: + from _heapq import * +except ImportError: + pass + +def merge(*iterables): + '''Merge multiple sorted inputs into a single sorted output. + + Similar to sorted(itertools.chain(*iterables)) but returns a generator, + does not pull the data into memory all at once, and assumes that each of + the input streams is already sorted (smallest to largest). + + >>> list(merge([1,3,5,7], [0,2,4,8], [5,10,15,20], [], [25])) + [0, 1, 2, 3, 4, 5, 5, 7, 8, 10, 15, 20, 25] + + ''' + _heappop, _heapreplace, _StopIteration = heappop, heapreplace, StopIteration + _len = len + + h = [] + h_append = h.append + for itnum, it in enumerate(map(iter, iterables)): + try: + next = it.next + h_append([next(), itnum, next]) + except _StopIteration: + pass + heapify(h) + + while _len(h) > 1: + try: + while 1: + v, itnum, next = s = h[0] + yield v + s[0] = next() # raises StopIteration when exhausted + _heapreplace(h, s) # restore heap condition + except _StopIteration: + _heappop(h) # remove empty iterator + if h: + # fast case when only a single iterator remains + v, itnum, next = h[0] + yield v + for v in next.__self__: + yield v + +# Extend the implementations of nsmallest and nlargest to use a key= argument +_nsmallest = nsmallest +def nsmallest(n, iterable, key=None): + """Find the n smallest elements in a dataset. + + Equivalent to: sorted(iterable, key=key)[:n] + """ + # Short-cut for n==1 is to use min() when len(iterable)>0 + if n == 1: + it = iter(iterable) + head = list(islice(it, 1)) + if not head: + return [] + if key is None: + return [min(chain(head, it))] + return [min(chain(head, it), key=key)] + + # When n>=size, it's faster to use sorted() + try: + size = len(iterable) + except (TypeError, AttributeError): + pass + else: + if n >= size: + return sorted(iterable, key=key)[:n] + + # When key is none, use simpler decoration + if key is None: + it = izip(iterable, count()) # decorate + result = _nsmallest(n, it) + return map(itemgetter(0), result) # undecorate + + # General case, slowest method + in1, in2 = tee(iterable) + it = izip(imap(key, in1), count(), in2) # decorate + result = _nsmallest(n, it) + return map(itemgetter(2), result) # undecorate + +_nlargest = nlargest +def nlargest(n, iterable, key=None): + """Find the n largest elements in a dataset. + + Equivalent to: sorted(iterable, key=key, reverse=True)[:n] + """ + + # Short-cut for n==1 is to use max() when len(iterable)>0 + if n == 1: + it = iter(iterable) + head = list(islice(it, 1)) + if not head: + return [] + if key is None: + return [max(chain(head, it))] + return [max(chain(head, it), key=key)] + + # When n>=size, it's faster to use sorted() + try: + size = len(iterable) + except (TypeError, AttributeError): + pass + else: + if n >= size: + return sorted(iterable, key=key, reverse=True)[:n] + + # When key is none, use simpler decoration + if key is None: + it = izip(iterable, count(0,-1)) # decorate + result = _nlargest(n, it) + return map(itemgetter(0), result) # undecorate + + # General case, slowest method + in1, in2 = tee(iterable) + it = izip(imap(key, in1), count(0,-1), in2) # decorate + result = _nlargest(n, it) + return map(itemgetter(2), result) # undecorate + +if __name__ == "__main__": + # Simple sanity test + heap = [] + data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0] + for item in data: + heappush(heap, item) + sort = [] + while heap: + sort.append(heappop(heap)) + print sort + + import doctest + doctest.testmod() diff --git a/PythonHome/Lib/heapq.pyc b/PythonHome/Lib/heapq.pyc index ff1774440caa8ab47fdd231c2e17dbe45831085e..b1c1f0ab064bfe1d1a1eb311f7ba27f2e8229c22 100644 GIT binary patch delta 1025 zcmeAwd{??*s+6G>0|P^On82Uo>#EHUr>N^jDKlKL1{^hOKMVSdQ3oN zNk)F2M}BVVlP^~0K+X^)?GPF%Tt8M`doAp{rlQT3< zlMyyfniAw#o2li>$hvvGmKhnEH-FJqXCcF>S_a(Aq-$I3VoZjv&B12d$?)1_NsB@N DAY5Yh delta 409 zcmaD?+Eut=suaHj0|SGzRZKu-Nk)F2k@@6fQeV-e)>;(;02u;uuK)l5 diff --git a/PythonHome/Lib/hmac.py b/PythonHome/Lib/hmac.py new file mode 100644 index 0000000000..9cd1a9fd91 --- /dev/null +++ b/PythonHome/Lib/hmac.py @@ -0,0 +1,136 @@ +"""HMAC (Keyed-Hashing for Message Authentication) Python module. + +Implements the HMAC algorithm as described by RFC 2104. +""" + +import warnings as _warnings + +from operator import _compare_digest as compare_digest + + +trans_5C = "".join ([chr (x ^ 0x5C) for x in xrange(256)]) +trans_36 = "".join ([chr (x ^ 0x36) for x in xrange(256)]) + +# The size of the digests returned by HMAC depends on the underlying +# hashing module used. Use digest_size from the instance of HMAC instead. +digest_size = None + +# A unique object passed by HMAC.copy() to the HMAC constructor, in order +# that the latter return very quickly. HMAC("") in contrast is quite +# expensive. +_secret_backdoor_key = [] + +class HMAC: + """RFC 2104 HMAC class. Also complies with RFC 4231. + + This supports the API for Cryptographic Hash Functions (PEP 247). + """ + blocksize = 64 # 512-bit HMAC; can be changed in subclasses. + + def __init__(self, key, msg = None, digestmod = None): + """Create a new HMAC object. + + key: key for the keyed hash object. + msg: Initial input for the hash, if provided. + digestmod: A module supporting PEP 247. *OR* + A hashlib constructor returning a new hash object. + Defaults to hashlib.md5. + """ + + if key is _secret_backdoor_key: # cheap + return + + if digestmod is None: + import hashlib + digestmod = hashlib.md5 + + if hasattr(digestmod, '__call__'): + self.digest_cons = digestmod + else: + self.digest_cons = lambda d='': digestmod.new(d) + + self.outer = self.digest_cons() + self.inner = self.digest_cons() + self.digest_size = self.inner.digest_size + + if hasattr(self.inner, 'block_size'): + blocksize = self.inner.block_size + if blocksize < 16: + # Very low blocksize, most likely a legacy value like + # Lib/sha.py and Lib/md5.py have. + _warnings.warn('block_size of %d seems too small; using our ' + 'default of %d.' % (blocksize, self.blocksize), + RuntimeWarning, 2) + blocksize = self.blocksize + else: + _warnings.warn('No block_size attribute on given digest object; ' + 'Assuming %d.' % (self.blocksize), + RuntimeWarning, 2) + blocksize = self.blocksize + + if len(key) > blocksize: + key = self.digest_cons(key).digest() + + key = key + chr(0) * (blocksize - len(key)) + self.outer.update(key.translate(trans_5C)) + self.inner.update(key.translate(trans_36)) + if msg is not None: + self.update(msg) + +## def clear(self): +## raise NotImplementedError, "clear() method not available in HMAC." + + def update(self, msg): + """Update this hashing object with the string msg. + """ + self.inner.update(msg) + + def copy(self): + """Return a separate copy of this hashing object. + + An update to this copy won't affect the original object. + """ + other = self.__class__(_secret_backdoor_key) + other.digest_cons = self.digest_cons + other.digest_size = self.digest_size + other.inner = self.inner.copy() + other.outer = self.outer.copy() + return other + + def _current(self): + """Return a hash object for the current state. + + To be used only internally with digest() and hexdigest(). + """ + h = self.outer.copy() + h.update(self.inner.digest()) + return h + + def digest(self): + """Return the hash value of this hashing object. + + This returns a string containing 8-bit data. The object is + not altered in any way by this function; you can continue + updating the object after calling this function. + """ + h = self._current() + return h.digest() + + def hexdigest(self): + """Like digest(), but returns a string of hexadecimal digits instead. + """ + h = self._current() + return h.hexdigest() + +def new(key, msg = None, digestmod = None): + """Create a new hashing object and return it. + + key: The starting key for the hash. + msg: if available, will immediately be hashed into the object's starting + state. + + You can now feed arbitrary strings into the object using its update() + method, and can ask for the hash value at any time by calling its digest() + method. + """ + return HMAC(key, msg, digestmod) diff --git a/PythonHome/Lib/hmac.pyc b/PythonHome/Lib/hmac.pyc deleted file mode 100644 index 1d6315aae08568033421895e6492e88bdf46eb5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4392 zcma)9Yi}FJ6`kcvA}vLZUvZE&9kg*n1q#t9b{@77L{%EZNFoa>H)#mBi{b8&9BLoT z&eAdqyI&Oa@jLpVf1$srUkmhWd+wcGlCo7hqINhtd*|-Vx#ylctp9tnGuW|5p(y`a z`2G}^{U@48h(20RL^Tn6qF>{FUBq>fG(^8Cyr>~2Ein>8uZgHBPCfD2@2`pey3lQ* z*G1G4dl>seO?-cg9`-xpWi!?mGe$h)0=>MyN$=>tA|m+2NL&0M#HkS9^|$CT{ddF< zu)9e8qwWUn;4zvnzTVrH-7ocANAG^2?AW9uIm~kTwYFA`wA`B&W1SWzRE5dXZFx8^ z##t(pESkl-*Xi6#rm;?7VI>SDyHoKf%S|y(q_Q&7Hq6aHM{+Qi{^$F0_q|`;>~+k4 z@psVmu!Ld@O%P_uROLE|%t+g!z>qKkkIh5seSoHDprIEmVo}GyuW{K!G#dLyAkcCY z`gO(vaMXC?O%c@zlzxj4rVa;$IvfV-v_-VWk2=CX>bA-ApU_mRcDoB>Wo=K&z1U`w zRvjB{>b`?bocZ5w8%!envP8<33vJVEDZ@_ zE4zokIh4CMKiuxI7xO8W5H`>d^_sY7+x8#8=7}c&)bYB=5mrwe{gt^$_cuA@o``GW zX+t~#3G3o-LZpl$nbpN0f3m%j)x1c*)XXRjQ`(+PO%%vv7~CArFo~cJIxI@U5NVF}{5E~#4_#&pB^LTfp)oO~n&OP4OzfzdaW6H6QL!}XbXF|p(ySe6 zhH{!`k4&T^M=YA}vJKgMTke%fT``uFpkyN0{?2{>9j0UT*7AFg*A$xpQX#cPJ_`$| zN3M%mo{|T*)pOUq;^{LzRI`|pB&+=OlIYfQod>KJ#X6WD1fh!KAn-{$LTc!$;kt~= zZlVFHCrns`?T9s|RGK;-0(vJqG%a#nO7#U4UEDZ7y@y|!!NYN)!rpYwFTWeBWDu!O zcFBb7KujS9aTXp2*8EYMi}c|3nK79S<&8*MtrOZ{CT)TZ+>tX&0A;fr8p+#thCM@j zv3JoNWOC_Rs-l39&cGiC@W?#UX&Jtf5qIRCwX=kr-iUez^F{Y6n&JwY!0HfD2?i=W zj8Z0PAh+{z*0sCr<-dbG1n8OD;jWCl6WmrkhJ(H&Bt=JF}KE87k;_b@sNGf?s=njXMciIv0^B2o+_BMn0xR??_TE_@=X|2i6X`%}988QtP? z&GXx4`y)KJ1n>k?767hj@uEV6vph$(fipmM1-%ClAPu2H>B-V~ zj=F-J2TJJjfybq0cU!6y#YsP|?w5?~l2kAzKJAfN)-=OAf2>iD&_M!-|eF7s(r%|y6 z?W#)ekH-B=O#I3m>#}rpw|68;T6thtffG>xpH!qngKA0E2FC+~+N0IV`Na{4Hp3~p zq#$pSh3%!g`Xy#lhPYkTH@t%`RRhPjAXSMD0xt7G;C}YtmP8>4qAY|OkX-w84Dcm2 zq^pkW3yghw#S&TWouja{W(tWVL1{HwUaPistKDpGwA<}YSjQk;g#A7)wknwA$aFe! z)+=&Hb66I0&|;Xw_@nq_&rp*XCkla&37f!)9geJHRh@uX_TvcUZxm@|BSct z1VzMf8sFV!uZhNQ)M$rAiE>BTe3LMQ65E2POYfHIhv=id~lb7!Z6=dggaBd7Wec zhQ#nOPCp}!>Wi*_9j*TcH9w(-3CgeI>c#m%lb37$KeXhP-F3|Wgl0H;);4Mv>$~1= Lqt$HHE)V|)+M&W& diff --git a/PythonHome/Lib/hotshot/__init__.py b/PythonHome/Lib/hotshot/__init__.py new file mode 100644 index 0000000000..1556ab3f2b --- /dev/null +++ b/PythonHome/Lib/hotshot/__init__.py @@ -0,0 +1,78 @@ +"""High-perfomance logging profiler, mostly written in C.""" + +import _hotshot +from _hotshot import ProfilerError + +from warnings import warnpy3k as _warnpy3k +_warnpy3k("The 'hotshot' module is not supported in 3.x, " + "use the 'profile' module instead.", stacklevel=2) + +class Profile: + def __init__(self, logfn, lineevents=0, linetimings=1): + self.lineevents = lineevents and 1 or 0 + self.linetimings = (linetimings and lineevents) and 1 or 0 + self._prof = p = _hotshot.profiler( + logfn, self.lineevents, self.linetimings) + + # Attempt to avoid confusing results caused by the presence of + # Python wrappers around these functions, but only if we can + # be sure the methods have not been overridden or extended. + if self.__class__ is Profile: + self.close = p.close + self.start = p.start + self.stop = p.stop + self.addinfo = p.addinfo + + def close(self): + """Close the logfile and terminate the profiler.""" + self._prof.close() + + def fileno(self): + """Return the file descriptor of the profiler's log file.""" + return self._prof.fileno() + + def start(self): + """Start the profiler.""" + self._prof.start() + + def stop(self): + """Stop the profiler.""" + self._prof.stop() + + def addinfo(self, key, value): + """Add an arbitrary labelled value to the profile log.""" + self._prof.addinfo(key, value) + + # These methods offer the same interface as the profile.Profile class, + # but delegate most of the work to the C implementation underneath. + + def run(self, cmd): + """Profile an exec-compatible string in the script + environment. + + The globals from the __main__ module are used as both the + globals and locals for the script. + """ + import __main__ + dict = __main__.__dict__ + return self.runctx(cmd, dict, dict) + + def runctx(self, cmd, globals, locals): + """Evaluate an exec-compatible string in a specific + environment. + + The string is compiled before profiling begins. + """ + code = compile(cmd, "", "exec") + self._prof.runcode(code, globals, locals) + return self + + def runcall(self, func, *args, **kw): + """Profile a single call of a callable. + + Additional positional and keyword arguments may be passed + along; the result of the call is returned, and exceptions are + allowed to propogate cleanly, while ensuring that profiling is + disabled on the way out. + """ + return self._prof.runcall(func, args, kw) diff --git a/PythonHome/Lib/hotshot/__init__.pyc b/PythonHome/Lib/hotshot/__init__.pyc deleted file mode 100644 index 4214cf3264d7379676c1801991f2342f7aeeb183..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3319 zcmbVOU2hvj6rHu554$NTMJ=DI1|CRMrIt`7UZ^UdD&hf^YJ-G`DlO~Xv9ry3XEif! z5-EL3CH?>p{1RUHS^NMv=kBiKQnd=TJ>xsycg{Wc-s%5+b@b=YzwT$M{S5H`HH!ZQ zRj$+l>PY21RYvLn0)BnU^PW2Bsfg`?D*I|aPzP%&GHWWwZ(ZdZ>O6{~d{gBkl@HYm zrOuW5ct_Z&gc07jCqtZMxWzj=3Y@lj&St8m; z-?yBbpfW%dkaeKG5EOwZ;5q0MN(uvFNI{UKAb3*PP(YLda1~Gwh6I>BBNaEe7C1*0 z#3mb{T0`Og0~G%UsSy1b-qYHr` z`Cx0YVw&egHMP6kr5Q2hR3?L=(<@2uU)o zPaA#Pwm89cu8eL(A4luaCu`f$mV7hr+7+?fyXa^PK=d&P1McsVb^Z>j2fU0hmiobS zbXw&)7zdcr(2R7@j33FmnApXnv3N}U4keV!+(VXqgt?v?sNSpk(k)l@-Iqhe=VKEV zt`cQM)7<#X6?L#q+o^PSn(lZ81kG9F3!OnUrPx>5x6qt`-$Hq<=5IjyJ*?X&Szgle zB|K@=x6q2qK6^{8c%yv~_w`C`y`55A_W6oZbe*mUDc?uO(#VVuJ$2q>g_fFkG2xp$ z2N`whCPi?mJJn@6F=dHh`z$RNpr&0_oCbdhP!dT(gAg?E{3CNJt|;p-O<8Vq8>KTm znM*fb21oA1gob3N)N@2e1inZ;N9;q$LlgId+-K}-f|dUZD;_twhgUQwCcBf_d7Xx0 z0vGhbF_$5yFqJeUAL;gEs%M3>)f{1MJX-cLOU+6Q2v!>THF~U!-CuVA4izZyr)Dwf(i@!kFZ$g)Q z&C2_N6FDMumNe7uB%xS32(-tDaqeLy=1-ixHq^CqLmEasYog4zrt#SfFcyON=sc^--%=> zT>02KFxkx(bOo>H=_z2;HL|tImu5*zTg|=_7CYk?W$03coQr3ilcZwuJxP4#Br`Qn z^w{~rH=v_EhTRZyV6)oJ$dIfwX;q%?>ElD@O;h=WxNSI0!-{DOzf>kKJTI7Q+j#ad zRJIGaap&7Bxr&yfQE~K&`_N;i^eGCsyT>C7aqalB9u$9y>EEF=!ECd6E0JtTQl)bP zw`F2S;E;DNo;}QJlC@)|i%=z4D} My4JgfIJ43F7m*gsMgRZ+ diff --git a/PythonHome/Lib/hotshot/log.py b/PythonHome/Lib/hotshot/log.py new file mode 100644 index 0000000000..17e8b50515 --- /dev/null +++ b/PythonHome/Lib/hotshot/log.py @@ -0,0 +1,194 @@ +import _hotshot +import os.path +import parser +import symbol + +from _hotshot import \ + WHAT_ENTER, \ + WHAT_EXIT, \ + WHAT_LINENO, \ + WHAT_DEFINE_FILE, \ + WHAT_DEFINE_FUNC, \ + WHAT_ADD_INFO + + +__all__ = ["LogReader", "ENTER", "EXIT", "LINE"] + + +ENTER = WHAT_ENTER +EXIT = WHAT_EXIT +LINE = WHAT_LINENO + + +class LogReader: + def __init__(self, logfn): + # fileno -> filename + self._filemap = {} + # (fileno, lineno) -> filename, funcname + self._funcmap = {} + + self._reader = _hotshot.logreader(logfn) + self._nextitem = self._reader.next + self._info = self._reader.info + if 'current-directory' in self._info: + self.cwd = self._info['current-directory'] + else: + self.cwd = None + + # This mirrors the call stack of the profiled code as the log + # is read back in. It contains tuples of the form: + # + # (file name, line number of function def, function name) + # + self._stack = [] + self._append = self._stack.append + self._pop = self._stack.pop + + def close(self): + self._reader.close() + + def fileno(self): + """Return the file descriptor of the log reader's log file.""" + return self._reader.fileno() + + def addinfo(self, key, value): + """This method is called for each additional ADD_INFO record. + + This can be overridden by applications that want to receive + these events. The default implementation does not need to be + called by alternate implementations. + + The initial set of ADD_INFO records do not pass through this + mechanism; this is only needed to receive notification when + new values are added. Subclasses can inspect self._info after + calling LogReader.__init__(). + """ + pass + + def get_filename(self, fileno): + try: + return self._filemap[fileno] + except KeyError: + raise ValueError, "unknown fileno" + + def get_filenames(self): + return self._filemap.values() + + def get_fileno(self, filename): + filename = os.path.normcase(os.path.normpath(filename)) + for fileno, name in self._filemap.items(): + if name == filename: + return fileno + raise ValueError, "unknown filename" + + def get_funcname(self, fileno, lineno): + try: + return self._funcmap[(fileno, lineno)] + except KeyError: + raise ValueError, "unknown function location" + + # Iteration support: + # This adds an optional (& ignored) parameter to next() so that the + # same bound method can be used as the __getitem__() method -- this + # avoids using an additional method call which kills the performance. + + def next(self, index=0): + while 1: + # This call may raise StopIteration: + what, tdelta, fileno, lineno = self._nextitem() + + # handle the most common cases first + + if what == WHAT_ENTER: + filename, funcname = self._decode_location(fileno, lineno) + t = (filename, lineno, funcname) + self._append(t) + return what, t, tdelta + + if what == WHAT_EXIT: + try: + return what, self._pop(), tdelta + except IndexError: + raise StopIteration + + if what == WHAT_LINENO: + filename, firstlineno, funcname = self._stack[-1] + return what, (filename, lineno, funcname), tdelta + + if what == WHAT_DEFINE_FILE: + filename = os.path.normcase(os.path.normpath(tdelta)) + self._filemap[fileno] = filename + elif what == WHAT_DEFINE_FUNC: + filename = self._filemap[fileno] + self._funcmap[(fileno, lineno)] = (filename, tdelta) + elif what == WHAT_ADD_INFO: + # value already loaded into self.info; call the + # overridable addinfo() handler so higher-level code + # can pick up the new value + if tdelta == 'current-directory': + self.cwd = lineno + self.addinfo(tdelta, lineno) + else: + raise ValueError, "unknown event type" + + def __iter__(self): + return self + + # + # helpers + # + + def _decode_location(self, fileno, lineno): + try: + return self._funcmap[(fileno, lineno)] + except KeyError: + # + # This should only be needed when the log file does not + # contain all the DEFINE_FUNC records needed to allow the + # function name to be retrieved from the log file. + # + if self._loadfile(fileno): + filename = funcname = None + try: + filename, funcname = self._funcmap[(fileno, lineno)] + except KeyError: + filename = self._filemap.get(fileno) + funcname = None + self._funcmap[(fileno, lineno)] = (filename, funcname) + return filename, funcname + + def _loadfile(self, fileno): + try: + filename = self._filemap[fileno] + except KeyError: + print "Could not identify fileId", fileno + return 1 + if filename is None: + return 1 + absname = os.path.normcase(os.path.join(self.cwd, filename)) + + try: + fp = open(absname) + except IOError: + return + st = parser.suite(fp.read()) + fp.close() + + # Scan the tree looking for def and lambda nodes, filling in + # self._funcmap with all the available information. + funcdef = symbol.funcdef + lambdef = symbol.lambdef + + stack = [st.totuple(1)] + + while stack: + tree = stack.pop() + try: + sym = tree[0] + except (IndexError, TypeError): + continue + if sym == funcdef: + self._funcmap[(fileno, tree[2][2])] = filename, tree[2][1] + elif sym == lambdef: + self._funcmap[(fileno, tree[1][2])] = filename, "" + stack.extend(list(tree[1:])) diff --git a/PythonHome/Lib/hotshot/log.pyc b/PythonHome/Lib/hotshot/log.pyc deleted file mode 100644 index 3e161f12f04514ab739bb2e640361c6f5632762d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5332 zcmb7IUvnEt5uaJf`e)fm?EG^`!iGx`9o&gKiUNvD9T#Hf&JdKUmBGfC5^L?qURl~z zc1LkkmAqW8j;E`u;(>y(_{p%i= z{<+ln%l0q3eU<-}@%tX0^mk|ie6<=WwOi0y?K<=KCAC|c(`B_=7TO{IctPzhsBuN@ zR@AtvcB^V!Q@b@auB+X;8aLE#L+JpMF=s&q6?K65i^^bHQyENKQU=qO6?tkZsH%^Y zdZyIRcF$0wZmSOM!hhkf)2e{94K&*y+}Y}Fbhb7;%i*lMv$%Ol(G;N8i>qQnu)~R955tJQ&%71Od2X^$mpU9 z7KLc4pee+X^13Z{;>FV`ryt|I7}tx;D88L=o#i)z>u5li##vUG983P(&$JLx&J{b`bz z$i5kbiRs%onYDO=wuYuR2uEh@Px8(*>KC2E*rs^o#76N!lATzUlXAKYIx>$lmL93l znz5W<7!6`M-JVb-aQ2S_8S2E5v2?m#YW@C^kp5(1qQHvqoaU5CJdr6q5V9ZXrDik` z+0bebwZNyONza37@7)jg_j29$z|o$}vdux0(Dr(l!IWO)B&UwgiasNsRi|F9gX(LH z%pW;qT95~bFOC$0VqLOyL?>?N&87S!2!GRKwe|}Zgy6;QkNa_wNGfxW8k|e{$grh$GmUi z$<%iGJS;xkyBLkGAwa`@rT@VDt-~;N$HpGUfeWhdk47eN2T<1d{X^Feg3yL>hJCnx>z;~^?9bHjntJP6MC0|!sYXCER@U+%r=rFP9#nKl=hQu7DxV64Dyge@Ja|B;pUFn3fO&{~UxB5F9#lVxH!Z>7Hu!_)RgtWV&Zc zt^eYx+H=%Xe8DHIM~+I`>WQPe58G-R(4U>hiL+p4df_Z!q!#l64o|5#l?*WP?V%h@ z6er`pkC37X+2M#MMxkRc9i`rDpjzBY=7nSx%!6b(HxbFhIL!f4c44#l$LOVerSx@u zRX24_7g$($Cf#;+;kjpG`vd1C|9ty@`R5u06gEMMCdvWMGq}rKl_i?@6*jWl5~;#5 zCB-6O3G*2Ef7!C|Q7lEXY+*{_qZi<#D0%W~h+8lA`5U18<4<*#t#JN(<^1fQfO0i6`Az0hHzB5R5{f&5(=nQ#jRlD=Ow3#@|ybf6`+==~k3_g`HQrYm5W zyO`ug*Ul!U#X8AjNP2jvKNby;l>^h8`=57-!&3CnPX!`3qrg1Q5R>&w*T$1gikCFSu-)&$< z)|UYHSYdf@kXeF1_iK0~-pK7{5GJWTb%c0lFcB5MO235$$n9J%H}z$~? zBh!FInEn}^SHsb#MY{YW1BQ+TuM~$)?$D9S0CEH~oNjha{0=(f@{-}%p5Q!&w;%qg z5cK=GpzQjS1&25#7~#7Ylba!w zVL;i|8gk%v^rgZoZCV9@^FFNi{s)Na?hcFy10U5?@_mMR7sXO`Wz2~TO@NRN0h16@ zQnRyk=nQmd_haxnLBlil=QM*)m2b$;JK+=EY@?dqprQ4WSm}a90$`8y53bVh#52N zzrpTJHeY4aX2ZLJfVlTPQjBts+CATeQ2+HG3Lejpc~5YmqU)FHrFyx(T(97_T3>A5 zLc5wtlkCZoN{%m1+ft&6+q{Rj9sxtLYnDSLJC^v4CiZA?nb_;$&V}9an7kUBIvXl- dTCK%uw=+AvOFx&a&xC}J)2^?SD!{W!>E9#$^UDAL diff --git a/PythonHome/Lib/hotshot/stats.py b/PythonHome/Lib/hotshot/stats.py new file mode 100644 index 0000000000..7ff2277a18 --- /dev/null +++ b/PythonHome/Lib/hotshot/stats.py @@ -0,0 +1,93 @@ +"""Statistics analyzer for HotShot.""" + +import profile +import pstats + +import hotshot.log + +from hotshot.log import ENTER, EXIT + + +def load(filename): + return StatsLoader(filename).load() + + +class StatsLoader: + def __init__(self, logfn): + self._logfn = logfn + self._code = {} + self._stack = [] + self.pop_frame = self._stack.pop + + def load(self): + # The timer selected by the profiler should never be used, so make + # sure it doesn't work: + p = Profile() + p.get_time = _brokentimer + log = hotshot.log.LogReader(self._logfn) + taccum = 0 + for event in log: + what, (filename, lineno, funcname), tdelta = event + if tdelta > 0: + taccum += tdelta + + # We multiply taccum to convert from the microseconds we + # have to the seconds that the profile/pstats module work + # with; this allows the numbers to have some basis in + # reality (ignoring calibration issues for now). + + if what == ENTER: + frame = self.new_frame(filename, lineno, funcname) + p.trace_dispatch_call(frame, taccum * .000001) + taccum = 0 + + elif what == EXIT: + frame = self.pop_frame() + p.trace_dispatch_return(frame, taccum * .000001) + taccum = 0 + + # no further work for line events + + assert not self._stack + return pstats.Stats(p) + + def new_frame(self, *args): + # args must be filename, firstlineno, funcname + # our code objects are cached since we don't need to create + # new ones every time + try: + code = self._code[args] + except KeyError: + code = FakeCode(*args) + self._code[args] = code + # frame objects are create fresh, since the back pointer will + # vary considerably + if self._stack: + back = self._stack[-1] + else: + back = None + frame = FakeFrame(code, back) + self._stack.append(frame) + return frame + + +class Profile(profile.Profile): + def simulate_cmd_complete(self): + pass + + +class FakeCode: + def __init__(self, filename, firstlineno, funcname): + self.co_filename = filename + self.co_firstlineno = firstlineno + self.co_name = self.__name__ = funcname + + +class FakeFrame: + def __init__(self, code, back): + self.f_back = back + self.f_code = code + + +def _brokentimer(): + raise RuntimeError, "this timer should not be called" diff --git a/PythonHome/Lib/hotshot/stats.pyc b/PythonHome/Lib/hotshot/stats.pyc deleted file mode 100644 index 828813fd2852a77cefb84ffe460692f5286844f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3083 zcmbtW&u<$=6n^7fujABi5+yD40v1$Yij)(A1Em5=%a2x}T31c6f);0YovdT;n%xN{ z$d*vU5&j2`zzHG2pTK{^1r8j`_q}y&T104tlQ;WjcIM5z?|tvhI)5~mf7$+|6Uyx8 z;Q1z`_zq1Z(nV_|s>skt7fPvDq+2=B9qGENJ2G@+RF!U3MxJy%F_9}@!9-1>szhfc z^4L8V`KY@jQB7hagSzx#a%ujeE)o7$BwC&iElYGpqE(3+^C9$`>~tGETBp6n6SvTG zY|kczO~RtpOMAnkFXFt_&+^uLneFUnb~AZ^-&VVVskVyd+ScuBzICbHegAf7piub! zDx_FNV?`!7HV$ie_)eQMW;V`1<(|dOtQW<(S{g#tId%ze`^hj)d!x7wU9>6AL)+ZB zne6W1NCjl4poz`#kx%$(v)~ED_y8da*2pLbO{yl(#m>r8u zjaWEpB&Y}uHgIK7RsTGObE>FK9r^qxnN;MRkAIM5@$AG65}( z9JrDn$OPcj$W+$DUITHv1jEz99@yYD))kCW#qRITamqQe*5{`KY#u4 ziY5t8Dsn5&$V%IQ9_;4XL7duT1ojfwz1Rlq>C72FHK+)f2K8pP=f@XSp(L ztZAa`(VS~D?EW%W(Dc}68PJ(vVt6>xnek`vPN{cqzh`~-WXdo}<1{N%^e_#XqUF*k z9wHm*TS;9gkC(Sh>*6A(JEZ10(;~PA`cI=MI)7e?yEh7Wrx9Yfu|XnX5Yaa%$u*Dd9-Itv0|lBNs?fk2wql zK5>a7ARvjZvj^a+OU@WPI+~|jS|r%D{cD)PRJ79rir(pXu* zSJ#>H3TAISj?<{EMA0~LZZF>}G$2|!II@ev;kTeXRz2{^uU8>jNX2!`8h~z?HNd`F z@yv=@HM-@ja4@t%V7Y$~jI!u(h^|laYq?c(i;Yz~twghwt#Ef@f6oi_<{7+a2!yVcyVVNT`_mXLcn;wPkKJIdI zgs--WXF0x~6fM2hTKL2|97Ziv`_^vU;#CySKG3uX9O~_-)otPDf5wb=)DA=sC+3lr zZ9N(}7z9xkqWn-Fmlv=96m;eA?0((E-RkqpMsL&do@6-n^G}mbGfjEnbK^&LJ0&Pu g1230V?+U9;v4O_pO;l-A&O3E?{q+mg_1e1k7l*1R6#xJL diff --git a/PythonHome/Lib/hotshot/stones.py b/PythonHome/Lib/hotshot/stones.py new file mode 100644 index 0000000000..fb88d581d3 --- /dev/null +++ b/PythonHome/Lib/hotshot/stones.py @@ -0,0 +1,30 @@ +import errno +import hotshot +import hotshot.stats +import sys +import test.pystone + +def main(logfile): + p = hotshot.Profile(logfile) + benchtime, stones = p.runcall(test.pystone.pystones) + p.close() + + print "Pystone(%s) time for %d passes = %g" % \ + (test.pystone.__version__, test.pystone.LOOPS, benchtime) + print "This machine benchmarks at %g pystones/second" % stones + + stats = hotshot.stats.load(logfile) + stats.strip_dirs() + stats.sort_stats('time', 'calls') + try: + stats.print_stats(20) + except IOError, e: + if e.errno != errno.EPIPE: + raise + +if __name__ == '__main__': + if sys.argv[1:]: + main(sys.argv[1]) + else: + import tempfile + main(tempfile.NamedTemporaryFile().name) diff --git a/PythonHome/Lib/hotshot/stones.pyc b/PythonHome/Lib/hotshot/stones.pyc deleted file mode 100644 index 5d73a6914f9d369891ae2e9856dabbc1e81bd32c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1126 zcmah{U2fAr5T3P@rb!dpMioB-2}`I_5F%Uv5E3d-scNI7Qc)Dixbdd3V|(45ZKX)* z3*`uX;3V9DK5!il05fYFc*F5dW@o?o`M$OLv(x%^@@X`M@^R_^4K4giCZtzD0xAsFm|hW4aRi{9r!|tYakmCy0CCS-+*)>UWc#-kF^F#XVw0}wE%H`Q&nif zxM|Ou5VznOAl?8*WOkrYuTH~7zvwxf3Ub$Iap)~A{6WT0hJY1t(iJ%ZVh0R0t3h1n z;KYF|dR=?8#vKGPEfI~%S%;MaGZ*f@|3GwB*5T52s7B}KI!^<=Krb+a@baPx zzCbxuS!il37gaMX;50}QjCRQDZF9UqX08mx+!xMFEKgpsa4zDY5EQ zR8AC1vq53szmysymHECsIXF5RjI4(yFlg%~DhN%Bz-V-o`(dQ9*eY%O0>-6s9c9&? zN8LZ#)0!YmMQWWX>+KEp2YXgWJ9nbaEC>E@a?>PhHL@D8*j8j5a(%-X*&_qi;63vC zlY{7VQmQg3(EWUA=T3tt<3aEd=ZH=5P_!JEY}4tAme>-m*rsS#Sb=<>@xC8%n_ipD zkX0W#WK4%l*`!}Eb}52%dki!rI5oB1hfH^PpQ9|h?`J_ONnF0!K%ZUOsF7)IX?H1l wNPzH|B1#8(`HpXt!JPM(?Ee{ax0k63FB18hDIkA1ZBhQ5X16UmV#jHV-#_Z^>i_@% diff --git a/PythonHome/Lib/htmlentitydefs.py b/PythonHome/Lib/htmlentitydefs.py new file mode 100644 index 0000000000..3dd14a79fa --- /dev/null +++ b/PythonHome/Lib/htmlentitydefs.py @@ -0,0 +1,273 @@ +"""HTML character entity references.""" + +# maps the HTML entity name to the Unicode codepoint +name2codepoint = { + 'AElig': 0x00c6, # latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1 + 'Aacute': 0x00c1, # latin capital letter A with acute, U+00C1 ISOlat1 + 'Acirc': 0x00c2, # latin capital letter A with circumflex, U+00C2 ISOlat1 + 'Agrave': 0x00c0, # latin capital letter A with grave = latin capital letter A grave, U+00C0 ISOlat1 + 'Alpha': 0x0391, # greek capital letter alpha, U+0391 + 'Aring': 0x00c5, # latin capital letter A with ring above = latin capital letter A ring, U+00C5 ISOlat1 + 'Atilde': 0x00c3, # latin capital letter A with tilde, U+00C3 ISOlat1 + 'Auml': 0x00c4, # latin capital letter A with diaeresis, U+00C4 ISOlat1 + 'Beta': 0x0392, # greek capital letter beta, U+0392 + 'Ccedil': 0x00c7, # latin capital letter C with cedilla, U+00C7 ISOlat1 + 'Chi': 0x03a7, # greek capital letter chi, U+03A7 + 'Dagger': 0x2021, # double dagger, U+2021 ISOpub + 'Delta': 0x0394, # greek capital letter delta, U+0394 ISOgrk3 + 'ETH': 0x00d0, # latin capital letter ETH, U+00D0 ISOlat1 + 'Eacute': 0x00c9, # latin capital letter E with acute, U+00C9 ISOlat1 + 'Ecirc': 0x00ca, # latin capital letter E with circumflex, U+00CA ISOlat1 + 'Egrave': 0x00c8, # latin capital letter E with grave, U+00C8 ISOlat1 + 'Epsilon': 0x0395, # greek capital letter epsilon, U+0395 + 'Eta': 0x0397, # greek capital letter eta, U+0397 + 'Euml': 0x00cb, # latin capital letter E with diaeresis, U+00CB ISOlat1 + 'Gamma': 0x0393, # greek capital letter gamma, U+0393 ISOgrk3 + 'Iacute': 0x00cd, # latin capital letter I with acute, U+00CD ISOlat1 + 'Icirc': 0x00ce, # latin capital letter I with circumflex, U+00CE ISOlat1 + 'Igrave': 0x00cc, # latin capital letter I with grave, U+00CC ISOlat1 + 'Iota': 0x0399, # greek capital letter iota, U+0399 + 'Iuml': 0x00cf, # latin capital letter I with diaeresis, U+00CF ISOlat1 + 'Kappa': 0x039a, # greek capital letter kappa, U+039A + 'Lambda': 0x039b, # greek capital letter lambda, U+039B ISOgrk3 + 'Mu': 0x039c, # greek capital letter mu, U+039C + 'Ntilde': 0x00d1, # latin capital letter N with tilde, U+00D1 ISOlat1 + 'Nu': 0x039d, # greek capital letter nu, U+039D + 'OElig': 0x0152, # latin capital ligature OE, U+0152 ISOlat2 + 'Oacute': 0x00d3, # latin capital letter O with acute, U+00D3 ISOlat1 + 'Ocirc': 0x00d4, # latin capital letter O with circumflex, U+00D4 ISOlat1 + 'Ograve': 0x00d2, # latin capital letter O with grave, U+00D2 ISOlat1 + 'Omega': 0x03a9, # greek capital letter omega, U+03A9 ISOgrk3 + 'Omicron': 0x039f, # greek capital letter omicron, U+039F + 'Oslash': 0x00d8, # latin capital letter O with stroke = latin capital letter O slash, U+00D8 ISOlat1 + 'Otilde': 0x00d5, # latin capital letter O with tilde, U+00D5 ISOlat1 + 'Ouml': 0x00d6, # latin capital letter O with diaeresis, U+00D6 ISOlat1 + 'Phi': 0x03a6, # greek capital letter phi, U+03A6 ISOgrk3 + 'Pi': 0x03a0, # greek capital letter pi, U+03A0 ISOgrk3 + 'Prime': 0x2033, # double prime = seconds = inches, U+2033 ISOtech + 'Psi': 0x03a8, # greek capital letter psi, U+03A8 ISOgrk3 + 'Rho': 0x03a1, # greek capital letter rho, U+03A1 + 'Scaron': 0x0160, # latin capital letter S with caron, U+0160 ISOlat2 + 'Sigma': 0x03a3, # greek capital letter sigma, U+03A3 ISOgrk3 + 'THORN': 0x00de, # latin capital letter THORN, U+00DE ISOlat1 + 'Tau': 0x03a4, # greek capital letter tau, U+03A4 + 'Theta': 0x0398, # greek capital letter theta, U+0398 ISOgrk3 + 'Uacute': 0x00da, # latin capital letter U with acute, U+00DA ISOlat1 + 'Ucirc': 0x00db, # latin capital letter U with circumflex, U+00DB ISOlat1 + 'Ugrave': 0x00d9, # latin capital letter U with grave, U+00D9 ISOlat1 + 'Upsilon': 0x03a5, # greek capital letter upsilon, U+03A5 ISOgrk3 + 'Uuml': 0x00dc, # latin capital letter U with diaeresis, U+00DC ISOlat1 + 'Xi': 0x039e, # greek capital letter xi, U+039E ISOgrk3 + 'Yacute': 0x00dd, # latin capital letter Y with acute, U+00DD ISOlat1 + 'Yuml': 0x0178, # latin capital letter Y with diaeresis, U+0178 ISOlat2 + 'Zeta': 0x0396, # greek capital letter zeta, U+0396 + 'aacute': 0x00e1, # latin small letter a with acute, U+00E1 ISOlat1 + 'acirc': 0x00e2, # latin small letter a with circumflex, U+00E2 ISOlat1 + 'acute': 0x00b4, # acute accent = spacing acute, U+00B4 ISOdia + 'aelig': 0x00e6, # latin small letter ae = latin small ligature ae, U+00E6 ISOlat1 + 'agrave': 0x00e0, # latin small letter a with grave = latin small letter a grave, U+00E0 ISOlat1 + 'alefsym': 0x2135, # alef symbol = first transfinite cardinal, U+2135 NEW + 'alpha': 0x03b1, # greek small letter alpha, U+03B1 ISOgrk3 + 'amp': 0x0026, # ampersand, U+0026 ISOnum + 'and': 0x2227, # logical and = wedge, U+2227 ISOtech + 'ang': 0x2220, # angle, U+2220 ISOamso + 'aring': 0x00e5, # latin small letter a with ring above = latin small letter a ring, U+00E5 ISOlat1 + 'asymp': 0x2248, # almost equal to = asymptotic to, U+2248 ISOamsr + 'atilde': 0x00e3, # latin small letter a with tilde, U+00E3 ISOlat1 + 'auml': 0x00e4, # latin small letter a with diaeresis, U+00E4 ISOlat1 + 'bdquo': 0x201e, # double low-9 quotation mark, U+201E NEW + 'beta': 0x03b2, # greek small letter beta, U+03B2 ISOgrk3 + 'brvbar': 0x00a6, # broken bar = broken vertical bar, U+00A6 ISOnum + 'bull': 0x2022, # bullet = black small circle, U+2022 ISOpub + 'cap': 0x2229, # intersection = cap, U+2229 ISOtech + 'ccedil': 0x00e7, # latin small letter c with cedilla, U+00E7 ISOlat1 + 'cedil': 0x00b8, # cedilla = spacing cedilla, U+00B8 ISOdia + 'cent': 0x00a2, # cent sign, U+00A2 ISOnum + 'chi': 0x03c7, # greek small letter chi, U+03C7 ISOgrk3 + 'circ': 0x02c6, # modifier letter circumflex accent, U+02C6 ISOpub + 'clubs': 0x2663, # black club suit = shamrock, U+2663 ISOpub + 'cong': 0x2245, # approximately equal to, U+2245 ISOtech + 'copy': 0x00a9, # copyright sign, U+00A9 ISOnum + 'crarr': 0x21b5, # downwards arrow with corner leftwards = carriage return, U+21B5 NEW + 'cup': 0x222a, # union = cup, U+222A ISOtech + 'curren': 0x00a4, # currency sign, U+00A4 ISOnum + 'dArr': 0x21d3, # downwards double arrow, U+21D3 ISOamsa + 'dagger': 0x2020, # dagger, U+2020 ISOpub + 'darr': 0x2193, # downwards arrow, U+2193 ISOnum + 'deg': 0x00b0, # degree sign, U+00B0 ISOnum + 'delta': 0x03b4, # greek small letter delta, U+03B4 ISOgrk3 + 'diams': 0x2666, # black diamond suit, U+2666 ISOpub + 'divide': 0x00f7, # division sign, U+00F7 ISOnum + 'eacute': 0x00e9, # latin small letter e with acute, U+00E9 ISOlat1 + 'ecirc': 0x00ea, # latin small letter e with circumflex, U+00EA ISOlat1 + 'egrave': 0x00e8, # latin small letter e with grave, U+00E8 ISOlat1 + 'empty': 0x2205, # empty set = null set = diameter, U+2205 ISOamso + 'emsp': 0x2003, # em space, U+2003 ISOpub + 'ensp': 0x2002, # en space, U+2002 ISOpub + 'epsilon': 0x03b5, # greek small letter epsilon, U+03B5 ISOgrk3 + 'equiv': 0x2261, # identical to, U+2261 ISOtech + 'eta': 0x03b7, # greek small letter eta, U+03B7 ISOgrk3 + 'eth': 0x00f0, # latin small letter eth, U+00F0 ISOlat1 + 'euml': 0x00eb, # latin small letter e with diaeresis, U+00EB ISOlat1 + 'euro': 0x20ac, # euro sign, U+20AC NEW + 'exist': 0x2203, # there exists, U+2203 ISOtech + 'fnof': 0x0192, # latin small f with hook = function = florin, U+0192 ISOtech + 'forall': 0x2200, # for all, U+2200 ISOtech + 'frac12': 0x00bd, # vulgar fraction one half = fraction one half, U+00BD ISOnum + 'frac14': 0x00bc, # vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum + 'frac34': 0x00be, # vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum + 'frasl': 0x2044, # fraction slash, U+2044 NEW + 'gamma': 0x03b3, # greek small letter gamma, U+03B3 ISOgrk3 + 'ge': 0x2265, # greater-than or equal to, U+2265 ISOtech + 'gt': 0x003e, # greater-than sign, U+003E ISOnum + 'hArr': 0x21d4, # left right double arrow, U+21D4 ISOamsa + 'harr': 0x2194, # left right arrow, U+2194 ISOamsa + 'hearts': 0x2665, # black heart suit = valentine, U+2665 ISOpub + 'hellip': 0x2026, # horizontal ellipsis = three dot leader, U+2026 ISOpub + 'iacute': 0x00ed, # latin small letter i with acute, U+00ED ISOlat1 + 'icirc': 0x00ee, # latin small letter i with circumflex, U+00EE ISOlat1 + 'iexcl': 0x00a1, # inverted exclamation mark, U+00A1 ISOnum + 'igrave': 0x00ec, # latin small letter i with grave, U+00EC ISOlat1 + 'image': 0x2111, # blackletter capital I = imaginary part, U+2111 ISOamso + 'infin': 0x221e, # infinity, U+221E ISOtech + 'int': 0x222b, # integral, U+222B ISOtech + 'iota': 0x03b9, # greek small letter iota, U+03B9 ISOgrk3 + 'iquest': 0x00bf, # inverted question mark = turned question mark, U+00BF ISOnum + 'isin': 0x2208, # element of, U+2208 ISOtech + 'iuml': 0x00ef, # latin small letter i with diaeresis, U+00EF ISOlat1 + 'kappa': 0x03ba, # greek small letter kappa, U+03BA ISOgrk3 + 'lArr': 0x21d0, # leftwards double arrow, U+21D0 ISOtech + 'lambda': 0x03bb, # greek small letter lambda, U+03BB ISOgrk3 + 'lang': 0x2329, # left-pointing angle bracket = bra, U+2329 ISOtech + 'laquo': 0x00ab, # left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum + 'larr': 0x2190, # leftwards arrow, U+2190 ISOnum + 'lceil': 0x2308, # left ceiling = apl upstile, U+2308 ISOamsc + 'ldquo': 0x201c, # left double quotation mark, U+201C ISOnum + 'le': 0x2264, # less-than or equal to, U+2264 ISOtech + 'lfloor': 0x230a, # left floor = apl downstile, U+230A ISOamsc + 'lowast': 0x2217, # asterisk operator, U+2217 ISOtech + 'loz': 0x25ca, # lozenge, U+25CA ISOpub + 'lrm': 0x200e, # left-to-right mark, U+200E NEW RFC 2070 + 'lsaquo': 0x2039, # single left-pointing angle quotation mark, U+2039 ISO proposed + 'lsquo': 0x2018, # left single quotation mark, U+2018 ISOnum + 'lt': 0x003c, # less-than sign, U+003C ISOnum + 'macr': 0x00af, # macron = spacing macron = overline = APL overbar, U+00AF ISOdia + 'mdash': 0x2014, # em dash, U+2014 ISOpub + 'micro': 0x00b5, # micro sign, U+00B5 ISOnum + 'middot': 0x00b7, # middle dot = Georgian comma = Greek middle dot, U+00B7 ISOnum + 'minus': 0x2212, # minus sign, U+2212 ISOtech + 'mu': 0x03bc, # greek small letter mu, U+03BC ISOgrk3 + 'nabla': 0x2207, # nabla = backward difference, U+2207 ISOtech + 'nbsp': 0x00a0, # no-break space = non-breaking space, U+00A0 ISOnum + 'ndash': 0x2013, # en dash, U+2013 ISOpub + 'ne': 0x2260, # not equal to, U+2260 ISOtech + 'ni': 0x220b, # contains as member, U+220B ISOtech + 'not': 0x00ac, # not sign, U+00AC ISOnum + 'notin': 0x2209, # not an element of, U+2209 ISOtech + 'nsub': 0x2284, # not a subset of, U+2284 ISOamsn + 'ntilde': 0x00f1, # latin small letter n with tilde, U+00F1 ISOlat1 + 'nu': 0x03bd, # greek small letter nu, U+03BD ISOgrk3 + 'oacute': 0x00f3, # latin small letter o with acute, U+00F3 ISOlat1 + 'ocirc': 0x00f4, # latin small letter o with circumflex, U+00F4 ISOlat1 + 'oelig': 0x0153, # latin small ligature oe, U+0153 ISOlat2 + 'ograve': 0x00f2, # latin small letter o with grave, U+00F2 ISOlat1 + 'oline': 0x203e, # overline = spacing overscore, U+203E NEW + 'omega': 0x03c9, # greek small letter omega, U+03C9 ISOgrk3 + 'omicron': 0x03bf, # greek small letter omicron, U+03BF NEW + 'oplus': 0x2295, # circled plus = direct sum, U+2295 ISOamsb + 'or': 0x2228, # logical or = vee, U+2228 ISOtech + 'ordf': 0x00aa, # feminine ordinal indicator, U+00AA ISOnum + 'ordm': 0x00ba, # masculine ordinal indicator, U+00BA ISOnum + 'oslash': 0x00f8, # latin small letter o with stroke, = latin small letter o slash, U+00F8 ISOlat1 + 'otilde': 0x00f5, # latin small letter o with tilde, U+00F5 ISOlat1 + 'otimes': 0x2297, # circled times = vector product, U+2297 ISOamsb + 'ouml': 0x00f6, # latin small letter o with diaeresis, U+00F6 ISOlat1 + 'para': 0x00b6, # pilcrow sign = paragraph sign, U+00B6 ISOnum + 'part': 0x2202, # partial differential, U+2202 ISOtech + 'permil': 0x2030, # per mille sign, U+2030 ISOtech + 'perp': 0x22a5, # up tack = orthogonal to = perpendicular, U+22A5 ISOtech + 'phi': 0x03c6, # greek small letter phi, U+03C6 ISOgrk3 + 'pi': 0x03c0, # greek small letter pi, U+03C0 ISOgrk3 + 'piv': 0x03d6, # greek pi symbol, U+03D6 ISOgrk3 + 'plusmn': 0x00b1, # plus-minus sign = plus-or-minus sign, U+00B1 ISOnum + 'pound': 0x00a3, # pound sign, U+00A3 ISOnum + 'prime': 0x2032, # prime = minutes = feet, U+2032 ISOtech + 'prod': 0x220f, # n-ary product = product sign, U+220F ISOamsb + 'prop': 0x221d, # proportional to, U+221D ISOtech + 'psi': 0x03c8, # greek small letter psi, U+03C8 ISOgrk3 + 'quot': 0x0022, # quotation mark = APL quote, U+0022 ISOnum + 'rArr': 0x21d2, # rightwards double arrow, U+21D2 ISOtech + 'radic': 0x221a, # square root = radical sign, U+221A ISOtech + 'rang': 0x232a, # right-pointing angle bracket = ket, U+232A ISOtech + 'raquo': 0x00bb, # right-pointing double angle quotation mark = right pointing guillemet, U+00BB ISOnum + 'rarr': 0x2192, # rightwards arrow, U+2192 ISOnum + 'rceil': 0x2309, # right ceiling, U+2309 ISOamsc + 'rdquo': 0x201d, # right double quotation mark, U+201D ISOnum + 'real': 0x211c, # blackletter capital R = real part symbol, U+211C ISOamso + 'reg': 0x00ae, # registered sign = registered trade mark sign, U+00AE ISOnum + 'rfloor': 0x230b, # right floor, U+230B ISOamsc + 'rho': 0x03c1, # greek small letter rho, U+03C1 ISOgrk3 + 'rlm': 0x200f, # right-to-left mark, U+200F NEW RFC 2070 + 'rsaquo': 0x203a, # single right-pointing angle quotation mark, U+203A ISO proposed + 'rsquo': 0x2019, # right single quotation mark, U+2019 ISOnum + 'sbquo': 0x201a, # single low-9 quotation mark, U+201A NEW + 'scaron': 0x0161, # latin small letter s with caron, U+0161 ISOlat2 + 'sdot': 0x22c5, # dot operator, U+22C5 ISOamsb + 'sect': 0x00a7, # section sign, U+00A7 ISOnum + 'shy': 0x00ad, # soft hyphen = discretionary hyphen, U+00AD ISOnum + 'sigma': 0x03c3, # greek small letter sigma, U+03C3 ISOgrk3 + 'sigmaf': 0x03c2, # greek small letter final sigma, U+03C2 ISOgrk3 + 'sim': 0x223c, # tilde operator = varies with = similar to, U+223C ISOtech + 'spades': 0x2660, # black spade suit, U+2660 ISOpub + 'sub': 0x2282, # subset of, U+2282 ISOtech + 'sube': 0x2286, # subset of or equal to, U+2286 ISOtech + 'sum': 0x2211, # n-ary sumation, U+2211 ISOamsb + 'sup': 0x2283, # superset of, U+2283 ISOtech + 'sup1': 0x00b9, # superscript one = superscript digit one, U+00B9 ISOnum + 'sup2': 0x00b2, # superscript two = superscript digit two = squared, U+00B2 ISOnum + 'sup3': 0x00b3, # superscript three = superscript digit three = cubed, U+00B3 ISOnum + 'supe': 0x2287, # superset of or equal to, U+2287 ISOtech + 'szlig': 0x00df, # latin small letter sharp s = ess-zed, U+00DF ISOlat1 + 'tau': 0x03c4, # greek small letter tau, U+03C4 ISOgrk3 + 'there4': 0x2234, # therefore, U+2234 ISOtech + 'theta': 0x03b8, # greek small letter theta, U+03B8 ISOgrk3 + 'thetasym': 0x03d1, # greek small letter theta symbol, U+03D1 NEW + 'thinsp': 0x2009, # thin space, U+2009 ISOpub + 'thorn': 0x00fe, # latin small letter thorn with, U+00FE ISOlat1 + 'tilde': 0x02dc, # small tilde, U+02DC ISOdia + 'times': 0x00d7, # multiplication sign, U+00D7 ISOnum + 'trade': 0x2122, # trade mark sign, U+2122 ISOnum + 'uArr': 0x21d1, # upwards double arrow, U+21D1 ISOamsa + 'uacute': 0x00fa, # latin small letter u with acute, U+00FA ISOlat1 + 'uarr': 0x2191, # upwards arrow, U+2191 ISOnum + 'ucirc': 0x00fb, # latin small letter u with circumflex, U+00FB ISOlat1 + 'ugrave': 0x00f9, # latin small letter u with grave, U+00F9 ISOlat1 + 'uml': 0x00a8, # diaeresis = spacing diaeresis, U+00A8 ISOdia + 'upsih': 0x03d2, # greek upsilon with hook symbol, U+03D2 NEW + 'upsilon': 0x03c5, # greek small letter upsilon, U+03C5 ISOgrk3 + 'uuml': 0x00fc, # latin small letter u with diaeresis, U+00FC ISOlat1 + 'weierp': 0x2118, # script capital P = power set = Weierstrass p, U+2118 ISOamso + 'xi': 0x03be, # greek small letter xi, U+03BE ISOgrk3 + 'yacute': 0x00fd, # latin small letter y with acute, U+00FD ISOlat1 + 'yen': 0x00a5, # yen sign = yuan sign, U+00A5 ISOnum + 'yuml': 0x00ff, # latin small letter y with diaeresis, U+00FF ISOlat1 + 'zeta': 0x03b6, # greek small letter zeta, U+03B6 ISOgrk3 + 'zwj': 0x200d, # zero width joiner, U+200D NEW RFC 2070 + 'zwnj': 0x200c, # zero width non-joiner, U+200C NEW RFC 2070 +} + +# maps the Unicode codepoint to the HTML entity name +codepoint2name = {} + +# maps the HTML entity name to the character +# (or a character reference if the character is outside the Latin-1 range) +entitydefs = {} + +for (name, codepoint) in name2codepoint.iteritems(): + codepoint2name[codepoint] = name + if codepoint <= 0xff: + entitydefs[name] = chr(codepoint) + else: + entitydefs[name] = '&#%d;' % codepoint + +del name, codepoint diff --git a/PythonHome/Lib/htmlentitydefs.pyc b/PythonHome/Lib/htmlentitydefs.pyc index 5805462935e68aa30526bd214e04b8ff2e329a35..cc773558ff9f95275403d099b5154a19afe136d7 100644 GIT binary patch delta 62 zcmca*_{VU=R53$m1_p*ytC;l6l8n-%nDG1xJ+EMYzn}o;82{3eg3^*0m(--v^q7Fk Rl8pR3kNn)!%}d10m;lF*7O4OL delta 28 jcmexkc*}6ZR55-<1_lOatC)bwl8pR3BlFG2#LSogkOm1) diff --git a/PythonHome/Lib/htmllib.py b/PythonHome/Lib/htmllib.py new file mode 100644 index 0000000000..44647dbf02 --- /dev/null +++ b/PythonHome/Lib/htmllib.py @@ -0,0 +1,491 @@ +"""HTML 2.0 parser. + +See the HTML 2.0 specification: +http://www.w3.org/hypertext/WWW/MarkUp/html-spec/html-spec_toc.html +""" + +from warnings import warnpy3k +warnpy3k("the htmllib module has been removed in Python 3.0", + stacklevel=2) +del warnpy3k + +import sgmllib + +from formatter import AS_IS + +__all__ = ["HTMLParser", "HTMLParseError"] + + +class HTMLParseError(sgmllib.SGMLParseError): + """Error raised when an HTML document can't be parsed.""" + + +class HTMLParser(sgmllib.SGMLParser): + """This is the basic HTML parser class. + + It supports all entity names required by the XHTML 1.0 Recommendation. + It also defines handlers for all HTML 2.0 and many HTML 3.0 and 3.2 + elements. + + """ + + from htmlentitydefs import entitydefs + + def __init__(self, formatter, verbose=0): + """Creates an instance of the HTMLParser class. + + The formatter parameter is the formatter instance associated with + the parser. + + """ + sgmllib.SGMLParser.__init__(self, verbose) + self.formatter = formatter + + def error(self, message): + raise HTMLParseError(message) + + def reset(self): + sgmllib.SGMLParser.reset(self) + self.savedata = None + self.isindex = 0 + self.title = None + self.base = None + self.anchor = None + self.anchorlist = [] + self.nofill = 0 + self.list_stack = [] + + # ------ Methods used internally; some may be overridden + + # --- Formatter interface, taking care of 'savedata' mode; + # shouldn't need to be overridden + + def handle_data(self, data): + if self.savedata is not None: + self.savedata = self.savedata + data + else: + if self.nofill: + self.formatter.add_literal_data(data) + else: + self.formatter.add_flowing_data(data) + + # --- Hooks to save data; shouldn't need to be overridden + + def save_bgn(self): + """Begins saving character data in a buffer instead of sending it + to the formatter object. + + Retrieve the stored data via the save_end() method. Use of the + save_bgn() / save_end() pair may not be nested. + + """ + self.savedata = '' + + def save_end(self): + """Ends buffering character data and returns all data saved since + the preceding call to the save_bgn() method. + + If the nofill flag is false, whitespace is collapsed to single + spaces. A call to this method without a preceding call to the + save_bgn() method will raise a TypeError exception. + + """ + data = self.savedata + self.savedata = None + if not self.nofill: + data = ' '.join(data.split()) + return data + + # --- Hooks for anchors; should probably be overridden + + def anchor_bgn(self, href, name, type): + """This method is called at the start of an anchor region. + + The arguments correspond to the attributes of the tag with + the same names. The default implementation maintains a list of + hyperlinks (defined by the HREF attribute for tags) within + the document. The list of hyperlinks is available as the data + attribute anchorlist. + + """ + self.anchor = href + if self.anchor: + self.anchorlist.append(href) + + def anchor_end(self): + """This method is called at the end of an anchor region. + + The default implementation adds a textual footnote marker using an + index into the list of hyperlinks created by the anchor_bgn()method. + + """ + if self.anchor: + self.handle_data("[%d]" % len(self.anchorlist)) + self.anchor = None + + # --- Hook for images; should probably be overridden + + def handle_image(self, src, alt, *args): + """This method is called to handle images. + + The default implementation simply passes the alt value to the + handle_data() method. + + """ + self.handle_data(alt) + + # --------- Top level elememts + + def start_html(self, attrs): pass + def end_html(self): pass + + def start_head(self, attrs): pass + def end_head(self): pass + + def start_body(self, attrs): pass + def end_body(self): pass + + # ------ Head elements + + def start_title(self, attrs): + self.save_bgn() + + def end_title(self): + self.title = self.save_end() + + def do_base(self, attrs): + for a, v in attrs: + if a == 'href': + self.base = v + + def do_isindex(self, attrs): + self.isindex = 1 + + def do_link(self, attrs): + pass + + def do_meta(self, attrs): + pass + + def do_nextid(self, attrs): # Deprecated + pass + + # ------ Body elements + + # --- Headings + + def start_h1(self, attrs): + self.formatter.end_paragraph(1) + self.formatter.push_font(('h1', 0, 1, 0)) + + def end_h1(self): + self.formatter.end_paragraph(1) + self.formatter.pop_font() + + def start_h2(self, attrs): + self.formatter.end_paragraph(1) + self.formatter.push_font(('h2', 0, 1, 0)) + + def end_h2(self): + self.formatter.end_paragraph(1) + self.formatter.pop_font() + + def start_h3(self, attrs): + self.formatter.end_paragraph(1) + self.formatter.push_font(('h3', 0, 1, 0)) + + def end_h3(self): + self.formatter.end_paragraph(1) + self.formatter.pop_font() + + def start_h4(self, attrs): + self.formatter.end_paragraph(1) + self.formatter.push_font(('h4', 0, 1, 0)) + + def end_h4(self): + self.formatter.end_paragraph(1) + self.formatter.pop_font() + + def start_h5(self, attrs): + self.formatter.end_paragraph(1) + self.formatter.push_font(('h5', 0, 1, 0)) + + def end_h5(self): + self.formatter.end_paragraph(1) + self.formatter.pop_font() + + def start_h6(self, attrs): + self.formatter.end_paragraph(1) + self.formatter.push_font(('h6', 0, 1, 0)) + + def end_h6(self): + self.formatter.end_paragraph(1) + self.formatter.pop_font() + + # --- Block Structuring Elements + + def do_p(self, attrs): + self.formatter.end_paragraph(1) + + def start_pre(self, attrs): + self.formatter.end_paragraph(1) + self.formatter.push_font((AS_IS, AS_IS, AS_IS, 1)) + self.nofill = self.nofill + 1 + + def end_pre(self): + self.formatter.end_paragraph(1) + self.formatter.pop_font() + self.nofill = max(0, self.nofill - 1) + + def start_xmp(self, attrs): + self.start_pre(attrs) + self.setliteral('xmp') # Tell SGML parser + + def end_xmp(self): + self.end_pre() + + def start_listing(self, attrs): + self.start_pre(attrs) + self.setliteral('listing') # Tell SGML parser + + def end_listing(self): + self.end_pre() + + def start_address(self, attrs): + self.formatter.end_paragraph(0) + self.formatter.push_font((AS_IS, 1, AS_IS, AS_IS)) + + def end_address(self): + self.formatter.end_paragraph(0) + self.formatter.pop_font() + + def start_blockquote(self, attrs): + self.formatter.end_paragraph(1) + self.formatter.push_margin('blockquote') + + def end_blockquote(self): + self.formatter.end_paragraph(1) + self.formatter.pop_margin() + + # --- List Elements + + def start_ul(self, attrs): + self.formatter.end_paragraph(not self.list_stack) + self.formatter.push_margin('ul') + self.list_stack.append(['ul', '*', 0]) + + def end_ul(self): + if self.list_stack: del self.list_stack[-1] + self.formatter.end_paragraph(not self.list_stack) + self.formatter.pop_margin() + + def do_li(self, attrs): + self.formatter.end_paragraph(0) + if self.list_stack: + [dummy, label, counter] = top = self.list_stack[-1] + top[2] = counter = counter+1 + else: + label, counter = '*', 0 + self.formatter.add_label_data(label, counter) + + def start_ol(self, attrs): + self.formatter.end_paragraph(not self.list_stack) + self.formatter.push_margin('ol') + label = '1.' + for a, v in attrs: + if a == 'type': + if len(v) == 1: v = v + '.' + label = v + self.list_stack.append(['ol', label, 0]) + + def end_ol(self): + if self.list_stack: del self.list_stack[-1] + self.formatter.end_paragraph(not self.list_stack) + self.formatter.pop_margin() + + def start_menu(self, attrs): + self.start_ul(attrs) + + def end_menu(self): + self.end_ul() + + def start_dir(self, attrs): + self.start_ul(attrs) + + def end_dir(self): + self.end_ul() + + def start_dl(self, attrs): + self.formatter.end_paragraph(1) + self.list_stack.append(['dl', '', 0]) + + def end_dl(self): + self.ddpop(1) + if self.list_stack: del self.list_stack[-1] + + def do_dt(self, attrs): + self.ddpop() + + def do_dd(self, attrs): + self.ddpop() + self.formatter.push_margin('dd') + self.list_stack.append(['dd', '', 0]) + + def ddpop(self, bl=0): + self.formatter.end_paragraph(bl) + if self.list_stack: + if self.list_stack[-1][0] == 'dd': + del self.list_stack[-1] + self.formatter.pop_margin() + + # --- Phrase Markup + + # Idiomatic Elements + + def start_cite(self, attrs): self.start_i(attrs) + def end_cite(self): self.end_i() + + def start_code(self, attrs): self.start_tt(attrs) + def end_code(self): self.end_tt() + + def start_em(self, attrs): self.start_i(attrs) + def end_em(self): self.end_i() + + def start_kbd(self, attrs): self.start_tt(attrs) + def end_kbd(self): self.end_tt() + + def start_samp(self, attrs): self.start_tt(attrs) + def end_samp(self): self.end_tt() + + def start_strong(self, attrs): self.start_b(attrs) + def end_strong(self): self.end_b() + + def start_var(self, attrs): self.start_i(attrs) + def end_var(self): self.end_i() + + # Typographic Elements + + def start_i(self, attrs): + self.formatter.push_font((AS_IS, 1, AS_IS, AS_IS)) + def end_i(self): + self.formatter.pop_font() + + def start_b(self, attrs): + self.formatter.push_font((AS_IS, AS_IS, 1, AS_IS)) + def end_b(self): + self.formatter.pop_font() + + def start_tt(self, attrs): + self.formatter.push_font((AS_IS, AS_IS, AS_IS, 1)) + def end_tt(self): + self.formatter.pop_font() + + def start_a(self, attrs): + href = '' + name = '' + type = '' + for attrname, value in attrs: + value = value.strip() + if attrname == 'href': + href = value + if attrname == 'name': + name = value + if attrname == 'type': + type = value.lower() + self.anchor_bgn(href, name, type) + + def end_a(self): + self.anchor_end() + + # --- Line Break + + def do_br(self, attrs): + self.formatter.add_line_break() + + # --- Horizontal Rule + + def do_hr(self, attrs): + self.formatter.add_hor_rule() + + # --- Image + + def do_img(self, attrs): + align = '' + alt = '(image)' + ismap = '' + src = '' + width = 0 + height = 0 + for attrname, value in attrs: + if attrname == 'align': + align = value + if attrname == 'alt': + alt = value + if attrname == 'ismap': + ismap = value + if attrname == 'src': + src = value + if attrname == 'width': + try: width = int(value) + except ValueError: pass + if attrname == 'height': + try: height = int(value) + except ValueError: pass + self.handle_image(src, alt, ismap, align, width, height) + + # --- Really Old Unofficial Deprecated Stuff + + def do_plaintext(self, attrs): + self.start_pre(attrs) + self.setnomoretags() # Tell SGML parser + + # --- Unhandled tags + + def unknown_starttag(self, tag, attrs): + pass + + def unknown_endtag(self, tag): + pass + + +def test(args = None): + import sys, formatter + + if not args: + args = sys.argv[1:] + + silent = args and args[0] == '-s' + if silent: + del args[0] + + if args: + file = args[0] + else: + file = 'test.html' + + if file == '-': + f = sys.stdin + else: + try: + f = open(file, 'r') + except IOError, msg: + print file, ":", msg + sys.exit(1) + + data = f.read() + + if f is not sys.stdin: + f.close() + + if silent: + f = formatter.NullFormatter() + else: + f = formatter.AbstractFormatter(formatter.DumbWriter()) + + p = HTMLParser(f) + p.feed(data) + p.close() + + +if __name__ == '__main__': + test() diff --git a/PythonHome/Lib/htmllib.pyc b/PythonHome/Lib/htmllib.pyc deleted file mode 100644 index 882aff5c1d0ffb2b0f1482745662dbe1075c21a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18944 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 A + + +HTTPConnection goes through a number of "states", which define when a client +may legally make another request or fetch the response for a particular +request. This diagram details these state transitions: + + (null) + | + | HTTPConnection() + v + Idle + | + | putrequest() + v + Request-started + | + | ( putheader() )* endheaders() + v + Request-sent + | + | response = getresponse() + v + Unread-response [Response-headers-read] + |\____________________ + | | + | response.read() | putrequest() + v v + Idle Req-started-unread-response + ______/| + / | + response.read() | | ( putheader() )* endheaders() + v v + Request-started Req-sent-unread-response + | + | response.read() + v + Request-sent + +This diagram presents the following rules: + -- a second request may not be started until {response-headers-read} + -- a response [object] cannot be retrieved until {request-sent} + -- there is no differentiation between an unread response body and a + partially read response body + +Note: this enforcement is applied by the HTTPConnection class. The + HTTPResponse class does not enforce this state machine, which + implies sophisticated clients may accelerate the request/response + pipeline. Caution should be taken, though: accelerating the states + beyond the above pattern may imply knowledge of the server's + connection-close behavior for certain requests. For example, it + is impossible to tell whether the server will close the connection + UNTIL the response headers have been read; this means that further + requests cannot be placed into the pipeline until it is known that + the server will NOT be closing the connection. + +Logical State __state __response +------------- ------- ---------- +Idle _CS_IDLE None +Request-started _CS_REQ_STARTED None +Request-sent _CS_REQ_SENT None +Unread-response _CS_IDLE +Req-started-unread-response _CS_REQ_STARTED +Req-sent-unread-response _CS_REQ_SENT +""" + +from array import array +import os +import socket +from sys import py3kwarning +from urlparse import urlsplit +import warnings +with warnings.catch_warnings(): + if py3kwarning: + warnings.filterwarnings("ignore", ".*mimetools has been removed", + DeprecationWarning) + import mimetools + +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + +__all__ = ["HTTP", "HTTPResponse", "HTTPConnection", + "HTTPException", "NotConnected", "UnknownProtocol", + "UnknownTransferEncoding", "UnimplementedFileMode", + "IncompleteRead", "InvalidURL", "ImproperConnectionState", + "CannotSendRequest", "CannotSendHeader", "ResponseNotReady", + "BadStatusLine", "error", "responses"] + +HTTP_PORT = 80 +HTTPS_PORT = 443 + +_UNKNOWN = 'UNKNOWN' + +# connection states +_CS_IDLE = 'Idle' +_CS_REQ_STARTED = 'Request-started' +_CS_REQ_SENT = 'Request-sent' + +# status codes +# informational +CONTINUE = 100 +SWITCHING_PROTOCOLS = 101 +PROCESSING = 102 + +# successful +OK = 200 +CREATED = 201 +ACCEPTED = 202 +NON_AUTHORITATIVE_INFORMATION = 203 +NO_CONTENT = 204 +RESET_CONTENT = 205 +PARTIAL_CONTENT = 206 +MULTI_STATUS = 207 +IM_USED = 226 + +# redirection +MULTIPLE_CHOICES = 300 +MOVED_PERMANENTLY = 301 +FOUND = 302 +SEE_OTHER = 303 +NOT_MODIFIED = 304 +USE_PROXY = 305 +TEMPORARY_REDIRECT = 307 + +# client error +BAD_REQUEST = 400 +UNAUTHORIZED = 401 +PAYMENT_REQUIRED = 402 +FORBIDDEN = 403 +NOT_FOUND = 404 +METHOD_NOT_ALLOWED = 405 +NOT_ACCEPTABLE = 406 +PROXY_AUTHENTICATION_REQUIRED = 407 +REQUEST_TIMEOUT = 408 +CONFLICT = 409 +GONE = 410 +LENGTH_REQUIRED = 411 +PRECONDITION_FAILED = 412 +REQUEST_ENTITY_TOO_LARGE = 413 +REQUEST_URI_TOO_LONG = 414 +UNSUPPORTED_MEDIA_TYPE = 415 +REQUESTED_RANGE_NOT_SATISFIABLE = 416 +EXPECTATION_FAILED = 417 +UNPROCESSABLE_ENTITY = 422 +LOCKED = 423 +FAILED_DEPENDENCY = 424 +UPGRADE_REQUIRED = 426 + +# server error +INTERNAL_SERVER_ERROR = 500 +NOT_IMPLEMENTED = 501 +BAD_GATEWAY = 502 +SERVICE_UNAVAILABLE = 503 +GATEWAY_TIMEOUT = 504 +HTTP_VERSION_NOT_SUPPORTED = 505 +INSUFFICIENT_STORAGE = 507 +NOT_EXTENDED = 510 + +# Mapping status codes to official W3C names +responses = { + 100: 'Continue', + 101: 'Switching Protocols', + + 200: 'OK', + 201: 'Created', + 202: 'Accepted', + 203: 'Non-Authoritative Information', + 204: 'No Content', + 205: 'Reset Content', + 206: 'Partial Content', + + 300: 'Multiple Choices', + 301: 'Moved Permanently', + 302: 'Found', + 303: 'See Other', + 304: 'Not Modified', + 305: 'Use Proxy', + 306: '(Unused)', + 307: 'Temporary Redirect', + + 400: 'Bad Request', + 401: 'Unauthorized', + 402: 'Payment Required', + 403: 'Forbidden', + 404: 'Not Found', + 405: 'Method Not Allowed', + 406: 'Not Acceptable', + 407: 'Proxy Authentication Required', + 408: 'Request Timeout', + 409: 'Conflict', + 410: 'Gone', + 411: 'Length Required', + 412: 'Precondition Failed', + 413: 'Request Entity Too Large', + 414: 'Request-URI Too Long', + 415: 'Unsupported Media Type', + 416: 'Requested Range Not Satisfiable', + 417: 'Expectation Failed', + + 500: 'Internal Server Error', + 501: 'Not Implemented', + 502: 'Bad Gateway', + 503: 'Service Unavailable', + 504: 'Gateway Timeout', + 505: 'HTTP Version Not Supported', +} + +# maximal amount of data to read at one time in _safe_read +MAXAMOUNT = 1048576 + +# maximal line length when calling readline(). +_MAXLINE = 65536 + +class HTTPMessage(mimetools.Message): + + def addheader(self, key, value): + """Add header for field key handling repeats.""" + prev = self.dict.get(key) + if prev is None: + self.dict[key] = value + else: + combined = ", ".join((prev, value)) + self.dict[key] = combined + + def addcontinue(self, key, more): + """Add more field data from a continuation line.""" + prev = self.dict[key] + self.dict[key] = prev + "\n " + more + + def readheaders(self): + """Read header lines. + + Read header lines up to the entirely blank line that terminates them. + The (normally blank) line that ends the headers is skipped, but not + included in the returned list. If a non-header line ends the headers, + (which is an error), an attempt is made to backspace over it; it is + never included in the returned list. + + The variable self.status is set to the empty string if all went well, + otherwise it is an error message. The variable self.headers is a + completely uninterpreted list of lines contained in the header (so + printing them will reproduce the header exactly as it appears in the + file). + + If multiple header fields with the same name occur, they are combined + according to the rules in RFC 2616 sec 4.2: + + Appending each subsequent field-value to the first, each separated + by a comma. The order in which header fields with the same field-name + are received is significant to the interpretation of the combined + field value. + """ + # XXX The implementation overrides the readheaders() method of + # rfc822.Message. The base class design isn't amenable to + # customized behavior here so the method here is a copy of the + # base class code with a few small changes. + + self.dict = {} + self.unixfrom = '' + self.headers = hlist = [] + self.status = '' + headerseen = "" + firstline = 1 + startofline = unread = tell = None + if hasattr(self.fp, 'unread'): + unread = self.fp.unread + elif self.seekable: + tell = self.fp.tell + while True: + if tell: + try: + startofline = tell() + except IOError: + startofline = tell = None + self.seekable = 0 + line = self.fp.readline(_MAXLINE + 1) + if len(line) > _MAXLINE: + raise LineTooLong("header line") + if not line: + self.status = 'EOF in headers' + break + # Skip unix From name time lines + if firstline and line.startswith('From '): + self.unixfrom = self.unixfrom + line + continue + firstline = 0 + if headerseen and line[0] in ' \t': + # XXX Not sure if continuation lines are handled properly + # for http and/or for repeating headers + # It's a continuation line. + hlist.append(line) + self.addcontinue(headerseen, line.strip()) + continue + elif self.iscomment(line): + # It's a comment. Ignore it. + continue + elif self.islast(line): + # Note! No pushback here! The delimiter line gets eaten. + break + headerseen = self.isheader(line) + if headerseen: + # It's a legal header line, save it. + hlist.append(line) + self.addheader(headerseen, line[len(headerseen)+1:].strip()) + continue + else: + # It's not a header line; throw it back and stop here. + if not self.dict: + self.status = 'No headers' + else: + self.status = 'Non-header line where header expected' + # Try to undo the read. + if unread: + unread(line) + elif tell: + self.fp.seek(startofline) + else: + self.status = self.status + '; bad seek' + break + +class HTTPResponse: + + # strict: If true, raise BadStatusLine if the status line can't be + # parsed as a valid HTTP/1.0 or 1.1 status line. By default it is + # false because it prevents clients from talking to HTTP/0.9 + # servers. Note that a response with a sufficiently corrupted + # status line will look like an HTTP/0.9 response. + + # See RFC 2616 sec 19.6 and RFC 1945 sec 6 for details. + + def __init__(self, sock, debuglevel=0, strict=0, method=None, buffering=False): + if buffering: + # The caller won't be using any sock.recv() calls, so buffering + # is fine and recommended for performance. + self.fp = sock.makefile('rb') + else: + # The buffer size is specified as zero, because the headers of + # the response are read with readline(). If the reads were + # buffered the readline() calls could consume some of the + # response, which make be read via a recv() on the underlying + # socket. + self.fp = sock.makefile('rb', 0) + self.debuglevel = debuglevel + self.strict = strict + self._method = method + + self.msg = None + + # from the Status-Line of the response + self.version = _UNKNOWN # HTTP-Version + self.status = _UNKNOWN # Status-Code + self.reason = _UNKNOWN # Reason-Phrase + + self.chunked = _UNKNOWN # is "chunked" being used? + self.chunk_left = _UNKNOWN # bytes left to read in current chunk + self.length = _UNKNOWN # number of bytes left in response + self.will_close = _UNKNOWN # conn will close at end of response + + def _read_status(self): + # Initialize with Simple-Response defaults + line = self.fp.readline(_MAXLINE + 1) + if len(line) > _MAXLINE: + raise LineTooLong("header line") + if self.debuglevel > 0: + print "reply:", repr(line) + if not line: + # Presumably, the server closed the connection before + # sending a valid response. + raise BadStatusLine(line) + try: + [version, status, reason] = line.split(None, 2) + except ValueError: + try: + [version, status] = line.split(None, 1) + reason = "" + except ValueError: + # empty version will cause next test to fail and status + # will be treated as 0.9 response. + version = "" + if not version.startswith('HTTP/'): + if self.strict: + self.close() + raise BadStatusLine(line) + else: + # assume it's a Simple-Response from an 0.9 server + self.fp = LineAndFileWrapper(line, self.fp) + return "HTTP/0.9", 200, "" + + # The status code is a three-digit number + try: + status = int(status) + if status < 100 or status > 999: + raise BadStatusLine(line) + except ValueError: + raise BadStatusLine(line) + return version, status, reason + + def begin(self): + if self.msg is not None: + # we've already started reading the response + return + + # read until we get a non-100 response + while True: + version, status, reason = self._read_status() + if status != CONTINUE: + break + # skip the header from the 100 response + while True: + skip = self.fp.readline(_MAXLINE + 1) + if len(skip) > _MAXLINE: + raise LineTooLong("header line") + skip = skip.strip() + if not skip: + break + if self.debuglevel > 0: + print "header:", skip + + self.status = status + self.reason = reason.strip() + if version == 'HTTP/1.0': + self.version = 10 + elif version.startswith('HTTP/1.'): + self.version = 11 # use HTTP/1.1 code for HTTP/1.x where x>=1 + elif version == 'HTTP/0.9': + self.version = 9 + else: + raise UnknownProtocol(version) + + if self.version == 9: + self.length = None + self.chunked = 0 + self.will_close = 1 + self.msg = HTTPMessage(StringIO()) + return + + self.msg = HTTPMessage(self.fp, 0) + if self.debuglevel > 0: + for hdr in self.msg.headers: + print "header:", hdr, + + # don't let the msg keep an fp + self.msg.fp = None + + # are we using the chunked-style of transfer encoding? + tr_enc = self.msg.getheader('transfer-encoding') + if tr_enc and tr_enc.lower() == "chunked": + self.chunked = 1 + self.chunk_left = None + else: + self.chunked = 0 + + # will the connection close at the end of the response? + self.will_close = self._check_close() + + # do we have a Content-Length? + # NOTE: RFC 2616, S4.4, #3 says we ignore this if tr_enc is "chunked" + length = self.msg.getheader('content-length') + if length and not self.chunked: + try: + self.length = int(length) + except ValueError: + self.length = None + else: + if self.length < 0: # ignore nonsensical negative lengths + self.length = None + else: + self.length = None + + # does the body have a fixed length? (of zero) + if (status == NO_CONTENT or status == NOT_MODIFIED or + 100 <= status < 200 or # 1xx codes + self._method == 'HEAD'): + self.length = 0 + + # if the connection remains open, and we aren't using chunked, and + # a content-length was not provided, then assume that the connection + # WILL close. + if not self.will_close and \ + not self.chunked and \ + self.length is None: + self.will_close = 1 + + def _check_close(self): + conn = self.msg.getheader('connection') + if self.version == 11: + # An HTTP/1.1 proxy is assumed to stay open unless + # explicitly closed. + conn = self.msg.getheader('connection') + if conn and "close" in conn.lower(): + return True + return False + + # Some HTTP/1.0 implementations have support for persistent + # connections, using rules different than HTTP/1.1. + + # For older HTTP, Keep-Alive indicates persistent connection. + if self.msg.getheader('keep-alive'): + return False + + # At least Akamai returns a "Connection: Keep-Alive" header, + # which was supposed to be sent by the client. + if conn and "keep-alive" in conn.lower(): + return False + + # Proxy-Connection is a netscape hack. + pconn = self.msg.getheader('proxy-connection') + if pconn and "keep-alive" in pconn.lower(): + return False + + # otherwise, assume it will close + return True + + def close(self): + if self.fp: + self.fp.close() + self.fp = None + + def isclosed(self): + # NOTE: it is possible that we will not ever call self.close(). This + # case occurs when will_close is TRUE, length is None, and we + # read up to the last byte, but NOT past it. + # + # IMPLIES: if will_close is FALSE, then self.close() will ALWAYS be + # called, meaning self.isclosed() is meaningful. + return self.fp is None + + # XXX It would be nice to have readline and __iter__ for this, too. + + def read(self, amt=None): + if self.fp is None: + return '' + + if self._method == 'HEAD': + self.close() + return '' + + if self.chunked: + return self._read_chunked(amt) + + if amt is None: + # unbounded read + if self.length is None: + s = self.fp.read() + else: + try: + s = self._safe_read(self.length) + except IncompleteRead: + self.close() + raise + self.length = 0 + self.close() # we read everything + return s + + if self.length is not None: + if amt > self.length: + # clip the read to the "end of response" + amt = self.length + + # we do not use _safe_read() here because this may be a .will_close + # connection, and the user is reading more bytes than will be provided + # (for example, reading in 1k chunks) + s = self.fp.read(amt) + if not s and amt: + # Ideally, we would raise IncompleteRead if the content-length + # wasn't satisfied, but it might break compatibility. + self.close() + if self.length is not None: + self.length -= len(s) + if not self.length: + self.close() + + return s + + def _read_chunked(self, amt): + assert self.chunked != _UNKNOWN + chunk_left = self.chunk_left + value = [] + while True: + if chunk_left is None: + line = self.fp.readline(_MAXLINE + 1) + if len(line) > _MAXLINE: + raise LineTooLong("chunk size") + i = line.find(';') + if i >= 0: + line = line[:i] # strip chunk-extensions + try: + chunk_left = int(line, 16) + except ValueError: + # close the connection as protocol synchronisation is + # probably lost + self.close() + raise IncompleteRead(''.join(value)) + if chunk_left == 0: + break + if amt is None: + value.append(self._safe_read(chunk_left)) + elif amt < chunk_left: + value.append(self._safe_read(amt)) + self.chunk_left = chunk_left - amt + return ''.join(value) + elif amt == chunk_left: + value.append(self._safe_read(amt)) + self._safe_read(2) # toss the CRLF at the end of the chunk + self.chunk_left = None + return ''.join(value) + else: + value.append(self._safe_read(chunk_left)) + amt -= chunk_left + + # we read the whole chunk, get another + self._safe_read(2) # toss the CRLF at the end of the chunk + chunk_left = None + + # read and discard trailer up to the CRLF terminator + ### note: we shouldn't have any trailers! + while True: + line = self.fp.readline(_MAXLINE + 1) + if len(line) > _MAXLINE: + raise LineTooLong("trailer line") + if not line: + # a vanishingly small number of sites EOF without + # sending the trailer + break + if line == '\r\n': + break + + # we read everything; close the "file" + self.close() + + return ''.join(value) + + def _safe_read(self, amt): + """Read the number of bytes requested, compensating for partial reads. + + Normally, we have a blocking socket, but a read() can be interrupted + by a signal (resulting in a partial read). + + Note that we cannot distinguish between EOF and an interrupt when zero + bytes have been read. IncompleteRead() will be raised in this + situation. + + This function should be used when bytes "should" be present for + reading. If the bytes are truly not available (due to EOF), then the + IncompleteRead exception can be used to detect the problem. + """ + # NOTE(gps): As of svn r74426 socket._fileobject.read(x) will never + # return less than x bytes unless EOF is encountered. It now handles + # signal interruptions (socket.error EINTR) internally. This code + # never caught that exception anyways. It seems largely pointless. + # self.fp.read(amt) will work fine. + s = [] + while amt > 0: + chunk = self.fp.read(min(amt, MAXAMOUNT)) + if not chunk: + raise IncompleteRead(''.join(s), amt) + s.append(chunk) + amt -= len(chunk) + return ''.join(s) + + def fileno(self): + return self.fp.fileno() + + def getheader(self, name, default=None): + if self.msg is None: + raise ResponseNotReady() + return self.msg.getheader(name, default) + + def getheaders(self): + """Return list of (header, value) tuples.""" + if self.msg is None: + raise ResponseNotReady() + return self.msg.items() + + +class HTTPConnection: + + _http_vsn = 11 + _http_vsn_str = 'HTTP/1.1' + + response_class = HTTPResponse + default_port = HTTP_PORT + auto_open = 1 + debuglevel = 0 + strict = 0 + + def __init__(self, host, port=None, strict=None, + timeout=socket._GLOBAL_DEFAULT_TIMEOUT, source_address=None): + self.timeout = timeout + self.source_address = source_address + self.sock = None + self._buffer = [] + self.__response = None + self.__state = _CS_IDLE + self._method = None + self._tunnel_host = None + self._tunnel_port = None + self._tunnel_headers = {} + if strict is not None: + self.strict = strict + + (self.host, self.port) = self._get_hostport(host, port) + + # This is stored as an instance variable to allow unittests + # to replace with a suitable mock + self._create_connection = socket.create_connection + + def set_tunnel(self, host, port=None, headers=None): + """ Set up host and port for HTTP CONNECT tunnelling. + + In a connection that uses HTTP Connect tunneling, the host passed to the + constructor is used as proxy server that relays all communication to the + endpoint passed to set_tunnel. This is done by sending a HTTP CONNECT + request to the proxy server when the connection is established. + + This method must be called before the HTML connection has been + established. + + The headers argument should be a mapping of extra HTTP headers + to send with the CONNECT request. + """ + # Verify if this is required. + if self.sock: + raise RuntimeError("Can't setup tunnel for established connection.") + + self._tunnel_host = host + self._tunnel_port = port + if headers: + self._tunnel_headers = headers + else: + self._tunnel_headers.clear() + + def _get_hostport(self, host, port): + if port is None: + i = host.rfind(':') + j = host.rfind(']') # ipv6 addresses have [...] + if i > j: + try: + port = int(host[i+1:]) + except ValueError: + if host[i+1:] == "": # http://foo.com:/ == http://foo.com/ + port = self.default_port + else: + raise InvalidURL("nonnumeric port: '%s'" % host[i+1:]) + host = host[:i] + else: + port = self.default_port + if host and host[0] == '[' and host[-1] == ']': + host = host[1:-1] + return (host, port) + + def set_debuglevel(self, level): + self.debuglevel = level + + def _tunnel(self): + (host, port) = self._get_hostport(self._tunnel_host, self._tunnel_port) + self.send("CONNECT %s:%d HTTP/1.0\r\n" % (host, port)) + for header, value in self._tunnel_headers.iteritems(): + self.send("%s: %s\r\n" % (header, value)) + self.send("\r\n") + response = self.response_class(self.sock, strict = self.strict, + method = self._method) + (version, code, message) = response._read_status() + + if code != 200: + self.close() + raise socket.error("Tunnel connection failed: %d %s" % (code, + message.strip())) + while True: + line = response.fp.readline(_MAXLINE + 1) + if len(line) > _MAXLINE: + raise LineTooLong("header line") + if not line: + # for sites which EOF without sending trailer + break + if line == '\r\n': + break + + + def connect(self): + """Connect to the host and port specified in __init__.""" + self.sock = self._create_connection((self.host,self.port), + self.timeout, self.source_address) + + if self._tunnel_host: + self._tunnel() + + def close(self): + """Close the connection to the HTTP server.""" + if self.sock: + self.sock.close() # close it manually... there may be other refs + self.sock = None + if self.__response: + self.__response.close() + self.__response = None + self.__state = _CS_IDLE + + def send(self, data): + """Send `data' to the server.""" + if self.sock is None: + if self.auto_open: + self.connect() + else: + raise NotConnected() + + if self.debuglevel > 0: + print "send:", repr(data) + blocksize = 8192 + if hasattr(data,'read') and not isinstance(data, array): + if self.debuglevel > 0: print "sendIng a read()able" + datablock = data.read(blocksize) + while datablock: + self.sock.sendall(datablock) + datablock = data.read(blocksize) + else: + self.sock.sendall(data) + + def _output(self, s): + """Add a line of output to the current request buffer. + + Assumes that the line does *not* end with \\r\\n. + """ + self._buffer.append(s) + + def _send_output(self, message_body=None): + """Send the currently buffered request and clear the buffer. + + Appends an extra \\r\\n to the buffer. + A message_body may be specified, to be appended to the request. + """ + self._buffer.extend(("", "")) + msg = "\r\n".join(self._buffer) + del self._buffer[:] + # If msg and message_body are sent in a single send() call, + # it will avoid performance problems caused by the interaction + # between delayed ack and the Nagle algorithm. + if isinstance(message_body, str): + msg += message_body + message_body = None + self.send(msg) + if message_body is not None: + #message_body was not a string (i.e. it is a file) and + #we must run the risk of Nagle + self.send(message_body) + + def putrequest(self, method, url, skip_host=0, skip_accept_encoding=0): + """Send a request to the server. + + `method' specifies an HTTP request method, e.g. 'GET'. + `url' specifies the object being requested, e.g. '/index.html'. + `skip_host' if True does not add automatically a 'Host:' header + `skip_accept_encoding' if True does not add automatically an + 'Accept-Encoding:' header + """ + + # if a prior response has been completed, then forget about it. + if self.__response and self.__response.isclosed(): + self.__response = None + + + # in certain cases, we cannot issue another request on this connection. + # this occurs when: + # 1) we are in the process of sending a request. (_CS_REQ_STARTED) + # 2) a response to a previous request has signalled that it is going + # to close the connection upon completion. + # 3) the headers for the previous response have not been read, thus + # we cannot determine whether point (2) is true. (_CS_REQ_SENT) + # + # if there is no prior response, then we can request at will. + # + # if point (2) is true, then we will have passed the socket to the + # response (effectively meaning, "there is no prior response"), and + # will open a new one when a new request is made. + # + # Note: if a prior response exists, then we *can* start a new request. + # We are not allowed to begin fetching the response to this new + # request, however, until that prior response is complete. + # + if self.__state == _CS_IDLE: + self.__state = _CS_REQ_STARTED + else: + raise CannotSendRequest() + + # Save the method we use, we need it later in the response phase + self._method = method + if not url: + url = '/' + hdr = '%s %s %s' % (method, url, self._http_vsn_str) + + self._output(hdr) + + if self._http_vsn == 11: + # Issue some standard headers for better HTTP/1.1 compliance + + if not skip_host: + # this header is issued *only* for HTTP/1.1 + # connections. more specifically, this means it is + # only issued when the client uses the new + # HTTPConnection() class. backwards-compat clients + # will be using HTTP/1.0 and those clients may be + # issuing this header themselves. we should NOT issue + # it twice; some web servers (such as Apache) barf + # when they see two Host: headers + + # If we need a non-standard port,include it in the + # header. If the request is going through a proxy, + # but the host of the actual URL, not the host of the + # proxy. + + netloc = '' + if url.startswith('http'): + nil, netloc, nil, nil, nil = urlsplit(url) + + if netloc: + try: + netloc_enc = netloc.encode("ascii") + except UnicodeEncodeError: + netloc_enc = netloc.encode("idna") + self.putheader('Host', netloc_enc) + else: + if self._tunnel_host: + host = self._tunnel_host + port = self._tunnel_port + else: + host = self.host + port = self.port + + try: + host_enc = host.encode("ascii") + except UnicodeEncodeError: + host_enc = host.encode("idna") + # Wrap the IPv6 Host Header with [] (RFC 2732) + if host_enc.find(':') >= 0: + host_enc = "[" + host_enc + "]" + if port == self.default_port: + self.putheader('Host', host_enc) + else: + self.putheader('Host', "%s:%s" % (host_enc, port)) + + # note: we are assuming that clients will not attempt to set these + # headers since *this* library must deal with the + # consequences. this also means that when the supporting + # libraries are updated to recognize other forms, then this + # code should be changed (removed or updated). + + # we only want a Content-Encoding of "identity" since we don't + # support encodings such as x-gzip or x-deflate. + if not skip_accept_encoding: + self.putheader('Accept-Encoding', 'identity') + + # we can accept "chunked" Transfer-Encodings, but no others + # NOTE: no TE header implies *only* "chunked" + #self.putheader('TE', 'chunked') + + # if TE is supplied in the header, then it must appear in a + # Connection header. + #self.putheader('Connection', 'TE') + + else: + # For HTTP/1.0, the server will assume "not chunked" + pass + + def putheader(self, header, *values): + """Send a request header line to the server. + + For example: h.putheader('Accept', 'text/html') + """ + if self.__state != _CS_REQ_STARTED: + raise CannotSendHeader() + + hdr = '%s: %s' % (header, '\r\n\t'.join([str(v) for v in values])) + self._output(hdr) + + def endheaders(self, message_body=None): + """Indicate that the last header line has been sent to the server. + + This method sends the request to the server. The optional + message_body argument can be used to pass a message body + associated with the request. The message body will be sent in + the same packet as the message headers if it is string, otherwise it is + sent as a separate packet. + """ + if self.__state == _CS_REQ_STARTED: + self.__state = _CS_REQ_SENT + else: + raise CannotSendHeader() + self._send_output(message_body) + + def request(self, method, url, body=None, headers={}): + """Send a complete request to the server.""" + self._send_request(method, url, body, headers) + + def _set_content_length(self, body): + # Set the content-length based on the body. + thelen = None + try: + thelen = str(len(body)) + except TypeError, te: + # If this is a file-like object, try to + # fstat its file descriptor + try: + thelen = str(os.fstat(body.fileno()).st_size) + except (AttributeError, OSError): + # Don't send a length if this failed + if self.debuglevel > 0: print "Cannot stat!!" + + if thelen is not None: + self.putheader('Content-Length', thelen) + + def _send_request(self, method, url, body, headers): + # Honor explicitly requested Host: and Accept-Encoding: headers. + header_names = dict.fromkeys([k.lower() for k in headers]) + skips = {} + if 'host' in header_names: + skips['skip_host'] = 1 + if 'accept-encoding' in header_names: + skips['skip_accept_encoding'] = 1 + + self.putrequest(method, url, **skips) + + if body is not None and 'content-length' not in header_names: + self._set_content_length(body) + for hdr, value in headers.iteritems(): + self.putheader(hdr, value) + self.endheaders(body) + + def getresponse(self, buffering=False): + "Get the response from the server." + + # if a prior response has been completed, then forget about it. + if self.__response and self.__response.isclosed(): + self.__response = None + + # + # if a prior response exists, then it must be completed (otherwise, we + # cannot read this response's header to determine the connection-close + # behavior) + # + # note: if a prior response existed, but was connection-close, then the + # socket and response were made independent of this HTTPConnection + # object since a new request requires that we open a whole new + # connection + # + # this means the prior response had one of two states: + # 1) will_close: this connection was reset and the prior socket and + # response operate independently + # 2) persistent: the response was retained and we await its + # isclosed() status to become true. + # + if self.__state != _CS_REQ_SENT or self.__response: + raise ResponseNotReady() + + args = (self.sock,) + kwds = {"strict":self.strict, "method":self._method} + if self.debuglevel > 0: + args += (self.debuglevel,) + if buffering: + #only add this keyword if non-default, for compatibility with + #other response_classes. + kwds["buffering"] = True; + response = self.response_class(*args, **kwds) + + response.begin() + assert response.will_close != _UNKNOWN + self.__state = _CS_IDLE + + if response.will_close: + # this effectively passes the connection to the response + self.close() + else: + # remember this, so we can tell when it is complete + self.__response = response + + return response + + +class HTTP: + "Compatibility class with httplib.py from 1.5." + + _http_vsn = 10 + _http_vsn_str = 'HTTP/1.0' + + debuglevel = 0 + + _connection_class = HTTPConnection + + def __init__(self, host='', port=None, strict=None): + "Provide a default host, since the superclass requires one." + + # some joker passed 0 explicitly, meaning default port + if port == 0: + port = None + + # Note that we may pass an empty string as the host; this will raise + # an error when we attempt to connect. Presumably, the client code + # will call connect before then, with a proper host. + self._setup(self._connection_class(host, port, strict)) + + def _setup(self, conn): + self._conn = conn + + # set up delegation to flesh out interface + self.send = conn.send + self.putrequest = conn.putrequest + self.putheader = conn.putheader + self.endheaders = conn.endheaders + self.set_debuglevel = conn.set_debuglevel + + conn._http_vsn = self._http_vsn + conn._http_vsn_str = self._http_vsn_str + + self.file = None + + def connect(self, host=None, port=None): + "Accept arguments to set the host/port, since the superclass doesn't." + + if host is not None: + self._conn._set_hostport(host, port) + self._conn.connect() + + def getfile(self): + "Provide a getfile, since the superclass' does not use this concept." + return self.file + + def getreply(self, buffering=False): + """Compat definition since superclass does not define it. + + Returns a tuple consisting of: + - server status code (e.g. '200' if all goes well) + - server "reason" corresponding to status code + - any RFC822 headers in the response from the server + """ + try: + if not buffering: + response = self._conn.getresponse() + else: + #only add this keyword if non-default for compatibility + #with other connection classes + response = self._conn.getresponse(buffering) + except BadStatusLine, e: + ### hmm. if getresponse() ever closes the socket on a bad request, + ### then we are going to have problems with self.sock + + ### should we keep this behavior? do people use it? + # keep the socket open (as a file), and return it + self.file = self._conn.sock.makefile('rb', 0) + + # close our socket -- we want to restart after any protocol error + self.close() + + self.headers = None + return -1, e.line, None + + self.headers = response.msg + self.file = response.fp + return response.status, response.reason, response.msg + + def close(self): + self._conn.close() + + # note that self.file == response.fp, which gets closed by the + # superclass. just clear the object ref here. + ### hmm. messy. if status==-1, then self.file is owned by us. + ### well... we aren't explicitly closing, but losing this ref will + ### do it + self.file = None + +try: + import ssl +except ImportError: + pass +else: + class HTTPSConnection(HTTPConnection): + "This class allows communication via SSL." + + default_port = HTTPS_PORT + + def __init__(self, host, port=None, key_file=None, cert_file=None, + strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, + source_address=None): + HTTPConnection.__init__(self, host, port, strict, timeout, + source_address) + self.key_file = key_file + self.cert_file = cert_file + + def connect(self): + "Connect to a host on a given (SSL) port." + + sock = self._create_connection((self.host, self.port), + self.timeout, self.source_address) + if self._tunnel_host: + self.sock = sock + self._tunnel() + self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file) + + __all__.append("HTTPSConnection") + + class HTTPS(HTTP): + """Compatibility with 1.5 httplib interface + + Python 1.5.2 did not have an HTTPS class, but it defined an + interface for sending http requests that is also useful for + https. + """ + + _connection_class = HTTPSConnection + + def __init__(self, host='', port=None, key_file=None, cert_file=None, + strict=None): + # provide a default host, pass the X509 cert info + + # urf. compensate for bad input. + if port == 0: + port = None + self._setup(self._connection_class(host, port, key_file, + cert_file, strict)) + + # we never actually use these for anything, but we keep them + # here for compatibility with post-1.5.2 CVS. + self.key_file = key_file + self.cert_file = cert_file + + + def FakeSocket (sock, sslobj): + warnings.warn("FakeSocket is deprecated, and won't be in 3.x. " + + "Use the result of ssl.wrap_socket() directly instead.", + DeprecationWarning, stacklevel=2) + return sslobj + + +class HTTPException(Exception): + # Subclasses that define an __init__ must call Exception.__init__ + # or define self.args. Otherwise, str() will fail. + pass + +class NotConnected(HTTPException): + pass + +class InvalidURL(HTTPException): + pass + +class UnknownProtocol(HTTPException): + def __init__(self, version): + self.args = version, + self.version = version + +class UnknownTransferEncoding(HTTPException): + pass + +class UnimplementedFileMode(HTTPException): + pass + +class IncompleteRead(HTTPException): + def __init__(self, partial, expected=None): + self.args = partial, + self.partial = partial + self.expected = expected + def __repr__(self): + if self.expected is not None: + e = ', %i more expected' % self.expected + else: + e = '' + return 'IncompleteRead(%i bytes read%s)' % (len(self.partial), e) + def __str__(self): + return repr(self) + +class ImproperConnectionState(HTTPException): + pass + +class CannotSendRequest(ImproperConnectionState): + pass + +class CannotSendHeader(ImproperConnectionState): + pass + +class ResponseNotReady(ImproperConnectionState): + pass + +class BadStatusLine(HTTPException): + def __init__(self, line): + if not line: + line = repr(line) + self.args = line, + self.line = line + +class LineTooLong(HTTPException): + def __init__(self, line_type): + HTTPException.__init__(self, "got more than %d bytes when reading %s" + % (_MAXLINE, line_type)) + +# for backwards compatibility +error = HTTPException + +class LineAndFileWrapper: + """A limited file-like object for HTTP/0.9 responses.""" + + # The status-line parsing code calls readline(), which normally + # get the HTTP status line. For a 0.9 response, however, this is + # actually the first line of the body! Clients need to get a + # readable file object that contains that line. + + def __init__(self, line, file): + self._line = line + self._file = file + self._line_consumed = 0 + self._line_offset = 0 + self._line_left = len(line) + + def __getattr__(self, attr): + return getattr(self._file, attr) + + def _done(self): + # called when the last byte is read from the line. After the + # call, all read methods are delegated to the underlying file + # object. + self._line_consumed = 1 + self.read = self._file.read + self.readline = self._file.readline + self.readlines = self._file.readlines + + def read(self, amt=None): + if self._line_consumed: + return self._file.read(amt) + assert self._line_left + if amt is None or amt > self._line_left: + s = self._line[self._line_offset:] + self._done() + if amt is None: + return s + self._file.read() + else: + return s + self._file.read(amt - len(s)) + else: + assert amt <= self._line_left + i = self._line_offset + j = i + amt + s = self._line[i:j] + self._line_offset = j + self._line_left -= amt + if self._line_left == 0: + self._done() + return s + + def readline(self): + if self._line_consumed: + return self._file.readline() + assert self._line_left + s = self._line[self._line_offset:] + self._done() + return s + + def readlines(self, size=None): + if self._line_consumed: + return self._file.readlines(size) + assert self._line_left + L = [self._line[self._line_offset:]] + self._done() + if size is None: + return L + self._file.readlines() + else: + return L + self._file.readlines(size) diff --git a/PythonHome/Lib/httplib.pyc b/PythonHome/Lib/httplib.pyc index dbe7afb6a2e95bdce5d35265f8e7e73b94df7f0a..ef4df152481940fb5895b00a3a93f145185c79ca 100644 GIT binary patch delta 4210 zcmbW4-%C?*7{+&|%dm(>$F_?uW>mY$Ic-KcOG+nAX&Xf|>}a?;9k*&f&&mA|*Gke| zbkjG9f(oGIj?2o~AS<|TfTYRxG#KX%70Qfkj{fMjWBOlYK)7AzEP2@3#R zbv*&7Qfrc*T5vmoZ0KP7Tphm{ed|~OFt&X7I=>h@+xZlrc6i?d)UhFvt$U07B$c}q zAQIZ>)&Pv@KIvXh6=_P_OqXgSm?Y@%xDhy|$EXaraIIiO2xgMGlt&|7Z>@TtEj9XfX(@X1!C zpuU3L!;1*~XXL03x1axlzz(}eZKFs(P$1F>giFfBI>0F9!^H#I4(4&gGC~vY~`v3ZfpUm4iXH1zMuu&zN(fX)@QGR_Od${tdTW^Cw!O zk0J$;Lr(?@;uE;DDCq}06N3nq@+1iJz@qTX&(rtz^m^|1zVCuxmXnrp zNuf}bU2nDy^>=i4T{Dp*Z4X$~t*62CEJ@8T(_dXUckIuKi=5rrJxYL@oJ5rfDbsGC zy1aThAeOh60OO5<*OHPO3LO%R_KTK*@fEMg*nTw^yQ~yPp$m_ib^ubSBq&;v@x}@; zo%sVWjfF(UTNV$5u&dOEFsb|ix6Y`DfaSM}W7u%kX5iE+9T?2o^wd%POZ1>njZso@ zyyh#M;CI%G0M~6tz~sBUCEw#cyIC#T^LFDV==tNFa_CLwyF21(xidRjUw{E!cGgM> z>~+4uQN7C|?=$Dxg%L;H*$Dr(YoQAlb*fP5x}OY?79YSDan^d~p$}Zi)EyN!q$KZi zk@08mFa&X5?@fSmx}N^`dB9=1UxV?V9<_n6X~2lCZwGrsAvuSf!2X=W!oxApwT|2d z_GJY9Jbq*+{_k*BJ9-2xKhP^O`6bYg07f?i-J+C!2QfPE7@2Mi+0xi1_$`Dgf$5$c z0xJwdKVA+`N+4{Rm;iS6kItW51+JMYmY-wE)HvE4Km94nS^La@LTkha!hexcHNZ}) Gl}-UbXV=#N diff --git a/PythonHome/Lib/idlelib/AutoComplete.py b/PythonHome/Lib/idlelib/AutoComplete.py new file mode 100644 index 0000000000..1248f000ea --- /dev/null +++ b/PythonHome/Lib/idlelib/AutoComplete.py @@ -0,0 +1,229 @@ +"""AutoComplete.py - An IDLE extension for automatically completing names. + +This extension can complete either attribute names of file names. It can pop +a window with all available names, for the user to select from. +""" +import os +import sys +import string + +from idlelib.configHandler import idleConf + +# This string includes all chars that may be in a file name (without a path +# separator) +FILENAME_CHARS = string.ascii_letters + string.digits + os.curdir + "._~#$:-" +# This string includes all chars that may be in an identifier +ID_CHARS = string.ascii_letters + string.digits + "_" + +# These constants represent the two different types of completions +COMPLETE_ATTRIBUTES, COMPLETE_FILES = range(1, 2+1) + +from idlelib import AutoCompleteWindow +from idlelib.HyperParser import HyperParser + +import __main__ + +SEPS = os.sep +if os.altsep: # e.g. '/' on Windows... + SEPS += os.altsep + +class AutoComplete: + + menudefs = [ + ('edit', [ + ("Show Completions", "<>"), + ]) + ] + + popupwait = idleConf.GetOption("extensions", "AutoComplete", + "popupwait", type="int", default=0) + + def __init__(self, editwin=None): + self.editwin = editwin + if editwin is None: # subprocess and test + return + self.text = editwin.text + self.autocompletewindow = None + + # id of delayed call, and the index of the text insert when the delayed + # call was issued. If _delayed_completion_id is None, there is no + # delayed call. + self._delayed_completion_id = None + self._delayed_completion_index = None + + def _make_autocomplete_window(self): + return AutoCompleteWindow.AutoCompleteWindow(self.text) + + def _remove_autocomplete_window(self, event=None): + if self.autocompletewindow: + self.autocompletewindow.hide_window() + self.autocompletewindow = None + + def force_open_completions_event(self, event): + """Happens when the user really wants to open a completion list, even + if a function call is needed. + """ + self.open_completions(True, False, True) + + def try_open_completions_event(self, event): + """Happens when it would be nice to open a completion list, but not + really necessary, for example after an dot, so function + calls won't be made. + """ + lastchar = self.text.get("insert-1c") + if lastchar == ".": + self._open_completions_later(False, False, False, + COMPLETE_ATTRIBUTES) + elif lastchar in SEPS: + self._open_completions_later(False, False, False, + COMPLETE_FILES) + + def autocomplete_event(self, event): + """Happens when the user wants to complete his word, and if necessary, + open a completion list after that (if there is more than one + completion) + """ + if hasattr(event, "mc_state") and event.mc_state: + # A modifier was pressed along with the tab, continue as usual. + return + if self.autocompletewindow and self.autocompletewindow.is_active(): + self.autocompletewindow.complete() + return "break" + else: + opened = self.open_completions(False, True, True) + if opened: + return "break" + + def _open_completions_later(self, *args): + self._delayed_completion_index = self.text.index("insert") + if self._delayed_completion_id is not None: + self.text.after_cancel(self._delayed_completion_id) + self._delayed_completion_id = \ + self.text.after(self.popupwait, self._delayed_open_completions, + *args) + + def _delayed_open_completions(self, *args): + self._delayed_completion_id = None + if self.text.index("insert") != self._delayed_completion_index: + return + self.open_completions(*args) + + def open_completions(self, evalfuncs, complete, userWantsWin, mode=None): + """Find the completions and create the AutoCompleteWindow. + Return True if successful (no syntax error or so found). + if complete is True, then if there's nothing to complete and no + start of completion, won't open completions and return False. + If mode is given, will open a completion list only in this mode. + """ + # Cancel another delayed call, if it exists. + if self._delayed_completion_id is not None: + self.text.after_cancel(self._delayed_completion_id) + self._delayed_completion_id = None + + hp = HyperParser(self.editwin, "insert") + curline = self.text.get("insert linestart", "insert") + i = j = len(curline) + if hp.is_in_string() and (not mode or mode==COMPLETE_FILES): + self._remove_autocomplete_window() + mode = COMPLETE_FILES + while i and curline[i-1] in FILENAME_CHARS: + i -= 1 + comp_start = curline[i:j] + j = i + while i and curline[i-1] in FILENAME_CHARS + SEPS: + i -= 1 + comp_what = curline[i:j] + elif hp.is_in_code() and (not mode or mode==COMPLETE_ATTRIBUTES): + self._remove_autocomplete_window() + mode = COMPLETE_ATTRIBUTES + while i and curline[i-1] in ID_CHARS: + i -= 1 + comp_start = curline[i:j] + if i and curline[i-1] == '.': + hp.set_index("insert-%dc" % (len(curline)-(i-1))) + comp_what = hp.get_expression() + if not comp_what or \ + (not evalfuncs and comp_what.find('(') != -1): + return + else: + comp_what = "" + else: + return + + if complete and not comp_what and not comp_start: + return + comp_lists = self.fetch_completions(comp_what, mode) + if not comp_lists[0]: + return + self.autocompletewindow = self._make_autocomplete_window() + return not self.autocompletewindow.show_window( + comp_lists, "insert-%dc" % len(comp_start), + complete, mode, userWantsWin) + + def fetch_completions(self, what, mode): + """Return a pair of lists of completions for something. The first list + is a sublist of the second. Both are sorted. + + If there is a Python subprocess, get the comp. list there. Otherwise, + either fetch_completions() is running in the subprocess itself or it + was called in an IDLE EditorWindow before any script had been run. + + The subprocess environment is that of the most recently run script. If + two unrelated modules are being edited some calltips in the current + module may be inoperative if the module was not the last to run. + """ + try: + rpcclt = self.editwin.flist.pyshell.interp.rpcclt + except: + rpcclt = None + if rpcclt: + return rpcclt.remotecall("exec", "get_the_completion_list", + (what, mode), {}) + else: + if mode == COMPLETE_ATTRIBUTES: + if what == "": + namespace = __main__.__dict__.copy() + namespace.update(__main__.__builtins__.__dict__) + bigl = eval("dir()", namespace) + bigl.sort() + if "__all__" in bigl: + smalll = sorted(eval("__all__", namespace)) + else: + smalll = [s for s in bigl if s[:1] != '_'] + else: + try: + entity = self.get_entity(what) + bigl = dir(entity) + bigl.sort() + if "__all__" in bigl: + smalll = sorted(entity.__all__) + else: + smalll = [s for s in bigl if s[:1] != '_'] + except: + return [], [] + + elif mode == COMPLETE_FILES: + if what == "": + what = "." + try: + expandedpath = os.path.expanduser(what) + bigl = os.listdir(expandedpath) + bigl.sort() + smalll = [s for s in bigl if s[:1] != '.'] + except OSError: + return [], [] + + if not smalll: + smalll = bigl + return smalll, bigl + + def get_entity(self, name): + """Lookup name in a namespace spanning sys.modules and __main.dict__""" + namespace = sys.modules.copy() + namespace.update(__main__.__dict__) + return eval(name, namespace) + + +if __name__ == '__main__': + from unittest import main + main('idlelib.idle_test.test_autocomplete', verbosity=2) diff --git a/PythonHome/Lib/idlelib/AutoComplete.pyc b/PythonHome/Lib/idlelib/AutoComplete.pyc deleted file mode 100644 index 036fd01f1f8cd902557b575440404c444e6b7b70..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7818 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", "") +KEYPRESS_VIRTUAL_EVENT_NAME = "<>" +# We need to bind event beyond so that the function will be called +# before the default specific IDLE function +KEYPRESS_SEQUENCES = ("", "", "", "", + "", "", "", "", + "", "") +KEYRELEASE_VIRTUAL_EVENT_NAME = "<>" +KEYRELEASE_SEQUENCE = "" +LISTUPDATE_SEQUENCE = "" +WINCONFIG_SEQUENCE = "" +DOUBLECLICK_SEQUENCE = "" + +class AutoCompleteWindow: + + def __init__(self, widget): + # The widget (Text) on which we place the AutoCompleteWindow + self.widget = widget + # The widgets we create + self.autocompletewindow = self.listbox = self.scrollbar = None + # The default foreground and background of a selection. Saved because + # they are changed to the regular colors of list items when the + # completion start is not a prefix of the selected completion + self.origselforeground = self.origselbackground = None + # The list of completions + self.completions = None + # A list with more completions, or None + self.morecompletions = None + # The completion mode. Either AutoComplete.COMPLETE_ATTRIBUTES or + # AutoComplete.COMPLETE_FILES + self.mode = None + # The current completion start, on the text box (a string) + self.start = None + # The index of the start of the completion + self.startindex = None + # The last typed start, used so that when the selection changes, + # the new start will be as close as possible to the last typed one. + self.lasttypedstart = None + # Do we have an indication that the user wants the completion window + # (for example, he clicked the list) + self.userwantswindow = None + # event ids + self.hideid = self.keypressid = self.listupdateid = self.winconfigid \ + = self.keyreleaseid = self.doubleclickid = None + # Flag set if last keypress was a tab + self.lastkey_was_tab = False + + def _change_start(self, newstart): + min_len = min(len(self.start), len(newstart)) + i = 0 + while i < min_len and self.start[i] == newstart[i]: + i += 1 + if i < len(self.start): + self.widget.delete("%s+%dc" % (self.startindex, i), + "%s+%dc" % (self.startindex, len(self.start))) + if i < len(newstart): + self.widget.insert("%s+%dc" % (self.startindex, i), + newstart[i:]) + self.start = newstart + + def _binary_search(self, s): + """Find the first index in self.completions where completions[i] is + greater or equal to s, or the last index if there is no such + one.""" + i = 0; j = len(self.completions) + while j > i: + m = (i + j) // 2 + if self.completions[m] >= s: + j = m + else: + i = m + 1 + return min(i, len(self.completions)-1) + + def _complete_string(self, s): + """Assuming that s is the prefix of a string in self.completions, + return the longest string which is a prefix of all the strings which + s is a prefix of them. If s is not a prefix of a string, return s.""" + first = self._binary_search(s) + if self.completions[first][:len(s)] != s: + # There is not even one completion which s is a prefix of. + return s + # Find the end of the range of completions where s is a prefix of. + i = first + 1 + j = len(self.completions) + while j > i: + m = (i + j) // 2 + if self.completions[m][:len(s)] != s: + j = m + else: + i = m + 1 + last = i-1 + + if first == last: # only one possible completion + return self.completions[first] + + # We should return the maximum prefix of first and last + first_comp = self.completions[first] + last_comp = self.completions[last] + min_len = min(len(first_comp), len(last_comp)) + i = len(s) + while i < min_len and first_comp[i] == last_comp[i]: + i += 1 + return first_comp[:i] + + def _selection_changed(self): + """Should be called when the selection of the Listbox has changed. + Updates the Listbox display and calls _change_start.""" + cursel = int(self.listbox.curselection()[0]) + + self.listbox.see(cursel) + + lts = self.lasttypedstart + selstart = self.completions[cursel] + if self._binary_search(lts) == cursel: + newstart = lts + else: + min_len = min(len(lts), len(selstart)) + i = 0 + while i < min_len and lts[i] == selstart[i]: + i += 1 + newstart = selstart[:i] + self._change_start(newstart) + + if self.completions[cursel][:len(self.start)] == self.start: + # start is a prefix of the selected completion + self.listbox.configure(selectbackground=self.origselbackground, + selectforeground=self.origselforeground) + else: + self.listbox.configure(selectbackground=self.listbox.cget("bg"), + selectforeground=self.listbox.cget("fg")) + # If there are more completions, show them, and call me again. + if self.morecompletions: + self.completions = self.morecompletions + self.morecompletions = None + self.listbox.delete(0, END) + for item in self.completions: + self.listbox.insert(END, item) + self.listbox.select_set(self._binary_search(self.start)) + self._selection_changed() + + def show_window(self, comp_lists, index, complete, mode, userWantsWin): + """Show the autocomplete list, bind events. + If complete is True, complete the text, and if there is exactly one + matching completion, don't open a list.""" + # Handle the start we already have + self.completions, self.morecompletions = comp_lists + self.mode = mode + self.startindex = self.widget.index(index) + self.start = self.widget.get(self.startindex, "insert") + if complete: + completed = self._complete_string(self.start) + start = self.start + self._change_start(completed) + i = self._binary_search(completed) + if self.completions[i] == completed and \ + (i == len(self.completions)-1 or + self.completions[i+1][:len(completed)] != completed): + # There is exactly one matching completion + return completed == start + self.userwantswindow = userWantsWin + self.lasttypedstart = self.start + + # Put widgets in place + self.autocompletewindow = acw = Toplevel(self.widget) + # Put it in a position so that it is not seen. + acw.wm_geometry("+10000+10000") + # Make it float + acw.wm_overrideredirect(1) + try: + # This command is only needed and available on Tk >= 8.4.0 for OSX + # Without it, call tips intrude on the typing process by grabbing + # the focus. + acw.tk.call("::tk::unsupported::MacWindowStyle", "style", acw._w, + "help", "noActivates") + except TclError: + pass + self.scrollbar = scrollbar = Scrollbar(acw, orient=VERTICAL) + self.listbox = listbox = Listbox(acw, yscrollcommand=scrollbar.set, + exportselection=False, bg="white") + for item in self.completions: + listbox.insert(END, item) + self.origselforeground = listbox.cget("selectforeground") + self.origselbackground = listbox.cget("selectbackground") + scrollbar.config(command=listbox.yview) + scrollbar.pack(side=RIGHT, fill=Y) + listbox.pack(side=LEFT, fill=BOTH, expand=True) + + # Initialize the listbox selection + self.listbox.select_set(self._binary_search(self.start)) + self._selection_changed() + + # bind events + self.hideid = self.widget.bind(HIDE_VIRTUAL_EVENT_NAME, + self.hide_event) + for seq in HIDE_SEQUENCES: + self.widget.event_add(HIDE_VIRTUAL_EVENT_NAME, seq) + self.keypressid = self.widget.bind(KEYPRESS_VIRTUAL_EVENT_NAME, + self.keypress_event) + for seq in KEYPRESS_SEQUENCES: + self.widget.event_add(KEYPRESS_VIRTUAL_EVENT_NAME, seq) + self.keyreleaseid = self.widget.bind(KEYRELEASE_VIRTUAL_EVENT_NAME, + self.keyrelease_event) + self.widget.event_add(KEYRELEASE_VIRTUAL_EVENT_NAME,KEYRELEASE_SEQUENCE) + self.listupdateid = listbox.bind(LISTUPDATE_SEQUENCE, + self.listselect_event) + self.winconfigid = acw.bind(WINCONFIG_SEQUENCE, self.winconfig_event) + self.doubleclickid = listbox.bind(DOUBLECLICK_SEQUENCE, + self.doubleclick_event) + + def winconfig_event(self, event): + if not self.is_active(): + return + # Position the completion list window + text = self.widget + text.see(self.startindex) + x, y, cx, cy = text.bbox(self.startindex) + acw = self.autocompletewindow + acw_width, acw_height = acw.winfo_width(), acw.winfo_height() + text_width, text_height = text.winfo_width(), text.winfo_height() + new_x = text.winfo_rootx() + min(x, max(0, text_width - acw_width)) + new_y = text.winfo_rooty() + y + if (text_height - (y + cy) >= acw_height # enough height below + or y < acw_height): # not enough height above + # place acw below current line + new_y += cy + else: + # place acw above current line + new_y -= acw_height + acw.wm_geometry("+%d+%d" % (new_x, new_y)) + + def hide_event(self, event): + if not self.is_active(): + return + self.hide_window() + + def listselect_event(self, event): + if not self.is_active(): + return + self.userwantswindow = True + cursel = int(self.listbox.curselection()[0]) + self._change_start(self.completions[cursel]) + + def doubleclick_event(self, event): + # Put the selected completion in the text, and close the list + cursel = int(self.listbox.curselection()[0]) + self._change_start(self.completions[cursel]) + self.hide_window() + + def keypress_event(self, event): + if not self.is_active(): + return + keysym = event.keysym + if hasattr(event, "mc_state"): + state = event.mc_state + else: + state = 0 + if keysym != "Tab": + self.lastkey_was_tab = False + if (len(keysym) == 1 or keysym in ("underscore", "BackSpace") + or (self.mode == COMPLETE_FILES and keysym in + ("period", "minus"))) \ + and not (state & ~MC_SHIFT): + # Normal editing of text + if len(keysym) == 1: + self._change_start(self.start + keysym) + elif keysym == "underscore": + self._change_start(self.start + '_') + elif keysym == "period": + self._change_start(self.start + '.') + elif keysym == "minus": + self._change_start(self.start + '-') + else: + # keysym == "BackSpace" + if len(self.start) == 0: + self.hide_window() + return + self._change_start(self.start[:-1]) + self.lasttypedstart = self.start + self.listbox.select_clear(0, int(self.listbox.curselection()[0])) + self.listbox.select_set(self._binary_search(self.start)) + self._selection_changed() + return "break" + + elif keysym == "Return": + self.hide_window() + return + + elif (self.mode == COMPLETE_ATTRIBUTES and keysym in + ("period", "space", "parenleft", "parenright", "bracketleft", + "bracketright")) or \ + (self.mode == COMPLETE_FILES and keysym in + ("slash", "backslash", "quotedbl", "apostrophe")) \ + and not (state & ~MC_SHIFT): + # If start is a prefix of the selection, but is not '' when + # completing file names, put the whole + # selected completion. Anyway, close the list. + cursel = int(self.listbox.curselection()[0]) + if self.completions[cursel][:len(self.start)] == self.start \ + and (self.mode == COMPLETE_ATTRIBUTES or self.start): + self._change_start(self.completions[cursel]) + self.hide_window() + return + + elif keysym in ("Home", "End", "Prior", "Next", "Up", "Down") and \ + not state: + # Move the selection in the listbox + self.userwantswindow = True + cursel = int(self.listbox.curselection()[0]) + if keysym == "Home": + newsel = 0 + elif keysym == "End": + newsel = len(self.completions)-1 + elif keysym in ("Prior", "Next"): + jump = self.listbox.nearest(self.listbox.winfo_height()) - \ + self.listbox.nearest(0) + if keysym == "Prior": + newsel = max(0, cursel-jump) + else: + assert keysym == "Next" + newsel = min(len(self.completions)-1, cursel+jump) + elif keysym == "Up": + newsel = max(0, cursel-1) + else: + assert keysym == "Down" + newsel = min(len(self.completions)-1, cursel+1) + self.listbox.select_clear(cursel) + self.listbox.select_set(newsel) + self._selection_changed() + self._change_start(self.completions[newsel]) + return "break" + + elif (keysym == "Tab" and not state): + if self.lastkey_was_tab: + # two tabs in a row; insert current selection and close acw + cursel = int(self.listbox.curselection()[0]) + self._change_start(self.completions[cursel]) + self.hide_window() + return "break" + else: + # first tab; let AutoComplete handle the completion + self.userwantswindow = True + self.lastkey_was_tab = True + return + + elif any(s in keysym for s in ("Shift", "Control", "Alt", + "Meta", "Command", "Option")): + # A modifier key, so ignore + return + + else: + # Unknown event, close the window and let it through. + self.hide_window() + return + + def keyrelease_event(self, event): + if not self.is_active(): + return + if self.widget.index("insert") != \ + self.widget.index("%s+%dc" % (self.startindex, len(self.start))): + # If we didn't catch an event which moved the insert, close window + self.hide_window() + + def is_active(self): + return self.autocompletewindow is not None + + def complete(self): + self._change_start(self._complete_string(self.start)) + # The selection doesn't change. + + def hide_window(self): + if not self.is_active(): + return + + # unbind events + for seq in HIDE_SEQUENCES: + self.widget.event_delete(HIDE_VIRTUAL_EVENT_NAME, seq) + self.widget.unbind(HIDE_VIRTUAL_EVENT_NAME, self.hideid) + self.hideid = None + for seq in KEYPRESS_SEQUENCES: + self.widget.event_delete(KEYPRESS_VIRTUAL_EVENT_NAME, seq) + self.widget.unbind(KEYPRESS_VIRTUAL_EVENT_NAME, self.keypressid) + self.keypressid = None + self.widget.event_delete(KEYRELEASE_VIRTUAL_EVENT_NAME, + KEYRELEASE_SEQUENCE) + self.widget.unbind(KEYRELEASE_VIRTUAL_EVENT_NAME, self.keyreleaseid) + self.keyreleaseid = None + self.listbox.unbind(LISTUPDATE_SEQUENCE, self.listupdateid) + self.listupdateid = None + self.autocompletewindow.unbind(WINCONFIG_SEQUENCE, self.winconfigid) + self.winconfigid = None + + # destroy widgets + self.scrollbar.destroy() + self.scrollbar = None + self.listbox.destroy() + self.listbox = None + self.autocompletewindow.destroy() + self.autocompletewindow = None diff --git a/PythonHome/Lib/idlelib/AutoCompleteWindow.pyc b/PythonHome/Lib/idlelib/AutoCompleteWindow.pyc deleted file mode 100644 index 2ecee947cbe69cacd6ea2e5d0aba0719b8dc1515..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12198 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 diff --git a/PythonHome/Lib/idlelib/AutoExpand.py b/PythonHome/Lib/idlelib/AutoExpand.py new file mode 100644 index 0000000000..7059054281 --- /dev/null +++ b/PythonHome/Lib/idlelib/AutoExpand.py @@ -0,0 +1,104 @@ +'''Complete the current word before the cursor with words in the editor. + +Each menu selection or shortcut key selection replaces the word with a +different word with the same prefix. The search for matches begins +before the target and moves toward the top of the editor. It then starts +after the cursor and moves down. It then returns to the original word and +the cycle starts again. + +Changing the current text line or leaving the cursor in a different +place before requesting the next selection causes AutoExpand to reset +its state. + +This is an extension file and there is only one instance of AutoExpand. +''' +import string +import re + +###$ event <> +###$ win +###$ unix + +class AutoExpand: + + menudefs = [ + ('edit', [ + ('E_xpand Word', '<>'), + ]), + ] + + wordchars = string.ascii_letters + string.digits + "_" + + def __init__(self, editwin): + self.text = editwin.text + self.state = None + + def expand_word_event(self, event): + "Replace the current word with the next expansion." + curinsert = self.text.index("insert") + curline = self.text.get("insert linestart", "insert lineend") + if not self.state: + words = self.getwords() + index = 0 + else: + words, index, insert, line = self.state + if insert != curinsert or line != curline: + words = self.getwords() + index = 0 + if not words: + self.text.bell() + return "break" + word = self.getprevword() + self.text.delete("insert - %d chars" % len(word), "insert") + newword = words[index] + index = (index + 1) % len(words) + if index == 0: + self.text.bell() # Warn we cycled around + self.text.insert("insert", newword) + curinsert = self.text.index("insert") + curline = self.text.get("insert linestart", "insert lineend") + self.state = words, index, curinsert, curline + return "break" + + def getwords(self): + "Return a list of words that match the prefix before the cursor." + word = self.getprevword() + if not word: + return [] + before = self.text.get("1.0", "insert wordstart") + wbefore = re.findall(r"\b" + word + r"\w+\b", before) + del before + after = self.text.get("insert wordend", "end") + wafter = re.findall(r"\b" + word + r"\w+\b", after) + del after + if not wbefore and not wafter: + return [] + words = [] + dict = {} + # search backwards through words before + wbefore.reverse() + for w in wbefore: + if dict.get(w): + continue + words.append(w) + dict[w] = w + # search onwards through words after + for w in wafter: + if dict.get(w): + continue + words.append(w) + dict[w] = w + words.append(word) + return words + + def getprevword(self): + "Return the word prefix before the cursor." + line = self.text.get("insert linestart", "insert") + i = len(line) + while i > 0 and line[i-1] in self.wordchars: + i = i-1 + return line[i:] + +if __name__ == '__main__': + import unittest + unittest.main('idlelib.idle_test.test_autoexpand', verbosity=2) diff --git a/PythonHome/Lib/idlelib/AutoExpand.pyc b/PythonHome/Lib/idlelib/AutoExpand.pyc deleted file mode 100644 index 071649913d76f85678ba0a506eec84bbc4025e54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3412 zcmb7G&2Ah;5U!s6v3GHPAaR@!p$t+23n(jsI3X)Qf)7Y2LgPpg#$hy`>Gh7ip0THU zy|!fMVk9nHcmeJ_1s9$rFTex9_tmVuj$}b%d3&m>yQ-_JzpuI*e_!hM{`_q>j<)MO%SXpLlnjEt;7sO3P`0?8VZbtG%b&mt!xKdd#xHYIDxb|6)JI<+NhEwL@x zYDO&V( z*GV_a2Ln3`LA4CbB|A3Ut?VE_=!Z|Kut|j#5n;HK_;d(g8+J1=vPeop;@2;BBQ7kQQ!#<|ivBMgMGmW&OA+=v`-* zRgOTCQJqB?b-7-8n2r#(x(<`gBrlM)$HSz++|AQfbm!h4_;8dLmI)l$WdGa*hJn;4 z;aQ@(n#t3{s_fp_I)7?W(ADff(q!zAg|ElHTshd~b`Wx9o%P+^I|k=1qIx>aalj7y z4PkE!$HN@t2wzQxI3Ny}#pn%gsV(l;>b z79gy|^`@Tz-R=q$%ga_Z_X)v=550jdPC*Je{XK^4ZlO6cvV|7oh_MzxMFEp&^rXk# z=xRJY6`mk9zD0YcwMUPt$8ik&9D0mvk{3OQqK&%^slWbRzOkNXBRj%(mbd=yp`XWi z9Op&u<2Z!uxIHloMq_54snD38A}mCUn76cioESL{PBn;J>&QtU#|>3B#I2~%WKB6n zJ!#5uONvL+(RFlHbKI8WIXP;}Q6Sr}s^kdW2IcCPi##BVrnujA2*I@I-{9m{8C_df zn?D`Ik+uc9JYubq8>o7S(7^tvCAW?{{NRL_I0JEF212B+skP6T>4xhyQ0b<9;KImJ zr*`(5Ingz-M{I2X8F@$9Mbtf>fqQ@^s%zLQ)SZLls?ru&4vi>?HY%HJySHaE?uYlXFdZh9%ZWfO=#iq3n9GX{IAj+EFrr4mgAPM< z3d9XN8u_>CDJZS`9MKpvRB&(AdSr`;M5^6$0~(Fp$1UMGfYMlRNg<6M3zyE(g(CV_ z54xld5~I2nNl@4c9bJKsG2Opd{Y zIYw1;rus|v{t!aHO?K5vgAZ9cFUuHwM&s6n#>VWu{4e8|@@(oC%rszT8-(B~x-Zd0 zdJTpN5bZqg0!0A$k@)(KR;tvO`00J6H>2LJeMhuD=zn^i8|p!?OqS2}4M!xePd zR}|HkgEI*_MKiO=-(&pTb2QT;sJ8&hKCxz)4x*HLGR!R8prN^Oq#wn`uxTo@5eryIKexyuC$taFlD23 zxj)QFraB;UNO=**S((Oh^f43>-!U3N^dZN&oiQFQbgJ~=(r>sSb+TON_93~iht$Tg LEwrzFkJkJP5J?5o diff --git a/PythonHome/Lib/idlelib/Bindings.py b/PythonHome/Lib/idlelib/Bindings.py new file mode 100644 index 0000000000..df2b251426 --- /dev/null +++ b/PythonHome/Lib/idlelib/Bindings.py @@ -0,0 +1,89 @@ +"""Define the menu contents, hotkeys, and event bindings. + +There is additional configuration information in the EditorWindow class (and +subclasses): the menus are created there based on the menu_specs (class) +variable, and menus not created are silently skipped in the code here. This +makes it possible, for example, to define a Debug menu which is only present in +the PythonShell window, and a Format menu which is only present in the Editor +windows. + +""" +from idlelib.configHandler import idleConf + +# Warning: menudefs is altered in macosxSupport.overrideRootMenu() +# after it is determined that an OS X Aqua Tk is in use, +# which cannot be done until after Tk() is first called. +# Do not alter the 'file', 'options', or 'help' cascades here +# without altering overrideRootMenu() as well. +# TODO: Make this more robust + +menudefs = [ + # underscore prefixes character to underscore + ('file', [ + ('_New File', '<>'), + ('_Open...', '<>'), + ('Open _Module...', '<>'), + ('Class _Browser', '<>'), + ('_Path Browser', '<>'), + None, + ('_Save', '<>'), + ('Save _As...', '<>'), + ('Save Cop_y As...', '<>'), + None, + ('Prin_t Window', '<>'), + None, + ('_Close', '<>'), + ('E_xit', '<>'), + ]), + ('edit', [ + ('_Undo', '<>'), + ('_Redo', '<>'), + None, + ('Cu_t', '<>'), + ('_Copy', '<>'), + ('_Paste', '<>'), + ('Select _All', '<>'), + None, + ('_Find...', '<>'), + ('Find A_gain', '<>'), + ('Find _Selection', '<>'), + ('Find in Files...', '<>'), + ('R_eplace...', '<>'), + ('Go to _Line', '<>'), + ]), +('format', [ + ('_Indent Region', '<>'), + ('_Dedent Region', '<>'), + ('Comment _Out Region', '<>'), + ('U_ncomment Region', '<>'), + ('Tabify Region', '<>'), + ('Untabify Region', '<>'), + ('Toggle Tabs', '<>'), + ('New Indent Width', '<>'), + ]), + ('run', [ + ('Python Shell', '<>'), + ]), + ('shell', [ + ('_View Last Restart', '<>'), + ('_Restart Shell', '<>'), + ]), + ('debug', [ + ('_Go to File/Line', '<>'), + ('!_Debugger', '<>'), + ('_Stack Viewer', '<>'), + ('!_Auto-open Stack Viewer', '<>'), + ]), + ('options', [ + ('_Configure IDLE...', '<>'), + None, + ]), + ('help', [ + ('_About IDLE', '<>'), + None, + ('_IDLE Help', '<>'), + ('Python _Docs', '<>'), + ]), +] + +default_keydefs = idleConf.GetCurrentKeySet() diff --git a/PythonHome/Lib/idlelib/Bindings.pyc b/PythonHome/Lib/idlelib/Bindings.pyc deleted file mode 100644 index e72606cf5106375709099ddc8edfdb4c9ad7c1a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4565 zcmbtXS##Sq5Qc2$QktXp^-%Q9nJL|ezI8a7I(Dw9n|N%e?qo8!>P#!LXCxbBGg2vFNFG1sIP?jTBvVCex7`83iYkX zJG8zf)OSLCFY+aN+!E>sp`Hr$qfkGIe1(Mfh58wH44BV^`h^1cRjA(r20TAl5qe2H zJ|mvO;m;yqclCEn$e)mqO+7HBmVT(^NSBSwZ0U9B-FtFq{ehmqA}y8Fhai-FQz}#D zZmrwh8|qq1<7BFo@y3>EfwlvaH+727(v$;RkEUzd;RZl$y$@dOSY}1)oLmL(UDx#K zNxN$w9)$v~VTY{Nsn-gn@YGKotiky--o#Zp121HLt$Uc(ChZrRgT@0nSz3SO1wA@b zz*&lkbO)xYz@1@tnN?ciE^AWm4UOxL(gW?J@v^ec8S)AzlKM$Hs&ET$rQ+lNbf5Xoz z)Kd8K@L^P;H=q)J1s(=)Sa$&y$z45`H}UCZc#30N=`t$yIATA&o(3x|H$Bv0UkA(fC>KGCN|~%XjO}&uGlPjzH$BVMDR#qF$wacj zJFP)xt4U-B!TF3KhPz#xGVyYsD(TQw99JOoN3r;`AWSw2>vYg(xNh}$k{ihr;~k%t z)oD=#i0k#Jk{a#~ANxLBAF5UyH?RafWn)JliECH}vyCS4?i>Y{HGYbPvrd8wJRgWD z%f}zT@E-5z93$ji;T#}~YLbCh?Du3- z{~M@C)&lVkZrBkFD9Gx)=EyA{JY!7@$KCEHWspx}c!kc?OvNo6J997Xo55rX<#0X8 zS{$bSe#z1)lBYuxq%9T`xM%ac&=Op`aP2%vB5;98$NJ!y38~sQ$`8YZ&xUE4Yp4+B zW{e6*@iO4+rgSgBe;$mICS$k>G@>dRn32PY8M>F&)Fa8K2DaORPKEHDPir6U*dfRv zb`nkN5)fev&Pae9bFXlelb?h;1Y7NW>JlywbqP+w&?>GA@xKdo2fG|b9H%g(hP;6k zqM-S<>(lH&V%&h7nQstkb`W9Qgnfftt~bz+m}^oSaoFIo@zHT(kJsH+NWzZO zgmi$!tmU1}ts8i2X2&ooBW2RU=8$5f4ajyycPLr!TWC)-3zs)VL4+g&N5YdQsFb(S zg6}>WgKnm($)?SwEfWf=K+@~oU0nhX^AQw7=VvL#&q-AbUWl*QWC7A5gB?0BljRH{ z^?K}X0p?kYqxWFmtgO`!$G}xmb*)o~169 z;+L5KX6j-wb|UrB5p$7z4*Fso^%auKvmDmCA?i7i$QU<2n=yWVN^9ddh1XipspQ5m zVyiH#PouRN^c>vA=*0+*Z5CrWwwaUa7`y=AvB4aq$G`=dkBw#q", "") +CHECKHIDE_VIRTUAL_EVENT_NAME = "<>" +CHECKHIDE_SEQUENCES = ("", "") +CHECKHIDE_TIME = 100 # miliseconds + +MARK_RIGHT = "calltipwindowregion_right" + +class CallTip: + + def __init__(self, widget): + self.widget = widget + self.tipwindow = self.label = None + self.parenline = self.parencol = None + self.lastline = None + self.hideid = self.checkhideid = None + self.checkhide_after_id = None + + def position_window(self): + """Check if needs to reposition the window, and if so - do it.""" + curline = int(self.widget.index("insert").split('.')[0]) + if curline == self.lastline: + return + self.lastline = curline + self.widget.see("insert") + if curline == self.parenline: + box = self.widget.bbox("%d.%d" % (self.parenline, + self.parencol)) + else: + box = self.widget.bbox("%d.0" % curline) + if not box: + box = list(self.widget.bbox("insert")) + # align to left of window + box[0] = 0 + box[2] = 0 + x = box[0] + self.widget.winfo_rootx() + 2 + y = box[1] + box[3] + self.widget.winfo_rooty() + self.tipwindow.wm_geometry("+%d+%d" % (x, y)) + + def showtip(self, text, parenleft, parenright): + """Show the calltip, bind events which will close it and reposition it. + """ + # Only called in CallTips, where lines are truncated + self.text = text + if self.tipwindow or not self.text: + return + + self.widget.mark_set(MARK_RIGHT, parenright) + self.parenline, self.parencol = map( + int, self.widget.index(parenleft).split(".")) + + self.tipwindow = tw = Toplevel(self.widget) + self.position_window() + # remove border on calltip window + tw.wm_overrideredirect(1) + try: + # This command is only needed and available on Tk >= 8.4.0 for OSX + # Without it, call tips intrude on the typing process by grabbing + # the focus. + tw.tk.call("::tk::unsupported::MacWindowStyle", "style", tw._w, + "help", "noActivates") + except TclError: + pass + self.label = Label(tw, text=self.text, justify=LEFT, + background="#ffffe0", relief=SOLID, borderwidth=1, + font = self.widget['font']) + self.label.pack() + + self.checkhideid = self.widget.bind(CHECKHIDE_VIRTUAL_EVENT_NAME, + self.checkhide_event) + for seq in CHECKHIDE_SEQUENCES: + self.widget.event_add(CHECKHIDE_VIRTUAL_EVENT_NAME, seq) + self.widget.after(CHECKHIDE_TIME, self.checkhide_event) + self.hideid = self.widget.bind(HIDE_VIRTUAL_EVENT_NAME, + self.hide_event) + for seq in HIDE_SEQUENCES: + self.widget.event_add(HIDE_VIRTUAL_EVENT_NAME, seq) + + def checkhide_event(self, event=None): + if not self.tipwindow: + # If the event was triggered by the same event that unbinded + # this function, the function will be called nevertheless, + # so do nothing in this case. + return + curline, curcol = map(int, self.widget.index("insert").split('.')) + if curline < self.parenline or \ + (curline == self.parenline and curcol <= self.parencol) or \ + self.widget.compare("insert", ">", MARK_RIGHT): + self.hidetip() + else: + self.position_window() + if self.checkhide_after_id is not None: + self.widget.after_cancel(self.checkhide_after_id) + self.checkhide_after_id = \ + self.widget.after(CHECKHIDE_TIME, self.checkhide_event) + + def hide_event(self, event): + if not self.tipwindow: + # See the explanation in checkhide_event. + return + self.hidetip() + + def hidetip(self): + if not self.tipwindow: + return + + for seq in CHECKHIDE_SEQUENCES: + self.widget.event_delete(CHECKHIDE_VIRTUAL_EVENT_NAME, seq) + self.widget.unbind(CHECKHIDE_VIRTUAL_EVENT_NAME, self.checkhideid) + self.checkhideid = None + for seq in HIDE_SEQUENCES: + self.widget.event_delete(HIDE_VIRTUAL_EVENT_NAME, seq) + self.widget.unbind(HIDE_VIRTUAL_EVENT_NAME, self.hideid) + self.hideid = None + + self.label.destroy() + self.label = None + self.tipwindow.destroy() + self.tipwindow = None + + self.widget.mark_unset(MARK_RIGHT) + self.parenline = self.parencol = self.lastline = None + + def is_active(self): + return bool(self.tipwindow) + + +def _calltip_window(parent): + root = Tk() + root.title("Test calltips") + width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) + root.geometry("+%d+%d"%(x, y + 150)) + + class MyEditWin: # comparenceptually an editor_window + def __init__(self): + text = self.text = Text(root) + text.pack(side=LEFT, fill=BOTH, expand=1) + text.insert("insert", "string.split") + root.update() + self.calltip = CallTip(text) + + text.event_add("<>", "(") + text.event_add("<>", ")") + text.bind("<>", self.calltip_show) + text.bind("<>", self.calltip_hide) + + text.focus_set() + root.mainloop() + + def calltip_show(self, event): + self.calltip.showtip("Hello world", "insert", "end") + + def calltip_hide(self, event): + self.calltip.hidetip() + + editwin = MyEditWin() + +if __name__=='__main__': + from idlelib.idle_test.htest import run + run(_calltip_window) diff --git a/PythonHome/Lib/idlelib/CallTipWindow.pyc b/PythonHome/Lib/idlelib/CallTipWindow.pyc deleted file mode 100644 index 3ade0fe92d1dad21e73d6ce3727089a1f909d070..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6200 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 hMHbh6m|db`>;)8c++ON>"), + ]) + ] + + def __init__(self, editwin=None): + if editwin is None: # subprocess and test + self.editwin = None + return + self.editwin = editwin + self.text = editwin.text + self.calltip = None + self._make_calltip_window = self._make_tk_calltip_window + + def close(self): + self._make_calltip_window = None + + def _make_tk_calltip_window(self): + # See __init__ for usage + return CallTipWindow.CallTip(self.text) + + def _remove_calltip_window(self, event=None): + if self.calltip: + self.calltip.hidetip() + self.calltip = None + + def force_open_calltip_event(self, event): + """Happens when the user really wants to open a CallTip, even if a + function call is needed. + """ + self.open_calltip(True) + + def try_open_calltip_event(self, event): + """Happens when it would be nice to open a CallTip, but not really + necessary, for example after an opening bracket, so function calls + won't be made. + """ + self.open_calltip(False) + + def refresh_calltip_event(self, event): + """If there is already a calltip window, check if it is still needed, + and if so, reload it. + """ + if self.calltip and self.calltip.is_active(): + self.open_calltip(False) + + def open_calltip(self, evalfuncs): + self._remove_calltip_window() + + hp = HyperParser(self.editwin, "insert") + sur_paren = hp.get_surrounding_brackets('(') + if not sur_paren: + return + hp.set_index(sur_paren[0]) + expression = hp.get_expression() + if not expression or (not evalfuncs and expression.find('(') != -1): + return + arg_text = self.fetch_tip(expression) + if not arg_text: + return + self.calltip = self._make_calltip_window() + self.calltip.showtip(arg_text, sur_paren[0], sur_paren[1]) + + def fetch_tip(self, expression): + """Return the argument list and docstring of a function or class + + If there is a Python subprocess, get the calltip there. Otherwise, + either fetch_tip() is running in the subprocess itself or it was called + in an IDLE EditorWindow before any script had been run. + + The subprocess environment is that of the most recently run script. If + two unrelated modules are being edited some calltips in the current + module may be inoperative if the module was not the last to run. + + To find methods, fetch_tip must be fed a fully qualified name. + + """ + try: + rpcclt = self.editwin.flist.pyshell.interp.rpcclt + except AttributeError: + rpcclt = None + if rpcclt: + return rpcclt.remotecall("exec", "get_the_calltip", + (expression,), {}) + else: + entity = self.get_entity(expression) + return get_arg_text(entity) + + def get_entity(self, expression): + """Return the object corresponding to expression evaluated + in a namespace spanning sys.modules and __main.dict__. + """ + if expression: + namespace = sys.modules.copy() + namespace.update(__main__.__dict__) + try: + return eval(expression, namespace) + except BaseException: + # An uncaught exception closes idle, and eval can raise any + # exception, especially if user classes are involved. + return None + +def _find_constructor(class_ob): + # Given a class object, return a function object used for the + # constructor (ie, __init__() ) or None if we can't find one. + try: + return class_ob.__init__.im_func + except AttributeError: + for base in class_ob.__bases__: + rc = _find_constructor(base) + if rc is not None: return rc + return None + +# The following are used in get_arg_text +_MAX_COLS = 85 +_MAX_LINES = 5 # enough for bytes +_INDENT = ' '*4 # for wrapped signatures + +def get_arg_text(ob): + '''Return a string describing the signature of a callable object, or ''. + + For Python-coded functions and methods, the first line is introspected. + Delete 'self' parameter for classes (.__init__) and bound methods. + The next lines are the first lines of the doc string up to the first + empty line or _MAX_LINES. For builtins, this typically includes + the arguments in addition to the return value. + ''' + argspec = "" + try: + ob_call = ob.__call__ + except BaseException: + if type(ob) is types.ClassType: # old-style + ob_call = ob + else: + return argspec + + arg_offset = 0 + if type(ob) in (types.ClassType, types.TypeType): + # Look for the first __init__ in the class chain with .im_func. + # Slot wrappers (builtins, classes defined in funcs) do not. + fob = _find_constructor(ob) + if fob is None: + fob = lambda: None + else: + arg_offset = 1 + elif type(ob) == types.MethodType: + # bit of a hack for methods - turn it into a function + # and drop the "self" param for bound methods + fob = ob.im_func + if ob.im_self is not None: + arg_offset = 1 + elif type(ob_call) == types.MethodType: + # a callable class instance + fob = ob_call.im_func + arg_offset = 1 + else: + fob = ob + # Try to build one for Python defined functions + if type(fob) in [types.FunctionType, types.LambdaType]: + argcount = fob.func_code.co_argcount + real_args = fob.func_code.co_varnames[arg_offset:argcount] + defaults = fob.func_defaults or [] + defaults = list(map(lambda name: "=%s" % repr(name), defaults)) + defaults = [""] * (len(real_args) - len(defaults)) + defaults + items = map(lambda arg, dflt: arg + dflt, real_args, defaults) + for flag, pre, name in ((0x4, '*', 'args'), (0x8, '**', 'kwargs')): + if fob.func_code.co_flags & flag: + pre_name = pre + name + if name not in real_args: + items.append(pre_name) + else: + i = 1 + while ((name+'%s') % i) in real_args: + i += 1 + items.append((pre_name+'%s') % i) + argspec = ", ".join(items) + argspec = "(%s)" % re.sub("(?", argspec) + + lines = (textwrap.wrap(argspec, _MAX_COLS, subsequent_indent=_INDENT) + if len(argspec) > _MAX_COLS else [argspec] if argspec else []) + + if isinstance(ob_call, types.MethodType): + doc = ob_call.__doc__ + else: + doc = getattr(ob, "__doc__", "") + if doc: + for line in doc.split('\n', _MAX_LINES)[:_MAX_LINES]: + line = line.strip() + if not line: + break + if len(line) > _MAX_COLS: + line = line[: _MAX_COLS - 3] + '...' + lines.append(line) + argspec = '\n'.join(lines) + return argspec + +if __name__ == '__main__': + from unittest import main + main('idlelib.idle_test.test_calltips', verbosity=2) diff --git a/PythonHome/Lib/idlelib/CallTips.pyc b/PythonHome/Lib/idlelib/CallTips.pyc deleted file mode 100644 index fa5fc61fefd2fd438f19a8929d839aa9db07f683..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7888 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 diff --git a/PythonHome/Lib/idlelib/ClassBrowser.py b/PythonHome/Lib/idlelib/ClassBrowser.py new file mode 100644 index 0000000000..6183be92ae --- /dev/null +++ b/PythonHome/Lib/idlelib/ClassBrowser.py @@ -0,0 +1,229 @@ +"""Class browser. + +XXX TO DO: + +- reparse when source changed (maybe just a button would be OK?) + (or recheck on window popup) +- add popup menu with more options (e.g. doc strings, base classes, imports) +- show function argument list? (have to do pattern matching on source) +- should the classes and methods lists also be in the module's menu bar? +- add base classes to class browser tree +""" + +import os +import sys +import pyclbr + +from idlelib import PyShell +from idlelib.WindowList import ListedToplevel +from idlelib.TreeWidget import TreeNode, TreeItem, ScrolledCanvas +from idlelib.configHandler import idleConf + +class ClassBrowser: + + def __init__(self, flist, name, path, _htest=False): + # XXX This API should change, if the file doesn't end in ".py" + # XXX the code here is bogus! + """ + _htest - bool, change box when location running htest. + """ + self.name = name + self.file = os.path.join(path[0], self.name + ".py") + self._htest = _htest + self.init(flist) + + def close(self, event=None): + self.top.destroy() + self.node.destroy() + + def init(self, flist): + self.flist = flist + # reset pyclbr + pyclbr._modules.clear() + # create top + self.top = top = ListedToplevel(flist.root) + top.protocol("WM_DELETE_WINDOW", self.close) + top.bind("", self.close) + if self._htest: # place dialog below parent if running htest + top.geometry("+%d+%d" % + (flist.root.winfo_rootx(), flist.root.winfo_rooty() + 200)) + self.settitle() + top.focus_set() + # create scrolled canvas + theme = idleConf.GetOption('main','Theme','name') + background = idleConf.GetHighlight(theme, 'normal')['background'] + sc = ScrolledCanvas(top, bg=background, highlightthickness=0, takefocus=1) + sc.frame.pack(expand=1, fill="both") + item = self.rootnode() + self.node = node = TreeNode(sc.canvas, None, item) + node.update() + node.expand() + + def settitle(self): + self.top.wm_title("Class Browser - " + self.name) + self.top.wm_iconname("Class Browser") + + def rootnode(self): + return ModuleBrowserTreeItem(self.file) + +class ModuleBrowserTreeItem(TreeItem): + + def __init__(self, file): + self.file = file + + def GetText(self): + return os.path.basename(self.file) + + def GetIconName(self): + return "python" + + def GetSubList(self): + sublist = [] + for name in self.listclasses(): + item = ClassBrowserTreeItem(name, self.classes, self.file) + sublist.append(item) + return sublist + + def OnDoubleClick(self): + if os.path.normcase(self.file[-3:]) != ".py": + return + if not os.path.exists(self.file): + return + PyShell.flist.open(self.file) + + def IsExpandable(self): + return os.path.normcase(self.file[-3:]) == ".py" + + def listclasses(self): + dir, file = os.path.split(self.file) + name, ext = os.path.splitext(file) + if os.path.normcase(ext) != ".py": + return [] + try: + dict = pyclbr.readmodule_ex(name, [dir] + sys.path) + except ImportError, msg: + return [] + items = [] + self.classes = {} + for key, cl in dict.items(): + if cl.module == name: + s = key + if hasattr(cl, 'super') and cl.super: + supers = [] + for sup in cl.super: + if type(sup) is type(''): + sname = sup + else: + sname = sup.name + if sup.module != cl.module: + sname = "%s.%s" % (sup.module, sname) + supers.append(sname) + s = s + "(%s)" % ", ".join(supers) + items.append((cl.lineno, s)) + self.classes[s] = cl + items.sort() + list = [] + for item, s in items: + list.append(s) + return list + +class ClassBrowserTreeItem(TreeItem): + + def __init__(self, name, classes, file): + self.name = name + self.classes = classes + self.file = file + try: + self.cl = self.classes[self.name] + except (IndexError, KeyError): + self.cl = None + self.isfunction = isinstance(self.cl, pyclbr.Function) + + def GetText(self): + if self.isfunction: + return "def " + self.name + "(...)" + else: + return "class " + self.name + + def GetIconName(self): + if self.isfunction: + return "python" + else: + return "folder" + + def IsExpandable(self): + if self.cl: + try: + return not not self.cl.methods + except AttributeError: + return False + + def GetSubList(self): + if not self.cl: + return [] + sublist = [] + for name in self.listmethods(): + item = MethodBrowserTreeItem(name, self.cl, self.file) + sublist.append(item) + return sublist + + def OnDoubleClick(self): + if not os.path.exists(self.file): + return + edit = PyShell.flist.open(self.file) + if hasattr(self.cl, 'lineno'): + lineno = self.cl.lineno + edit.gotoline(lineno) + + def listmethods(self): + if not self.cl: + return [] + items = [] + for name, lineno in self.cl.methods.items(): + items.append((lineno, name)) + items.sort() + list = [] + for item, name in items: + list.append(name) + return list + +class MethodBrowserTreeItem(TreeItem): + + def __init__(self, name, cl, file): + self.name = name + self.cl = cl + self.file = file + + def GetText(self): + return "def " + self.name + "(...)" + + def GetIconName(self): + return "python" # XXX + + def IsExpandable(self): + return 0 + + def OnDoubleClick(self): + if not os.path.exists(self.file): + return + edit = PyShell.flist.open(self.file) + edit.gotoline(self.cl.methods[self.name]) + +def _class_browser(parent): #Wrapper for htest + try: + file = __file__ + except NameError: + file = sys.argv[0] + if sys.argv[1:]: + file = sys.argv[1] + else: + file = sys.argv[0] + dir, file = os.path.split(file) + name = os.path.splitext(file)[0] + flist = PyShell.PyShellFileList(parent) + ClassBrowser(flist, name, [dir], _htest=True) + parent.mainloop() + +if __name__ == "__main__": + from idlelib.idle_test.htest import run + run(_class_browser) diff --git a/PythonHome/Lib/idlelib/ClassBrowser.pyc b/PythonHome/Lib/idlelib/ClassBrowser.pyc deleted file mode 100644 index be5ef0b6391e1700c7b10a78b042a38ae1a97222..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9054 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 diff --git a/PythonHome/Lib/idlelib/CodeContext.py b/PythonHome/Lib/idlelib/CodeContext.py new file mode 100644 index 0000000000..2f6f737b67 --- /dev/null +++ b/PythonHome/Lib/idlelib/CodeContext.py @@ -0,0 +1,176 @@ +"""CodeContext - Extension to display the block context above the edit window + +Once code has scrolled off the top of a window, it can be difficult to +determine which block you are in. This extension implements a pane at the top +of each IDLE edit window which provides block structure hints. These hints are +the lines which contain the block opening keywords, e.g. 'if', for the +enclosing block. The number of hint lines is determined by the numlines +variable in the CodeContext section of config-extensions.def. Lines which do +not open blocks are not shown in the context hints pane. + +""" +import Tkinter +from Tkconstants import TOP, LEFT, X, W, SUNKEN +import re +from sys import maxint as INFINITY +from idlelib.configHandler import idleConf + +BLOCKOPENERS = set(["class", "def", "elif", "else", "except", "finally", "for", + "if", "try", "while", "with"]) +UPDATEINTERVAL = 100 # millisec +FONTUPDATEINTERVAL = 1000 # millisec + +getspacesfirstword =\ + lambda s, c=re.compile(r"^(\s*)(\w*)"): c.match(s).groups() + +class CodeContext: + menudefs = [('options', [('!Code Conte_xt', '<>')])] + context_depth = idleConf.GetOption("extensions", "CodeContext", + "numlines", type="int", default=3) + bgcolor = idleConf.GetOption("extensions", "CodeContext", + "bgcolor", type="str", default="LightGray") + fgcolor = idleConf.GetOption("extensions", "CodeContext", + "fgcolor", type="str", default="Black") + def __init__(self, editwin): + self.editwin = editwin + self.text = editwin.text + self.textfont = self.text["font"] + self.label = None + # self.info is a list of (line number, indent level, line text, block + # keyword) tuples providing the block structure associated with + # self.topvisible (the linenumber of the line displayed at the top of + # the edit window). self.info[0] is initialized as a 'dummy' line which + # starts the toplevel 'block' of the module. + self.info = [(0, -1, "", False)] + self.topvisible = 1 + visible = idleConf.GetOption("extensions", "CodeContext", + "visible", type="bool", default=False) + if visible: + self.toggle_code_context_event() + self.editwin.setvar('<>', True) + # Start two update cycles, one for context lines, one for font changes. + self.text.after(UPDATEINTERVAL, self.timer_event) + self.text.after(FONTUPDATEINTERVAL, self.font_timer_event) + + def toggle_code_context_event(self, event=None): + if not self.label: + # Calculate the border width and horizontal padding required to + # align the context with the text in the main Text widget. + # + # All values are passed through int(str()), since some + # values may be pixel objects, which can't simply be added to ints. + widgets = self.editwin.text, self.editwin.text_frame + # Calculate the required vertical padding + padx = 0 + for widget in widgets: + padx += int(str( widget.pack_info()['padx'] )) + padx += int(str( widget.cget('padx') )) + # Calculate the required border width + border = 0 + for widget in widgets: + border += int(str( widget.cget('border') )) + self.label = Tkinter.Label(self.editwin.top, + text="\n" * (self.context_depth - 1), + anchor=W, justify=LEFT, + font=self.textfont, + bg=self.bgcolor, fg=self.fgcolor, + width=1, #don't request more than we get + padx=padx, border=border, + relief=SUNKEN) + # Pack the label widget before and above the text_frame widget, + # thus ensuring that it will appear directly above text_frame + self.label.pack(side=TOP, fill=X, expand=False, + before=self.editwin.text_frame) + else: + self.label.destroy() + self.label = None + idleConf.SetOption("extensions", "CodeContext", "visible", + str(self.label is not None)) + idleConf.SaveUserCfgFiles() + + def get_line_info(self, linenum): + """Get the line indent value, text, and any block start keyword + + If the line does not start a block, the keyword value is False. + The indentation of empty lines (or comment lines) is INFINITY. + + """ + text = self.text.get("%d.0" % linenum, "%d.end" % linenum) + spaces, firstword = getspacesfirstword(text) + opener = firstword in BLOCKOPENERS and firstword + if len(text) == len(spaces) or text[len(spaces)] == '#': + indent = INFINITY + else: + indent = len(spaces) + return indent, text, opener + + def get_context(self, new_topvisible, stopline=1, stopindent=0): + """Get context lines, starting at new_topvisible and working backwards. + + Stop when stopline or stopindent is reached. Return a tuple of context + data and the indent level at the top of the region inspected. + + """ + assert stopline > 0 + lines = [] + # The indentation level we are currently in: + lastindent = INFINITY + # For a line to be interesting, it must begin with a block opening + # keyword, and have less indentation than lastindent. + for linenum in xrange(new_topvisible, stopline-1, -1): + indent, text, opener = self.get_line_info(linenum) + if indent < lastindent: + lastindent = indent + if opener in ("else", "elif"): + # We also show the if statement + lastindent += 1 + if opener and linenum < new_topvisible and indent >= stopindent: + lines.append((linenum, indent, text, opener)) + if lastindent <= stopindent: + break + lines.reverse() + return lines, lastindent + + def update_code_context(self): + """Update context information and lines visible in the context pane. + + """ + new_topvisible = int(self.text.index("@0,0").split('.')[0]) + if self.topvisible == new_topvisible: # haven't scrolled + return + if self.topvisible < new_topvisible: # scroll down + lines, lastindent = self.get_context(new_topvisible, + self.topvisible) + # retain only context info applicable to the region + # between topvisible and new_topvisible: + while self.info[-1][1] >= lastindent: + del self.info[-1] + elif self.topvisible > new_topvisible: # scroll up + stopindent = self.info[-1][1] + 1 + # retain only context info associated + # with lines above new_topvisible: + while self.info[-1][0] >= new_topvisible: + stopindent = self.info[-1][1] + del self.info[-1] + lines, lastindent = self.get_context(new_topvisible, + self.info[-1][0]+1, + stopindent) + self.info.extend(lines) + self.topvisible = new_topvisible + # empty lines in context pane: + context_strings = [""] * max(0, self.context_depth - len(self.info)) + # followed by the context hint lines: + context_strings += [x[2] for x in self.info[-self.context_depth:]] + self.label["text"] = '\n'.join(context_strings) + + def timer_event(self): + if self.label: + self.update_code_context() + self.text.after(UPDATEINTERVAL, self.timer_event) + + def font_timer_event(self): + newtextfont = self.text["font"] + if self.label and newtextfont != self.textfont: + self.textfont = newtextfont + self.label["font"] = self.textfont + self.text.after(FONTUPDATEINTERVAL, self.font_timer_event) diff --git a/PythonHome/Lib/idlelib/CodeContext.pyc b/PythonHome/Lib/idlelib/CodeContext.pyc deleted file mode 100644 index 75782dba9db07794ff67aa517dd791bbf066d5c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6522 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 diff --git a/PythonHome/Lib/idlelib/ColorDelegator.py b/PythonHome/Lib/idlelib/ColorDelegator.py new file mode 100644 index 0000000000..0c625d3c5b --- /dev/null +++ b/PythonHome/Lib/idlelib/ColorDelegator.py @@ -0,0 +1,275 @@ +import time +import re +import keyword +import __builtin__ +from Tkinter import * +from idlelib.Delegator import Delegator +from idlelib.configHandler import idleConf + +DEBUG = False + +def any(name, alternates): + "Return a named group pattern matching list of alternates." + return "(?P<%s>" % name + "|".join(alternates) + ")" + +def make_pat(): + kw = r"\b" + any("KEYWORD", keyword.kwlist) + r"\b" + builtinlist = [str(name) for name in dir(__builtin__) + if not name.startswith('_')] + # We don't know whether "print" is a function or a keyword, + # so we always treat is as a keyword (the most common case). + builtinlist.remove('print') + # self.file = file("file") : + # 1st 'file' colorized normal, 2nd as builtin, 3rd as string + builtin = r"([^.'\"\\#]\b|^)" + any("BUILTIN", builtinlist) + r"\b" + comment = any("COMMENT", [r"#[^\n]*"]) + stringprefix = r"(\br|u|ur|R|U|UR|Ur|uR|b|B|br|Br|bR|BR)?" + sqstring = stringprefix + r"'[^'\\\n]*(\\.[^'\\\n]*)*'?" + dqstring = stringprefix + r'"[^"\\\n]*(\\.[^"\\\n]*)*"?' + sq3string = stringprefix + r"'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?" + dq3string = stringprefix + r'"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(""")?' + string = any("STRING", [sq3string, dq3string, sqstring, dqstring]) + return kw + "|" + builtin + "|" + comment + "|" + string +\ + "|" + any("SYNC", [r"\n"]) + +prog = re.compile(make_pat(), re.S) +idprog = re.compile(r"\s+(\w+)", re.S) +asprog = re.compile(r".*?\b(as)\b") + +class ColorDelegator(Delegator): + + def __init__(self): + Delegator.__init__(self) + self.prog = prog + self.idprog = idprog + self.asprog = asprog + self.LoadTagDefs() + + def setdelegate(self, delegate): + if self.delegate is not None: + self.unbind("<>") + Delegator.setdelegate(self, delegate) + if delegate is not None: + self.config_colors() + self.bind("<>", self.toggle_colorize_event) + self.notify_range("1.0", "end") + else: + # No delegate - stop any colorizing + self.stop_colorizing = True + self.allow_colorizing = False + + def config_colors(self): + for tag, cnf in self.tagdefs.items(): + if cnf: + self.tag_configure(tag, **cnf) + self.tag_raise('sel') + + def LoadTagDefs(self): + theme = idleConf.GetOption('main','Theme','name') + self.tagdefs = { + "COMMENT": idleConf.GetHighlight(theme, "comment"), + "KEYWORD": idleConf.GetHighlight(theme, "keyword"), + "BUILTIN": idleConf.GetHighlight(theme, "builtin"), + "STRING": idleConf.GetHighlight(theme, "string"), + "DEFINITION": idleConf.GetHighlight(theme, "definition"), + "SYNC": {'background':None,'foreground':None}, + "TODO": {'background':None,'foreground':None}, + "BREAK": idleConf.GetHighlight(theme, "break"), + "ERROR": idleConf.GetHighlight(theme, "error"), + # The following is used by ReplaceDialog: + "hit": idleConf.GetHighlight(theme, "hit"), + } + + if DEBUG: print 'tagdefs',self.tagdefs + + def insert(self, index, chars, tags=None): + index = self.index(index) + self.delegate.insert(index, chars, tags) + self.notify_range(index, index + "+%dc" % len(chars)) + + def delete(self, index1, index2=None): + index1 = self.index(index1) + self.delegate.delete(index1, index2) + self.notify_range(index1) + + after_id = None + allow_colorizing = True + colorizing = False + + def notify_range(self, index1, index2=None): + self.tag_add("TODO", index1, index2) + if self.after_id: + if DEBUG: print "colorizing already scheduled" + return + if self.colorizing: + self.stop_colorizing = True + if DEBUG: print "stop colorizing" + if self.allow_colorizing: + if DEBUG: print "schedule colorizing" + self.after_id = self.after(1, self.recolorize) + + close_when_done = None # Window to be closed when done colorizing + + def close(self, close_when_done=None): + if self.after_id: + after_id = self.after_id + self.after_id = None + if DEBUG: print "cancel scheduled recolorizer" + self.after_cancel(after_id) + self.allow_colorizing = False + self.stop_colorizing = True + if close_when_done: + if not self.colorizing: + close_when_done.destroy() + else: + self.close_when_done = close_when_done + + def toggle_colorize_event(self, event): + if self.after_id: + after_id = self.after_id + self.after_id = None + if DEBUG: print "cancel scheduled recolorizer" + self.after_cancel(after_id) + if self.allow_colorizing and self.colorizing: + if DEBUG: print "stop colorizing" + self.stop_colorizing = True + self.allow_colorizing = not self.allow_colorizing + if self.allow_colorizing and not self.colorizing: + self.after_id = self.after(1, self.recolorize) + if DEBUG: + print "auto colorizing turned",\ + self.allow_colorizing and "on" or "off" + return "break" + + def recolorize(self): + self.after_id = None + if not self.delegate: + if DEBUG: print "no delegate" + return + if not self.allow_colorizing: + if DEBUG: print "auto colorizing is off" + return + if self.colorizing: + if DEBUG: print "already colorizing" + return + try: + self.stop_colorizing = False + self.colorizing = True + if DEBUG: print "colorizing..." + t0 = time.clock() + self.recolorize_main() + t1 = time.clock() + if DEBUG: print "%.3f seconds" % (t1-t0) + finally: + self.colorizing = False + if self.allow_colorizing and self.tag_nextrange("TODO", "1.0"): + if DEBUG: print "reschedule colorizing" + self.after_id = self.after(1, self.recolorize) + if self.close_when_done: + top = self.close_when_done + self.close_when_done = None + top.destroy() + + def recolorize_main(self): + next = "1.0" + while True: + item = self.tag_nextrange("TODO", next) + if not item: + break + head, tail = item + self.tag_remove("SYNC", head, tail) + item = self.tag_prevrange("SYNC", head) + if item: + head = item[1] + else: + head = "1.0" + + chars = "" + next = head + lines_to_get = 1 + ok = False + while not ok: + mark = next + next = self.index(mark + "+%d lines linestart" % + lines_to_get) + lines_to_get = min(lines_to_get * 2, 100) + ok = "SYNC" in self.tag_names(next + "-1c") + line = self.get(mark, next) + ##print head, "get", mark, next, "->", repr(line) + if not line: + return + for tag in self.tagdefs.keys(): + self.tag_remove(tag, mark, next) + chars = chars + line + m = self.prog.search(chars) + while m: + for key, value in m.groupdict().items(): + if value: + a, b = m.span(key) + self.tag_add(key, + head + "+%dc" % a, + head + "+%dc" % b) + if value in ("def", "class"): + m1 = self.idprog.match(chars, b) + if m1: + a, b = m1.span(1) + self.tag_add("DEFINITION", + head + "+%dc" % a, + head + "+%dc" % b) + elif value == "import": + # color all the "as" words on same line, except + # if in a comment; cheap approximation to the + # truth + if '#' in chars: + endpos = chars.index('#') + else: + endpos = len(chars) + while True: + m1 = self.asprog.match(chars, b, endpos) + if not m1: + break + a, b = m1.span(1) + self.tag_add("KEYWORD", + head + "+%dc" % a, + head + "+%dc" % b) + m = self.prog.search(chars, m.end()) + if "SYNC" in self.tag_names(next + "-1c"): + head = next + chars = "" + else: + ok = False + if not ok: + # We're in an inconsistent state, and the call to + # update may tell us to stop. It may also change + # the correct value for "next" (since this is a + # line.col string, not a true mark). So leave a + # crumb telling the next invocation to resume here + # in case update tells us to leave. + self.tag_add("TODO", next) + self.update() + if self.stop_colorizing: + if DEBUG: print "colorizing stopped" + return + + def removecolors(self): + for tag in self.tagdefs.keys(): + self.tag_remove(tag, "1.0", "end") + +def _color_delegator(parent): + from idlelib.Percolator import Percolator + root = Tk() + root.title("Test ColorDelegator") + width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) + root.geometry("+%d+%d"%(x, y + 150)) + source = "if somename: x = 'abc' # comment\nprint" + text = Text(root, background="white") + text.insert("insert", source) + text.pack(expand=1, fill="both") + p = Percolator(text) + d = ColorDelegator() + p.insertfilter(d) + root.mainloop() + +if __name__ == "__main__": + from idlelib.idle_test.htest import run + run(_color_delegator) diff --git a/PythonHome/Lib/idlelib/ColorDelegator.pyc b/PythonHome/Lib/idlelib/ColorDelegator.pyc deleted file mode 100644 index f9e34154d1f7801740b28e2c5636e7d81480eed5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9036 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 L{@)8zMfCn37ALmq diff --git a/PythonHome/Lib/idlelib/Debugger.py b/PythonHome/Lib/idlelib/Debugger.py new file mode 100644 index 0000000000..94a8cb2514 --- /dev/null +++ b/PythonHome/Lib/idlelib/Debugger.py @@ -0,0 +1,481 @@ +import os +import bdb +import types +from Tkinter import * +from idlelib.WindowList import ListedToplevel +from idlelib.ScrolledList import ScrolledList +from idlelib import macosxSupport + + +class Idb(bdb.Bdb): + + def __init__(self, gui): + self.gui = gui + bdb.Bdb.__init__(self) + + def user_line(self, frame): + if self.in_rpc_code(frame): + self.set_step() + return + message = self.__frame2message(frame) + self.gui.interaction(message, frame) + + def user_exception(self, frame, info): + if self.in_rpc_code(frame): + self.set_step() + return + message = self.__frame2message(frame) + self.gui.interaction(message, frame, info) + + def in_rpc_code(self, frame): + if frame.f_code.co_filename.count('rpc.py'): + return True + else: + prev_frame = frame.f_back + if prev_frame.f_code.co_filename.count('Debugger.py'): + # (that test will catch both Debugger.py and RemoteDebugger.py) + return False + return self.in_rpc_code(prev_frame) + + def __frame2message(self, frame): + code = frame.f_code + filename = code.co_filename + lineno = frame.f_lineno + basename = os.path.basename(filename) + message = "%s:%s" % (basename, lineno) + if code.co_name != "?": + message = "%s: %s()" % (message, code.co_name) + return message + + +class Debugger: + + vstack = vsource = vlocals = vglobals = None + + def __init__(self, pyshell, idb=None): + if idb is None: + idb = Idb(self) + self.pyshell = pyshell + self.idb = idb + self.frame = None + self.make_gui() + self.interacting = 0 + + def run(self, *args): + try: + self.interacting = 1 + return self.idb.run(*args) + finally: + self.interacting = 0 + + def close(self, event=None): + if self.interacting: + self.top.bell() + return + if self.stackviewer: + self.stackviewer.close(); self.stackviewer = None + # Clean up pyshell if user clicked debugger control close widget. + # (Causes a harmless extra cycle through close_debugger() if user + # toggled debugger from pyshell Debug menu) + self.pyshell.close_debugger() + # Now close the debugger control window.... + self.top.destroy() + + def make_gui(self): + pyshell = self.pyshell + self.flist = pyshell.flist + self.root = root = pyshell.root + self.top = top = ListedToplevel(root) + self.top.wm_title("Debug Control") + self.top.wm_iconname("Debug") + top.wm_protocol("WM_DELETE_WINDOW", self.close) + self.top.bind("", self.close) + # + self.bframe = bframe = Frame(top) + self.bframe.pack(anchor="w") + self.buttons = bl = [] + # + self.bcont = b = Button(bframe, text="Go", command=self.cont) + bl.append(b) + self.bstep = b = Button(bframe, text="Step", command=self.step) + bl.append(b) + self.bnext = b = Button(bframe, text="Over", command=self.next) + bl.append(b) + self.bret = b = Button(bframe, text="Out", command=self.ret) + bl.append(b) + self.bret = b = Button(bframe, text="Quit", command=self.quit) + bl.append(b) + # + for b in bl: + b.configure(state="disabled") + b.pack(side="left") + # + self.cframe = cframe = Frame(bframe) + self.cframe.pack(side="left") + # + if not self.vstack: + self.__class__.vstack = BooleanVar(top) + self.vstack.set(1) + self.bstack = Checkbutton(cframe, + text="Stack", command=self.show_stack, variable=self.vstack) + self.bstack.grid(row=0, column=0) + if not self.vsource: + self.__class__.vsource = BooleanVar(top) + self.bsource = Checkbutton(cframe, + text="Source", command=self.show_source, variable=self.vsource) + self.bsource.grid(row=0, column=1) + if not self.vlocals: + self.__class__.vlocals = BooleanVar(top) + self.vlocals.set(1) + self.blocals = Checkbutton(cframe, + text="Locals", command=self.show_locals, variable=self.vlocals) + self.blocals.grid(row=1, column=0) + if not self.vglobals: + self.__class__.vglobals = BooleanVar(top) + self.bglobals = Checkbutton(cframe, + text="Globals", command=self.show_globals, variable=self.vglobals) + self.bglobals.grid(row=1, column=1) + # + self.status = Label(top, anchor="w") + self.status.pack(anchor="w") + self.error = Label(top, anchor="w") + self.error.pack(anchor="w", fill="x") + self.errorbg = self.error.cget("background") + # + self.fstack = Frame(top, height=1) + self.fstack.pack(expand=1, fill="both") + self.flocals = Frame(top) + self.flocals.pack(expand=1, fill="both") + self.fglobals = Frame(top, height=1) + self.fglobals.pack(expand=1, fill="both") + # + if self.vstack.get(): + self.show_stack() + if self.vlocals.get(): + self.show_locals() + if self.vglobals.get(): + self.show_globals() + + def interaction(self, message, frame, info=None): + self.frame = frame + self.status.configure(text=message) + # + if info: + type, value, tb = info + try: + m1 = type.__name__ + except AttributeError: + m1 = "%s" % str(type) + if value is not None: + try: + m1 = "%s: %s" % (m1, str(value)) + except: + pass + bg = "yellow" + else: + m1 = "" + tb = None + bg = self.errorbg + self.error.configure(text=m1, background=bg) + # + sv = self.stackviewer + if sv: + stack, i = self.idb.get_stack(self.frame, tb) + sv.load_stack(stack, i) + # + self.show_variables(1) + # + if self.vsource.get(): + self.sync_source_line() + # + for b in self.buttons: + b.configure(state="normal") + # + self.top.wakeup() + self.root.mainloop() + # + for b in self.buttons: + b.configure(state="disabled") + self.status.configure(text="") + self.error.configure(text="", background=self.errorbg) + self.frame = None + + def sync_source_line(self): + frame = self.frame + if not frame: + return + filename, lineno = self.__frame2fileline(frame) + if filename[:1] + filename[-1:] != "<>" and os.path.exists(filename): + self.flist.gotofileline(filename, lineno) + + def __frame2fileline(self, frame): + code = frame.f_code + filename = code.co_filename + lineno = frame.f_lineno + return filename, lineno + + def cont(self): + self.idb.set_continue() + self.root.quit() + + def step(self): + self.idb.set_step() + self.root.quit() + + def next(self): + self.idb.set_next(self.frame) + self.root.quit() + + def ret(self): + self.idb.set_return(self.frame) + self.root.quit() + + def quit(self): + self.idb.set_quit() + self.root.quit() + + stackviewer = None + + def show_stack(self): + if not self.stackviewer and self.vstack.get(): + self.stackviewer = sv = StackViewer(self.fstack, self.flist, self) + if self.frame: + stack, i = self.idb.get_stack(self.frame, None) + sv.load_stack(stack, i) + else: + sv = self.stackviewer + if sv and not self.vstack.get(): + self.stackviewer = None + sv.close() + self.fstack['height'] = 1 + + def show_source(self): + if self.vsource.get(): + self.sync_source_line() + + def show_frame(self, stackitem): + self.frame = stackitem[0] # lineno is stackitem[1] + self.show_variables() + + localsviewer = None + globalsviewer = None + + def show_locals(self): + lv = self.localsviewer + if self.vlocals.get(): + if not lv: + self.localsviewer = NamespaceViewer(self.flocals, "Locals") + else: + if lv: + self.localsviewer = None + lv.close() + self.flocals['height'] = 1 + self.show_variables() + + def show_globals(self): + gv = self.globalsviewer + if self.vglobals.get(): + if not gv: + self.globalsviewer = NamespaceViewer(self.fglobals, "Globals") + else: + if gv: + self.globalsviewer = None + gv.close() + self.fglobals['height'] = 1 + self.show_variables() + + def show_variables(self, force=0): + lv = self.localsviewer + gv = self.globalsviewer + frame = self.frame + if not frame: + ldict = gdict = None + else: + ldict = frame.f_locals + gdict = frame.f_globals + if lv and gv and ldict is gdict: + ldict = None + if lv: + lv.load_dict(ldict, force, self.pyshell.interp.rpcclt) + if gv: + gv.load_dict(gdict, force, self.pyshell.interp.rpcclt) + + def set_breakpoint_here(self, filename, lineno): + self.idb.set_break(filename, lineno) + + def clear_breakpoint_here(self, filename, lineno): + self.idb.clear_break(filename, lineno) + + def clear_file_breaks(self, filename): + self.idb.clear_all_file_breaks(filename) + + def load_breakpoints(self): + "Load PyShellEditorWindow breakpoints into subprocess debugger" + pyshell_edit_windows = self.pyshell.flist.inversedict.keys() + for editwin in pyshell_edit_windows: + filename = editwin.io.filename + try: + for lineno in editwin.breakpoints: + self.set_breakpoint_here(filename, lineno) + except AttributeError: + continue + +class StackViewer(ScrolledList): + + def __init__(self, master, flist, gui): + if macosxSupport.isAquaTk(): + # At least on with the stock AquaTk version on OSX 10.4 you'll + # get an shaking GUI that eventually kills IDLE if the width + # argument is specified. + ScrolledList.__init__(self, master) + else: + ScrolledList.__init__(self, master, width=80) + self.flist = flist + self.gui = gui + self.stack = [] + + def load_stack(self, stack, index=None): + self.stack = stack + self.clear() + for i in range(len(stack)): + frame, lineno = stack[i] + try: + modname = frame.f_globals["__name__"] + except: + modname = "?" + code = frame.f_code + filename = code.co_filename + funcname = code.co_name + import linecache + sourceline = linecache.getline(filename, lineno) + import string + sourceline = string.strip(sourceline) + if funcname in ("?", "", None): + item = "%s, line %d: %s" % (modname, lineno, sourceline) + else: + item = "%s.%s(), line %d: %s" % (modname, funcname, + lineno, sourceline) + if i == index: + item = "> " + item + self.append(item) + if index is not None: + self.select(index) + + def popup_event(self, event): + "override base method" + if self.stack: + return ScrolledList.popup_event(self, event) + + def fill_menu(self): + "override base method" + menu = self.menu + menu.add_command(label="Go to source line", + command=self.goto_source_line) + menu.add_command(label="Show stack frame", + command=self.show_stack_frame) + + def on_select(self, index): + "override base method" + if 0 <= index < len(self.stack): + self.gui.show_frame(self.stack[index]) + + def on_double(self, index): + "override base method" + self.show_source(index) + + def goto_source_line(self): + index = self.listbox.index("active") + self.show_source(index) + + def show_stack_frame(self): + index = self.listbox.index("active") + if 0 <= index < len(self.stack): + self.gui.show_frame(self.stack[index]) + + def show_source(self, index): + if not (0 <= index < len(self.stack)): + return + frame, lineno = self.stack[index] + code = frame.f_code + filename = code.co_filename + if os.path.isfile(filename): + edit = self.flist.open(filename) + if edit: + edit.gotoline(lineno) + + +class NamespaceViewer: + + def __init__(self, master, title, dict=None): + width = 0 + height = 40 + if dict: + height = 20*len(dict) # XXX 20 == observed height of Entry widget + self.master = master + self.title = title + import repr + self.repr = repr.Repr() + self.repr.maxstring = 60 + self.repr.maxother = 60 + self.frame = frame = Frame(master) + self.frame.pack(expand=1, fill="both") + self.label = Label(frame, text=title, borderwidth=2, relief="groove") + self.label.pack(fill="x") + self.vbar = vbar = Scrollbar(frame, name="vbar") + vbar.pack(side="right", fill="y") + self.canvas = canvas = Canvas(frame, + height=min(300, max(40, height)), + scrollregion=(0, 0, width, height)) + canvas.pack(side="left", fill="both", expand=1) + vbar["command"] = canvas.yview + canvas["yscrollcommand"] = vbar.set + self.subframe = subframe = Frame(canvas) + self.sfid = canvas.create_window(0, 0, window=subframe, anchor="nw") + self.load_dict(dict) + + dict = -1 + + def load_dict(self, dict, force=0, rpc_client=None): + if dict is self.dict and not force: + return + subframe = self.subframe + frame = self.frame + for c in subframe.children.values(): + c.destroy() + self.dict = None + if not dict: + l = Label(subframe, text="None") + l.grid(row=0, column=0) + else: + names = dict.keys() + names.sort() + row = 0 + for name in names: + value = dict[name] + svalue = self.repr.repr(value) # repr(value) + # Strip extra quotes caused by calling repr on the (already) + # repr'd value sent across the RPC interface: + if rpc_client: + svalue = svalue[1:-1] + l = Label(subframe, text=name) + l.grid(row=row, column=0, sticky="nw") + l = Entry(subframe, width=0, borderwidth=0) + l.insert(0, svalue) + l.grid(row=row, column=1, sticky="nw") + row = row+1 + self.dict = dict + # XXX Could we use a callback for the following? + subframe.update_idletasks() # Alas! + width = subframe.winfo_reqwidth() + height = subframe.winfo_reqheight() + canvas = self.canvas + self.canvas["scrollregion"] = (0, 0, width, height) + if height > 300: + canvas["height"] = 300 + frame.pack(expand=1) + else: + canvas["height"] = height + frame.pack(expand=0) + + def close(self): + self.frame.destroy() diff --git a/PythonHome/Lib/idlelib/Debugger.pyc b/PythonHome/Lib/idlelib/Debugger.pyc deleted file mode 100644 index 453e1e052a259a1d9694bdbd72fd503ae7617d7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16270 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 diff --git a/PythonHome/Lib/idlelib/Delegator.py b/PythonHome/Lib/idlelib/Delegator.py new file mode 100644 index 0000000000..c4765163f8 --- /dev/null +++ b/PythonHome/Lib/idlelib/Delegator.py @@ -0,0 +1,25 @@ +class Delegator: + + # The cache is only used to be able to change delegates! + + def __init__(self, delegate=None): + self.delegate = delegate + self.__cache = set() + + def __getattr__(self, name): + attr = getattr(self.delegate, name) # May raise AttributeError + setattr(self, name, attr) + self.__cache.add(name) + return attr + + def resetcache(self): + for key in self.__cache: + try: + delattr(self, key) + except AttributeError: + pass + self.__cache.clear() + + def setdelegate(self, delegate): + self.resetcache() + self.delegate = delegate diff --git a/PythonHome/Lib/idlelib/Delegator.pyc b/PythonHome/Lib/idlelib/Delegator.pyc deleted file mode 100644 index 29e79587f08ddbc047f40065f5a7f17eb7f44216..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1178 zcmb7DO>fgc5S_K%Gzl#COb3l&5Ywe`~BbJucJa%pBT?KIPDXN62DkVBex<;kE}g-(AWAKG7@nw~RSb zoFLj~&<;;OR%fSGS-Tp~P5j}Hg_g0lnpNIfB5s*SOwTBE)}`YZr#*u33U>+ufF8+B zBt9YmQi^05i-9qXWt!*>1Dib#yqMqbLYzCFd*3Kjb%2{XlsQFSmfD7l)s@>UzjUhb z;@$Z@K)ki9g4S}*En6$*u{prEAT&0xgQGM*K>2k|MO*3!2ZcXj-MyDF+ zGw#AI?oPUofX1Pzx*v~VwR;c(zOfmYebWu&{bw`zjs*C`zS>bN{FVf-X9pCzV`?g~ z`>h;D0&MH$X5H1+_02G4e^y(`kz4D@#@fqyc~#S7#o>JBGPWvXvVe*2#', self.destroy, '+') + + def nearwindow(self, near): + # Place the help dialog near the window specified by parent. + # Note - this may not reposition the window in Metacity + # if "/apps/metacity/general/disable_workarounds" is enabled + dlg = self.dlg + geom = (near.winfo_rootx() + 10, near.winfo_rooty() + 10) + dlg.withdraw() + dlg.geometry("=+%d+%d" % geom) + dlg.deiconify() + dlg.lift() + + def destroy(self, ev=None): + self.dlg = None + self.parent = None + +helpDialog = HelpDialog() # singleton instance +def _help_dialog(parent): # wrapper for htest + helpDialog.show_dialog(parent) + + +class EditorWindow(object): + from idlelib.Percolator import Percolator + from idlelib.ColorDelegator import ColorDelegator + from idlelib.UndoDelegator import UndoDelegator + from idlelib.IOBinding import IOBinding, filesystemencoding, encoding + from idlelib import Bindings + from Tkinter import Toplevel + from idlelib.MultiStatusBar import MultiStatusBar + + help_url = None + + def __init__(self, flist=None, filename=None, key=None, root=None): + if EditorWindow.help_url is None: + dochome = os.path.join(sys.prefix, 'Doc', 'index.html') + if sys.platform.count('linux'): + # look for html docs in a couple of standard places + pyver = 'python-docs-' + '%s.%s.%s' % sys.version_info[:3] + if os.path.isdir('/var/www/html/python/'): # "python2" rpm + dochome = '/var/www/html/python/index.html' + else: + basepath = '/usr/share/doc/' # standard location + dochome = os.path.join(basepath, pyver, + 'Doc', 'index.html') + elif sys.platform[:3] == 'win': + chmfile = os.path.join(sys.prefix, 'Doc', + 'Python%s.chm' % _sphinx_version()) + if os.path.isfile(chmfile): + dochome = chmfile + elif sys.platform == 'darwin': + # documentation may be stored inside a python framework + dochome = os.path.join(sys.prefix, + 'Resources/English.lproj/Documentation/index.html') + dochome = os.path.normpath(dochome) + if os.path.isfile(dochome): + EditorWindow.help_url = dochome + if sys.platform == 'darwin': + # Safari requires real file:-URLs + EditorWindow.help_url = 'file://' + EditorWindow.help_url + else: + EditorWindow.help_url = "http://docs.python.org/%d.%d" % sys.version_info[:2] + currentTheme=idleConf.CurrentTheme() + self.flist = flist + root = root or flist.root + self.root = root + try: + sys.ps1 + except AttributeError: + sys.ps1 = '>>> ' + self.menubar = Menu(root) + self.top = top = WindowList.ListedToplevel(root, menu=self.menubar) + if flist: + self.tkinter_vars = flist.vars + #self.top.instance_dict makes flist.inversedict available to + #configDialog.py so it can access all EditorWindow instances + self.top.instance_dict = flist.inversedict + else: + self.tkinter_vars = {} # keys: Tkinter event names + # values: Tkinter variable instances + self.top.instance_dict = {} + self.recent_files_path = os.path.join(idleConf.GetUserCfgDir(), + 'recent-files.lst') + self.text_frame = text_frame = Frame(top) + self.vbar = vbar = Scrollbar(text_frame, name='vbar') + self.width = idleConf.GetOption('main','EditorWindow','width', type='int') + text_options = { + 'name': 'text', + 'padx': 5, + 'wrap': 'none', + 'width': self.width, + 'height': idleConf.GetOption('main', 'EditorWindow', 'height', type='int')} + if TkVersion >= 8.5: + # Starting with tk 8.5 we have to set the new tabstyle option + # to 'wordprocessor' to achieve the same display of tabs as in + # older tk versions. + text_options['tabstyle'] = 'wordprocessor' + self.text = text = MultiCallCreator(Text)(text_frame, **text_options) + self.top.focused_widget = self.text + + self.createmenubar() + self.apply_bindings() + + self.top.protocol("WM_DELETE_WINDOW", self.close) + self.top.bind("<>", self.close_event) + if macosxSupport.isAquaTk(): + # Command-W on editorwindows doesn't work without this. + text.bind('<>', self.close_event) + # Some OS X systems have only one mouse button, + # so use control-click for pulldown menus there. + # (Note, AquaTk defines <2> as the right button if + # present and the Tk Text widget already binds <2>.) + text.bind("",self.right_menu_event) + else: + # Elsewhere, use right-click for pulldown menus. + text.bind("<3>",self.right_menu_event) + text.bind("<>", self.cut) + text.bind("<>", self.copy) + text.bind("<>", self.paste) + text.bind("<>", self.center_insert_event) + text.bind("<>", self.help_dialog) + text.bind("<>", self.python_docs) + text.bind("<>", self.about_dialog) + text.bind("<>", self.config_dialog) + text.bind("<>", self.open_module) + text.bind("<>", lambda event: "break") + text.bind("<>", self.select_all) + text.bind("<>", self.remove_selection) + text.bind("<>", self.find_event) + text.bind("<>", self.find_again_event) + text.bind("<>", self.find_in_files_event) + text.bind("<>", self.find_selection_event) + text.bind("<>", self.replace_event) + text.bind("<>", self.goto_line_event) + text.bind("<>",self.smart_backspace_event) + text.bind("<>",self.newline_and_indent_event) + text.bind("<>",self.smart_indent_event) + text.bind("<>",self.indent_region_event) + text.bind("<>",self.dedent_region_event) + text.bind("<>",self.comment_region_event) + text.bind("<>",self.uncomment_region_event) + text.bind("<>",self.tabify_region_event) + text.bind("<>",self.untabify_region_event) + text.bind("<>",self.toggle_tabs_event) + text.bind("<>",self.change_indentwidth_event) + text.bind("", self.move_at_edge_if_selection(0)) + text.bind("", self.move_at_edge_if_selection(1)) + text.bind("<>", self.del_word_left) + text.bind("<>", self.del_word_right) + text.bind("<>", self.home_callback) + + if flist: + flist.inversedict[self] = key + if key: + flist.dict[key] = self + text.bind("<>", self.new_callback) + text.bind("<>", self.flist.close_all_callback) + text.bind("<>", self.open_class_browser) + text.bind("<>", self.open_path_browser) + + self.set_status_bar() + vbar['command'] = text.yview + vbar.pack(side=RIGHT, fill=Y) + text['yscrollcommand'] = vbar.set + fontWeight = 'normal' + if idleConf.GetOption('main', 'EditorWindow', 'font-bold', type='bool'): + fontWeight='bold' + text.config(font=(idleConf.GetOption('main', 'EditorWindow', 'font'), + idleConf.GetOption('main', 'EditorWindow', + 'font-size', type='int'), + fontWeight)) + text_frame.pack(side=LEFT, fill=BOTH, expand=1) + text.pack(side=TOP, fill=BOTH, expand=1) + text.focus_set() + + # usetabs true -> literal tab characters are used by indent and + # dedent cmds, possibly mixed with spaces if + # indentwidth is not a multiple of tabwidth, + # which will cause Tabnanny to nag! + # false -> tab characters are converted to spaces by indent + # and dedent cmds, and ditto TAB keystrokes + # Although use-spaces=0 can be configured manually in config-main.def, + # configuration of tabs v. spaces is not supported in the configuration + # dialog. IDLE promotes the preferred Python indentation: use spaces! + usespaces = idleConf.GetOption('main', 'Indent', 'use-spaces', type='bool') + self.usetabs = not usespaces + + # tabwidth is the display width of a literal tab character. + # CAUTION: telling Tk to use anything other than its default + # tab setting causes it to use an entirely different tabbing algorithm, + # treating tab stops as fixed distances from the left margin. + # Nobody expects this, so for now tabwidth should never be changed. + self.tabwidth = 8 # must remain 8 until Tk is fixed. + + # indentwidth is the number of screen characters per indent level. + # The recommended Python indentation is four spaces. + self.indentwidth = self.tabwidth + self.set_notabs_indentwidth() + + # If context_use_ps1 is true, parsing searches back for a ps1 line; + # else searches for a popular (if, def, ...) Python stmt. + self.context_use_ps1 = False + + # When searching backwards for a reliable place to begin parsing, + # first start num_context_lines[0] lines back, then + # num_context_lines[1] lines back if that didn't work, and so on. + # The last value should be huge (larger than the # of lines in a + # conceivable file). + # Making the initial values larger slows things down more often. + self.num_context_lines = 50, 500, 5000000 + + self.per = per = self.Percolator(text) + + self.undo = undo = self.UndoDelegator() + per.insertfilter(undo) + text.undo_block_start = undo.undo_block_start + text.undo_block_stop = undo.undo_block_stop + undo.set_saved_change_hook(self.saved_change_hook) + + # IOBinding implements file I/O and printing functionality + self.io = io = self.IOBinding(self) + io.set_filename_change_hook(self.filename_change_hook) + + # Create the recent files submenu + self.recent_files_menu = Menu(self.menubar) + self.menudict['file'].insert_cascade(3, label='Recent Files', + underline=0, + menu=self.recent_files_menu) + self.update_recent_files_list() + + self.color = None # initialized below in self.ResetColorizer + if filename: + if os.path.exists(filename) and not os.path.isdir(filename): + io.loadfile(filename) + else: + io.set_filename(filename) + self.ResetColorizer() + self.saved_change_hook() + + self.set_indentation_params(self.ispythonsource(filename)) + + self.load_extensions() + + menu = self.menudict.get('windows') + if menu: + end = menu.index("end") + if end is None: + end = -1 + if end >= 0: + menu.add_separator() + end = end + 1 + self.wmenu_end = end + WindowList.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._highlight_workaround() # Fix selection tags on Windows + + def _highlight_workaround(self): + # On Windows, Tk removes painting of the selection + # tags which is different behavior than on Linux and Mac. + # See issue14146 for more information. + if not sys.platform.startswith('win'): + return + + text = self.text + text.event_add("<>", "") + text.event_add("<>", "") + def highlight_fix(focus): + sel_range = text.tag_ranges("sel") + if sel_range: + if focus == 'out': + HILITE_CONFIG = idleConf.GetHighlight( + idleConf.CurrentTheme(), 'hilite') + text.tag_config("sel_fix", HILITE_CONFIG) + text.tag_raise("sel_fix") + text.tag_add("sel_fix", *sel_range) + elif focus == 'in': + text.tag_remove("sel_fix", "1.0", "end") + + text.bind("<>", + lambda ev: highlight_fix("out")) + text.bind("<>", + lambda ev: highlight_fix("in")) + + + def _filename_to_unicode(self, filename): + """convert filename to unicode in order to display it in Tk""" + if isinstance(filename, unicode) or not filename: + return filename + else: + try: + return filename.decode(self.filesystemencoding) + except UnicodeDecodeError: + # XXX + try: + return filename.decode(self.encoding) + except UnicodeDecodeError: + # byte-to-byte conversion + return filename.decode('iso8859-1') + + def new_callback(self, event): + dirname, basename = self.io.defaultfilename() + self.flist.new(dirname) + return "break" + + def home_callback(self, event): + if (event.state & 4) != 0 and event.keysym == "Home": + # state&4==Control. If , use the Tk binding. + return + if self.text.index("iomark") and \ + self.text.compare("iomark", "<=", "insert lineend") and \ + self.text.compare("insert linestart", "<=", "iomark"): + # In Shell on input line, go to just after prompt + insertpt = int(self.text.index("iomark").split(".")[1]) + else: + line = self.text.get("insert linestart", "insert lineend") + for insertpt in xrange(len(line)): + if line[insertpt] not in (' ','\t'): + break + else: + insertpt=len(line) + lineat = int(self.text.index("insert").split('.')[1]) + if insertpt == lineat: + insertpt = 0 + dest = "insert linestart+"+str(insertpt)+"c" + if (event.state&1) == 0: + # shift was not pressed + self.text.tag_remove("sel", "1.0", "end") + else: + if not self.text.index("sel.first"): + self.text.mark_set("my_anchor", "insert") # there was no previous selection + else: + if self.text.compare(self.text.index("sel.first"), "<", self.text.index("insert")): + self.text.mark_set("my_anchor", "sel.first") # extend back + else: + self.text.mark_set("my_anchor", "sel.last") # extend forward + first = self.text.index(dest) + last = self.text.index("my_anchor") + if self.text.compare(first,">",last): + first,last = last,first + self.text.tag_remove("sel", "1.0", "end") + self.text.tag_add("sel", first, last) + self.text.mark_set("insert", dest) + self.text.see("insert") + return "break" + + def set_status_bar(self): + self.status_bar = self.MultiStatusBar(self.top) + if sys.platform == "darwin": + # Insert some padding to avoid obscuring some of the statusbar + # by the resize widget. + self.status_bar.set_label('_padding1', ' ', side=RIGHT) + self.status_bar.set_label('column', 'Col: ?', side=RIGHT) + self.status_bar.set_label('line', 'Ln: ?', side=RIGHT) + self.status_bar.pack(side=BOTTOM, fill=X) + self.text.bind("<>", self.set_line_and_column) + self.text.event_add("<>", + "", "") + self.text.after_idle(self.set_line_and_column) + + def set_line_and_column(self, event=None): + line, column = self.text.index(INSERT).split('.') + self.status_bar.set_label('column', 'Col: %s' % column) + self.status_bar.set_label('line', 'Ln: %s' % line) + + menu_specs = [ + ("file", "_File"), + ("edit", "_Edit"), + ("format", "F_ormat"), + ("run", "_Run"), + ("options", "_Options"), + ("windows", "_Windows"), + ("help", "_Help"), + ] + + if sys.platform == "darwin": + menu_specs[-2] = ("windows", "_Window") + + + def createmenubar(self): + mbar = self.menubar + self.menudict = menudict = {} + for name, label in self.menu_specs: + underline, label = prepstr(label) + menudict[name] = menu = Menu(mbar, name=name) + mbar.add_cascade(label=label, menu=menu, underline=underline) + + if macosxSupport.isCarbonTk(): + # Insert the application menu + menudict['application'] = menu = Menu(mbar, name='apple') + mbar.add_cascade(label='IDLE', menu=menu) + + self.fill_menus() + self.base_helpmenu_length = self.menudict['help'].index(END) + self.reset_help_menu_entries() + + def postwindowsmenu(self): + # Only called when Windows menu exists + menu = self.menudict['windows'] + end = menu.index("end") + if end is None: + end = -1 + if end > self.wmenu_end: + menu.delete(self.wmenu_end+1, end) + WindowList.add_windows_to_menu(menu) + + rmenu = None + + def right_menu_event(self, event): + self.text.mark_set("insert", "@%d,%d" % (event.x, event.y)) + if not self.rmenu: + self.make_rmenu() + rmenu = self.rmenu + self.event = event + iswin = sys.platform[:3] == 'win' + if iswin: + self.text.config(cursor="arrow") + + for item in self.rmenu_specs: + try: + label, eventname, verify_state = item + except ValueError: # see issue1207589 + continue + + if verify_state is None: + continue + state = getattr(self, verify_state)() + rmenu.entryconfigure(label, state=state) + + rmenu.tk_popup(event.x_root, event.y_root) + if iswin: + self.text.config(cursor="ibeam") + + rmenu_specs = [ + # ("Label", "<>", "statefuncname"), ... + ("Close", "<>", None), # Example + ] + + def make_rmenu(self): + rmenu = Menu(self.text, tearoff=0) + for item in self.rmenu_specs: + label, eventname = item[0], item[1] + if label is not None: + def command(text=self.text, eventname=eventname): + text.event_generate(eventname) + rmenu.add_command(label=label, command=command) + else: + rmenu.add_separator() + self.rmenu = rmenu + + def rmenu_check_cut(self): + return self.rmenu_check_copy() + + def rmenu_check_copy(self): + try: + indx = self.text.index('sel.first') + except TclError: + return 'disabled' + else: + return 'normal' if indx else 'disabled' + + def rmenu_check_paste(self): + try: + self.text.tk.call('tk::GetSelection', self.text, 'CLIPBOARD') + except TclError: + return 'disabled' + else: + return 'normal' + + def about_dialog(self, event=None): + aboutDialog.AboutDialog(self.top,'About IDLE') + + def config_dialog(self, event=None): + configDialog.ConfigDialog(self.top,'Settings') + + def help_dialog(self, event=None): + if self.root: + parent = self.root + else: + parent = self.top + helpDialog.display(parent, near=self.top) + + def python_docs(self, event=None): + if sys.platform[:3] == 'win': + try: + os.startfile(self.help_url) + except WindowsError as why: + tkMessageBox.showerror(title='Document Start Failure', + message=str(why), parent=self.text) + else: + webbrowser.open(self.help_url) + return "break" + + def cut(self,event): + self.text.event_generate("<>") + return "break" + + def copy(self,event): + if not self.text.tag_ranges("sel"): + # There is no selection, so do nothing and maybe interrupt. + return + self.text.event_generate("<>") + return "break" + + def paste(self,event): + self.text.event_generate("<>") + self.text.see("insert") + return "break" + + def select_all(self, event=None): + self.text.tag_add("sel", "1.0", "end-1c") + self.text.mark_set("insert", "1.0") + self.text.see("insert") + return "break" + + def remove_selection(self, event=None): + self.text.tag_remove("sel", "1.0", "end") + self.text.see("insert") + + def move_at_edge_if_selection(self, edge_index): + """Cursor move begins at start or end of selection + + When a left/right cursor key is pressed create and return to Tkinter a + function which causes a cursor move from the associated edge of the + selection. + + """ + self_text_index = self.text.index + self_text_mark_set = self.text.mark_set + edges_table = ("sel.first+1c", "sel.last-1c") + def move_at_edge(event): + if (event.state & 5) == 0: # no shift(==1) or control(==4) pressed + try: + self_text_index("sel.first") + self_text_mark_set("insert", edges_table[edge_index]) + except TclError: + pass + return move_at_edge + + def del_word_left(self, event): + self.text.event_generate('') + return "break" + + def del_word_right(self, event): + self.text.event_generate('') + return "break" + + def find_event(self, event): + SearchDialog.find(self.text) + return "break" + + def find_again_event(self, event): + SearchDialog.find_again(self.text) + return "break" + + def find_selection_event(self, event): + SearchDialog.find_selection(self.text) + return "break" + + def find_in_files_event(self, event): + GrepDialog.grep(self.text, self.io, self.flist) + return "break" + + def replace_event(self, event): + ReplaceDialog.replace(self.text) + return "break" + + def goto_line_event(self, event): + text = self.text + lineno = tkSimpleDialog.askinteger("Goto", + "Go to line number:",parent=text) + if lineno is None: + return "break" + if lineno <= 0: + text.bell() + return "break" + text.mark_set("insert", "%d.0" % lineno) + text.see("insert") + + def open_module(self, event=None): + # XXX Shouldn't this be in IOBinding or in FileList? + try: + name = self.text.get("sel.first", "sel.last") + except TclError: + name = "" + else: + name = name.strip() + name = tkSimpleDialog.askstring("Module", + "Enter the name of a Python module\n" + "to search on sys.path and open:", + parent=self.text, initialvalue=name) + if name: + name = name.strip() + if not name: + return + # XXX Ought to insert current file's directory in front of path + try: + (f, file, (suffix, mode, type)) = _find_module(name) + except (NameError, ImportError) as msg: + tkMessageBox.showerror("Import error", str(msg), parent=self.text) + return + if type != imp.PY_SOURCE: + tkMessageBox.showerror("Unsupported type", + "%s is not a source module" % name, parent=self.text) + return + if f: + f.close() + if self.flist: + self.flist.open(file) + else: + self.io.loadfile(file) + + def open_class_browser(self, event=None): + filename = self.io.filename + if not filename: + tkMessageBox.showerror( + "No filename", + "This buffer has no associated filename", + master=self.text) + self.text.focus_set() + return None + head, tail = os.path.split(filename) + base, ext = os.path.splitext(tail) + from idlelib import ClassBrowser + ClassBrowser.ClassBrowser(self.flist, base, [head]) + + def open_path_browser(self, event=None): + from idlelib import PathBrowser + PathBrowser.PathBrowser(self.flist) + + def gotoline(self, lineno): + if lineno is not None and lineno > 0: + self.text.mark_set("insert", "%d.0" % lineno) + self.text.tag_remove("sel", "1.0", "end") + self.text.tag_add("sel", "insert", "insert +1l") + self.center() + + def ispythonsource(self, filename): + if not filename or os.path.isdir(filename): + return True + base, ext = os.path.splitext(os.path.basename(filename)) + if os.path.normcase(ext) in (".py", ".pyw"): + return True + try: + f = open(filename) + line = f.readline() + f.close() + except IOError: + return False + return line.startswith('#!') and line.find('python') >= 0 + + def close_hook(self): + if self.flist: + self.flist.unregister_maybe_terminate(self) + self.flist = None + + def set_close_hook(self, close_hook): + self.close_hook = close_hook + + def filename_change_hook(self): + if self.flist: + self.flist.filename_changed_edit(self) + self.saved_change_hook() + self.top.update_windowlist_registry(self) + self.ResetColorizer() + + def _addcolorizer(self): + if self.color: + return + if self.ispythonsource(self.io.filename): + self.color = self.ColorDelegator() + # can add more colorizers here... + if self.color: + self.per.removefilter(self.undo) + self.per.insertfilter(self.color) + self.per.insertfilter(self.undo) + + def _rmcolorizer(self): + if not self.color: + return + self.color.removecolors() + self.per.removefilter(self.color) + self.color = None + + def ResetColorizer(self): + "Update the colour theme" + # Called from self.filename_change_hook and from configDialog.py + self._rmcolorizer() + self._addcolorizer() + theme = idleConf.GetOption('main','Theme','name') + normal_colors = idleConf.GetHighlight(theme, 'normal') + cursor_color = idleConf.GetHighlight(theme, 'cursor', fgBg='fg') + select_colors = idleConf.GetHighlight(theme, 'hilite') + self.text.config( + foreground=normal_colors['foreground'], + background=normal_colors['background'], + insertbackground=cursor_color, + selectforeground=select_colors['foreground'], + selectbackground=select_colors['background'], + ) + + def ResetFont(self): + "Update the text widgets' font if it is changed" + # Called from configDialog.py + fontWeight='normal' + if idleConf.GetOption('main','EditorWindow','font-bold',type='bool'): + fontWeight='bold' + self.text.config(font=(idleConf.GetOption('main','EditorWindow','font'), + idleConf.GetOption('main','EditorWindow','font-size', + type='int'), + fontWeight)) + + def RemoveKeybindings(self): + "Remove the keybindings before they are changed." + # Called from configDialog.py + self.Bindings.default_keydefs = keydefs = idleConf.GetCurrentKeySet() + for event, keylist in keydefs.items(): + self.text.event_delete(event, *keylist) + for extensionName in self.get_standard_extension_names(): + xkeydefs = idleConf.GetExtensionBindings(extensionName) + if xkeydefs: + for event, keylist in xkeydefs.items(): + self.text.event_delete(event, *keylist) + + def ApplyKeybindings(self): + "Update the keybindings after they are changed" + # Called from configDialog.py + self.Bindings.default_keydefs = keydefs = idleConf.GetCurrentKeySet() + self.apply_bindings() + for extensionName in self.get_standard_extension_names(): + xkeydefs = idleConf.GetExtensionBindings(extensionName) + if xkeydefs: + self.apply_bindings(xkeydefs) + #update menu accelerators + menuEventDict = {} + for menu in self.Bindings.menudefs: + menuEventDict[menu[0]] = {} + for item in menu[1]: + if item: + menuEventDict[menu[0]][prepstr(item[0])[1]] = item[1] + for menubarItem in self.menudict.keys(): + menu = self.menudict[menubarItem] + end = menu.index(END) + if end is None: + # Skip empty menus + continue + end += 1 + for index in range(0, end): + if menu.type(index) == 'command': + accel = menu.entrycget(index, 'accelerator') + if accel: + itemName = menu.entrycget(index, 'label') + event = '' + if menubarItem in menuEventDict: + if itemName in menuEventDict[menubarItem]: + event = menuEventDict[menubarItem][itemName] + if event: + accel = get_accelerator(keydefs, event) + menu.entryconfig(index, accelerator=accel) + + def set_notabs_indentwidth(self): + "Update the indentwidth if changed and not using tabs in this window" + # Called from configDialog.py + if not self.usetabs: + self.indentwidth = idleConf.GetOption('main', 'Indent','num-spaces', + type='int') + + def reset_help_menu_entries(self): + "Update the additional help entries on the Help menu" + help_list = idleConf.GetAllExtraHelpSourcesList() + helpmenu = self.menudict['help'] + # first delete the extra help entries, if any + helpmenu_length = helpmenu.index(END) + if helpmenu_length > self.base_helpmenu_length: + helpmenu.delete((self.base_helpmenu_length + 1), helpmenu_length) + # then rebuild them + if help_list: + helpmenu.add_separator() + for entry in help_list: + cmd = self.__extra_help_callback(entry[1]) + helpmenu.add_command(label=entry[0], command=cmd) + # and update the menu dictionary + self.menudict['help'] = helpmenu + + def __extra_help_callback(self, helpfile): + "Create a callback with the helpfile value frozen at definition time" + def display_extra_help(helpfile=helpfile): + if not helpfile.startswith(('www', 'http')): + helpfile = os.path.normpath(helpfile) + if sys.platform[:3] == 'win': + try: + os.startfile(helpfile) + except WindowsError as why: + tkMessageBox.showerror(title='Document Start Failure', + message=str(why), parent=self.text) + else: + webbrowser.open(helpfile) + return display_extra_help + + def update_recent_files_list(self, new_file=None): + "Load and update the recent files list and menus" + rf_list = [] + if os.path.exists(self.recent_files_path): + with open(self.recent_files_path, 'r') as rf_list_file: + rf_list = rf_list_file.readlines() + if new_file: + new_file = os.path.abspath(new_file) + '\n' + if new_file in rf_list: + rf_list.remove(new_file) # move to top + rf_list.insert(0, new_file) + # clean and save the recent files list + bad_paths = [] + for path in rf_list: + if '\0' in path or not os.path.exists(path[0:-1]): + bad_paths.append(path) + rf_list = [path for path in rf_list if path not in bad_paths] + ulchars = "1234567890ABCDEFGHIJK" + rf_list = rf_list[0:len(ulchars)] + try: + with open(self.recent_files_path, 'w') as rf_file: + rf_file.writelines(rf_list) + except IOError as err: + if not getattr(self.root, "recentfilelist_error_displayed", False): + self.root.recentfilelist_error_displayed = True + tkMessageBox.showerror(title='IDLE Error', + message='Unable to update Recent Files list:\n%s' + % str(err), + parent=self.text) + # for each edit window instance, construct the recent files menu + for instance in self.top.instance_dict.keys(): + menu = instance.recent_files_menu + menu.delete(0, END) # clear, and rebuild: + for i, file_name in enumerate(rf_list): + file_name = file_name.rstrip() # zap \n + # make unicode string to display non-ASCII chars correctly + ufile_name = self._filename_to_unicode(file_name) + callback = instance.__recent_file_callback(file_name) + menu.add_command(label=ulchars[i] + " " + ufile_name, + command=callback, + underline=0) + + def __recent_file_callback(self, file_name): + def open_recent_file(fn_closure=file_name): + self.io.open(editFile=fn_closure) + return open_recent_file + + def saved_change_hook(self): + short = self.short_title() + long = self.long_title() + if short and long: + title = short + " - " + long + elif short: + title = short + elif long: + title = long + else: + title = "Untitled" + icon = short or long or title + if not self.get_saved(): + title = "*%s*" % title + icon = "*%s" % icon + self.top.wm_title(title) + self.top.wm_iconname(icon) + + def get_saved(self): + return self.undo.get_saved() + + def set_saved(self, flag): + self.undo.set_saved(flag) + + def reset_undo(self): + self.undo.reset_undo() + + def short_title(self): + pyversion = "Python " + python_version() + ": " + filename = self.io.filename + if filename: + filename = os.path.basename(filename) + else: + filename = "Untitled" + # return unicode string to display non-ASCII chars correctly + return pyversion + self._filename_to_unicode(filename) + + def long_title(self): + # return unicode string to display non-ASCII chars correctly + return self._filename_to_unicode(self.io.filename or "") + + def center_insert_event(self, event): + self.center() + + def center(self, mark="insert"): + text = self.text + top, bot = self.getwindowlines() + lineno = self.getlineno(mark) + height = bot - top + newtop = max(1, lineno - height//2) + text.yview(float(newtop)) + + def getwindowlines(self): + text = self.text + top = self.getlineno("@0,0") + bot = self.getlineno("@0,65535") + if top == bot and text.winfo_height() == 1: + # Geometry manager hasn't run yet + height = int(text['height']) + bot = top + height - 1 + return top, bot + + def getlineno(self, mark="insert"): + text = self.text + return int(float(text.index(mark))) + + def get_geometry(self): + "Return (width, height, x, y)" + geom = self.top.wm_geometry() + m = re.match(r"(\d+)x(\d+)\+(-?\d+)\+(-?\d+)", geom) + tuple = (map(int, m.groups())) + return tuple + + def close_event(self, event): + self.close() + + def maybesave(self): + if self.io: + if not self.get_saved(): + if self.top.state()!='normal': + self.top.deiconify() + self.top.lower() + self.top.lift() + return self.io.maybesave() + + def close(self): + reply = self.maybesave() + if str(reply) != "cancel": + self._close() + return reply + + def _close(self): + if self.io.filename: + self.update_recent_files_list(new_file=self.io.filename) + WindowList.unregister_callback(self.postwindowsmenu) + self.unload_extensions() + self.io.close() + self.io = None + self.undo = None + if self.color: + self.color.close(False) + self.color = None + self.text = None + self.tkinter_vars = None + self.per.close() + self.per = None + self.top.destroy() + if self.close_hook: + # unless override: unregister from flist, terminate if last window + self.close_hook() + + def load_extensions(self): + self.extensions = {} + self.load_standard_extensions() + + def unload_extensions(self): + for ins in self.extensions.values(): + if hasattr(ins, "close"): + ins.close() + self.extensions = {} + + def load_standard_extensions(self): + for name in self.get_standard_extension_names(): + try: + self.load_extension(name) + except: + print "Failed to load extension", repr(name) + import traceback + traceback.print_exc() + + def get_standard_extension_names(self): + return idleConf.GetExtensions(editor_only=True) + + def load_extension(self, name): + try: + mod = __import__(name, globals(), locals(), []) + except ImportError: + print "\nFailed to import extension: ", name + return + cls = getattr(mod, name) + keydefs = idleConf.GetExtensionBindings(name) + if hasattr(cls, "menudefs"): + self.fill_menus(cls.menudefs, keydefs) + ins = cls(self) + self.extensions[name] = ins + if keydefs: + self.apply_bindings(keydefs) + for vevent in keydefs.keys(): + methodname = vevent.replace("-", "_") + while methodname[:1] == '<': + methodname = methodname[1:] + while methodname[-1:] == '>': + methodname = methodname[:-1] + methodname = methodname + "_event" + if hasattr(ins, methodname): + self.text.bind(vevent, getattr(ins, methodname)) + + def apply_bindings(self, keydefs=None): + if keydefs is None: + keydefs = self.Bindings.default_keydefs + text = self.text + text.keydefs = keydefs + for event, keylist in keydefs.items(): + if keylist: + text.event_add(event, *keylist) + + def fill_menus(self, menudefs=None, keydefs=None): + """Add appropriate entries to the menus and submenus + + Menus that are absent or None in self.menudict are ignored. + """ + if menudefs is None: + menudefs = self.Bindings.menudefs + if keydefs is None: + keydefs = self.Bindings.default_keydefs + menudict = self.menudict + text = self.text + for mname, entrylist in menudefs: + menu = menudict.get(mname) + if not menu: + continue + for entry in entrylist: + if not entry: + menu.add_separator() + else: + label, eventname = entry + checkbutton = (label[:1] == '!') + if checkbutton: + label = label[1:] + underline, label = prepstr(label) + accelerator = get_accelerator(keydefs, eventname) + def command(text=text, eventname=eventname): + text.event_generate(eventname) + if checkbutton: + var = self.get_var_obj(eventname, BooleanVar) + menu.add_checkbutton(label=label, underline=underline, + command=command, accelerator=accelerator, + variable=var) + else: + menu.add_command(label=label, underline=underline, + command=command, + accelerator=accelerator) + + def getvar(self, name): + var = self.get_var_obj(name) + if var: + value = var.get() + return value + else: + raise NameError, name + + def setvar(self, name, value, vartype=None): + var = self.get_var_obj(name, vartype) + if var: + var.set(value) + else: + raise NameError, name + + def get_var_obj(self, name, vartype=None): + var = self.tkinter_vars.get(name) + if not var and vartype: + # create a Tkinter variable object with self.text as master: + self.tkinter_vars[name] = var = vartype(self.text) + return var + + # Tk implementations of "virtual text methods" -- each platform + # reusing IDLE's support code needs to define these for its GUI's + # flavor of widget. + + # Is character at text_index in a Python string? Return 0 for + # "guaranteed no", true for anything else. This info is expensive + # to compute ab initio, but is probably already known by the + # platform's colorizer. + + def is_char_in_string(self, text_index): + if self.color: + # Return true iff colorizer hasn't (re)gotten this far + # yet, or the character is tagged as being in a string + return self.text.tag_prevrange("TODO", text_index) or \ + "STRING" in self.text.tag_names(text_index) + else: + # The colorizer is missing: assume the worst + return 1 + + # If a selection is defined in the text widget, return (start, + # end) as Tkinter text indices, otherwise return (None, None) + def get_selection_indices(self): + try: + first = self.text.index("sel.first") + last = self.text.index("sel.last") + return first, last + except TclError: + return None, None + + # Return the text widget's current view of what a tab stop means + # (equivalent width in spaces). + + def get_tabwidth(self): + current = self.text['tabs'] or TK_TABWIDTH_DEFAULT + return int(current) + + # Set the text widget's current view of what a tab stop means. + + def set_tabwidth(self, newtabwidth): + text = self.text + if self.get_tabwidth() != newtabwidth: + pixels = text.tk.call("font", "measure", text["font"], + "-displayof", text.master, + "n" * newtabwidth) + text.configure(tabs=pixels) + + # If ispythonsource and guess are true, guess a good value for + # indentwidth based on file content (if possible), and if + # indentwidth != tabwidth set usetabs false. + # In any case, adjust the Text widget's view of what a tab + # character means. + + def set_indentation_params(self, ispythonsource, guess=True): + if guess and ispythonsource: + i = self.guess_indent() + if 2 <= i <= 8: + self.indentwidth = i + if self.indentwidth != self.tabwidth: + self.usetabs = False + self.set_tabwidth(self.tabwidth) + + def smart_backspace_event(self, event): + text = self.text + first, last = self.get_selection_indices() + if first and last: + text.delete(first, last) + text.mark_set("insert", first) + return "break" + # Delete whitespace left, until hitting a real char or closest + # preceding virtual tab stop. + chars = text.get("insert linestart", "insert") + if chars == '': + if text.compare("insert", ">", "1.0"): + # easy: delete preceding newline + text.delete("insert-1c") + else: + text.bell() # at start of buffer + return "break" + if chars[-1] not in " \t": + # easy: delete preceding real char + text.delete("insert-1c") + return "break" + # Ick. It may require *inserting* spaces if we back up over a + # tab character! This is written to be clear, not fast. + tabwidth = self.tabwidth + have = len(chars.expandtabs(tabwidth)) + assert have > 0 + want = ((have - 1) // self.indentwidth) * self.indentwidth + # Debug prompt is multilined.... + if self.context_use_ps1: + last_line_of_prompt = sys.ps1.split('\n')[-1] + else: + last_line_of_prompt = '' + ncharsdeleted = 0 + while 1: + if chars == last_line_of_prompt: + break + chars = chars[:-1] + ncharsdeleted = ncharsdeleted + 1 + have = len(chars.expandtabs(tabwidth)) + if have <= want or chars[-1] not in " \t": + break + text.undo_block_start() + text.delete("insert-%dc" % ncharsdeleted, "insert") + if have < want: + text.insert("insert", ' ' * (want - have)) + text.undo_block_stop() + return "break" + + def smart_indent_event(self, event): + # if intraline selection: + # delete it + # elif multiline selection: + # do indent-region + # else: + # indent one level + text = self.text + first, last = self.get_selection_indices() + text.undo_block_start() + try: + if first and last: + if index2line(first) != index2line(last): + return self.indent_region_event(event) + text.delete(first, last) + text.mark_set("insert", first) + prefix = text.get("insert linestart", "insert") + raw, effective = classifyws(prefix, self.tabwidth) + if raw == len(prefix): + # only whitespace to the left + self.reindent_to(effective + self.indentwidth) + else: + # tab to the next 'stop' within or to right of line's text: + if self.usetabs: + pad = '\t' + else: + effective = len(prefix.expandtabs(self.tabwidth)) + n = self.indentwidth + pad = ' ' * (n - effective % n) + text.insert("insert", pad) + text.see("insert") + return "break" + finally: + text.undo_block_stop() + + def newline_and_indent_event(self, event): + text = self.text + first, last = self.get_selection_indices() + text.undo_block_start() + try: + if first and last: + text.delete(first, last) + text.mark_set("insert", first) + line = text.get("insert linestart", "insert") + i, n = 0, len(line) + while i < n and line[i] in " \t": + i = i+1 + if i == n: + # the cursor is in or at leading indentation in a continuation + # line; just inject an empty line at the start + text.insert("insert linestart", '\n') + return "break" + indent = line[:i] + # strip whitespace before insert point unless it's in the prompt + i = 0 + last_line_of_prompt = sys.ps1.split('\n')[-1] + while line and line[-1] in " \t" and line != last_line_of_prompt: + line = line[:-1] + i = i+1 + if i: + text.delete("insert - %d chars" % i, "insert") + # strip whitespace after insert point + while text.get("insert") in " \t": + text.delete("insert") + # start new line + text.insert("insert", '\n') + + # adjust indentation for continuations and block + # open/close first need to find the last stmt + lno = index2line(text.index('insert')) + y = PyParse.Parser(self.indentwidth, self.tabwidth) + if not self.context_use_ps1: + for context in self.num_context_lines: + startat = max(lno - context, 1) + startatindex = repr(startat) + ".0" + rawtext = text.get(startatindex, "insert") + y.set_str(rawtext) + bod = y.find_good_parse_start( + self.context_use_ps1, + self._build_char_in_string_func(startatindex)) + if bod is not None or startat == 1: + break + y.set_lo(bod or 0) + else: + r = text.tag_prevrange("console", "insert") + if r: + startatindex = r[1] + else: + startatindex = "1.0" + rawtext = text.get(startatindex, "insert") + y.set_str(rawtext) + y.set_lo(0) + + c = y.get_continuation_type() + if c != PyParse.C_NONE: + # The current stmt hasn't ended yet. + if c == PyParse.C_STRING_FIRST_LINE: + # after the first line of a string; do not indent at all + pass + elif c == PyParse.C_STRING_NEXT_LINES: + # inside a string which started before this line; + # just mimic the current indent + text.insert("insert", indent) + elif c == PyParse.C_BRACKET: + # line up with the first (if any) element of the + # last open bracket structure; else indent one + # level beyond the indent of the line with the + # last open bracket + self.reindent_to(y.compute_bracket_indent()) + elif c == PyParse.C_BACKSLASH: + # if more than one line in this stmt already, just + # mimic the current indent; else if initial line + # has a start on an assignment stmt, indent to + # beyond leftmost =; else to beyond first chunk of + # non-whitespace on initial line + if y.get_num_lines_in_stmt() > 1: + text.insert("insert", indent) + else: + self.reindent_to(y.compute_backslash_indent()) + else: + assert 0, "bogus continuation type %r" % (c,) + return "break" + + # This line starts a brand new stmt; indent relative to + # indentation of initial line of closest preceding + # interesting stmt. + indent = y.get_base_indent_string() + text.insert("insert", indent) + if y.is_block_opener(): + self.smart_indent_event(event) + elif indent and y.is_block_closer(): + self.smart_backspace_event(event) + return "break" + finally: + text.see("insert") + text.undo_block_stop() + + # Our editwin provides a is_char_in_string function that works + # with a Tk text index, but PyParse only knows about offsets into + # a string. This builds a function for PyParse that accepts an + # offset. + + def _build_char_in_string_func(self, startindex): + def inner(offset, _startindex=startindex, + _icis=self.is_char_in_string): + return _icis(_startindex + "+%dc" % offset) + return inner + + def indent_region_event(self, event): + head, tail, chars, lines = self.get_region() + for pos in range(len(lines)): + line = lines[pos] + if line: + raw, effective = classifyws(line, self.tabwidth) + effective = effective + self.indentwidth + lines[pos] = self._make_blanks(effective) + line[raw:] + self.set_region(head, tail, chars, lines) + return "break" + + def dedent_region_event(self, event): + head, tail, chars, lines = self.get_region() + for pos in range(len(lines)): + line = lines[pos] + if line: + raw, effective = classifyws(line, self.tabwidth) + effective = max(effective - self.indentwidth, 0) + lines[pos] = self._make_blanks(effective) + line[raw:] + self.set_region(head, tail, chars, lines) + return "break" + + def comment_region_event(self, event): + head, tail, chars, lines = self.get_region() + for pos in range(len(lines) - 1): + line = lines[pos] + lines[pos] = '##' + line + self.set_region(head, tail, chars, lines) + + def uncomment_region_event(self, event): + head, tail, chars, lines = self.get_region() + for pos in range(len(lines)): + line = lines[pos] + if not line: + continue + if line[:2] == '##': + line = line[2:] + elif line[:1] == '#': + line = line[1:] + lines[pos] = line + self.set_region(head, tail, chars, lines) + + def tabify_region_event(self, event): + head, tail, chars, lines = self.get_region() + tabwidth = self._asktabwidth() + if tabwidth is None: return + for pos in range(len(lines)): + line = lines[pos] + if line: + raw, effective = classifyws(line, tabwidth) + ntabs, nspaces = divmod(effective, tabwidth) + lines[pos] = '\t' * ntabs + ' ' * nspaces + line[raw:] + self.set_region(head, tail, chars, lines) + + def untabify_region_event(self, event): + head, tail, chars, lines = self.get_region() + tabwidth = self._asktabwidth() + if tabwidth is None: return + for pos in range(len(lines)): + lines[pos] = lines[pos].expandtabs(tabwidth) + self.set_region(head, tail, chars, lines) + + def toggle_tabs_event(self, event): + if self.askyesno( + "Toggle tabs", + "Turn tabs " + ("on", "off")[self.usetabs] + + "?\nIndent width " + + ("will be", "remains at")[self.usetabs] + " 8." + + "\n Note: a tab is always 8 columns", + parent=self.text): + self.usetabs = not self.usetabs + # Try to prevent inconsistent indentation. + # User must change indent width manually after using tabs. + self.indentwidth = 8 + return "break" + + # XXX this isn't bound to anything -- see tabwidth comments +## def change_tabwidth_event(self, event): +## new = self._asktabwidth() +## if new != self.tabwidth: +## self.tabwidth = new +## self.set_indentation_params(0, guess=0) +## return "break" + + def change_indentwidth_event(self, event): + new = self.askinteger( + "Indent width", + "New indent width (2-16)\n(Always use 8 when using tabs)", + parent=self.text, + initialvalue=self.indentwidth, + minvalue=2, + maxvalue=16) + if new and new != self.indentwidth and not self.usetabs: + self.indentwidth = new + return "break" + + def get_region(self): + text = self.text + first, last = self.get_selection_indices() + if first and last: + head = text.index(first + " linestart") + tail = text.index(last + "-1c lineend +1c") + else: + head = text.index("insert linestart") + tail = text.index("insert lineend +1c") + chars = text.get(head, tail) + lines = chars.split("\n") + return head, tail, chars, lines + + def set_region(self, head, tail, chars, lines): + text = self.text + newchars = "\n".join(lines) + if newchars == chars: + text.bell() + return + text.tag_remove("sel", "1.0", "end") + text.mark_set("insert", head) + text.undo_block_start() + text.delete(head, tail) + text.insert(head, newchars) + text.undo_block_stop() + text.tag_add("sel", head, "insert") + + # Make string that displays as n leading blanks. + + def _make_blanks(self, n): + if self.usetabs: + ntabs, nspaces = divmod(n, self.tabwidth) + return '\t' * ntabs + ' ' * nspaces + else: + return ' ' * n + + # Delete from beginning of line to insert point, then reinsert + # column logical (meaning use tabs if appropriate) spaces. + + def reindent_to(self, column): + text = self.text + text.undo_block_start() + if text.compare("insert linestart", "!=", "insert"): + text.delete("insert linestart", "insert") + if column: + text.insert("insert", self._make_blanks(column)) + text.undo_block_stop() + + def _asktabwidth(self): + return self.askinteger( + "Tab width", + "Columns per tab? (2-16)", + parent=self.text, + initialvalue=self.indentwidth, + minvalue=2, + maxvalue=16) + + # Guess indentwidth from text content. + # Return guessed indentwidth. This should not be believed unless + # it's in a reasonable range (e.g., it will be 0 if no indented + # blocks are found). + + def guess_indent(self): + opener, indented = IndentSearcher(self.text, self.tabwidth).run() + if opener and indented: + raw, indentsmall = classifyws(opener, self.tabwidth) + raw, indentlarge = classifyws(indented, self.tabwidth) + else: + indentsmall = indentlarge = 0 + return indentlarge - indentsmall + +# "line.col" -> line, as an int +def index2line(index): + return int(float(index)) + +# Look at the leading whitespace in s. +# Return pair (# of leading ws characters, +# effective # of leading blanks after expanding +# tabs to width tabwidth) + +def classifyws(s, tabwidth): + raw = effective = 0 + for ch in s: + if ch == ' ': + raw = raw + 1 + effective = effective + 1 + elif ch == '\t': + raw = raw + 1 + effective = (effective // tabwidth + 1) * tabwidth + else: + break + return raw, effective + +import tokenize +_tokenize = tokenize +del tokenize + +class IndentSearcher(object): + + # .run() chews over the Text widget, looking for a block opener + # and the stmt following it. Returns a pair, + # (line containing block opener, line containing stmt) + # Either or both may be None. + + def __init__(self, text, tabwidth): + self.text = text + self.tabwidth = tabwidth + self.i = self.finished = 0 + self.blkopenline = self.indentedline = None + + def readline(self): + if self.finished: + return "" + i = self.i = self.i + 1 + mark = repr(i) + ".0" + if self.text.compare(mark, ">=", "end"): + return "" + return self.text.get(mark, mark + " lineend+1c") + + def tokeneater(self, type, token, start, end, line, + INDENT=_tokenize.INDENT, + NAME=_tokenize.NAME, + OPENERS=('class', 'def', 'for', 'if', 'try', 'while')): + if self.finished: + pass + elif type == NAME and token in OPENERS: + self.blkopenline = line + elif type == INDENT and self.blkopenline: + self.indentedline = line + self.finished = 1 + + def run(self): + save_tabsize = _tokenize.tabsize + _tokenize.tabsize = self.tabwidth + try: + try: + _tokenize.tokenize(self.readline, self.tokeneater) + except (_tokenize.TokenError, SyntaxError): + # since we cut off the tokenizer early, we can trigger + # spurious errors + pass + finally: + _tokenize.tabsize = save_tabsize + return self.blkopenline, self.indentedline + +### end autoindent code ### + +def prepstr(s): + # Helper to extract the underscore from a string, e.g. + # prepstr("Co_py") returns (2, "Copy"). + i = s.find('_') + if i >= 0: + s = s[:i] + s[i+1:] + return i, s + + +keynames = { + 'bracketleft': '[', + 'bracketright': ']', + 'slash': '/', +} + +def get_accelerator(keydefs, eventname): + keylist = keydefs.get(eventname) + # issue10940: temporary workaround to prevent hang with OS X Cocoa Tk 8.5 + # if not keylist: + if (not keylist) or (macosxSupport.isCocoaTk() and eventname in { + "<>", + "<>", + "<>"}): + return "" + s = keylist[0] + s = re.sub(r"-[a-z]\b", lambda m: m.group().upper(), s) + s = re.sub(r"\b\w+\b", lambda m: keynames.get(m.group(), m.group()), s) + s = re.sub("Key-", "", s) + s = re.sub("Cancel","Ctrl-Break",s) # dscherer@cmu.edu + s = re.sub("Control-", "Ctrl-", s) + s = re.sub("-", "+", s) + s = re.sub("><", " ", s) + s = re.sub("<", "", s) + s = re.sub(">", "", s) + return s + + +def fixwordbreaks(root): + # Make sure that Tk's double-click and next/previous word + # operations use our definition of a word (i.e. an identifier) + tk = root.tk + tk.call('tcl_wordBreakAfter', 'a b', 0) # make sure word.tcl is loaded + tk.call('set', 'tcl_wordchars', '[a-zA-Z0-9_]') + tk.call('set', 'tcl_nonwordchars', '[^a-zA-Z0-9_]') + + +def _editor_window(parent): + root = parent + fixwordbreaks(root) + if sys.argv[1:]: + filename = sys.argv[1] + else: + filename = None + macosxSupport.setupApp(root, None) + edit = EditorWindow(root=root, filename=filename) + edit.text.bind("<>", edit.close_event) + parent.mainloop() + + +if __name__ == '__main__': + from idlelib.idle_test.htest import run + run(_help_dialog, _editor_window) diff --git a/PythonHome/Lib/idlelib/EditorWindow.pyc b/PythonHome/Lib/idlelib/EditorWindow.pyc deleted file mode 100644 index 465877ec502c2f1870ee6e84844ad931c881b1b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55973 zcmc(|33Q#;b>Dj~0FnR%4&qFWR|73-0IAuM4AUY(Qlce6^ask2Xwoo%djVV$xEH+l zLIfN!9;kSVouoWe3<9VZ>x1=*$;(3#wx27{&(iO*<9X1}+tZot@qArc*pU`@rZYR^dC2*@(wSXpad$eiJ1y=>XZA$iX6Nlq zXZG?;7xtyn*7PdCxgnKrOr>qX*kv|YJZQhMpkEvbBqVrOnmr5&zQ zOr@Qza=Y5)ZcC-z&b~dB_Be7!3q*IOGk2yk;r{f2J5yq|zOZ+?&exrP7`0LQksS*rN&CpB9GG z;=y$0U@DXkrgAZr?@d>FQlVXEaFoJwh-OwC9bBw?abE!8ePTWK^SZHTn-@>G3h z{#a#dp*Ghk`Bc5U)Sb4Ol396aVQQw_ovgQ*U|%{0-?sZ>oRV`7}(8jcK2X(Rizw4Qc#<;L&)A;6$yyIMpmR zRvQQNxtpw1XKTe~t+-ULm6m79#pZmuIKDJrsjd|BBE?3tUa8I%mmB4hN>-|kCiCi& zGxLkZQf;Qu=%e-hjs1-V6op80fPZGDs-;S4s#$h!eTHNKX|__GTBs072UNJJ`JhLJ zdUvl52&%5JICUOytL|c@+K$cCYfck3Ei_fQQLck9O%1nRUMNp7{X~<4#?8bIo_)45 zeO8#Tz`w^!6%aG9?;t3>l@gN;kG+N3`$%eRCrCYe3)>1C3p)!#{@qxZQRjuedb1~f zoF%{vFxe|Vq-h2NnC~lvbnM(;)ciBSWM3Fa^+yyx-y>?Fbp{B|GryFecuzVDs(>(k zNeE)p*ryWAHrO(kPUST=x(0Yd)eY$i#W$wa&FPhm>HH=k-NeP+sSm`yFqrB;nhJ#i zlLAU9e=zO&cuyk#MSc@&-vLIQD6l>l0A0Vl$!%^*=ZDmziR$(3HvhZYym+GUVvM=D zIi25<&TmzJsCbqU^ry=M=@s7E=dRyXD6t?0jNSc8-$RR(rhbfXmVpQIw?;)uj=qBM z`-9#TYqQ15;?hA7sWiC=+Afq2+zmQ{+4G>>Lb*|#uaxT|AeEV^g<=#bR;L!rji$)d z!HVXtv5R1=R&3Ok>mdGYt==kWd<7$B8p2H?V+TainnLoiTD5GnYb-5PnvTsZ)EZ@@ zF}*Tn>FSwR!l{=g$De;88$Isah1yiB-=;g0lS@<0`N>I>)+0?;+w^j?e7s%<)kUXH zE{fX3vq;Y5q=rIyVc+B=FD0AD$eXP!C{H7-HQZ&j?o4+XB6mO)oie+;u%N~=tq~Vi zb&sVv*Nh@0sECJJDmP~8UTXnVgLBapr&(^Us29-MH7`3++sQ77?dQ4ipjznNSlG>a z+g!M@u%pmd*jwl&zL|e_^bY0mzMhRd4;2OqgN0oML*(i5Le3;+)QJ8QFplzTyo;a= zi?(?4DiM|>E39C)4kq@POOn#-$VTV(Id@aa#!ZrDghKkMRiR~LH$e%K%{bh!A~Xya zGy54c%gJt_ltH&NRWDbYhE-`H=War+MtNa&U66|juT(3{{?lqett4PEBfQnG-Nnaw z5J@sqztErRxB8KFW(p-L1W6KMqL4`yYq%`~sF}uB35v%mAkoySiT^x+E|$!q4-O6% zyZ(z27Ke*@MX5EAuJjiA)YhPx6rAQdQEVZ?knsOX2>*fn zWA2(J@L+SL>A^nDgNXwqVQQfv&OdStN?Wh39yWcr_kiUzK_|OQfk5M`=WCU!+4a

40n0 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', self.Ok) + self.wait_window() + + def CreateWidgets(self): + self.menu = StringVar(self) + self.path = StringVar(self) + self.fontSize = StringVar(self) + self.frameMain = Frame(self, borderwidth=2, relief=GROOVE) + self.frameMain.pack(side=TOP, expand=TRUE, fill=BOTH) + labelMenu = Label(self.frameMain, anchor=W, justify=LEFT, + text='Menu Item:') + self.entryMenu = Entry(self.frameMain, textvariable=self.menu, + width=30) + self.entryMenu.focus_set() + labelPath = Label(self.frameMain, anchor=W, justify=LEFT, + text='Help File Path: Enter URL or browse for file') + self.entryPath = Entry(self.frameMain, textvariable=self.path, + width=40) + self.entryMenu.focus_set() + labelMenu.pack(anchor=W, padx=5, pady=3) + self.entryMenu.pack(anchor=W, padx=5, pady=3) + labelPath.pack(anchor=W, padx=5, pady=3) + self.entryPath.pack(anchor=W, padx=5, pady=3) + browseButton = Button(self.frameMain, text='Browse', width=8, + command=self.browseFile) + browseButton.pack(pady=3) + frameButtons = Frame(self) + frameButtons.pack(side=BOTTOM, fill=X) + self.buttonOk = Button(frameButtons, text='OK', + width=8, default=ACTIVE, command=self.Ok) + self.buttonOk.grid(row=0, column=0, padx=5,pady=5) + self.buttonCancel = Button(frameButtons, text='Cancel', + width=8, command=self.Cancel) + self.buttonCancel.grid(row=0, column=1, padx=5, pady=5) + + def browseFile(self): + filetypes = [ + ("HTML Files", "*.htm *.html", "TEXT"), + ("PDF Files", "*.pdf", "TEXT"), + ("Windows Help Files", "*.chm"), + ("Text Files", "*.txt", "TEXT"), + ("All Files", "*")] + path = self.path.get() + if path: + dir, base = os.path.split(path) + else: + base = None + if sys.platform[:3] == 'win': + dir = os.path.join(os.path.dirname(sys.executable), 'Doc') + if not os.path.isdir(dir): + dir = os.getcwd() + else: + dir = os.getcwd() + opendialog = tkFileDialog.Open(parent=self, filetypes=filetypes) + file = opendialog.show(initialdir=dir, initialfile=base) + if file: + self.path.set(file) + + def MenuOk(self): + "Simple validity check for a sensible menu item name" + menuOk = True + menu = self.menu.get() + menu.strip() + if not menu: + tkMessageBox.showerror(title='Menu Item Error', + message='No menu item specified', + parent=self) + self.entryMenu.focus_set() + menuOk = False + elif len(menu) > 30: + tkMessageBox.showerror(title='Menu Item Error', + message='Menu item too long:' + '\nLimit 30 characters.', + parent=self) + self.entryMenu.focus_set() + menuOk = False + return menuOk + + def PathOk(self): + "Simple validity check for menu file path" + pathOk = True + path = self.path.get() + path.strip() + if not path: #no path specified + tkMessageBox.showerror(title='File Path Error', + message='No help file path specified.', + parent=self) + self.entryPath.focus_set() + pathOk = False + elif path.startswith(('www.', 'http')): + pass + else: + if path[:5] == 'file:': + path = path[5:] + if not os.path.exists(path): + tkMessageBox.showerror(title='File Path Error', + message='Help file path does not exist.', + parent=self) + self.entryPath.focus_set() + pathOk = False + return pathOk + + def Ok(self, event=None): + if self.MenuOk() and self.PathOk(): + self.result = (self.menu.get().strip(), + self.path.get().strip()) + if sys.platform == 'darwin': + path = self.result[1] + if path.startswith(('www', 'file:', 'http:')): + pass + else: + # Mac Safari insists on using the URI form for local files + self.result = list(self.result) + self.result[1] = "file://" + path + self.destroy() + + def Cancel(self, event=None): + self.result = None + self.destroy() + +if __name__ == '__main__': + from idlelib.idle_test.htest import run + run(GetHelpSourceDialog) diff --git a/PythonHome/Lib/idlelib/configHelpSourceEdit.pyc b/PythonHome/Lib/idlelib/configHelpSourceEdit.pyc deleted file mode 100644 index f1a8a39b1453e9f7620a650f5e7d609401e65e15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6414 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 J^e0|f{tGHgDNX30: #name too long + tkMessageBox.showerror(title='Name Error', + message='Name too long. It should be no more than '+ + '30 characters.', parent=self) + name = '' + elif name in self.used_names: + tkMessageBox.showerror(title='Name Error', + message='This name is already in use.', parent=self) + name = '' + return name + def Ok(self, event=None): + name = self.name_ok() + if name: + self.result = name + self.destroy() + def Cancel(self, event=None): + self.result = '' + self.destroy() +if __name__ == '__main__': + import unittest + unittest.main('idlelib.idle_test.test_config_name', verbosity=2, exit=False) + + from idlelib.idle_test.htest import run + run(GetCfgSectionNameDialog) diff --git a/PythonHome/Lib/idlelib/configSectionNameDialog.pyc b/PythonHome/Lib/idlelib/configSectionNameDialog.pyc deleted file mode 100644 index ee7f55b4e59f007aadc1441ff146f375ece9f141..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4268 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 diff --git a/PythonHome/Lib/idlelib/idle.py b/PythonHome/Lib/idlelib/idle.py new file mode 100644 index 0000000000..a249557dd1 --- /dev/null +++ b/PythonHome/Lib/idlelib/idle.py @@ -0,0 +1,11 @@ +import os.path +import sys + +# If we are working on a development version of IDLE, we need to prepend the +# parent of this idlelib dir to sys.path. Otherwise, importing idlelib gets +# the version installed with the Python used to call this module: +idlelib_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, idlelib_dir) + +import idlelib.PyShell +idlelib.PyShell.main() diff --git a/PythonHome/Lib/idlelib/idle.pyc b/PythonHome/Lib/idlelib/idle.pyc deleted file mode 100644 index da68244da04a996f802cd0afef7666c37499b03d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 391 zcmZWjOKQU~5Pg!9ICUJlD7}Np!Y2r&2PmcBMZp9VyHbga>;y|)c',self.FinalKeySelected) + self.listKeysFinal.grid(row=0,column=4,rowspan=4,sticky=NS) + scrollKeysFinal=Scrollbar(self.frameControlsBasic,orient=VERTICAL, + command=self.listKeysFinal.yview) + self.listKeysFinal.config(yscrollcommand=scrollKeysFinal.set) + scrollKeysFinal.grid(row=0,column=5,rowspan=4,sticky=NS) + self.buttonClear=Button(self.frameControlsBasic, + text='Clear Keys',command=self.ClearKeySeq) + self.buttonClear.grid(row=2,column=0,columnspan=4) + labelTitleAdvanced = Label(self.frameKeySeqAdvanced,justify=LEFT, + text="Enter new binding(s) for '"+self.action+"' :\n"+ + "(These bindings will not be checked for validity!)") + labelTitleAdvanced.pack(anchor=W) + self.entryKeysAdvanced=Entry(self.frameKeySeqAdvanced, + textvariable=self.keyString) + self.entryKeysAdvanced.pack(fill=X) + labelHelpAdvanced=Label(self.frameHelpAdvanced,justify=LEFT, + text="Key bindings are specified using Tkinter keysyms as\n"+ + "in these samples: , , ,\n" + ", , .\n" + "Upper case is used when the Shift modifier is present!\n\n" + + "'Emacs style' multi-keystroke bindings are specified as\n" + + "follows: , where the first key\n" + + "is the 'do-nothing' keybinding.\n\n" + + "Multiple separate bindings for one action should be\n"+ + "separated by a space, eg., ." ) + labelHelpAdvanced.grid(row=0,column=0,sticky=NSEW) + + def SetModifiersForPlatform(self): + """Determine list of names of key modifiers for this platform. + + The names are used to build Tk bindings -- it doesn't matter if the + keyboard has these keys, it matters if Tk understands them. The + order is also important: key binding equality depends on it, so + config-keys.def must use the same ordering. + """ + if sys.platform == "darwin": + self.modifiers = ['Shift', 'Control', 'Option', 'Command'] + else: + self.modifiers = ['Control', 'Alt', 'Shift'] + self.modifier_label = {'Control': 'Ctrl'} # short name + + def ToggleLevel(self): + if self.buttonLevel.cget('text')[:8]=='Advanced': + self.ClearKeySeq() + self.buttonLevel.config(text='<< Basic Key Binding Entry') + self.frameKeySeqAdvanced.lift() + self.frameHelpAdvanced.lift() + self.entryKeysAdvanced.focus_set() + self.advanced = True + else: + self.ClearKeySeq() + self.buttonLevel.config(text='Advanced Key Binding Entry >>') + self.frameKeySeqBasic.lift() + self.frameControlsBasic.lift() + self.advanced = False + + def FinalKeySelected(self,event): + self.BuildKeyString() + + def BuildKeyString(self): + keyList = modifiers = self.GetModifiers() + finalKey = self.listKeysFinal.get(ANCHOR) + if finalKey: + finalKey = self.TranslateKey(finalKey, modifiers) + keyList.append(finalKey) + self.keyString.set('<' + string.join(keyList,'-') + '>') + + def GetModifiers(self): + modList = [variable.get() for variable in self.modifier_vars] + return [mod for mod in modList if mod] + + def ClearKeySeq(self): + self.listKeysFinal.select_clear(0,END) + self.listKeysFinal.yview(MOVETO, '0.0') + for variable in self.modifier_vars: + variable.set('') + self.keyString.set('') + + def LoadFinalKeyList(self): + #these tuples are also available for use in validity checks + self.functionKeys=('F1','F2','F2','F4','F5','F6','F7','F8','F9', + 'F10','F11','F12') + self.alphanumKeys=tuple(string.ascii_lowercase+string.digits) + self.punctuationKeys=tuple('~!@#%^&*()_-+={}[]|;:,.<>/?') + self.whitespaceKeys=('Tab','Space','Return') + self.editKeys=('BackSpace','Delete','Insert') + self.moveKeys=('Home','End','Page Up','Page Down','Left Arrow', + 'Right Arrow','Up Arrow','Down Arrow') + #make a tuple of most of the useful common 'final' keys + keys=(self.alphanumKeys+self.punctuationKeys+self.functionKeys+ + self.whitespaceKeys+self.editKeys+self.moveKeys) + self.listKeysFinal.insert(END, *keys) + + def TranslateKey(self, key, modifiers): + "Translate from keycap symbol to the Tkinter keysym" + translateDict = {'Space':'space', + '~':'asciitilde','!':'exclam','@':'at','#':'numbersign', + '%':'percent','^':'asciicircum','&':'ampersand','*':'asterisk', + '(':'parenleft',')':'parenright','_':'underscore','-':'minus', + '+':'plus','=':'equal','{':'braceleft','}':'braceright', + '[':'bracketleft',']':'bracketright','|':'bar',';':'semicolon', + ':':'colon',',':'comma','.':'period','<':'less','>':'greater', + '/':'slash','?':'question','Page Up':'Prior','Page Down':'Next', + 'Left Arrow':'Left','Right Arrow':'Right','Up Arrow':'Up', + 'Down Arrow': 'Down', 'Tab':'Tab'} + if key in translateDict.keys(): + key = translateDict[key] + if 'Shift' in modifiers and key in string.ascii_lowercase: + key = key.upper() + key = 'Key-' + key + return key + + def OK(self, event=None): + if self.advanced or self.KeysOK(): # doesn't check advanced string yet + self.result=self.keyString.get() + self.destroy() + + def Cancel(self, event=None): + self.result='' + self.destroy() + + def KeysOK(self): + '''Validity check on user's 'basic' keybinding selection. + + Doesn't check the string produced by the advanced dialog because + 'modifiers' isn't set. + + ''' + keys = self.keyString.get() + keys.strip() + finalKey = self.listKeysFinal.get(ANCHOR) + modifiers = self.GetModifiers() + # create a key sequence list for overlap check: + keySequence = keys.split() + keysOK = False + title = 'Key Sequence Error' + if not keys: + tkMessageBox.showerror(title=title, parent=self, + message='No keys specified.') + elif not keys.endswith('>'): + tkMessageBox.showerror(title=title, parent=self, + message='Missing the final Key') + elif (not modifiers + and finalKey not in self.functionKeys + self.moveKeys): + tkMessageBox.showerror(title=title, parent=self, + message='No modifier key(s) specified.') + elif (modifiers == ['Shift']) \ + and (finalKey not in + self.functionKeys + self.moveKeys + ('Tab', 'Space')): + msg = 'The shift modifier by itself may not be used with'\ + ' this key symbol.' + tkMessageBox.showerror(title=title, parent=self, message=msg) + elif keySequence in self.currentKeySequences: + msg = 'This key combination is already in use.' + tkMessageBox.showerror(title=title, parent=self, message=msg) + else: + keysOK = True + return keysOK + +if __name__ == '__main__': + from idlelib.idle_test.htest import run + run(GetKeysDialog) diff --git a/PythonHome/Lib/idlelib/keybindingDialog.pyc b/PythonHome/Lib/idlelib/keybindingDialog.pyc deleted file mode 100644 index bcf0e60b5a6f136e8681bb07cc1ec11ebbf849ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11901 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 Tnu=i%#2V$VaQcU%2nYNR-!mO& diff --git a/PythonHome/Lib/idlelib/macosxSupport.py b/PythonHome/Lib/idlelib/macosxSupport.py new file mode 100644 index 0000000000..4f5259c465 --- /dev/null +++ b/PythonHome/Lib/idlelib/macosxSupport.py @@ -0,0 +1,235 @@ +""" +A number of functions that enhance IDLE on Mac OSX. +""" +import sys +import Tkinter +from os import path + + +import warnings + +def runningAsOSXApp(): + warnings.warn("runningAsOSXApp() is deprecated, use isAquaTk()", + DeprecationWarning, stacklevel=2) + return isAquaTk() + +def isCarbonAquaTk(root): + warnings.warn("isCarbonAquaTk(root) is deprecated, use isCarbonTk()", + DeprecationWarning, stacklevel=2) + return isCarbonTk() + +_tk_type = None + +def _initializeTkVariantTests(root): + """ + Initializes OS X Tk variant values for + isAquaTk(), isCarbonTk(), isCocoaTk(), and isXQuartz(). + """ + global _tk_type + if sys.platform == 'darwin': + ws = root.tk.call('tk', 'windowingsystem') + if 'x11' in ws: + _tk_type = "xquartz" + elif 'aqua' not in ws: + _tk_type = "other" + elif 'AppKit' in root.tk.call('winfo', 'server', '.'): + _tk_type = "cocoa" + else: + _tk_type = "carbon" + else: + _tk_type = "other" + +def isAquaTk(): + """ + Returns True if IDLE is using a native OS X Tk (Cocoa or Carbon). + """ + assert _tk_type is not None + return _tk_type == "cocoa" or _tk_type == "carbon" + +def isCarbonTk(): + """ + Returns True if IDLE is using a Carbon Aqua Tk (instead of the + newer Cocoa Aqua Tk). + """ + assert _tk_type is not None + return _tk_type == "carbon" + +def isCocoaTk(): + """ + Returns True if IDLE is using a Cocoa Aqua Tk. + """ + assert _tk_type is not None + return _tk_type == "cocoa" + +def isXQuartz(): + """ + Returns True if IDLE is using an OS X X11 Tk. + """ + assert _tk_type is not None + return _tk_type == "xquartz" + +def tkVersionWarning(root): + """ + Returns a string warning message if the Tk version in use appears to + be one known to cause problems with IDLE. + 1. Apple Cocoa-based Tk 8.5.7 shipped with Mac OS X 10.6 is unusable. + 2. Apple Cocoa-based Tk 8.5.9 in OS X 10.7 and 10.8 is better but + can still crash unexpectedly. + """ + + if isCocoaTk(): + patchlevel = root.tk.call('info', 'patchlevel') + if patchlevel not in ('8.5.7', '8.5.9'): + return False + return (r"WARNING: The version of Tcl/Tk ({0}) in use may" + r" be unstable.\n" + r"Visit http://www.python.org/download/mac/tcltk/" + r" for current information.".format(patchlevel)) + else: + return False + +def addOpenEventSupport(root, flist): + """ + This ensures that the application will respond to open AppleEvents, which + makes is feasible to use IDLE as the default application for python files. + """ + def doOpenFile(*args): + for fn in args: + flist.open(fn) + + # The command below is a hook in aquatk that is called whenever the app + # receives a file open event. The callback can have multiple arguments, + # one for every file that should be opened. + root.createcommand("::tk::mac::OpenDocument", doOpenFile) + +def hideTkConsole(root): + try: + root.tk.call('console', 'hide') + except Tkinter.TclError: + # Some versions of the Tk framework don't have a console object + pass + +def overrideRootMenu(root, flist): + """ + Replace the Tk root menu by something that is more appropriate for + IDLE with an Aqua Tk. + """ + # The menu that is attached to the Tk root (".") is also used by AquaTk for + # all windows that don't specify a menu of their own. The default menubar + # contains a number of menus, none of which are appropriate for IDLE. The + # Most annoying of those is an 'About Tck/Tk...' menu in the application + # menu. + # + # This function replaces the default menubar by a mostly empty one, it + # should only contain the correct application menu and the window menu. + # + # Due to a (mis-)feature of TkAqua the user will also see an empty Help + # menu. + from Tkinter import Menu, Text, Text + from idlelib.EditorWindow import prepstr, get_accelerator + from idlelib import Bindings + from idlelib import WindowList + from idlelib.MultiCall import MultiCallCreator + + closeItem = Bindings.menudefs[0][1][-2] + + # Remove the last 3 items of the file menu: a separator, close window and + # quit. Close window will be reinserted just above the save item, where + # it should be according to the HIG. Quit is in the application menu. + del Bindings.menudefs[0][1][-3:] + Bindings.menudefs[0][1].insert(6, closeItem) + + # Remove the 'About' entry from the help menu, it is in the application + # menu + del Bindings.menudefs[-1][1][0:2] + + # Remove the 'Configure' entry from the options menu, it is in the + # application menu as 'Preferences' + del Bindings.menudefs[-2][1][0:2] + + menubar = Menu(root) + root.configure(menu=menubar) + menudict = {} + + menudict['windows'] = menu = Menu(menubar, name='windows') + menubar.add_cascade(label='Window', menu=menu, underline=0) + + def postwindowsmenu(menu=menu): + end = menu.index('end') + if end is None: + end = -1 + + if end > 0: + menu.delete(0, end) + WindowList.add_windows_to_menu(menu) + WindowList.register_callback(postwindowsmenu) + + def about_dialog(event=None): + from idlelib import aboutDialog + aboutDialog.AboutDialog(root, 'About IDLE') + + def config_dialog(event=None): + from idlelib import configDialog + root.instance_dict = flist.inversedict + configDialog.ConfigDialog(root, 'Settings') + + def help_dialog(event=None): + from idlelib import textView + fn = path.join(path.abspath(path.dirname(__file__)), 'help.txt') + textView.view_file(root, 'Help', fn) + + root.bind('<>', about_dialog) + root.bind('<>', config_dialog) + root.createcommand('::tk::mac::ShowPreferences', config_dialog) + if flist: + root.bind('<>', flist.close_all_callback) + + # The binding above doesn't reliably work on all versions of Tk + # on MacOSX. Adding command definition below does seem to do the + # right thing for now. + root.createcommand('exit', flist.close_all_callback) + + if isCarbonTk(): + # for Carbon AquaTk, replace the default Tk apple menu + menudict['application'] = menu = Menu(menubar, name='apple') + menubar.add_cascade(label='IDLE', menu=menu) + Bindings.menudefs.insert(0, + ('application', [ + ('About IDLE', '<>'), + None, + ])) + tkversion = root.tk.eval('info patchlevel') + if tuple(map(int, tkversion.split('.'))) < (8, 4, 14): + # for earlier AquaTk versions, supply a Preferences menu item + Bindings.menudefs[0][1].append( + ('_Preferences....', '<>'), + ) + if isCocoaTk(): + # replace default About dialog with About IDLE one + root.createcommand('tkAboutDialog', about_dialog) + # replace default "Help" item in Help menu + root.createcommand('::tk::mac::ShowHelp', help_dialog) + # remove redundant "IDLE Help" from menu + del Bindings.menudefs[-1][1][0] + +def setupApp(root, flist): + """ + Perform initial OS X customizations if needed. + Called from PyShell.main() after initial calls to Tk() + + There are currently three major versions of Tk in use on OS X: + 1. Aqua Cocoa Tk (native default since OS X 10.6) + 2. Aqua Carbon Tk (original native, 32-bit only, deprecated) + 3. X11 (supported by some third-party distributors, deprecated) + There are various differences among the three that affect IDLE + behavior, primarily with menus, mouse key events, and accelerators. + Some one-time customizations are performed here. + Others are dynamically tested throughout idlelib by calls to the + isAquaTk(), isCarbonTk(), isCocoaTk(), isXQuartz() functions which + are initialized here as well. + """ + _initializeTkVariantTests(root) + if isAquaTk(): + hideTkConsole(root) + overrideRootMenu(root, flist) + addOpenEventSupport(root, flist) diff --git a/PythonHome/Lib/idlelib/macosxSupport.pyc b/PythonHome/Lib/idlelib/macosxSupport.pyc deleted file mode 100644 index 1c06608747bad34dc459e6fbc2734fce91ae3e68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8284 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 lT5>erf, '\n' + '-'*40 + print>>erf, 'Unhandled server exception!' + print>>erf, 'Thread: %s' % threading.currentThread().getName() + print>>erf, 'Client Address: ', client_address + print>>erf, 'Request: ', repr(request) + traceback.print_exc(file=erf) + print>>erf, '\n*** Unrecoverable, server exiting!' + print>>erf, '-'*40 + os._exit(0) + +#----------------- end class RPCServer -------------------- + +objecttable = {} +request_queue = Queue.Queue(0) +response_queue = Queue.Queue(0) + + +class SocketIO(object): + + nextseq = 0 + + def __init__(self, sock, objtable=None, debugging=None): + self.sockthread = threading.currentThread() + if debugging is not None: + self.debugging = debugging + self.sock = sock + if objtable is None: + objtable = objecttable + self.objtable = objtable + self.responses = {} + self.cvars = {} + + def close(self): + sock = self.sock + self.sock = None + if sock is not None: + sock.close() + + def exithook(self): + "override for specific exit action" + os._exit(0) + + def debug(self, *args): + if not self.debugging: + return + s = self.location + " " + str(threading.currentThread().getName()) + for a in args: + s = s + " " + str(a) + print>>sys.__stderr__, s + + def register(self, oid, object): + self.objtable[oid] = object + + def unregister(self, oid): + try: + del self.objtable[oid] + except KeyError: + pass + + def localcall(self, seq, request): + self.debug("localcall:", request) + try: + how, (oid, methodname, args, kwargs) = request + except TypeError: + return ("ERROR", "Bad request format") + if oid not in self.objtable: + return ("ERROR", "Unknown object id: %r" % (oid,)) + obj = self.objtable[oid] + if methodname == "__methods__": + methods = {} + _getmethods(obj, methods) + return ("OK", methods) + if methodname == "__attributes__": + attributes = {} + _getattributes(obj, attributes) + return ("OK", attributes) + if not hasattr(obj, methodname): + return ("ERROR", "Unsupported method name: %r" % (methodname,)) + method = getattr(obj, methodname) + try: + if how == 'CALL': + ret = method(*args, **kwargs) + if isinstance(ret, RemoteObject): + ret = remoteref(ret) + return ("OK", ret) + elif how == 'QUEUE': + request_queue.put((seq, (method, args, kwargs))) + return("QUEUED", None) + else: + return ("ERROR", "Unsupported message type: %s" % how) + except SystemExit: + raise + except socket.error: + raise + except: + msg = "*** Internal Error: rpc.py:SocketIO.localcall()\n\n"\ + " Object: %s \n Method: %s \n Args: %s\n" + print>>sys.__stderr__, msg % (oid, method, args) + traceback.print_exc(file=sys.__stderr__) + return ("EXCEPTION", None) + + def remotecall(self, oid, methodname, args, kwargs): + self.debug("remotecall:asynccall: ", oid, methodname) + seq = self.asynccall(oid, methodname, args, kwargs) + return self.asyncreturn(seq) + + def remotequeue(self, oid, methodname, args, kwargs): + self.debug("remotequeue:asyncqueue: ", oid, methodname) + seq = self.asyncqueue(oid, methodname, args, kwargs) + return self.asyncreturn(seq) + + def asynccall(self, oid, methodname, args, kwargs): + request = ("CALL", (oid, methodname, args, kwargs)) + seq = self.newseq() + if threading.currentThread() != self.sockthread: + cvar = threading.Condition() + self.cvars[seq] = cvar + self.debug(("asynccall:%d:" % seq), oid, methodname, args, kwargs) + self.putmessage((seq, request)) + return seq + + def asyncqueue(self, oid, methodname, args, kwargs): + request = ("QUEUE", (oid, methodname, args, kwargs)) + seq = self.newseq() + if threading.currentThread() != self.sockthread: + cvar = threading.Condition() + self.cvars[seq] = cvar + self.debug(("asyncqueue:%d:" % seq), oid, methodname, args, kwargs) + self.putmessage((seq, request)) + return seq + + def asyncreturn(self, seq): + self.debug("asyncreturn:%d:call getresponse(): " % seq) + response = self.getresponse(seq, wait=0.05) + self.debug(("asyncreturn:%d:response: " % seq), response) + return self.decoderesponse(response) + + def decoderesponse(self, response): + how, what = response + if how == "OK": + return what + if how == "QUEUED": + return None + if how == "EXCEPTION": + self.debug("decoderesponse: EXCEPTION") + return None + if how == "EOF": + self.debug("decoderesponse: EOF") + self.decode_interrupthook() + return None + if how == "ERROR": + self.debug("decoderesponse: Internal ERROR:", what) + raise RuntimeError, what + raise SystemError, (how, what) + + def decode_interrupthook(self): + "" + raise EOFError + + def mainloop(self): + """Listen on socket until I/O not ready or EOF + + pollresponse() will loop looking for seq number None, which + never comes, and exit on EOFError. + + """ + try: + self.getresponse(myseq=None, wait=0.05) + except EOFError: + self.debug("mainloop:return") + return + + def getresponse(self, myseq, wait): + response = self._getresponse(myseq, wait) + if response is not None: + how, what = response + if how == "OK": + response = how, self._proxify(what) + return response + + def _proxify(self, obj): + if isinstance(obj, RemoteProxy): + return RPCProxy(self, obj.oid) + if isinstance(obj, types.ListType): + return map(self._proxify, obj) + # XXX Check for other types -- not currently needed + return obj + + def _getresponse(self, myseq, wait): + self.debug("_getresponse:myseq:", myseq) + if threading.currentThread() is self.sockthread: + # this thread does all reading of requests or responses + while 1: + response = self.pollresponse(myseq, wait) + if response is not None: + return response + else: + # wait for notification from socket handling thread + cvar = self.cvars[myseq] + cvar.acquire() + while myseq not in self.responses: + cvar.wait() + response = self.responses[myseq] + self.debug("_getresponse:%s: thread woke up: response: %s" % + (myseq, response)) + del self.responses[myseq] + del self.cvars[myseq] + cvar.release() + return response + + def newseq(self): + self.nextseq = seq = self.nextseq + 2 + return seq + + def putmessage(self, message): + self.debug("putmessage:%d:" % message[0]) + try: + s = pickle.dumps(message) + except pickle.PicklingError: + print >>sys.__stderr__, "Cannot pickle:", repr(message) + raise + s = struct.pack(" 0: + try: + r, w, x = select.select([], [self.sock], []) + n = self.sock.send(s[:BUFSIZE]) + except (AttributeError, TypeError): + raise IOError, "socket no longer exists" + except socket.error: + raise + else: + s = s[n:] + + buffer = "" + bufneed = 4 + bufstate = 0 # meaning: 0 => reading count; 1 => reading data + + def pollpacket(self, wait): + self._stage0() + if len(self.buffer) < self.bufneed: + r, w, x = select.select([self.sock.fileno()], [], [], wait) + if len(r) == 0: + return None + try: + s = self.sock.recv(BUFSIZE) + except socket.error: + raise EOFError + if len(s) == 0: + raise EOFError + self.buffer += s + self._stage0() + return self._stage1() + + def _stage0(self): + if self.bufstate == 0 and len(self.buffer) >= 4: + s = self.buffer[:4] + self.buffer = self.buffer[4:] + self.bufneed = struct.unpack("= self.bufneed: + packet = self.buffer[:self.bufneed] + self.buffer = self.buffer[self.bufneed:] + self.bufneed = 4 + self.bufstate = 0 + return packet + + def pollmessage(self, wait): + packet = self.pollpacket(wait) + if packet is None: + return None + try: + message = pickle.loads(packet) + except pickle.UnpicklingError: + print >>sys.__stderr__, "-----------------------" + print >>sys.__stderr__, "cannot unpickle packet:", repr(packet) + traceback.print_stack(file=sys.__stderr__) + print >>sys.__stderr__, "-----------------------" + raise + return message + + def pollresponse(self, myseq, wait): + """Handle messages received on the socket. + + Some messages received may be asynchronous 'call' or 'queue' requests, + and some may be responses for other threads. + + 'call' requests are passed to self.localcall() with the expectation of + immediate execution, during which time the socket is not serviced. + + 'queue' requests are used for tasks (which may block or hang) to be + processed in a different thread. These requests are fed into + request_queue by self.localcall(). Responses to queued requests are + taken from response_queue and sent across the link with the associated + sequence numbers. Messages in the queues are (sequence_number, + request/response) tuples and code using this module removing messages + from the request_queue is responsible for returning the correct + sequence number in the response_queue. + + pollresponse() will loop until a response message with the myseq + sequence number is received, and will save other responses in + self.responses and notify the owning thread. + + """ + while 1: + # send queued response if there is one available + try: + qmsg = response_queue.get(0) + except Queue.Empty: + pass + else: + seq, response = qmsg + message = (seq, ('OK', response)) + self.putmessage(message) + # poll for message on link + try: + message = self.pollmessage(wait) + if message is None: # socket not ready + return None + except EOFError: + self.handle_EOF() + return None + except AttributeError: + return None + seq, resq = message + how = resq[0] + self.debug("pollresponse:%d:myseq:%s" % (seq, myseq)) + # process or queue a request + if how in ("CALL", "QUEUE"): + self.debug("pollresponse:%d:localcall:call:" % seq) + response = self.localcall(seq, resq) + self.debug("pollresponse:%d:localcall:response:%s" + % (seq, response)) + if how == "CALL": + self.putmessage((seq, response)) + elif how == "QUEUE": + # don't acknowledge the 'queue' request! + pass + continue + # return if completed message transaction + elif seq == myseq: + return resq + # must be a response for a different thread: + else: + cv = self.cvars.get(seq, None) + # response involving unknown sequence number is discarded, + # probably intended for prior incarnation of server + if cv is not None: + cv.acquire() + self.responses[seq] = resq + cv.notify() + cv.release() + continue + + def handle_EOF(self): + "action taken upon link being closed by peer" + self.EOFhook() + self.debug("handle_EOF") + for key in self.cvars: + cv = self.cvars[key] + cv.acquire() + self.responses[key] = ('EOF', None) + cv.notify() + cv.release() + # call our (possibly overridden) exit function + self.exithook() + + def EOFhook(self): + "Classes using rpc client/server can override to augment EOF action" + pass + +#----------------- end class SocketIO -------------------- + +class RemoteObject(object): + # Token mix-in class + pass + +def remoteref(obj): + oid = id(obj) + objecttable[oid] = obj + return RemoteProxy(oid) + +class RemoteProxy(object): + + def __init__(self, oid): + self.oid = oid + +class RPCHandler(SocketServer.BaseRequestHandler, SocketIO): + + debugging = False + location = "#S" # Server + + def __init__(self, sock, addr, svr): + svr.current_handler = self ## cgt xxx + SocketIO.__init__(self, sock) + SocketServer.BaseRequestHandler.__init__(self, sock, addr, svr) + + def handle(self): + "handle() method required by SocketServer" + self.mainloop() + + def get_remote_proxy(self, oid): + return RPCProxy(self, oid) + +class RPCClient(SocketIO): + + debugging = False + location = "#C" # Client + + nextseq = 1 # Requests coming from the client are odd numbered + + def __init__(self, address, family=socket.AF_INET, type=socket.SOCK_STREAM): + self.listening_sock = socket.socket(family, type) + self.listening_sock.bind(address) + self.listening_sock.listen(1) + + def accept(self): + working_sock, address = self.listening_sock.accept() + if self.debugging: + print>>sys.__stderr__, "****** Connection request from ", address + if address[0] == LOCALHOST: + SocketIO.__init__(self, working_sock) + else: + print>>sys.__stderr__, "** Invalid host: ", address + raise socket.error + + def get_remote_proxy(self, oid): + return RPCProxy(self, oid) + +class RPCProxy(object): + + __methods = None + __attributes = None + + def __init__(self, sockio, oid): + self.sockio = sockio + self.oid = oid + + def __getattr__(self, name): + if self.__methods is None: + self.__getmethods() + if self.__methods.get(name): + return MethodProxy(self.sockio, self.oid, name) + if self.__attributes is None: + self.__getattributes() + if name in self.__attributes: + value = self.sockio.remotecall(self.oid, '__getattribute__', + (name,), {}) + return value + else: + raise AttributeError, name + + def __getattributes(self): + self.__attributes = self.sockio.remotecall(self.oid, + "__attributes__", (), {}) + + def __getmethods(self): + self.__methods = self.sockio.remotecall(self.oid, + "__methods__", (), {}) + +def _getmethods(obj, methods): + # Helper to get a list of methods from an object + # Adds names to dictionary argument 'methods' + for name in dir(obj): + attr = getattr(obj, name) + if hasattr(attr, '__call__'): + methods[name] = 1 + if type(obj) == types.InstanceType: + _getmethods(obj.__class__, methods) + if type(obj) == types.ClassType: + for super in obj.__bases__: + _getmethods(super, methods) + +def _getattributes(obj, attributes): + for name in dir(obj): + attr = getattr(obj, name) + if not hasattr(attr, '__call__'): + attributes[name] = 1 + +class MethodProxy(object): + + def __init__(self, sockio, oid, name): + self.sockio = sockio + self.oid = oid + self.name = name + + def __call__(self, *args, **kwargs): + value = self.sockio.remotecall(self.oid, self.name, args, kwargs) + return value + + +# XXX KBK 09Sep03 We need a proper unit test for this module. Previously +# existing test code was removed at Rev 1.27 (r34098). diff --git a/PythonHome/Lib/idlelib/rpc.pyc b/PythonHome/Lib/idlelib/rpc.pyc deleted file mode 100644 index 8612fb50455ee2e370ccd95b043ea455b0324a32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20887 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 1) + port = int(sys.argv[-1]) + except: + print>>sys.stderr, "IDLE Subprocess: no IP port passed in sys.argv." + return + + capture_warnings(True) + sys.argv[:] = [""] + sockthread = threading.Thread(target=manage_socket, + name='SockThread', + args=((LOCALHOST, port),)) + sockthread.setDaemon(True) + sockthread.start() + while 1: + try: + if exit_now: + try: + exit() + except KeyboardInterrupt: + # exiting but got an extra KBI? Try again! + continue + try: + seq, request = rpc.request_queue.get(block=True, timeout=0.05) + except Queue.Empty: + continue + method, args, kwargs = request + ret = method(*args, **kwargs) + rpc.response_queue.put((seq, ret)) + except KeyboardInterrupt: + if quitting: + exit_now = True + continue + except SystemExit: + capture_warnings(False) + raise + except: + type, value, tb = sys.exc_info() + try: + print_exception() + rpc.response_queue.put((seq, None)) + except: + # Link didn't work, print same exception to __stderr__ + traceback.print_exception(type, value, tb, file=sys.__stderr__) + exit() + else: + continue + +def manage_socket(address): + for i in range(3): + time.sleep(i) + try: + server = MyRPCServer(address, MyHandler) + break + except socket.error as err: + print>>sys.__stderr__,"IDLE Subprocess: socket error: "\ + + err.args[1] + ", retrying...." + else: + print>>sys.__stderr__, "IDLE Subprocess: Connection to "\ + "IDLE GUI failed, exiting." + show_socket_error(err, address) + global exit_now + exit_now = True + return + server.handle_request() # A single request only + +def show_socket_error(err, address): + import Tkinter + import tkMessageBox + root = Tkinter.Tk() + root.withdraw() + if err.args[0] == 61: # connection refused + msg = "IDLE's subprocess can't connect to %s:%d. This may be due "\ + "to your personal firewall configuration. It is safe to "\ + "allow this internal connection because no data is visible on "\ + "external ports." % address + tkMessageBox.showerror("IDLE Subprocess Error", msg, parent=root) + else: + tkMessageBox.showerror("IDLE Subprocess Error", + "Socket Error: %s" % err.args[1]) + root.destroy() + +def print_exception(): + import linecache + linecache.checkcache() + flush_stdout() + efile = sys.stderr + typ, val, tb = excinfo = sys.exc_info() + sys.last_type, sys.last_value, sys.last_traceback = excinfo + tbe = traceback.extract_tb(tb) + print>>efile, '\nTraceback (most recent call last):' + exclude = ("run.py", "rpc.py", "threading.py", "Queue.py", + "RemoteDebugger.py", "bdb.py") + cleanup_traceback(tbe, exclude) + traceback.print_list(tbe, file=efile) + lines = traceback.format_exception_only(typ, val) + for line in lines: + print>>efile, line, + +def cleanup_traceback(tb, exclude): + "Remove excluded traces from beginning/end of tb; get cached lines" + orig_tb = tb[:] + while tb: + for rpcfile in exclude: + if tb[0][0].count(rpcfile): + break # found an exclude, break for: and delete tb[0] + else: + break # no excludes, have left RPC code, break while: + del tb[0] + while tb: + for rpcfile in exclude: + if tb[-1][0].count(rpcfile): + break + else: + break + del tb[-1] + if len(tb) == 0: + # exception was in IDLE internals, don't prune! + tb[:] = orig_tb[:] + print>>sys.stderr, "** IDLE Internal Exception: " + rpchandler = rpc.objecttable['exec'].rpchandler + for i in range(len(tb)): + fn, ln, nm, line = tb[i] + if nm == '?': + nm = "-toplevel-" + if not line and fn.startswith(">erf, '\n' + '-'*40 + print>>erf, 'Unhandled server exception!' + print>>erf, 'Thread: %s' % threading.currentThread().getName() + print>>erf, 'Client Address: ', client_address + print>>erf, 'Request: ', repr(request) + traceback.print_exc(file=erf) + print>>erf, '\n*** Unrecoverable, server exiting!' + print>>erf, '-'*40 + quitting = True + thread.interrupt_main() + +class MyHandler(rpc.RPCHandler): + + def handle(self): + """Override base method""" + executive = Executive(self) + self.register("exec", executive) + self.console = self.get_remote_proxy("console") + sys.stdin = PyShell.PseudoInputFile(self.console, "stdin", + IOBinding.encoding) + sys.stdout = PyShell.PseudoOutputFile(self.console, "stdout", + IOBinding.encoding) + sys.stderr = PyShell.PseudoOutputFile(self.console, "stderr", + IOBinding.encoding) + + # Keep a reference to stdin so that it won't try to exit IDLE if + # sys.stdin gets changed from within IDLE's shell. See issue17838. + self._keep_stdin = sys.stdin + + self.interp = self.get_remote_proxy("interp") + rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05) + + def exithook(self): + "override SocketIO method - wait for MainThread to shut us down" + time.sleep(10) + + def EOFhook(self): + "Override SocketIO method - terminate wait on callback and exit thread" + global quitting + quitting = True + thread.interrupt_main() + + def decode_interrupthook(self): + "interrupt awakened thread" + global quitting + quitting = True + thread.interrupt_main() + + +class Executive(object): + + def __init__(self, rpchandler): + self.rpchandler = rpchandler + self.locals = __main__.__dict__ + self.calltip = CallTips.CallTips() + self.autocomplete = AutoComplete.AutoComplete() + + def runcode(self, code): + global interruptable + try: + self.usr_exc_info = None + interruptable = True + try: + exec code in self.locals + finally: + interruptable = False + except SystemExit: + # Scripts that raise SystemExit should just + # return to the interactive prompt + pass + except: + self.usr_exc_info = sys.exc_info() + if quitting: + exit() + print_exception() + jit = self.rpchandler.console.getvar("<>") + if jit: + self.rpchandler.interp.open_remote_stack_viewer() + else: + flush_stdout() + + def interrupt_the_server(self): + if interruptable: + thread.interrupt_main() + + def start_the_debugger(self, gui_adap_oid): + return RemoteDebugger.start_debugger(self.rpchandler, gui_adap_oid) + + def stop_the_debugger(self, idb_adap_oid): + "Unregister the Idb Adapter. Link objects and Idb then subject to GC" + self.rpchandler.unregister(idb_adap_oid) + + def get_the_calltip(self, name): + return self.calltip.fetch_tip(name) + + def get_the_completion_list(self, what, mode): + 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 + else: + return None + flist = None + if flist_oid is not None: + flist = self.rpchandler.get_remote_proxy(flist_oid) + while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]: + tb = tb.tb_next + sys.last_type = typ + sys.last_value = val + item = StackViewer.StackTreeItem(flist, tb) + return RemoteObjectBrowser.remote_object_tree_item(item) + +capture_warnings(False) # Make sure turned off; see issue 18081 diff --git a/PythonHome/Lib/idlelib/run.pyc b/PythonHome/Lib/idlelib/run.pyc deleted file mode 100644 index 281f78a0bd04b053f54175c58c0972b5cf2e9603..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12421 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

nyVmR~6qPrTs8n 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""" + if not tab_name in self._tab_names: + raise KeyError("No such Tab: '%s" % page_name) + + self._tab_names.remove(tab_name) + self._arrange_tabs() + + def set_selected_tab(self, tab_name): + """Show the tab named as the selected one""" + if tab_name == self._selected_tab: + return + if tab_name is not None and tab_name not in self._tabs: + raise KeyError("No such Tab: '%s" % page_name) + + # deselect the current selected tab + if self._selected_tab is not None: + self._tabs[self._selected_tab].set_normal() + self._selected_tab = None + + if tab_name is not None: + # activate the tab named tab_name + self._selected_tab = tab_name + tab = self._tabs[tab_name] + tab.set_selected() + # move the tab row with the selected tab to the bottom + tab_row = self._tab2row[tab] + tab_row.pack_forget() + tab_row.pack(side=TOP, fill=X, expand=0) + + def _add_tab_row(self, tab_names, expand_tabs): + if not tab_names: + return + + tab_row = Frame(self) + tab_row.pack(side=TOP, fill=X, expand=0) + self._tab_rows.append(tab_row) + + for tab_name in tab_names: + tab = TabSet.TabButton(tab_name, self.select_command, + tab_row, self) + if expand_tabs: + tab.pack(side=LEFT, fill=X, expand=True) + else: + tab.pack(side=LEFT) + self._tabs[tab_name] = tab + self._tab2row[tab] = tab_row + + # tab is the last one created in the above loop + tab.is_last_in_row = True + + def _reset_tab_rows(self): + while self._tab_rows: + tab_row = self._tab_rows.pop() + tab_row.destroy() + self._tab2row = {} + + def _arrange_tabs(self): + """ + Arrange the tabs in rows, in the order in which they were added. + + If n_rows >= 1, this will be the number of rows used. Otherwise the + number of rows will be calculated according to the number of tabs and + max_tabs_per_row. In this case, the number of rows may change when + adding/removing tabs. + + """ + # remove all tabs and rows + for tab_name in self._tabs.keys(): + self._tabs.pop(tab_name).destroy() + self._reset_tab_rows() + + if not self._tab_names: + return + + if self.n_rows is not None and self.n_rows > 0: + n_rows = self.n_rows + else: + # calculate the required number of rows + n_rows = (len(self._tab_names) - 1) // self.max_tabs_per_row + 1 + + # not expanding the tabs with more than one row is very ugly + expand_tabs = self.expand_tabs or n_rows > 1 + i = 0 # index in self._tab_names + for row_index in xrange(n_rows): + # calculate required number of tabs in this row + n_tabs = (len(self._tab_names) - i - 1) // (n_rows - row_index) + 1 + tab_names = self._tab_names[i:i + n_tabs] + i += n_tabs + self._add_tab_row(tab_names, expand_tabs) + + # re-select selected tab so it is properly displayed + selected = self._selected_tab + self.set_selected_tab(None) + if selected in self._tab_names: + self.set_selected_tab(selected) + + class TabButton(Frame): + """A simple tab-like widget.""" + + bw = 2 # borderwidth + + def __init__(self, name, select_command, tab_row, tab_set): + """Constructor arguments: + + name -- The tab's name, which will appear in its button. + + select_command -- The command to be called upon selection of the + tab. It is called with the tab's name as an argument. + + """ + Frame.__init__(self, tab_row, borderwidth=self.bw, relief=RAISED) + + self.name = name + self.select_command = select_command + self.tab_set = tab_set + self.is_last_in_row = False + + self.button = Radiobutton( + self, text=name, command=self._select_event, + padx=5, pady=1, takefocus=FALSE, indicatoron=FALSE, + highlightthickness=0, selectcolor='', borderwidth=0) + self.button.pack(side=LEFT, fill=X, expand=True) + + self._init_masks() + self.set_normal() + + def _select_event(self, *args): + """Event handler for tab selection. + + With TabbedPageSet, this calls TabbedPageSet.change_page, so that + selecting a tab changes the page. + + Note that this does -not- call set_selected -- it will be called by + TabSet.set_selected_tab, which should be called when whatever the + tabs are related to changes. + + """ + self.select_command(self.name) + return + + def set_selected(self): + """Assume selected look""" + self._place_masks(selected=True) + + def set_normal(self): + """Assume normal look""" + self._place_masks(selected=False) + + def _init_masks(self): + page_set = self.tab_set.page_set + background = page_set.pages_frame.cget('background') + # mask replaces the middle of the border with the background color + self.mask = Frame(page_set, borderwidth=0, relief=FLAT, + background=background) + # mskl replaces the bottom-left corner of the border with a normal + # left border + self.mskl = Frame(page_set, borderwidth=0, relief=FLAT, + background=background) + self.mskl.ml = Frame(self.mskl, borderwidth=self.bw, + relief=RAISED) + self.mskl.ml.place(x=0, y=-self.bw, + width=2*self.bw, height=self.bw*4) + # mskr replaces the bottom-right corner of the border with a normal + # right border + self.mskr = Frame(page_set, borderwidth=0, relief=FLAT, + background=background) + self.mskr.mr = Frame(self.mskr, borderwidth=self.bw, + relief=RAISED) + + def _place_masks(self, selected=False): + height = self.bw + if selected: + height += self.bw + + self.mask.place(in_=self, + relx=0.0, x=0, + rely=1.0, y=0, + relwidth=1.0, width=0, + relheight=0.0, height=height) + + self.mskl.place(in_=self, + relx=0.0, x=-self.bw, + rely=1.0, y=0, + relwidth=0.0, width=self.bw, + relheight=0.0, height=height) + + page_set = self.tab_set.page_set + if selected and ((not self.is_last_in_row) or + (self.winfo_rootx() + self.winfo_width() < + page_set.winfo_rootx() + page_set.winfo_width()) + ): + # for a selected tab, if its rightmost edge isn't on the + # rightmost edge of the page set, the right mask should be one + # borderwidth shorter (vertically) + height -= self.bw + + self.mskr.place(in_=self, + relx=1.0, x=0, + rely=1.0, y=0, + relwidth=0.0, width=self.bw, + relheight=0.0, height=height) + + self.mskr.mr.place(x=-self.bw, y=-self.bw, + width=2*self.bw, height=height + self.bw*2) + + # finally, lower the tab set so that all of the frames we just + # placed hide it + self.tab_set.lower() + +class TabbedPageSet(Frame): + """A Tkinter tabbed-pane widget. + + Constains set of 'pages' (or 'panes') with tabs above for selecting which + page is displayed. Only one page will be displayed at a time. + + Pages may be accessed through the 'pages' attribute, which is a dictionary + of pages, using the name given as the key. A page is an instance of a + subclass of Tk's Frame widget. + + The page widgets will be created (and destroyed when required) by the + TabbedPageSet. Do not call the page's pack/place/grid/destroy methods. + + Pages may be added or removed at any time using the add_page() and + remove_page() methods. + + """ + class Page(object): + """Abstract base class for TabbedPageSet's pages. + + Subclasses must override the _show() and _hide() methods. + + """ + uses_grid = False + + def __init__(self, page_set): + self.frame = Frame(page_set, borderwidth=2, relief=RAISED) + + def _show(self): + raise NotImplementedError + + def _hide(self): + raise NotImplementedError + + class PageRemove(Page): + """Page class using the grid placement manager's "remove" mechanism.""" + uses_grid = True + + def _show(self): + self.frame.grid(row=0, column=0, sticky=NSEW) + + def _hide(self): + self.frame.grid_remove() + + class PageLift(Page): + """Page class using the grid placement manager's "lift" mechanism.""" + uses_grid = True + + def __init__(self, page_set): + super(TabbedPageSet.PageLift, self).__init__(page_set) + self.frame.grid(row=0, column=0, sticky=NSEW) + self.frame.lower() + + def _show(self): + self.frame.lift() + + def _hide(self): + self.frame.lower() + + class PagePackForget(Page): + """Page class using the pack placement manager's "forget" mechanism.""" + def _show(self): + self.frame.pack(fill=BOTH, expand=True) + + def _hide(self): + self.frame.pack_forget() + + def __init__(self, parent, page_names=None, page_class=PageLift, + n_rows=1, max_tabs_per_row=5, expand_tabs=False, + **kw): + """Constructor arguments: + + page_names -- A list of strings, each will be the dictionary key to a + page's widget, and the name displayed on the page's tab. Should be + specified in the desired page order. The first page will be the default + and first active page. If page_names is None or empty, the + TabbedPageSet will be initialized empty. + + n_rows, max_tabs_per_row -- Parameters for the TabSet which will + manage the tabs. See TabSet's docs for details. + + page_class -- Pages can be shown/hidden using three mechanisms: + + * PageLift - All pages will be rendered one on top of the other. When + a page is selected, it will be brought to the top, thus hiding all + other pages. Using this method, the TabbedPageSet will not be resized + when pages are switched. (It may still be resized when pages are + added/removed.) + + * PageRemove - When a page is selected, the currently showing page is + hidden, and the new page shown in its place. Using this method, the + TabbedPageSet may resize when pages are changed. + + * PagePackForget - This mechanism uses the pack placement manager. + When a page is shown it is packed, and when it is hidden it is + unpacked (i.e. pack_forget). This mechanism may also cause the + TabbedPageSet to resize when the page is changed. + + """ + Frame.__init__(self, parent, **kw) + + self.page_class = page_class + self.pages = {} + self._pages_order = [] + self._current_page = None + self._default_page = None + + self.columnconfigure(0, weight=1) + self.rowconfigure(1, weight=1) + + self.pages_frame = Frame(self) + self.pages_frame.grid(row=1, column=0, sticky=NSEW) + if self.page_class.uses_grid: + self.pages_frame.columnconfigure(0, weight=1) + self.pages_frame.rowconfigure(0, weight=1) + + # the order of the following commands is important + self._tab_set = TabSet(self, self.change_page, n_rows=n_rows, + max_tabs_per_row=max_tabs_per_row, + expand_tabs=expand_tabs) + if page_names: + for name in page_names: + self.add_page(name) + self._tab_set.grid(row=0, column=0, sticky=NSEW) + + self.change_page(self._default_page) + + def add_page(self, page_name): + """Add a new page with the name given in page_name.""" + if not page_name: + raise InvalidNameError("Invalid TabPage name: '%s'" % page_name) + if page_name in self.pages: + raise AlreadyExistsError( + "TabPage named '%s' already exists" % page_name) + + self.pages[page_name] = self.page_class(self.pages_frame) + self._pages_order.append(page_name) + self._tab_set.add_tab(page_name) + + if len(self.pages) == 1: # adding first page + self._default_page = page_name + self.change_page(page_name) + + def remove_page(self, page_name): + """Destroy the page whose name is given in page_name.""" + if not page_name in self.pages: + raise KeyError("No such TabPage: '%s" % page_name) + + self._pages_order.remove(page_name) + + # handle removing last remaining, default, or currently shown page + if len(self._pages_order) > 0: + if page_name == self._default_page: + # set a new default page + self._default_page = self._pages_order[0] + else: + self._default_page = None + + if page_name == self._current_page: + self.change_page(self._default_page) + + self._tab_set.remove_tab(page_name) + page = self.pages.pop(page_name) + page.frame.destroy() + + def change_page(self, page_name): + """Show the page whose name is given in page_name.""" + if self._current_page == page_name: + return + if page_name is not None and page_name not in self.pages: + raise KeyError("No such TabPage: '%s'" % page_name) + + if self._current_page is not None: + self.pages[self._current_page]._hide() + self._current_page = None + + if page_name is not None: + self._current_page = page_name + self.pages[page_name]._show() + + self._tab_set.set_selected_tab(page_name) + +def _tabbed_pages(parent): + # test dialog + root=Tk() + width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) + root.geometry("+%d+%d"%(x, y + 175)) + root.title("Test tabbed pages") + tabPage=TabbedPageSet(root, page_names=['Foobar','Baz'], n_rows=0, + expand_tabs=False, + ) + tabPage.pack(side=TOP, expand=TRUE, fill=BOTH) + Label(tabPage.pages['Foobar'].frame, text='Foo', pady=20).pack() + Label(tabPage.pages['Foobar'].frame, text='Bar', pady=20).pack() + Label(tabPage.pages['Baz'].frame, text='Baz').pack() + entryPgName=Entry(root) + buttonAdd=Button(root, text='Add Page', + command=lambda:tabPage.add_page(entryPgName.get())) + buttonRemove=Button(root, text='Remove Page', + command=lambda:tabPage.remove_page(entryPgName.get())) + labelPgName=Label(root, text='name of page to add/remove:') + buttonAdd.pack(padx=5, pady=5) + buttonRemove.pack(padx=5, pady=5) + labelPgName.pack(padx=5) + entryPgName.pack(padx=5) + root.mainloop() + + +if __name__ == '__main__': + from idlelib.idle_test.htest import run + run(_tabbed_pages) diff --git a/PythonHome/Lib/idlelib/tabbedpages.pyc b/PythonHome/Lib/idlelib/tabbedpages.pyc deleted file mode 100644 index e3aea6a9ce033c69a6d44ffd8d74ea8bb9080806..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17961 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 Ky73Ite*PcCbjPy* diff --git a/PythonHome/Lib/idlelib/testcode.py b/PythonHome/Lib/idlelib/testcode.py new file mode 100644 index 0000000000..05eaa562cd --- /dev/null +++ b/PythonHome/Lib/idlelib/testcode.py @@ -0,0 +1,31 @@ +import string + +def f(): + a = 0 + b = 1 + c = 2 + d = 3 + e = 4 + g() + +def g(): + h() + +def h(): + i() + +def i(): + j() + +def j(): + k() + +def k(): + l() + +l = lambda: test() + +def test(): + string.capwords(1) + +f() diff --git a/PythonHome/Lib/idlelib/testcode.pyc b/PythonHome/Lib/idlelib/testcode.pyc deleted file mode 100644 index 63d5a1993f9f18353db7cf83ea4275e42fee4123..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1289 zcmbu8&q~8U5XL8enkKahiXe&)5HEcKDS}tYVS5myplLSNt*I^DhOQv17iF5#f#RbY)9U)$aZ$v{9Z5?lWo@Zuz~)AtPmOzE%r&CGtRi- zx(wOd0ylHR#f;kD0{7^KOBi*y1+H?#q3DnP!Xevjsf?sRe#!)ejOufu)yU;}mCq+S zAD)29gVyze@{#gHx|uoSKI8uMxIfWV_?$^YiLKFPwqBX1sl+Yv<;!BFt<#DWdgT;> z+S*N#eue5%2rs3rkOGCJEBT6)Db&0C?1XC*Fkk5BsvM%}>;X&PPvRt4pMDa21KM}K A-2eap diff --git a/PythonHome/Lib/idlelib/textView.py b/PythonHome/Lib/idlelib/textView.py new file mode 100644 index 0000000000..eb60274156 --- /dev/null +++ b/PythonHome/Lib/idlelib/textView.py @@ -0,0 +1,90 @@ +"""Simple text browser for IDLE + +""" + +from Tkinter import * +import tkMessageBox + +class TextViewer(Toplevel): + """A simple text viewer dialog for IDLE + + """ + def __init__(self, parent, title, text, modal=True, _htest=False): + """Show the given text in a scrollable window with a 'close' button + + If modal option set to False, user can interact with other windows, + otherwise they will be unable to interact with other windows until + the textview window is closed. + + _htest - bool; change box location when running htest. + """ + Toplevel.__init__(self, parent) + self.configure(borderwidth=5) + # place dialog below parent if running htest + self.geometry("=%dx%d+%d+%d" % (625, 500, + parent.winfo_rootx() + 10, + parent.winfo_rooty() + (10 if not _htest else 100))) + #elguavas - config placeholders til config stuff completed + self.bg = '#ffffff' + self.fg = '#000000' + + self.CreateWidgets() + self.title(title) + self.protocol("WM_DELETE_WINDOW", self.Ok) + self.parent = parent + self.textView.focus_set() + #key bindings for this dialog + self.bind('',self.Ok) #dismiss dialog + self.bind('',self.Ok) #dismiss dialog + self.textView.insert(0.0, text) + self.textView.config(state=DISABLED) + + if modal: + self.transient(parent) + self.grab_set() + self.wait_window() + + def CreateWidgets(self): + frameText = Frame(self, relief=SUNKEN, height=700) + frameButtons = Frame(self) + self.buttonOk = Button(frameButtons, text='Close', + command=self.Ok, takefocus=FALSE) + self.scrollbarView = Scrollbar(frameText, orient=VERTICAL, + takefocus=FALSE, highlightthickness=0) + self.textView = Text(frameText, wrap=WORD, highlightthickness=0, + fg=self.fg, bg=self.bg) + self.scrollbarView.config(command=self.textView.yview) + self.textView.config(yscrollcommand=self.scrollbarView.set) + self.buttonOk.pack() + self.scrollbarView.pack(side=RIGHT,fill=Y) + self.textView.pack(side=LEFT,expand=TRUE,fill=BOTH) + frameButtons.pack(side=BOTTOM,fill=X) + frameText.pack(side=TOP,expand=TRUE,fill=BOTH) + + def Ok(self, event=None): + self.destroy() + + +def view_text(parent, title, text, modal=True): + return TextViewer(parent, title, text, modal) + +def view_file(parent, title, filename, encoding=None, modal=True): + try: + if encoding: + import codecs + textFile = codecs.open(filename, 'r') + else: + textFile = open(filename, 'r') + except IOError: + tkMessageBox.showerror(title='File Load Error', + message='Unable to load file %r .' % filename, + parent=parent) + else: + return view_text(parent, title, textFile.read(), modal) + + +if __name__ == '__main__': + import unittest + unittest.main('idlelib.idle_test.test_textview', verbosity=2, exit=False) + from idlelib.idle_test.htest import run + run(TextViewer) diff --git a/PythonHome/Lib/idlelib/textView.pyc b/PythonHome/Lib/idlelib/textView.pyc deleted file mode 100644 index c6f8430fdadfdc51c98afec4a3b07acf5bd56f15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3724 zcmb7HTTdLx6+YDi0}PkJ#>V#MvK_6gopm%`RH0)ze)w)6jI2 z?ivG<{e<80l;=F;k3`CkO5T(2J3WAtl~zvUs;N4s>fGv_ugZ;oF1I@W_)9OA>DR>X z7iiVr&?O>==#3-^`1qqRg0gb zQC5uJv&+X9GvI7+yA3$D#b`A}7_srOSm?p!On zt0SgB8!52LkUdApdgJ2EcVp|1($_YxQz6a$$gkqE$g*gF{5VVV1gp+cHwNR=I4dgq zsXv%FSLCf0kAvUN&_5}XDD#U`mlnBSS?9aLe->qx{oJ20x8f-G)7;rIid`+Pfa-Fp zp!)n;mXgoX3b{G97vN`^Kd}BJS9>7!2c%$?OS5ZH^ok~GO^`Znz(VQNxcN( z?;j@T50jtkzw}R@Ncu0tJ!LJWC=;oe!k-NFtH;06&+&{7UWD7--EO}d9_;LG?;lk2 zAU+PPo0R#JdeW`p=+r(LfuWyM%`S3wud@z{5c0!qFX^`>+VhqHyQ`Grw@~Lk1)L8IIgCW?Q9&&Vw`=Sy!nME_GQg_OvWq z5f_=R-#>P&+|#JExl^q?A7Y9cG%Vst6(W1w40Ry)ba|R1gPaa)lXd6zPVedFZg*RE zx-!bE^h)Tcj0P%3U5VguoyQ$2SJ{=#hQTe&0wSW4Xo=dcsjS-S#OPp!XjeVJXyd!x zbnso8WH!U^mHiv17XhX7*ehMUuxeJlwplhm^A^m4*TQJcESP0)4ZryFnxM2yOn_~m zF)OyXd#i>sAOqkF_zMI}Q2fSwizz?~SBH_eo*<%tof^-8Sws?rEqHTj8kmN&0ylte zz%MsPL<6h7Hl_q5$EiH_8Ws9i%4)+x3DmAD6s zR<9YegsaObRDuKSY7@JXRdH)zc#2&$sDW`ul3U{LDtjI5hJlyUP4|>~zupAYu0=ig z-VPL3uX7v0+|zR`aa4Aw!?8_AW0(FNNgVtb3-rXd2y2KCOXB1tLfWxBTy$(TBXwg@ zYI;%V7$P!?L9NHfxvi=c)H;jK%IGv;5(LaW$LzYO@$^bGQ@ctNt4TKmys3D5ehR&v zkGP3d{H%;njm)Ut%e_B#YdcLSnBz3Ay~udBsSBQna1hW8Y|2T`f4SKXk$v-NaW zE44NSEUh`3(r4OpaIhb2-&h{d(Lh0j=3Ed%9nALqHDHCSN8qsJELq z1sry`=>}u9+Jc{uf%YMIs`VL#j9$!h!VeBmPM)OdIAKAMz*>S{>$rk zPR2#R2kSp9{S6IdhYo8c#YJM{N)Nj@Mdp#QvtNs3;ke@$wb0GtT;o{bv1h3<_ygHI z8(i9nO1wEF1q|wB66(a}P=!a2o?P&Pd+8icgs%MmXG!T_LPB*1otTDcqCW59Qd~xb zw#=fZ@{##bnulTaF&0hl+71397b>^GPP0N`iN*8UmV=^7-9^fhQvd9E>guv>fP}|e zhX)WmBcJi=AL~;x_=;4fl%{P!<1|RY4o9!pG5OT430_ZBt_o;k@SLoB=)P~Iz7qrd pfAGDO*MR--J3 0: + raise ValueError, 'Attempted relative import in non-package' + else: + # __package__ not set, figure it out and set it + modname = globals.get('__name__') + if modname is None: + return None + if "__path__" in globals: + # __path__ is set so modname is already the package name + pkgname = modname + else: + # normal module, work out package name if any + if '.' not in modname: + if level > 0: + raise ValueError, ('Attempted relative import in ' + 'non-package') + globals['__package__'] = None + return None + pkgname = modname.rpartition('.')[0] + globals['__package__'] = pkgname + if level > 0: + dot = len(pkgname) + for x in range(level, 1, -1): + try: + dot = pkgname.rindex('.', 0, dot) + except ValueError: + raise ValueError('attempted relative import beyond ' + 'top-level package') + pkgname = pkgname[:dot] + try: + return sys.modules[pkgname] + except KeyError: + if level < 1: + warn("Parent module '%s' not found while handling " + "absolute import" % pkgname, RuntimeWarning, 1) + return None + else: + raise SystemError, ("Parent module '%s' not loaded, cannot " + "perform relative import" % pkgname) + + def find_head_package(self, parent, name): + if '.' in name: + i = name.find('.') + head = name[:i] + tail = name[i+1:] + else: + head = name + tail = "" + if parent: + qname = "%s.%s" % (parent.__name__, head) + else: + qname = head + q = self.import_it(head, qname, parent) + if q: return q, tail + if parent: + qname = head + parent = None + q = self.import_it(head, qname, parent) + if q: return q, tail + raise ImportError, "No module named '%s'" % qname + + def load_tail(self, q, tail): + m = q + while tail: + i = tail.find('.') + if i < 0: i = len(tail) + head, tail = tail[:i], tail[i+1:] + mname = "%s.%s" % (m.__name__, head) + m = self.import_it(head, mname, m) + if not m: + raise ImportError, "No module named '%s'" % mname + return m + + def ensure_fromlist(self, m, fromlist, recursive=0): + for sub in fromlist: + if sub == "*": + if not recursive: + try: + all = m.__all__ + except AttributeError: + pass + else: + self.ensure_fromlist(m, all, 1) + continue + if sub != "*" and not hasattr(m, sub): + subname = "%s.%s" % (m.__name__, sub) + submod = self.import_it(sub, subname, m) + if not submod: + raise ImportError, "No module named '%s'" % subname + + def import_it(self, partname, fqname, parent, force_load=0): + if not partname: + # completely empty module name should only happen in + # 'from . import' or __import__("") + return parent + if not force_load: + try: + return self.modules[fqname] + except KeyError: + pass + try: + path = parent and parent.__path__ + except AttributeError: + return None + partname = str(partname) + stuff = self.loader.find_module(partname, path) + if not stuff: + return None + fqname = str(fqname) + m = self.loader.load_module(fqname, stuff) + if parent: + setattr(parent, partname, m) + return m + + def reload(self, module): + name = str(module.__name__) + if '.' not in name: + return self.import_it(name, name, None, force_load=1) + i = name.rfind('.') + pname = name[:i] + parent = self.modules[pname] + return self.import_it(name[i+1:], name, parent, force_load=1) + + +default_importer = None +current_importer = None + +def install(importer = None): + global current_importer + current_importer = importer or default_importer or ModuleImporter() + current_importer.install() + +def uninstall(): + global current_importer + current_importer.uninstall() diff --git a/PythonHome/Lib/ihooks.pyc b/PythonHome/Lib/ihooks.pyc deleted file mode 100644 index 875b068e900fbd3b5e779037190a82e5cfe81d2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20337 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 diff --git a/PythonHome/Lib/imaplib.py b/PythonHome/Lib/imaplib.py new file mode 100644 index 0000000000..10ff340ef9 --- /dev/null +++ b/PythonHome/Lib/imaplib.py @@ -0,0 +1,1535 @@ +"""IMAP4 client. + +Based on RFC 2060. + +Public class: IMAP4 +Public variable: Debug +Public functions: Internaldate2tuple + Int2AP + ParseFlags + Time2Internaldate +""" + +# Author: Piers Lauder December 1997. +# +# Authentication code contributed by Donn Cave June 1998. +# String method conversion by ESR, February 2001. +# GET/SETACL contributed by Anthony Baxter April 2001. +# IMAP4_SSL contributed by Tino Lange March 2002. +# GET/SETQUOTA contributed by Andreas Zeidler June 2002. +# PROXYAUTH contributed by Rick Holbert November 2002. +# GET/SETANNOTATION contributed by Tomas Lindroos June 2005. + +__version__ = "2.58" + +import binascii, errno, random, re, socket, subprocess, sys, time + +__all__ = ["IMAP4", "IMAP4_stream", "Internaldate2tuple", + "Int2AP", "ParseFlags", "Time2Internaldate"] + +# Globals + +CRLF = '\r\n' +Debug = 0 +IMAP4_PORT = 143 +IMAP4_SSL_PORT = 993 +AllowedVersions = ('IMAP4REV1', 'IMAP4') # Most recent first + +# Maximal line length when calling readline(). This is to prevent +# reading arbitrary length lines. RFC 3501 and 2060 (IMAP 4rev1) +# don't specify a line length. RFC 2683 however suggests limiting client +# command lines to 1000 octets and server command lines to 8000 octets. +# We have selected 10000 for some extra margin and since that is supposedly +# also what UW and Panda IMAP does. +_MAXLINE = 10000 + + +# Commands + +Commands = { + # name valid states + 'APPEND': ('AUTH', 'SELECTED'), + 'AUTHENTICATE': ('NONAUTH',), + 'CAPABILITY': ('NONAUTH', 'AUTH', 'SELECTED', 'LOGOUT'), + 'CHECK': ('SELECTED',), + 'CLOSE': ('SELECTED',), + 'COPY': ('SELECTED',), + 'CREATE': ('AUTH', 'SELECTED'), + 'DELETE': ('AUTH', 'SELECTED'), + 'DELETEACL': ('AUTH', 'SELECTED'), + 'EXAMINE': ('AUTH', 'SELECTED'), + 'EXPUNGE': ('SELECTED',), + 'FETCH': ('SELECTED',), + 'GETACL': ('AUTH', 'SELECTED'), + 'GETANNOTATION':('AUTH', 'SELECTED'), + 'GETQUOTA': ('AUTH', 'SELECTED'), + 'GETQUOTAROOT': ('AUTH', 'SELECTED'), + 'MYRIGHTS': ('AUTH', 'SELECTED'), + 'LIST': ('AUTH', 'SELECTED'), + 'LOGIN': ('NONAUTH',), + 'LOGOUT': ('NONAUTH', 'AUTH', 'SELECTED', 'LOGOUT'), + 'LSUB': ('AUTH', 'SELECTED'), + 'NAMESPACE': ('AUTH', 'SELECTED'), + 'NOOP': ('NONAUTH', 'AUTH', 'SELECTED', 'LOGOUT'), + 'PARTIAL': ('SELECTED',), # NB: obsolete + 'PROXYAUTH': ('AUTH',), + 'RENAME': ('AUTH', 'SELECTED'), + 'SEARCH': ('SELECTED',), + 'SELECT': ('AUTH', 'SELECTED'), + 'SETACL': ('AUTH', 'SELECTED'), + 'SETANNOTATION':('AUTH', 'SELECTED'), + 'SETQUOTA': ('AUTH', 'SELECTED'), + 'SORT': ('SELECTED',), + 'STATUS': ('AUTH', 'SELECTED'), + 'STORE': ('SELECTED',), + 'SUBSCRIBE': ('AUTH', 'SELECTED'), + 'THREAD': ('SELECTED',), + 'UID': ('SELECTED',), + 'UNSUBSCRIBE': ('AUTH', 'SELECTED'), + } + +# Patterns to match server responses + +Continuation = re.compile(r'\+( (?P.*))?') +Flags = re.compile(r'.*FLAGS \((?P[^\)]*)\)') +InternalDate = re.compile(r'.*INTERNALDATE "' + r'(?P[ 0123][0-9])-(?P[A-Z][a-z][a-z])-(?P[0-9][0-9][0-9][0-9])' + r' (?P[0-9][0-9]):(?P[0-9][0-9]):(?P[0-9][0-9])' + r' (?P[-+])(?P[0-9][0-9])(?P[0-9][0-9])' + r'"') +Literal = re.compile(r'.*{(?P\d+)}$') +MapCRLF = re.compile(r'\r\n|\r|\n') +Response_code = re.compile(r'\[(?P[A-Z-]+)( (?P[^\]]*))?\]') +Untagged_response = re.compile(r'\* (?P[A-Z-]+)( (?P.*))?') +Untagged_status = re.compile(r'\* (?P\d+) (?P[A-Z-]+)( (?P.*))?') + + + +class IMAP4: + + """IMAP4 client class. + + Instantiate with: IMAP4([host[, port]]) + + host - host's name (default: localhost); + port - port number (default: standard IMAP4 port). + + All IMAP4rev1 commands are supported by methods of the same + name (in lower-case). + + All arguments to commands are converted to strings, except for + AUTHENTICATE, and the last argument to APPEND which is passed as + an IMAP4 literal. If necessary (the string contains any + non-printing characters or white-space and isn't enclosed with + either parentheses or double quotes) each string is quoted. + However, the 'password' argument to the LOGIN command is always + quoted. If you want to avoid having an argument string quoted + (eg: the 'flags' argument to STORE) then enclose the string in + parentheses (eg: "(\Deleted)"). + + Each command returns a tuple: (type, [data, ...]) where 'type' + is usually 'OK' or 'NO', and 'data' is either the text from the + tagged response, or untagged results from command. Each 'data' + is either a string, or a tuple. If a tuple, then the first part + is the header of the response, and the second part contains + the data (ie: 'literal' value). + + Errors raise the exception class .error(""). + IMAP4 server errors raise .abort(""), + which is a sub-class of 'error'. Mailbox status changes + from READ-WRITE to READ-ONLY raise the exception class + .readonly(""), which is a sub-class of 'abort'. + + "error" exceptions imply a program error. + "abort" exceptions imply the connection should be reset, and + the command re-tried. + "readonly" exceptions imply the command should be re-tried. + + Note: to use this module, you must read the RFCs pertaining to the + IMAP4 protocol, as the semantics of the arguments to each IMAP4 + command are left to the invoker, not to mention the results. Also, + most IMAP servers implement a sub-set of the commands available here. + """ + + class error(Exception): pass # Logical errors - debug required + class abort(error): pass # Service errors - close and retry + class readonly(abort): pass # Mailbox status changed to READ-ONLY + + mustquote = re.compile(r"[^\w!#$%&'*+,.:;<=>?^`|~-]") + + def __init__(self, host = '', port = IMAP4_PORT): + self.debug = Debug + self.state = 'LOGOUT' + self.literal = None # A literal argument to a command + self.tagged_commands = {} # Tagged commands awaiting response + self.untagged_responses = {} # {typ: [data, ...], ...} + self.continuation_response = '' # Last continuation response + self.is_readonly = False # READ-ONLY desired state + self.tagnum = 0 + + # Open socket to server. + + self.open(host, port) + + # Create unique tag for this session, + # and compile tagged response matcher. + + self.tagpre = Int2AP(random.randint(4096, 65535)) + self.tagre = re.compile(r'(?P' + + self.tagpre + + r'\d+) (?P[A-Z]+) (?P.*)') + + # Get server welcome message, + # request and store CAPABILITY response. + + if __debug__: + self._cmd_log_len = 10 + self._cmd_log_idx = 0 + self._cmd_log = {} # Last `_cmd_log_len' interactions + if self.debug >= 1: + self._mesg('imaplib version %s' % __version__) + self._mesg('new IMAP4 connection, tag=%s' % self.tagpre) + + self.welcome = self._get_response() + if 'PREAUTH' in self.untagged_responses: + self.state = 'AUTH' + elif 'OK' in self.untagged_responses: + self.state = 'NONAUTH' + else: + raise self.error(self.welcome) + + typ, dat = self.capability() + if dat == [None]: + raise self.error('no CAPABILITY response from server') + self.capabilities = tuple(dat[-1].upper().split()) + + if __debug__: + if self.debug >= 3: + self._mesg('CAPABILITIES: %r' % (self.capabilities,)) + + for version in AllowedVersions: + if not version in self.capabilities: + continue + self.PROTOCOL_VERSION = version + return + + raise self.error('server not IMAP4 compliant') + + + def __getattr__(self, attr): + # Allow UPPERCASE variants of IMAP4 command methods. + if attr in Commands: + return getattr(self, attr.lower()) + raise AttributeError("Unknown IMAP4 command: '%s'" % attr) + + + + # Overridable methods + + + def open(self, host = '', port = IMAP4_PORT): + """Setup connection to remote server on "host:port" + (default: localhost:standard IMAP4 port). + This connection will be used by the routines: + read, readline, send, shutdown. + """ + self.host = host + self.port = port + self.sock = socket.create_connection((host, port)) + self.file = self.sock.makefile('rb') + + + def read(self, size): + """Read 'size' bytes from remote.""" + return self.file.read(size) + + + def readline(self): + """Read line from remote.""" + line = self.file.readline(_MAXLINE + 1) + if len(line) > _MAXLINE: + raise self.error("got more than %d bytes" % _MAXLINE) + return line + + + def send(self, data): + """Send data to remote.""" + self.sock.sendall(data) + + + def shutdown(self): + """Close I/O established in "open".""" + self.file.close() + try: + self.sock.shutdown(socket.SHUT_RDWR) + except socket.error as e: + # The server might already have closed the connection + if e.errno != errno.ENOTCONN: + raise + finally: + self.sock.close() + + + def socket(self): + """Return socket instance used to connect to IMAP4 server. + + socket = .socket() + """ + return self.sock + + + + # Utility methods + + + def recent(self): + """Return most recent 'RECENT' responses if any exist, + else prompt server for an update using the 'NOOP' command. + + (typ, [data]) = .recent() + + 'data' is None if no new messages, + else list of RECENT responses, most recent last. + """ + name = 'RECENT' + typ, dat = self._untagged_response('OK', [None], name) + if dat[-1]: + return typ, dat + typ, dat = self.noop() # Prod server for response + return self._untagged_response(typ, dat, name) + + + def response(self, code): + """Return data for response 'code' if received, or None. + + Old value for response 'code' is cleared. + + (code, [data]) = .response(code) + """ + return self._untagged_response(code, [None], code.upper()) + + + + # IMAP4 commands + + + def append(self, mailbox, flags, date_time, message): + """Append message to named mailbox. + + (typ, [data]) = .append(mailbox, flags, date_time, message) + + All args except `message' can be None. + """ + name = 'APPEND' + if not mailbox: + mailbox = 'INBOX' + if flags: + if (flags[0],flags[-1]) != ('(',')'): + flags = '(%s)' % flags + else: + flags = None + if date_time: + date_time = Time2Internaldate(date_time) + else: + date_time = None + self.literal = MapCRLF.sub(CRLF, message) + return self._simple_command(name, mailbox, flags, date_time) + + + def authenticate(self, mechanism, authobject): + """Authenticate command - requires response processing. + + 'mechanism' specifies which authentication mechanism is to + be used - it must appear in .capabilities in the + form AUTH=. + + 'authobject' must be a callable object: + + data = authobject(response) + + It will be called to process server continuation responses. + It should return data that will be encoded and sent to server. + It should return None if the client abort response '*' should + be sent instead. + """ + mech = mechanism.upper() + # XXX: shouldn't this code be removed, not commented out? + #cap = 'AUTH=%s' % mech + #if not cap in self.capabilities: # Let the server decide! + # raise self.error("Server doesn't allow %s authentication." % mech) + self.literal = _Authenticator(authobject).process + typ, dat = self._simple_command('AUTHENTICATE', mech) + if typ != 'OK': + raise self.error(dat[-1]) + self.state = 'AUTH' + return typ, dat + + + def capability(self): + """(typ, [data]) = .capability() + Fetch capabilities list from server.""" + + name = 'CAPABILITY' + typ, dat = self._simple_command(name) + return self._untagged_response(typ, dat, name) + + + def check(self): + """Checkpoint mailbox on server. + + (typ, [data]) = .check() + """ + return self._simple_command('CHECK') + + + def close(self): + """Close currently selected mailbox. + + Deleted messages are removed from writable mailbox. + This is the recommended command before 'LOGOUT'. + + (typ, [data]) = .close() + """ + try: + typ, dat = self._simple_command('CLOSE') + finally: + self.state = 'AUTH' + return typ, dat + + + def copy(self, message_set, new_mailbox): + """Copy 'message_set' messages onto end of 'new_mailbox'. + + (typ, [data]) = .copy(message_set, new_mailbox) + """ + return self._simple_command('COPY', message_set, new_mailbox) + + + def create(self, mailbox): + """Create new mailbox. + + (typ, [data]) = .create(mailbox) + """ + return self._simple_command('CREATE', mailbox) + + + def delete(self, mailbox): + """Delete old mailbox. + + (typ, [data]) = .delete(mailbox) + """ + return self._simple_command('DELETE', mailbox) + + def deleteacl(self, mailbox, who): + """Delete the ACLs (remove any rights) set for who on mailbox. + + (typ, [data]) = .deleteacl(mailbox, who) + """ + return self._simple_command('DELETEACL', mailbox, who) + + def expunge(self): + """Permanently remove deleted items from selected mailbox. + + Generates 'EXPUNGE' response for each deleted message. + + (typ, [data]) = .expunge() + + 'data' is list of 'EXPUNGE'd message numbers in order received. + """ + name = 'EXPUNGE' + typ, dat = self._simple_command(name) + return self._untagged_response(typ, dat, name) + + + def fetch(self, message_set, message_parts): + """Fetch (parts of) messages. + + (typ, [data, ...]) = .fetch(message_set, message_parts) + + 'message_parts' should be a string of selected parts + enclosed in parentheses, eg: "(UID BODY[TEXT])". + + 'data' are tuples of message part envelope and data. + """ + name = 'FETCH' + typ, dat = self._simple_command(name, message_set, message_parts) + return self._untagged_response(typ, dat, name) + + + def getacl(self, mailbox): + """Get the ACLs for a mailbox. + + (typ, [data]) = .getacl(mailbox) + """ + typ, dat = self._simple_command('GETACL', mailbox) + return self._untagged_response(typ, dat, 'ACL') + + + def getannotation(self, mailbox, entry, attribute): + """(typ, [data]) = .getannotation(mailbox, entry, attribute) + Retrieve ANNOTATIONs.""" + + typ, dat = self._simple_command('GETANNOTATION', mailbox, entry, attribute) + return self._untagged_response(typ, dat, 'ANNOTATION') + + + def getquota(self, root): + """Get the quota root's resource usage and limits. + + Part of the IMAP4 QUOTA extension defined in rfc2087. + + (typ, [data]) = .getquota(root) + """ + typ, dat = self._simple_command('GETQUOTA', root) + return self._untagged_response(typ, dat, 'QUOTA') + + + def getquotaroot(self, mailbox): + """Get the list of quota roots for the named mailbox. + + (typ, [[QUOTAROOT responses...], [QUOTA responses]]) = .getquotaroot(mailbox) + """ + typ, dat = self._simple_command('GETQUOTAROOT', mailbox) + typ, quota = self._untagged_response(typ, dat, 'QUOTA') + typ, quotaroot = self._untagged_response(typ, dat, 'QUOTAROOT') + return typ, [quotaroot, quota] + + + def list(self, directory='""', pattern='*'): + """List mailbox names in directory matching pattern. + + (typ, [data]) = .list(directory='""', pattern='*') + + 'data' is list of LIST responses. + """ + name = 'LIST' + typ, dat = self._simple_command(name, directory, pattern) + return self._untagged_response(typ, dat, name) + + + def login(self, user, password): + """Identify client using plaintext password. + + (typ, [data]) = .login(user, password) + + NB: 'password' will be quoted. + """ + typ, dat = self._simple_command('LOGIN', user, self._quote(password)) + if typ != 'OK': + raise self.error(dat[-1]) + self.state = 'AUTH' + return typ, dat + + + def login_cram_md5(self, user, password): + """ Force use of CRAM-MD5 authentication. + + (typ, [data]) = .login_cram_md5(user, password) + """ + self.user, self.password = user, password + return self.authenticate('CRAM-MD5', self._CRAM_MD5_AUTH) + + + def _CRAM_MD5_AUTH(self, challenge): + """ Authobject to use with CRAM-MD5 authentication. """ + import hmac + return self.user + " " + hmac.HMAC(self.password, challenge).hexdigest() + + + def logout(self): + """Shutdown connection to server. + + (typ, [data]) = .logout() + + Returns server 'BYE' response. + """ + self.state = 'LOGOUT' + try: typ, dat = self._simple_command('LOGOUT') + except: typ, dat = 'NO', ['%s: %s' % sys.exc_info()[:2]] + self.shutdown() + if 'BYE' in self.untagged_responses: + return 'BYE', self.untagged_responses['BYE'] + return typ, dat + + + def lsub(self, directory='""', pattern='*'): + """List 'subscribed' mailbox names in directory matching pattern. + + (typ, [data, ...]) = .lsub(directory='""', pattern='*') + + 'data' are tuples of message part envelope and data. + """ + name = 'LSUB' + typ, dat = self._simple_command(name, directory, pattern) + return self._untagged_response(typ, dat, name) + + def myrights(self, mailbox): + """Show my ACLs for a mailbox (i.e. the rights that I have on mailbox). + + (typ, [data]) = .myrights(mailbox) + """ + typ,dat = self._simple_command('MYRIGHTS', mailbox) + return self._untagged_response(typ, dat, 'MYRIGHTS') + + def namespace(self): + """ Returns IMAP namespaces ala rfc2342 + + (typ, [data, ...]) = .namespace() + """ + name = 'NAMESPACE' + typ, dat = self._simple_command(name) + return self._untagged_response(typ, dat, name) + + + def noop(self): + """Send NOOP command. + + (typ, [data]) = .noop() + """ + if __debug__: + if self.debug >= 3: + self._dump_ur(self.untagged_responses) + return self._simple_command('NOOP') + + + def partial(self, message_num, message_part, start, length): + """Fetch truncated part of a message. + + (typ, [data, ...]) = .partial(message_num, message_part, start, length) + + 'data' is tuple of message part envelope and data. + """ + name = 'PARTIAL' + typ, dat = self._simple_command(name, message_num, message_part, start, length) + return self._untagged_response(typ, dat, 'FETCH') + + + def proxyauth(self, user): + """Assume authentication as "user". + + Allows an authorised administrator to proxy into any user's + mailbox. + + (typ, [data]) = .proxyauth(user) + """ + + name = 'PROXYAUTH' + return self._simple_command('PROXYAUTH', user) + + + def rename(self, oldmailbox, newmailbox): + """Rename old mailbox name to new. + + (typ, [data]) = .rename(oldmailbox, newmailbox) + """ + return self._simple_command('RENAME', oldmailbox, newmailbox) + + + def search(self, charset, *criteria): + """Search mailbox for matching messages. + + (typ, [data]) = .search(charset, criterion, ...) + + 'data' is space separated list of matching message numbers. + """ + name = 'SEARCH' + if charset: + typ, dat = self._simple_command(name, 'CHARSET', charset, *criteria) + else: + typ, dat = self._simple_command(name, *criteria) + return self._untagged_response(typ, dat, name) + + + def select(self, mailbox='INBOX', readonly=False): + """Select a mailbox. + + Flush all untagged responses. + + (typ, [data]) = .select(mailbox='INBOX', readonly=False) + + 'data' is count of messages in mailbox ('EXISTS' response). + + Mandated responses are ('FLAGS', 'EXISTS', 'RECENT', 'UIDVALIDITY'), so + other responses should be obtained via .response('FLAGS') etc. + """ + self.untagged_responses = {} # Flush old responses. + self.is_readonly = readonly + if readonly: + name = 'EXAMINE' + else: + name = 'SELECT' + typ, dat = self._simple_command(name, mailbox) + if typ != 'OK': + self.state = 'AUTH' # Might have been 'SELECTED' + return typ, dat + self.state = 'SELECTED' + if 'READ-ONLY' in self.untagged_responses \ + and not readonly: + if __debug__: + if self.debug >= 1: + self._dump_ur(self.untagged_responses) + raise self.readonly('%s is not writable' % mailbox) + return typ, self.untagged_responses.get('EXISTS', [None]) + + + def setacl(self, mailbox, who, what): + """Set a mailbox acl. + + (typ, [data]) = .setacl(mailbox, who, what) + """ + return self._simple_command('SETACL', mailbox, who, what) + + + def setannotation(self, *args): + """(typ, [data]) = .setannotation(mailbox[, entry, attribute]+) + Set ANNOTATIONs.""" + + typ, dat = self._simple_command('SETANNOTATION', *args) + return self._untagged_response(typ, dat, 'ANNOTATION') + + + def setquota(self, root, limits): + """Set the quota root's resource limits. + + (typ, [data]) = .setquota(root, limits) + """ + typ, dat = self._simple_command('SETQUOTA', root, limits) + return self._untagged_response(typ, dat, 'QUOTA') + + + def sort(self, sort_criteria, charset, *search_criteria): + """IMAP4rev1 extension SORT command. + + (typ, [data]) = .sort(sort_criteria, charset, search_criteria, ...) + """ + name = 'SORT' + #if not name in self.capabilities: # Let the server decide! + # raise self.error('unimplemented extension command: %s' % name) + if (sort_criteria[0],sort_criteria[-1]) != ('(',')'): + sort_criteria = '(%s)' % sort_criteria + typ, dat = self._simple_command(name, sort_criteria, charset, *search_criteria) + return self._untagged_response(typ, dat, name) + + + def status(self, mailbox, names): + """Request named status conditions for mailbox. + + (typ, [data]) = .status(mailbox, names) + """ + name = 'STATUS' + #if self.PROTOCOL_VERSION == 'IMAP4': # Let the server decide! + # raise self.error('%s unimplemented in IMAP4 (obtain IMAP4rev1 server, or re-code)' % name) + typ, dat = self._simple_command(name, mailbox, names) + return self._untagged_response(typ, dat, name) + + + def store(self, message_set, command, flags): + """Alters flag dispositions for messages in mailbox. + + (typ, [data]) = .store(message_set, command, flags) + """ + if (flags[0],flags[-1]) != ('(',')'): + flags = '(%s)' % flags # Avoid quoting the flags + typ, dat = self._simple_command('STORE', message_set, command, flags) + return self._untagged_response(typ, dat, 'FETCH') + + + def subscribe(self, mailbox): + """Subscribe to new mailbox. + + (typ, [data]) = .subscribe(mailbox) + """ + return self._simple_command('SUBSCRIBE', mailbox) + + + def thread(self, threading_algorithm, charset, *search_criteria): + """IMAPrev1 extension THREAD command. + + (type, [data]) = .thread(threading_algorithm, charset, search_criteria, ...) + """ + name = 'THREAD' + typ, dat = self._simple_command(name, threading_algorithm, charset, *search_criteria) + return self._untagged_response(typ, dat, name) + + + def uid(self, command, *args): + """Execute "command arg ..." with messages identified by UID, + rather than message number. + + (typ, [data]) = .uid(command, arg1, arg2, ...) + + Returns response appropriate to 'command'. + """ + command = command.upper() + if not command in Commands: + raise self.error("Unknown IMAP4 UID command: %s" % command) + if self.state not in Commands[command]: + raise self.error("command %s illegal in state %s, " + "only allowed in states %s" % + (command, self.state, + ', '.join(Commands[command]))) + name = 'UID' + typ, dat = self._simple_command(name, command, *args) + if command in ('SEARCH', 'SORT', 'THREAD'): + name = command + else: + name = 'FETCH' + return self._untagged_response(typ, dat, name) + + + def unsubscribe(self, mailbox): + """Unsubscribe from old mailbox. + + (typ, [data]) = .unsubscribe(mailbox) + """ + return self._simple_command('UNSUBSCRIBE', mailbox) + + + def xatom(self, name, *args): + """Allow simple extension commands + notified by server in CAPABILITY response. + + Assumes command is legal in current state. + + (typ, [data]) = .xatom(name, arg, ...) + + Returns response appropriate to extension command `name'. + """ + name = name.upper() + #if not name in self.capabilities: # Let the server decide! + # raise self.error('unknown extension command: %s' % name) + if not name in Commands: + Commands[name] = (self.state,) + return self._simple_command(name, *args) + + + + # Private methods + + + def _append_untagged(self, typ, dat): + + if dat is None: dat = '' + ur = self.untagged_responses + if __debug__: + if self.debug >= 5: + self._mesg('untagged_responses[%s] %s += ["%s"]' % + (typ, len(ur.get(typ,'')), dat)) + if typ in ur: + ur[typ].append(dat) + else: + ur[typ] = [dat] + + + def _check_bye(self): + bye = self.untagged_responses.get('BYE') + if bye: + raise self.abort(bye[-1]) + + + def _command(self, name, *args): + + if self.state not in Commands[name]: + self.literal = None + raise self.error("command %s illegal in state %s, " + "only allowed in states %s" % + (name, self.state, + ', '.join(Commands[name]))) + + for typ in ('OK', 'NO', 'BAD'): + if typ in self.untagged_responses: + del self.untagged_responses[typ] + + if 'READ-ONLY' in self.untagged_responses \ + and not self.is_readonly: + raise self.readonly('mailbox status changed to READ-ONLY') + + tag = self._new_tag() + data = '%s %s' % (tag, name) + for arg in args: + if arg is None: continue + data = '%s %s' % (data, self._checkquote(arg)) + + literal = self.literal + if literal is not None: + self.literal = None + if type(literal) is type(self._command): + literator = literal + else: + literator = None + data = '%s {%s}' % (data, len(literal)) + + if __debug__: + if self.debug >= 4: + self._mesg('> %s' % data) + else: + self._log('> %s' % data) + + try: + self.send('%s%s' % (data, CRLF)) + except (socket.error, OSError), val: + raise self.abort('socket error: %s' % val) + + if literal is None: + return tag + + while 1: + # Wait for continuation response + + while self._get_response(): + if self.tagged_commands[tag]: # BAD/NO? + return tag + + # Send literal + + if literator: + literal = literator(self.continuation_response) + + if __debug__: + if self.debug >= 4: + self._mesg('write literal size %s' % len(literal)) + + try: + self.send(literal) + self.send(CRLF) + except (socket.error, OSError), val: + raise self.abort('socket error: %s' % val) + + if not literator: + break + + return tag + + + def _command_complete(self, name, tag): + # BYE is expected after LOGOUT + if name != 'LOGOUT': + self._check_bye() + try: + typ, data = self._get_tagged_response(tag) + except self.abort, val: + raise self.abort('command: %s => %s' % (name, val)) + except self.error, val: + raise self.error('command: %s => %s' % (name, val)) + if name != 'LOGOUT': + self._check_bye() + if typ == 'BAD': + raise self.error('%s command error: %s %s' % (name, typ, data)) + return typ, data + + + def _get_response(self): + + # Read response and store. + # + # Returns None for continuation responses, + # otherwise first response line received. + + resp = self._get_line() + + # Command completion response? + + if self._match(self.tagre, resp): + tag = self.mo.group('tag') + if not tag in self.tagged_commands: + raise self.abort('unexpected tagged response: %s' % resp) + + typ = self.mo.group('type') + dat = self.mo.group('data') + self.tagged_commands[tag] = (typ, [dat]) + else: + dat2 = None + + # '*' (untagged) responses? + + if not self._match(Untagged_response, resp): + if self._match(Untagged_status, resp): + dat2 = self.mo.group('data2') + + if self.mo is None: + # Only other possibility is '+' (continuation) response... + + if self._match(Continuation, resp): + self.continuation_response = self.mo.group('data') + return None # NB: indicates continuation + + raise self.abort("unexpected response: '%s'" % resp) + + typ = self.mo.group('type') + dat = self.mo.group('data') + if dat is None: dat = '' # Null untagged response + if dat2: dat = dat + ' ' + dat2 + + # Is there a literal to come? + + while self._match(Literal, dat): + + # Read literal direct from connection. + + size = int(self.mo.group('size')) + if __debug__: + if self.debug >= 4: + self._mesg('read literal size %s' % size) + data = self.read(size) + + # Store response with literal as tuple + + self._append_untagged(typ, (dat, data)) + + # Read trailer - possibly containing another literal + + dat = self._get_line() + + self._append_untagged(typ, dat) + + # Bracketed response information? + + if typ in ('OK', 'NO', 'BAD') and self._match(Response_code, dat): + self._append_untagged(self.mo.group('type'), self.mo.group('data')) + + if __debug__: + if self.debug >= 1 and typ in ('NO', 'BAD', 'BYE'): + self._mesg('%s response: %s' % (typ, dat)) + + return resp + + + def _get_tagged_response(self, tag): + + while 1: + result = self.tagged_commands[tag] + if result is not None: + del self.tagged_commands[tag] + return result + + # If we've seen a BYE at this point, the socket will be + # closed, so report the BYE now. + + self._check_bye() + + # Some have reported "unexpected response" exceptions. + # Note that ignoring them here causes loops. + # Instead, send me details of the unexpected response and + # I'll update the code in `_get_response()'. + + try: + self._get_response() + except self.abort, val: + if __debug__: + if self.debug >= 1: + self.print_log() + raise + + + def _get_line(self): + + line = self.readline() + if not line: + raise self.abort('socket error: EOF') + + # Protocol mandates all lines terminated by CRLF + if not line.endswith('\r\n'): + raise self.abort('socket error: unterminated line') + + line = line[:-2] + if __debug__: + if self.debug >= 4: + self._mesg('< %s' % line) + else: + self._log('< %s' % line) + return line + + + def _match(self, cre, s): + + # Run compiled regular expression match method on 's'. + # Save result, return success. + + self.mo = cre.match(s) + if __debug__: + if self.mo is not None and self.debug >= 5: + self._mesg("\tmatched r'%s' => %r" % (cre.pattern, self.mo.groups())) + return self.mo is not None + + + def _new_tag(self): + + tag = '%s%s' % (self.tagpre, self.tagnum) + self.tagnum = self.tagnum + 1 + self.tagged_commands[tag] = None + return tag + + + def _checkquote(self, arg): + + # Must quote command args if non-alphanumeric chars present, + # and not already quoted. + + if type(arg) is not type(''): + return arg + if len(arg) >= 2 and (arg[0],arg[-1]) in (('(',')'),('"','"')): + return arg + if arg and self.mustquote.search(arg) is None: + return arg + return self._quote(arg) + + + def _quote(self, arg): + + arg = arg.replace('\\', '\\\\') + arg = arg.replace('"', '\\"') + + return '"%s"' % arg + + + def _simple_command(self, name, *args): + + return self._command_complete(name, self._command(name, *args)) + + + def _untagged_response(self, typ, dat, name): + + if typ == 'NO': + return typ, dat + if not name in self.untagged_responses: + return typ, [None] + data = self.untagged_responses.pop(name) + if __debug__: + if self.debug >= 5: + self._mesg('untagged_responses[%s] => %s' % (name, data)) + return typ, data + + + if __debug__: + + def _mesg(self, s, secs=None): + if secs is None: + secs = time.time() + tm = time.strftime('%M:%S', time.localtime(secs)) + sys.stderr.write(' %s.%02d %s\n' % (tm, (secs*100)%100, s)) + sys.stderr.flush() + + def _dump_ur(self, dict): + # Dump untagged responses (in `dict'). + l = dict.items() + if not l: return + t = '\n\t\t' + l = map(lambda x:'%s: "%s"' % (x[0], x[1][0] and '" "'.join(x[1]) or ''), l) + self._mesg('untagged responses dump:%s%s' % (t, t.join(l))) + + def _log(self, line): + # Keep log of last `_cmd_log_len' interactions for debugging. + self._cmd_log[self._cmd_log_idx] = (line, time.time()) + self._cmd_log_idx += 1 + if self._cmd_log_idx >= self._cmd_log_len: + self._cmd_log_idx = 0 + + def print_log(self): + self._mesg('last %d IMAP4 interactions:' % len(self._cmd_log)) + i, n = self._cmd_log_idx, self._cmd_log_len + while n: + try: + self._mesg(*self._cmd_log[i]) + except: + pass + i += 1 + if i >= self._cmd_log_len: + i = 0 + n -= 1 + + + +try: + import ssl +except ImportError: + pass +else: + class IMAP4_SSL(IMAP4): + + """IMAP4 client class over SSL connection + + Instantiate with: IMAP4_SSL([host[, port[, keyfile[, certfile]]]]) + + host - host's name (default: localhost); + port - port number (default: standard IMAP4 SSL port). + keyfile - PEM formatted file that contains your private key (default: None); + certfile - PEM formatted certificate chain file (default: None); + + for more documentation see the docstring of the parent class IMAP4. + """ + + + def __init__(self, host = '', port = IMAP4_SSL_PORT, keyfile = None, certfile = None): + self.keyfile = keyfile + self.certfile = certfile + IMAP4.__init__(self, host, port) + + + def open(self, host = '', port = IMAP4_SSL_PORT): + """Setup connection to remote server on "host:port". + (default: localhost:standard IMAP4 SSL port). + This connection will be used by the routines: + read, readline, send, shutdown. + """ + self.host = host + self.port = port + self.sock = socket.create_connection((host, port)) + self.sslobj = ssl.wrap_socket(self.sock, self.keyfile, self.certfile) + self.file = self.sslobj.makefile('rb') + + + def read(self, size): + """Read 'size' bytes from remote.""" + return self.file.read(size) + + + def readline(self): + """Read line from remote.""" + return self.file.readline() + + + def send(self, data): + """Send data to remote.""" + bytes = len(data) + while bytes > 0: + sent = self.sslobj.write(data) + if sent == bytes: + break # avoid copy + data = data[sent:] + bytes = bytes - sent + + + def shutdown(self): + """Close I/O established in "open".""" + self.file.close() + self.sock.close() + + + def socket(self): + """Return socket instance used to connect to IMAP4 server. + + socket = .socket() + """ + return self.sock + + + def ssl(self): + """Return SSLObject instance used to communicate with the IMAP4 server. + + ssl = ssl.wrap_socket(.socket) + """ + return self.sslobj + + __all__.append("IMAP4_SSL") + + +class IMAP4_stream(IMAP4): + + """IMAP4 client class over a stream + + Instantiate with: IMAP4_stream(command) + + where "command" is a string that can be passed to subprocess.Popen() + + for more documentation see the docstring of the parent class IMAP4. + """ + + + def __init__(self, command): + self.command = command + IMAP4.__init__(self) + + + def open(self, host = None, port = None): + """Setup a stream connection. + This connection will be used by the routines: + read, readline, send, shutdown. + """ + self.host = None # For compatibility with parent class + self.port = None + self.sock = None + self.file = None + self.process = subprocess.Popen(self.command, + stdin=subprocess.PIPE, stdout=subprocess.PIPE, + shell=True, close_fds=True) + self.writefile = self.process.stdin + self.readfile = self.process.stdout + + + def read(self, size): + """Read 'size' bytes from remote.""" + return self.readfile.read(size) + + + def readline(self): + """Read line from remote.""" + return self.readfile.readline() + + + def send(self, data): + """Send data to remote.""" + self.writefile.write(data) + self.writefile.flush() + + + def shutdown(self): + """Close I/O established in "open".""" + self.readfile.close() + self.writefile.close() + self.process.wait() + + + +class _Authenticator: + + """Private class to provide en/decoding + for base64-based authentication conversation. + """ + + def __init__(self, mechinst): + self.mech = mechinst # Callable object to provide/process data + + def process(self, data): + ret = self.mech(self.decode(data)) + if ret is None: + return '*' # Abort conversation + return self.encode(ret) + + def encode(self, inp): + # + # Invoke binascii.b2a_base64 iteratively with + # short even length buffers, strip the trailing + # line feed from the result and append. "Even" + # means a number that factors to both 6 and 8, + # so when it gets to the end of the 8-bit input + # there's no partial 6-bit output. + # + oup = '' + while inp: + if len(inp) > 48: + t = inp[:48] + inp = inp[48:] + else: + t = inp + inp = '' + e = binascii.b2a_base64(t) + if e: + oup = oup + e[:-1] + return oup + + def decode(self, inp): + if not inp: + return '' + return binascii.a2b_base64(inp) + + + +Mon2num = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6, + 'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12} + +def Internaldate2tuple(resp): + """Parse an IMAP4 INTERNALDATE string. + + Return corresponding local time. The return value is a + time.struct_time instance or None if the string has wrong format. + """ + + mo = InternalDate.match(resp) + if not mo: + return None + + mon = Mon2num[mo.group('mon')] + zonen = mo.group('zonen') + + day = int(mo.group('day')) + year = int(mo.group('year')) + hour = int(mo.group('hour')) + min = int(mo.group('min')) + sec = int(mo.group('sec')) + zoneh = int(mo.group('zoneh')) + zonem = int(mo.group('zonem')) + + # INTERNALDATE timezone must be subtracted to get UT + + zone = (zoneh*60 + zonem)*60 + if zonen == '-': + zone = -zone + + tt = (year, mon, day, hour, min, sec, -1, -1, -1) + + utc = time.mktime(tt) + + # Following is necessary because the time module has no 'mkgmtime'. + # 'mktime' assumes arg in local timezone, so adds timezone/altzone. + + lt = time.localtime(utc) + if time.daylight and lt[-1]: + zone = zone + time.altzone + else: + zone = zone + time.timezone + + return time.localtime(utc - zone) + + + +def Int2AP(num): + + """Convert integer to A-P string representation.""" + + val = ''; AP = 'ABCDEFGHIJKLMNOP' + num = int(abs(num)) + while num: + num, mod = divmod(num, 16) + val = AP[mod] + val + return val + + + +def ParseFlags(resp): + + """Convert IMAP4 flags response to python tuple.""" + + mo = Flags.match(resp) + if not mo: + return () + + return tuple(mo.group('flags').split()) + + +def Time2Internaldate(date_time): + + """Convert date_time to IMAP4 INTERNALDATE representation. + + Return string in form: '"DD-Mmm-YYYY HH:MM:SS +HHMM"'. The + date_time argument can be a number (int or float) representing + seconds since epoch (as returned by time.time()), a 9-tuple + representing local time (as returned by time.localtime()), or a + double-quoted string. In the last case, it is assumed to already + be in the correct format. + """ + + if isinstance(date_time, (int, float)): + tt = time.localtime(date_time) + elif isinstance(date_time, (tuple, time.struct_time)): + tt = date_time + elif isinstance(date_time, str) and (date_time[0],date_time[-1]) == ('"','"'): + return date_time # Assume in correct format + else: + raise ValueError("date_time not of a known type") + + dt = time.strftime("%d-%b-%Y %H:%M:%S", tt) + if dt[0] == '0': + dt = ' ' + dt[1:] + if time.daylight and tt[-1]: + zone = -time.altzone + else: + zone = -time.timezone + return '"' + dt + " %+03d%02d" % divmod(zone//60, 60) + '"' + + + +if __name__ == '__main__': + + # To test: invoke either as 'python imaplib.py [IMAP4_server_hostname]' + # or 'python imaplib.py -s "rsh IMAP4_server_hostname exec /etc/rimapd"' + # to test the IMAP4_stream class + + import getopt, getpass + + try: + optlist, args = getopt.getopt(sys.argv[1:], 'd:s:') + except getopt.error, val: + optlist, args = (), () + + stream_command = None + for opt,val in optlist: + if opt == '-d': + Debug = int(val) + elif opt == '-s': + stream_command = val + if not args: args = (stream_command,) + + if not args: args = ('',) + + host = args[0] + + USER = getpass.getuser() + PASSWD = getpass.getpass("IMAP password for %s on %s: " % (USER, host or "localhost")) + + test_mesg = 'From: %(user)s@localhost%(lf)sSubject: IMAP4 test%(lf)s%(lf)sdata...%(lf)s' % {'user':USER, 'lf':'\n'} + test_seq1 = ( + ('login', (USER, PASSWD)), + ('create', ('/tmp/xxx 1',)), + ('rename', ('/tmp/xxx 1', '/tmp/yyy')), + ('CREATE', ('/tmp/yyz 2',)), + ('append', ('/tmp/yyz 2', None, None, test_mesg)), + ('list', ('/tmp', 'yy*')), + ('select', ('/tmp/yyz 2',)), + ('search', (None, 'SUBJECT', 'test')), + ('fetch', ('1', '(FLAGS INTERNALDATE RFC822)')), + ('store', ('1', 'FLAGS', '(\Deleted)')), + ('namespace', ()), + ('expunge', ()), + ('recent', ()), + ('close', ()), + ) + + test_seq2 = ( + ('select', ()), + ('response',('UIDVALIDITY',)), + ('uid', ('SEARCH', 'ALL')), + ('response', ('EXISTS',)), + ('append', (None, None, None, test_mesg)), + ('recent', ()), + ('logout', ()), + ) + + def run(cmd, args): + M._mesg('%s %s' % (cmd, args)) + typ, dat = getattr(M, cmd)(*args) + M._mesg('%s => %s %s' % (cmd, typ, dat)) + if typ == 'NO': raise dat[0] + return dat + + try: + if stream_command: + M = IMAP4_stream(stream_command) + else: + M = IMAP4(host) + if M.state == 'AUTH': + test_seq1 = test_seq1[1:] # Login not needed + M._mesg('PROTOCOL_VERSION = %s' % M.PROTOCOL_VERSION) + M._mesg('CAPABILITIES = %r' % (M.capabilities,)) + + for cmd,args in test_seq1: + run(cmd, args) + + for ml in run('list', ('/tmp/', 'yy%')): + mo = re.match(r'.*"([^"]+)"$', ml) + if mo: path = mo.group(1) + else: path = ml.split()[-1] + run('delete', (path,)) + + for cmd,args in test_seq2: + dat = run(cmd, args) + + if (cmd,args) != ('uid', ('SEARCH', 'ALL')): + continue + + uid = dat[-1].split() + if not uid: continue + run('uid', ('FETCH', '%s' % uid[-1], + '(FLAGS INTERNALDATE RFC822.SIZE RFC822.HEADER RFC822.TEXT)')) + + print '\nAll tests OK.' + + except: + print '\nTests failed.' + + if not Debug: + print ''' +If you would like to see debugging output, +try: %s -d5 +''' % sys.argv[0] + + raise diff --git a/PythonHome/Lib/imaplib.pyc b/PythonHome/Lib/imaplib.pyc deleted file mode 100644 index 3e5bae5dd7bae1be39b52c12b0d37297381041a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43871 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 3 and \ + h[0] == 'P' and h[1] in '14' and h[2] in ' \t\n\r': + return 'pbm' + +tests.append(test_pbm) + +def test_pgm(h, f): + """PGM (portable graymap)""" + if len(h) >= 3 and \ + h[0] == 'P' and h[1] in '25' and h[2] in ' \t\n\r': + return 'pgm' + +tests.append(test_pgm) + +def test_ppm(h, f): + """PPM (portable pixmap)""" + if len(h) >= 3 and \ + h[0] == 'P' and h[1] in '36' and h[2] in ' \t\n\r': + return 'ppm' + +tests.append(test_ppm) + +def test_rast(h, f): + """Sun raster file""" + if h[:4] == '\x59\xA6\x6A\x95': + return 'rast' + +tests.append(test_rast) + +def test_xbm(h, f): + """X bitmap (X10 or X11)""" + s = '#define ' + if h[:len(s)] == s: + return 'xbm' + +tests.append(test_xbm) + +def test_bmp(h, f): + if h[:2] == 'BM': + return 'bmp' + +tests.append(test_bmp) + +#--------------------# +# Small test program # +#--------------------# + +def test(): + import sys + recursive = 0 + if sys.argv[1:] and sys.argv[1] == '-r': + del sys.argv[1:2] + recursive = 1 + try: + if sys.argv[1:]: + testall(sys.argv[1:], recursive, 1) + else: + testall(['.'], recursive, 1) + except KeyboardInterrupt: + sys.stderr.write('\n[Interrupted]\n') + sys.exit(1) + +def testall(list, recursive, toplevel): + import sys + import os + for filename in list: + if os.path.isdir(filename): + print filename + '/:', + if recursive or toplevel: + print 'recursing down:' + import glob + names = glob.glob(os.path.join(filename, '*')) + testall(names, recursive, 0) + else: + print '*** directory (use -r) ***' + else: + print filename + ':', + sys.stdout.flush() + try: + print what(filename) + except IOError: + print '*** not found ***' diff --git a/PythonHome/Lib/imghdr.pyc b/PythonHome/Lib/imghdr.pyc deleted file mode 100644 index 7c747835272595eb73c7f62421c2d3438b5aeddc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4598 zcmcgvTXP)66+W|<*^9N7EfI_jL_@fErHU1l05&e-B-rv=25nTcR7rqc%Ir?>s#m)+ z>+X@IrKBf#NfmkIFXTN%6_qM}Me@ks$PY-qb7p5H3Sm=%u+p6AKHYuh^mi_OI{%+q z^`D!6X?1Aw%i;Y;JoXO`QAqR=s6#!6K5{6$NMVjXLpx7B3>7HM(`RTDNfoH?k}A@t z4mn{#xTTC+O1VYhmNRZS<+{SHWZX*1EeW@pajPk}EZlP$_gu=Y2zMsq&ZOL`aBCU2 zmU7Pt_k6}ZpK@n}JDYK5Q*KST7c%aJlzU#d7c=g~lshZjISMaGW1g{U)#n(^rKCi69xl*Pfe!JHPsw+VigZ{cv(L2kXrDGWp$>-3 zKjecjH<1GYTVS{9d8pomf<&gRJ-q4_5ZP-pj#N@bPg@AyXMxq7-X;`IplOoH*0xPY~AhxQ`=*bK=06-$z5!y}4Xb<8}kmxuPwURDSgLcZ+ z@ggC17Omw6@9XvhJ?!m-W_dLBd6adx9=9CV$vZR7EdJ(l{J!ASKwW1h=hAscY{3GHZ!%@_w7T%o3RVb)(s+Rj*XVA4XB{44ASQ_Qh>1Utzfd zDSYF*{%}$=mv&vzEOUkuue}1&fcfiJZ(R3+DD!p1c{nDf#mJuWs?2QwS{RPOzyX#(k6q_Vy<4|ksWEhMVHRm^thmRu6 z(M-iuD{rKG=LqmB)mj==?P0SnQ+VA#MX87W(3CYrVbmVJ4*{0lpK^1~>&F2$wb=gy zhiCD*jmAkFdL|fu8wmebm~@Q8Z{Iu(hu#DS|5Z#rD+s;e2Uz{HgCNeZaT0`)K6oMq zzkBO63`Rc%2BYDFr(tk1(|+p=n1(JN_pQCiGl5MMS7rmH*>5EueE9eN7m{^&^enME zO*1SY%*0Y|l0-QY__@s^uYe$Cxp+&XSc*3fhKELXs9$R8-5{h1ZYvpy$ zqFXB~i*la59ICF4lqZpQkVRhVas0vKN^!tj^prBT&#+O^vf43?zRh?fE#e9acP^YBaJ3kuN0xv3i5ngDK&E;V2U`<`4^ z{>A_|?oH$s=m@tTm+dfFEY}>k0q#!c`+{`KBy+r1A2YYr$Zb#x!YkyufCN^~mOb*6@wu%3H zUMQ@1G*FM#K)&t&DPwcWje?=_?=Xi$mU~Z0Nuti@m}~jSWjC6ECETK zxiWZpT+M1uv;GXGiI&^jVcgl?p0p7F+uJ?^A^Y&zo&9;9%dQuUa03l}PPYCfCVZ9i z7nr=n|^v%Lx8<|^*YbD+gq V`V=PbtnZ?qJE`*>)G( z8|xGJG(L?l;RERZWJU}1LLA81Y?AZO`S>OLvC#Xr@o_Dq_6zX)1jF8d$%!^$1?2%1 zf;KS;=?fMEUdcQ31&bY?uk~lx=_bt6G~25y<773Edc?CrZ%5568CChXP;y|Zk-QsC zBK;HJn=FJM3v@A_Vc4%Qj_3$C3OWhMUM1(lI1%(&P>J1uck%Z)q{$k&kd6>i$Wfhy z^!&qPI_}VPnGfwE#2L!FbQJO)95(hJQU`*2Ju;t22*Kj#SPkOXdylb^&$2Uou1(ipR^E0~4)x=)GbhSpU z(jB!b%gRZsoPhoOzEAEP{ti(?Oze|g;dSMKj#jPk*=|i2EwA@iKR;cmoV8&^B zfmYkGw!h8$=9TmDPWs-BjlB#LZN1jpTYrGqN)laamn2a=bqm-}j6xj`RKogPCwmcw zf<>_?=EbrIF&4z7AY(!~4j!JB6HL&dT~8`nXiDyzy?&M$z;PT9;=g?r`E&Ql-Bl{f|%uEW;&i_ zH&)7qsYx@Z%zt9oUe?H8f{z1&CcBI4?Tl0$}Wk)3=l)d6gweyojSs=p5IZ fs#Gykd>VtF{qsF=77v;b9{Fl>g57XFn7i-`7?52F diff --git a/PythonHome/Lib/imputil.py b/PythonHome/Lib/imputil.py new file mode 100644 index 0000000000..a5fa6ea4f7 --- /dev/null +++ b/PythonHome/Lib/imputil.py @@ -0,0 +1,725 @@ +""" +Import utilities + +Exported classes: + ImportManager Manage the import process + + Importer Base class for replacing standard import functions + BuiltinImporter Emulate the import mechanism for builtin and frozen modules + + DynLoadSuffixImporter +""" +from warnings import warnpy3k +warnpy3k("the imputil module has been removed in Python 3.0", stacklevel=2) +del warnpy3k + +# note: avoid importing non-builtin modules +import imp ### not available in Jython? +import sys +import __builtin__ + +# for the DirectoryImporter +import struct +import marshal + +__all__ = ["ImportManager","Importer","BuiltinImporter"] + +_StringType = type('') +_ModuleType = type(sys) ### doesn't work in Jython... + +class ImportManager: + "Manage the import process." + + def install(self, namespace=vars(__builtin__)): + "Install this ImportManager into the specified namespace." + + if isinstance(namespace, _ModuleType): + namespace = vars(namespace) + + # Note: we have no notion of "chaining" + + # Record the previous import hook, then install our own. + self.previous_importer = namespace['__import__'] + self.namespace = namespace + namespace['__import__'] = self._import_hook + + ### fix this + #namespace['reload'] = self._reload_hook + + def uninstall(self): + "Restore the previous import mechanism." + self.namespace['__import__'] = self.previous_importer + + def add_suffix(self, suffix, importFunc): + assert hasattr(importFunc, '__call__') + self.fs_imp.add_suffix(suffix, importFunc) + + ###################################################################### + # + # PRIVATE METHODS + # + + clsFilesystemImporter = None + + def __init__(self, fs_imp=None): + # we're definitely going to be importing something in the future, + # so let's just load the OS-related facilities. + if not _os_stat: + _os_bootstrap() + + # This is the Importer that we use for grabbing stuff from the + # filesystem. It defines one more method (import_from_dir) for our use. + if fs_imp is None: + cls = self.clsFilesystemImporter or _FilesystemImporter + fs_imp = cls() + self.fs_imp = fs_imp + + # Initialize the set of suffixes that we recognize and import. + # The default will import dynamic-load modules first, followed by + # .py files (or a .py file's cached bytecode) + for desc in imp.get_suffixes(): + if desc[2] == imp.C_EXTENSION: + self.add_suffix(desc[0], + DynLoadSuffixImporter(desc).import_file) + self.add_suffix('.py', py_suffix_importer) + + def _import_hook(self, fqname, globals=None, locals=None, fromlist=None): + """Python calls this hook to locate and import a module.""" + + parts = fqname.split('.') + + # determine the context of this import + parent = self._determine_import_context(globals) + + # if there is a parent, then its importer should manage this import + if parent: + module = parent.__importer__._do_import(parent, parts, fromlist) + if module: + return module + + # has the top module already been imported? + try: + top_module = sys.modules[parts[0]] + except KeyError: + + # look for the topmost module + top_module = self._import_top_module(parts[0]) + if not top_module: + # the topmost module wasn't found at all. + raise ImportError, 'No module named ' + fqname + + # fast-path simple imports + if len(parts) == 1: + if not fromlist: + return top_module + + if not top_module.__dict__.get('__ispkg__'): + # __ispkg__ isn't defined (the module was not imported by us), + # or it is zero. + # + # In the former case, there is no way that we could import + # sub-modules that occur in the fromlist (but we can't raise an + # error because it may just be names) because we don't know how + # to deal with packages that were imported by other systems. + # + # In the latter case (__ispkg__ == 0), there can't be any sub- + # modules present, so we can just return. + # + # In both cases, since len(parts) == 1, the top_module is also + # the "bottom" which is the defined return when a fromlist + # exists. + return top_module + + importer = top_module.__dict__.get('__importer__') + if importer: + return importer._finish_import(top_module, parts[1:], fromlist) + + # Grrr, some people "import os.path" or do "from os.path import ..." + if len(parts) == 2 and hasattr(top_module, parts[1]): + if fromlist: + return getattr(top_module, parts[1]) + else: + return top_module + + # If the importer does not exist, then we have to bail. A missing + # importer means that something else imported the module, and we have + # no knowledge of how to get sub-modules out of the thing. + raise ImportError, 'No module named ' + fqname + + def _determine_import_context(self, globals): + """Returns the context in which a module should be imported. + + The context could be a loaded (package) module and the imported module + will be looked for within that package. The context could also be None, + meaning there is no context -- the module should be looked for as a + "top-level" module. + """ + + if not globals or not globals.get('__importer__'): + # globals does not refer to one of our modules or packages. That + # implies there is no relative import context (as far as we are + # concerned), and it should just pick it off the standard path. + return None + + # The globals refer to a module or package of ours. It will define + # the context of the new import. Get the module/package fqname. + parent_fqname = globals['__name__'] + + # if a package is performing the import, then return itself (imports + # refer to pkg contents) + if globals['__ispkg__']: + parent = sys.modules[parent_fqname] + assert globals is parent.__dict__ + return parent + + i = parent_fqname.rfind('.') + + # a module outside of a package has no particular import context + if i == -1: + return None + + # if a module in a package is performing the import, then return the + # package (imports refer to siblings) + parent_fqname = parent_fqname[:i] + parent = sys.modules[parent_fqname] + assert parent.__name__ == parent_fqname + return parent + + def _import_top_module(self, name): + # scan sys.path looking for a location in the filesystem that contains + # the module, or an Importer object that can import the module. + for item in sys.path: + if isinstance(item, _StringType): + module = self.fs_imp.import_from_dir(item, name) + else: + module = item.import_top(name) + if module: + return module + return None + + def _reload_hook(self, module): + "Python calls this hook to reload a module." + + # reloading of a module may or may not be possible (depending on the + # importer), but at least we can validate that it's ours to reload + importer = module.__dict__.get('__importer__') + if not importer: + ### oops. now what... + pass + + # okay. it is using the imputil system, and we must delegate it, but + # we don't know what to do (yet) + ### we should blast the module dict and do another get_code(). need to + ### flesh this out and add proper docco... + raise SystemError, "reload not yet implemented" + + +class Importer: + "Base class for replacing standard import functions." + + def import_top(self, name): + "Import a top-level module." + return self._import_one(None, name, name) + + ###################################################################### + # + # PRIVATE METHODS + # + def _finish_import(self, top, parts, fromlist): + # if "a.b.c" was provided, then load the ".b.c" portion down from + # below the top-level module. + bottom = self._load_tail(top, parts) + + # if the form is "import a.b.c", then return "a" + if not fromlist: + # no fromlist: return the top of the import tree + return top + + # the top module was imported by self. + # + # this means that the bottom module was also imported by self (just + # now, or in the past and we fetched it from sys.modules). + # + # since we imported/handled the bottom module, this means that we can + # also handle its fromlist (and reliably use __ispkg__). + + # if the bottom node is a package, then (potentially) import some + # modules. + # + # note: if it is not a package, then "fromlist" refers to names in + # the bottom module rather than modules. + # note: for a mix of names and modules in the fromlist, we will + # import all modules and insert those into the namespace of + # the package module. Python will pick up all fromlist names + # from the bottom (package) module; some will be modules that + # we imported and stored in the namespace, others are expected + # to be present already. + if bottom.__ispkg__: + self._import_fromlist(bottom, fromlist) + + # if the form is "from a.b import c, d" then return "b" + return bottom + + def _import_one(self, parent, modname, fqname): + "Import a single module." + + # has the module already been imported? + try: + return sys.modules[fqname] + except KeyError: + pass + + # load the module's code, or fetch the module itself + result = self.get_code(parent, modname, fqname) + if result is None: + return None + + module = self._process_result(result, fqname) + + # insert the module into its parent + if parent: + setattr(parent, modname, module) + return module + + def _process_result(self, result, fqname): + ispkg, code, values = result + # did get_code() return an actual module? (rather than a code object) + is_module = isinstance(code, _ModuleType) + + # use the returned module, or create a new one to exec code into + if is_module: + module = code + else: + module = imp.new_module(fqname) + + ### record packages a bit differently?? + module.__importer__ = self + module.__ispkg__ = ispkg + + # insert additional values into the module (before executing the code) + module.__dict__.update(values) + + # the module is almost ready... make it visible + sys.modules[fqname] = module + + # execute the code within the module's namespace + if not is_module: + try: + exec code in module.__dict__ + except: + if fqname in sys.modules: + del sys.modules[fqname] + raise + + # fetch from sys.modules instead of returning module directly. + # also make module's __name__ agree with fqname, in case + # the "exec code in module.__dict__" played games on us. + module = sys.modules[fqname] + module.__name__ = fqname + return module + + def _load_tail(self, m, parts): + """Import the rest of the modules, down from the top-level module. + + Returns the last module in the dotted list of modules. + """ + for part in parts: + fqname = "%s.%s" % (m.__name__, part) + m = self._import_one(m, part, fqname) + if not m: + raise ImportError, "No module named " + fqname + return m + + def _import_fromlist(self, package, fromlist): + 'Import any sub-modules in the "from" list.' + + # if '*' is present in the fromlist, then look for the '__all__' + # variable to find additional items (modules) to import. + if '*' in fromlist: + fromlist = list(fromlist) + \ + list(package.__dict__.get('__all__', [])) + + for sub in fromlist: + # if the name is already present, then don't try to import it (it + # might not be a module!). + if sub != '*' and not hasattr(package, sub): + subname = "%s.%s" % (package.__name__, sub) + submod = self._import_one(package, sub, subname) + if not submod: + raise ImportError, "cannot import name " + subname + + def _do_import(self, parent, parts, fromlist): + """Attempt to import the module relative to parent. + + This method is used when the import context specifies that + imported the parent module. + """ + top_name = parts[0] + top_fqname = parent.__name__ + '.' + top_name + top_module = self._import_one(parent, top_name, top_fqname) + if not top_module: + # this importer and parent could not find the module (relatively) + return None + + return self._finish_import(top_module, parts[1:], fromlist) + + ###################################################################### + # + # METHODS TO OVERRIDE + # + def get_code(self, parent, modname, fqname): + """Find and retrieve the code for the given module. + + parent specifies a parent module to define a context for importing. It + may be None, indicating no particular context for the search. + + modname specifies a single module (not dotted) within the parent. + + fqname specifies the fully-qualified module name. This is a + (potentially) dotted name from the "root" of the module namespace + down to the modname. + If there is no parent, then modname==fqname. + + This method should return None, or a 3-tuple. + + * If the module was not found, then None should be returned. + + * The first item of the 2- or 3-tuple should be the integer 0 or 1, + specifying whether the module that was found is a package or not. + + * The second item is the code object for the module (it will be + executed within the new module's namespace). This item can also + be a fully-loaded module object (e.g. loaded from a shared lib). + + * The third item is a dictionary of name/value pairs that will be + inserted into new module before the code object is executed. This + is provided in case the module's code expects certain values (such + as where the module was found). When the second item is a module + object, then these names/values will be inserted *after* the module + has been loaded/initialized. + """ + raise RuntimeError, "get_code not implemented" + + +###################################################################### +# +# Some handy stuff for the Importers +# + +# byte-compiled file suffix character +_suffix_char = __debug__ and 'c' or 'o' + +# byte-compiled file suffix +_suffix = '.py' + _suffix_char + +def _compile(pathname, timestamp): + """Compile (and cache) a Python source file. + + The file specified by is compiled to a code object and + returned. + + Presuming the appropriate privileges exist, the bytecodes will be + saved back to the filesystem for future imports. The source file's + modification timestamp must be provided as a Long value. + """ + codestring = open(pathname, 'rU').read() + if codestring and codestring[-1] != '\n': + codestring = codestring + '\n' + code = __builtin__.compile(codestring, pathname, 'exec') + + # try to cache the compiled code + try: + f = open(pathname + _suffix_char, 'wb') + except IOError: + pass + else: + f.write('\0\0\0\0') + f.write(struct.pack('= t_py: + f = open(file, 'rb') + if f.read(4) == imp.get_magic(): + t = struct.unpack('>> import foo +# >>> foo +# +# +# ---- revamped import mechanism +# >>> import imputil +# >>> imputil._test_revamp() +# >>> import foo +# >>> foo +# +# +# +# from MAL: +# should BuiltinImporter exist in sys.path or hard-wired in ImportManager? +# need __path__ processing +# performance +# move chaining to a subclass [gjs: it's been nuked] +# deinstall should be possible +# query mechanism needed: is a specific Importer installed? +# py/pyc/pyo piping hooks to filter/process these files +# wish list: +# distutils importer hooked to list of standard Internet repositories +# module->file location mapper to speed FS-based imports +# relative imports +# keep chaining so that it can play nice with other import hooks +# +# from Gordon: +# push MAL's mapper into sys.path[0] as a cache (hard-coded for apps) +# +# from Guido: +# need to change sys.* references for rexec environs +# need hook for MAL's walk-me-up import strategy, or Tim's absolute strategy +# watch out for sys.modules[...] is None +# flag to force absolute imports? (speeds _determine_import_context and +# checking for a relative module) +# insert names of archives into sys.path (see quote below) +# note: reload does NOT blast module dict +# shift import mechanisms and policies around; provide for hooks, overrides +# (see quote below) +# add get_source stuff +# get_topcode and get_subcode +# CRLF handling in _compile +# race condition in _compile +# refactoring of os.py to deal with _os_bootstrap problem +# any special handling to do for importing a module with a SyntaxError? +# (e.g. clean up the traceback) +# implement "domain" for path-type functionality using pkg namespace +# (rather than FS-names like __path__) +# don't use the word "private"... maybe "internal" +# +# +# Guido's comments on sys.path caching: +# +# We could cache this in a dictionary: the ImportManager can have a +# cache dict mapping pathnames to importer objects, and a separate +# method for coming up with an importer given a pathname that's not yet +# in the cache. The method should do a stat and/or look at the +# extension to decide which importer class to use; you can register new +# importer classes by registering a suffix or a Boolean function, plus a +# class. If you register a new importer class, the cache is zapped. +# The cache is independent from sys.path (but maintained per +# ImportManager instance) so that rearrangements of sys.path do the +# right thing. If a path is dropped from sys.path the corresponding +# cache entry is simply no longer used. +# +# My/Guido's comments on factoring ImportManager and Importer: +# +# > However, we still have a tension occurring here: +# > +# > 1) implementing policy in ImportManager assists in single-point policy +# > changes for app/rexec situations +# > 2) implementing policy in Importer assists in package-private policy +# > changes for normal, operating conditions +# > +# > I'll see if I can sort out a way to do this. Maybe the Importer class will +# > implement the methods (which can be overridden to change policy) by +# > delegating to ImportManager. +# +# Maybe also think about what kind of policies an Importer would be +# likely to want to change. I have a feeling that a lot of the code +# there is actually not so much policy but a *necessity* to get things +# working given the calling conventions for the __import__ hook: whether +# to return the head or tail of a dotted name, or when to do the "finish +# fromlist" stuff. +# diff --git a/PythonHome/Lib/imputil.pyc b/PythonHome/Lib/imputil.pyc deleted file mode 100644 index 80e10c2c0d73b5eaaaec8b0f1be1257823177bca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15053 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 diff --git a/PythonHome/Lib/inspect.py b/PythonHome/Lib/inspect.py new file mode 100644 index 0000000000..933694394d --- /dev/null +++ b/PythonHome/Lib/inspect.py @@ -0,0 +1,1059 @@ +# -*- coding: iso-8859-1 -*- +"""Get useful information from live Python objects. + +This module encapsulates the interface provided by the internal special +attributes (func_*, co_*, im_*, tb_*, etc.) in a friendlier fashion. +It also provides some help for examining source code and class layout. + +Here are some of the useful functions provided by this module: + + ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(), + isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(), + isroutine() - check object types + getmembers() - get members of an object that satisfy a given condition + + getfile(), getsourcefile(), getsource() - find an object's source code + getdoc(), getcomments() - get documentation on an object + getmodule() - determine the module that an object came from + getclasstree() - arrange classes so as to represent their hierarchy + + getargspec(), getargvalues(), getcallargs() - get info about function arguments + formatargspec(), formatargvalues() - format an argument spec + getouterframes(), getinnerframes() - get info about frames + currentframe() - get the current stack frame + stack(), trace() - get info about frames on the stack or in a traceback +""" + +# This module is in the public domain. No warranties. + +__author__ = 'Ka-Ping Yee ' +__date__ = '1 Jan 2001' + +import sys +import os +import types +import string +import re +import dis +import imp +import tokenize +import linecache +from operator import attrgetter +from collections import namedtuple + +# These constants are from Include/code.h. +CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 0x1, 0x2, 0x4, 0x8 +CO_NESTED, CO_GENERATOR, CO_NOFREE = 0x10, 0x20, 0x40 +# See Include/object.h +TPFLAGS_IS_ABSTRACT = 1 << 20 + +# ----------------------------------------------------------- type-checking +def ismodule(object): + """Return true if the object is a module. + + Module objects provide these attributes: + __doc__ documentation string + __file__ filename (missing for built-in modules)""" + return isinstance(object, types.ModuleType) + +def isclass(object): + """Return true if the object is a class. + + Class objects provide these attributes: + __doc__ documentation string + __module__ name of module in which this class was defined""" + return isinstance(object, (type, types.ClassType)) + +def ismethod(object): + """Return true if the object is an instance method. + + Instance method objects provide these attributes: + __doc__ documentation string + __name__ name with which this method was defined + im_class class object in which this method belongs + im_func function object containing implementation of method + im_self instance to which this method is bound, or None""" + return isinstance(object, types.MethodType) + +def ismethoddescriptor(object): + """Return true if the object is a method descriptor. + + But not if ismethod() or isclass() or isfunction() are true. + + This is new in Python 2.2, and, for example, is true of int.__add__. + An object passing this test has a __get__ attribute but not a __set__ + attribute, but beyond that the set of attributes varies. __name__ is + usually sensible, and __doc__ often is. + + Methods implemented via descriptors that also pass one of the other + tests return false from the ismethoddescriptor() test, simply because + the other tests promise more -- you can, e.g., count on having the + im_func attribute (etc) when an object passes ismethod().""" + return (hasattr(object, "__get__") + and not hasattr(object, "__set__") # else it's a data descriptor + and not ismethod(object) # mutual exclusion + and not isfunction(object) + and not isclass(object)) + +def isdatadescriptor(object): + """Return true if the object is a data descriptor. + + Data descriptors have both a __get__ and a __set__ attribute. Examples are + properties (defined in Python) and getsets and members (defined in C). + Typically, data descriptors will also have __name__ and __doc__ attributes + (properties, getsets, and members have both of these attributes), but this + is not guaranteed.""" + return (hasattr(object, "__set__") and hasattr(object, "__get__")) + +if hasattr(types, 'MemberDescriptorType'): + # CPython and equivalent + def ismemberdescriptor(object): + """Return true if the object is a member descriptor. + + Member descriptors are specialized descriptors defined in extension + modules.""" + return isinstance(object, types.MemberDescriptorType) +else: + # Other implementations + def ismemberdescriptor(object): + """Return true if the object is a member descriptor. + + Member descriptors are specialized descriptors defined in extension + modules.""" + return False + +if hasattr(types, 'GetSetDescriptorType'): + # CPython and equivalent + def isgetsetdescriptor(object): + """Return true if the object is a getset descriptor. + + getset descriptors are specialized descriptors defined in extension + modules.""" + return isinstance(object, types.GetSetDescriptorType) +else: + # Other implementations + def isgetsetdescriptor(object): + """Return true if the object is a getset descriptor. + + getset descriptors are specialized descriptors defined in extension + modules.""" + return False + +def isfunction(object): + """Return true if the object is a user-defined function. + + Function objects provide these attributes: + __doc__ documentation string + __name__ name with which this function was defined + func_code code object containing compiled function bytecode + func_defaults tuple of any default values for arguments + func_doc (same as __doc__) + func_globals global namespace in which this function was defined + func_name (same as __name__)""" + return isinstance(object, types.FunctionType) + +def isgeneratorfunction(object): + """Return true if the object is a user-defined generator function. + + Generator function objects provides same attributes as functions. + + See help(isfunction) for attributes listing.""" + return bool((isfunction(object) or ismethod(object)) and + object.func_code.co_flags & CO_GENERATOR) + +def isgenerator(object): + """Return true if the object is a generator. + + Generator objects provide these attributes: + __iter__ defined to support iteration over container + close raises a new GeneratorExit exception inside the + generator to terminate the iteration + gi_code code object + gi_frame frame object or possibly None once the generator has + been exhausted + gi_running set to 1 when generator is executing, 0 otherwise + next return the next item from the container + send resumes the generator and "sends" a value that becomes + the result of the current yield-expression + throw used to raise an exception inside the generator""" + return isinstance(object, types.GeneratorType) + +def istraceback(object): + """Return true if the object is a traceback. + + Traceback objects provide these attributes: + tb_frame frame object at this level + tb_lasti index of last attempted instruction in bytecode + tb_lineno current line number in Python source code + tb_next next inner traceback object (called by this level)""" + return isinstance(object, types.TracebackType) + +def isframe(object): + """Return true if the object is a frame object. + + Frame objects provide these attributes: + f_back next outer frame object (this frame's caller) + f_builtins built-in namespace seen by this frame + f_code code object being executed in this frame + f_exc_traceback traceback if raised in this frame, or None + f_exc_type exception type if raised in this frame, or None + f_exc_value exception value if raised in this frame, or None + f_globals global namespace seen by this frame + f_lasti index of last attempted instruction in bytecode + f_lineno current line number in Python source code + f_locals local namespace seen by this frame + f_restricted 0 or 1 if frame is in restricted execution mode + f_trace tracing function for this frame, or None""" + return isinstance(object, types.FrameType) + +def iscode(object): + """Return true if the object is a code object. + + Code objects provide these attributes: + co_argcount number of arguments (not including * or ** args) + co_code string of raw compiled bytecode + co_consts tuple of constants used in the bytecode + co_filename name of file in which this code object was created + co_firstlineno number of first line in Python source code + co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg + co_lnotab encoded mapping of line numbers to bytecode indices + co_name name with which this code object was defined + co_names tuple of names of local variables + co_nlocals number of local variables + co_stacksize virtual machine stack space required + co_varnames tuple of names of arguments and local variables""" + return isinstance(object, types.CodeType) + +def isbuiltin(object): + """Return true if the object is a built-in function or method. + + Built-in functions and methods provide these attributes: + __doc__ documentation string + __name__ original name of this function or method + __self__ instance to which a method is bound, or None""" + return isinstance(object, types.BuiltinFunctionType) + +def isroutine(object): + """Return true if the object is any kind of function or method.""" + return (isbuiltin(object) + or isfunction(object) + or ismethod(object) + or ismethoddescriptor(object)) + +def isabstract(object): + """Return true if the object is an abstract base class (ABC).""" + return bool(isinstance(object, type) and object.__flags__ & TPFLAGS_IS_ABSTRACT) + +def getmembers(object, predicate=None): + """Return all members of an object as (name, value) pairs sorted by name. + Optionally, only return members that satisfy a given predicate.""" + results = [] + for key in dir(object): + try: + value = getattr(object, key) + except AttributeError: + continue + if not predicate or predicate(value): + results.append((key, value)) + results.sort() + return results + +Attribute = namedtuple('Attribute', 'name kind defining_class object') + +def classify_class_attrs(cls): + """Return list of attribute-descriptor tuples. + + For each name in dir(cls), the return list contains a 4-tuple + with these elements: + + 0. The name (a string). + + 1. The kind of attribute this is, one of these strings: + 'class method' created via classmethod() + 'static method' created via staticmethod() + 'property' created via property() + 'method' any other flavor of method + 'data' not a method + + 2. The class which defined this attribute (a class). + + 3. The object as obtained directly from the defining class's + __dict__, not via getattr. This is especially important for + data attributes: C.data is just a data object, but + C.__dict__['data'] may be a data descriptor with additional + info, like a __doc__ string. + """ + + mro = getmro(cls) + names = dir(cls) + result = [] + for name in names: + # Get the object associated with the name, and where it was defined. + # Getting an obj from the __dict__ sometimes reveals more than + # using getattr. Static and class methods are dramatic examples. + # Furthermore, some objects may raise an Exception when fetched with + # getattr(). This is the case with some descriptors (bug #1785). + # Thus, we only use getattr() as a last resort. + homecls = None + for base in (cls,) + mro: + if name in base.__dict__: + obj = base.__dict__[name] + homecls = base + break + else: + obj = getattr(cls, name) + homecls = getattr(obj, "__objclass__", homecls) + + # Classify the object. + if isinstance(obj, staticmethod): + kind = "static method" + elif isinstance(obj, classmethod): + kind = "class method" + elif isinstance(obj, property): + kind = "property" + elif ismethoddescriptor(obj): + kind = "method" + elif isdatadescriptor(obj): + kind = "data" + else: + obj_via_getattr = getattr(cls, name) + if (ismethod(obj_via_getattr) or + ismethoddescriptor(obj_via_getattr)): + kind = "method" + else: + kind = "data" + obj = obj_via_getattr + + result.append(Attribute(name, kind, homecls, obj)) + + return result + +# ----------------------------------------------------------- class helpers +def _searchbases(cls, accum): + # Simulate the "classic class" search order. + if cls in accum: + return + accum.append(cls) + for base in cls.__bases__: + _searchbases(base, accum) + +def getmro(cls): + "Return tuple of base classes (including cls) in method resolution order." + if hasattr(cls, "__mro__"): + return cls.__mro__ + else: + result = [] + _searchbases(cls, result) + return tuple(result) + +# -------------------------------------------------- source code extraction +def indentsize(line): + """Return the indent size, in spaces, at the start of a line of text.""" + expline = string.expandtabs(line) + return len(expline) - len(string.lstrip(expline)) + +def getdoc(object): + """Get the documentation string for an object. + + All tabs are expanded to spaces. To clean up docstrings that are + indented to line up with blocks of code, any whitespace than can be + uniformly removed from the second line onwards is removed.""" + try: + doc = object.__doc__ + except AttributeError: + return None + if not isinstance(doc, types.StringTypes): + return None + return cleandoc(doc) + +def cleandoc(doc): + """Clean up indentation from docstrings. + + Any whitespace that can be uniformly removed from the second line + onwards is removed.""" + try: + lines = string.split(string.expandtabs(doc), '\n') + except UnicodeError: + return None + else: + # Find minimum indentation of any non-blank lines after first line. + margin = sys.maxint + for line in lines[1:]: + content = len(string.lstrip(line)) + if content: + indent = len(line) - content + margin = min(margin, indent) + # Remove indentation. + if lines: + lines[0] = lines[0].lstrip() + if margin < sys.maxint: + for i in range(1, len(lines)): lines[i] = lines[i][margin:] + # Remove any trailing or leading blank lines. + while lines and not lines[-1]: + lines.pop() + while lines and not lines[0]: + lines.pop(0) + return string.join(lines, '\n') + +def getfile(object): + """Work out which source or compiled file an object was defined in.""" + if ismodule(object): + if hasattr(object, '__file__'): + return object.__file__ + raise TypeError('{!r} is a built-in module'.format(object)) + if isclass(object): + object = sys.modules.get(object.__module__) + if hasattr(object, '__file__'): + return object.__file__ + raise TypeError('{!r} is a built-in class'.format(object)) + if ismethod(object): + object = object.im_func + if isfunction(object): + object = object.func_code + if istraceback(object): + object = object.tb_frame + if isframe(object): + object = object.f_code + if iscode(object): + return object.co_filename + raise TypeError('{!r} is not a module, class, method, ' + 'function, traceback, frame, or code object'.format(object)) + +ModuleInfo = namedtuple('ModuleInfo', 'name suffix mode module_type') + +def getmoduleinfo(path): + """Get the module name, suffix, mode, and module type for a given file.""" + filename = os.path.basename(path) + suffixes = map(lambda info: + (-len(info[0]), info[0], info[1], info[2]), + imp.get_suffixes()) + suffixes.sort() # try longest suffixes first, in case they overlap + for neglen, suffix, mode, mtype in suffixes: + if filename[neglen:] == suffix: + return ModuleInfo(filename[:neglen], suffix, mode, mtype) + +def getmodulename(path): + """Return the module name for a given file, or None.""" + info = getmoduleinfo(path) + if info: return info[0] + +def getsourcefile(object): + """Return the filename that can be used to locate an object's source. + Return None if no way can be identified to get the source. + """ + filename = getfile(object) + if string.lower(filename[-4:]) in ('.pyc', '.pyo'): + filename = filename[:-4] + '.py' + for suffix, mode, kind in imp.get_suffixes(): + if 'b' in mode and string.lower(filename[-len(suffix):]) == suffix: + # Looks like a binary file. We want to only return a text file. + return None + if os.path.exists(filename): + return filename + # only return a non-existent filename if the module has a PEP 302 loader + if hasattr(getmodule(object, filename), '__loader__'): + return filename + # or it is in the linecache + if filename in linecache.cache: + return filename + +def getabsfile(object, _filename=None): + """Return an absolute path to the source or compiled file for an object. + + The idea is for each object to have a unique origin, so this routine + normalizes the result as much as possible.""" + if _filename is None: + _filename = getsourcefile(object) or getfile(object) + return os.path.normcase(os.path.abspath(_filename)) + +modulesbyfile = {} +_filesbymodname = {} + +def getmodule(object, _filename=None): + """Return the module an object was defined in, or None if not found.""" + if ismodule(object): + return object + if hasattr(object, '__module__'): + return sys.modules.get(object.__module__) + # Try the filename to modulename cache + if _filename is not None and _filename in modulesbyfile: + return sys.modules.get(modulesbyfile[_filename]) + # Try the cache again with the absolute file name + try: + file = getabsfile(object, _filename) + except TypeError: + return None + if file in modulesbyfile: + return sys.modules.get(modulesbyfile[file]) + # Update the filename to module name cache and check yet again + # Copy sys.modules in order to cope with changes while iterating + for modname, module in sys.modules.items(): + if ismodule(module) and hasattr(module, '__file__'): + f = module.__file__ + if f == _filesbymodname.get(modname, None): + # Have already mapped this module, so skip it + continue + _filesbymodname[modname] = f + f = getabsfile(module) + # Always map to the name the module knows itself by + modulesbyfile[f] = modulesbyfile[ + os.path.realpath(f)] = module.__name__ + if file in modulesbyfile: + return sys.modules.get(modulesbyfile[file]) + # Check the main module + main = sys.modules['__main__'] + if not hasattr(object, '__name__'): + return None + if hasattr(main, object.__name__): + mainobject = getattr(main, object.__name__) + if mainobject is object: + return main + # Check builtins + builtin = sys.modules['__builtin__'] + if hasattr(builtin, object.__name__): + builtinobject = getattr(builtin, object.__name__) + if builtinobject is object: + return builtin + +def findsource(object): + """Return the entire source file and starting line number for an object. + + The argument may be a module, class, method, function, traceback, frame, + or code object. The source code is returned as a list of all the lines + in the file and the line number indexes a line in that list. An IOError + is raised if the source code cannot be retrieved.""" + + file = getfile(object) + sourcefile = getsourcefile(object) + if not sourcefile and file[:1] + file[-1:] != '<>': + raise IOError('source code not available') + file = sourcefile if sourcefile else file + + module = getmodule(object, file) + if module: + lines = linecache.getlines(file, module.__dict__) + else: + lines = linecache.getlines(file) + if not lines: + raise IOError('could not get source code') + + if ismodule(object): + return lines, 0 + + if isclass(object): + name = object.__name__ + pat = re.compile(r'^(\s*)class\s*' + name + r'\b') + # make some effort to find the best matching class definition: + # use the one with the least indentation, which is the one + # that's most probably not inside a function definition. + candidates = [] + for i in range(len(lines)): + match = pat.match(lines[i]) + if match: + # if it's at toplevel, it's already the best one + if lines[i][0] == 'c': + return lines, i + # else add whitespace to candidate list + candidates.append((match.group(1), i)) + if candidates: + # this will sort by whitespace, and by line number, + # less whitespace first + candidates.sort() + return lines, candidates[0][1] + else: + raise IOError('could not find class definition') + + if ismethod(object): + object = object.im_func + if isfunction(object): + object = object.func_code + if istraceback(object): + object = object.tb_frame + if isframe(object): + object = object.f_code + if iscode(object): + if not hasattr(object, 'co_firstlineno'): + raise IOError('could not find function definition') + lnum = object.co_firstlineno - 1 + pat = re.compile(r'^(\s*def\s)|(.*(? 0: + if pat.match(lines[lnum]): break + lnum = lnum - 1 + return lines, lnum + raise IOError('could not find code object') + +def getcomments(object): + """Get lines of comments immediately preceding an object's source code. + + Returns None when source can't be found. + """ + try: + lines, lnum = findsource(object) + except (IOError, TypeError): + return None + + if ismodule(object): + # Look for a comment block at the top of the file. + start = 0 + if lines and lines[0][:2] == '#!': start = 1 + while start < len(lines) and string.strip(lines[start]) in ('', '#'): + start = start + 1 + if start < len(lines) and lines[start][:1] == '#': + comments = [] + end = start + while end < len(lines) and lines[end][:1] == '#': + comments.append(string.expandtabs(lines[end])) + end = end + 1 + return string.join(comments, '') + + # Look for a preceding block of comments at the same indentation. + elif lnum > 0: + indent = indentsize(lines[lnum]) + end = lnum - 1 + if end >= 0 and string.lstrip(lines[end])[:1] == '#' and \ + indentsize(lines[end]) == indent: + comments = [string.lstrip(string.expandtabs(lines[end]))] + if end > 0: + end = end - 1 + comment = string.lstrip(string.expandtabs(lines[end])) + while comment[:1] == '#' and indentsize(lines[end]) == indent: + comments[:0] = [comment] + end = end - 1 + if end < 0: break + comment = string.lstrip(string.expandtabs(lines[end])) + while comments and string.strip(comments[0]) == '#': + comments[:1] = [] + while comments and string.strip(comments[-1]) == '#': + comments[-1:] = [] + return string.join(comments, '') + +class EndOfBlock(Exception): pass + +class BlockFinder: + """Provide a tokeneater() method to detect the end of a code block.""" + def __init__(self): + self.indent = 0 + self.islambda = False + self.started = False + self.passline = False + self.last = 1 + + def tokeneater(self, type, token, srow_scol, erow_ecol, line): + srow, scol = srow_scol + erow, ecol = erow_ecol + if not self.started: + # look for the first "def", "class" or "lambda" + if token in ("def", "class", "lambda"): + if token == "lambda": + self.islambda = True + self.started = True + self.passline = True # skip to the end of the line + elif type == tokenize.NEWLINE: + self.passline = False # stop skipping when a NEWLINE is seen + self.last = srow + if self.islambda: # lambdas always end at the first NEWLINE + raise EndOfBlock + elif self.passline: + pass + elif type == tokenize.INDENT: + self.indent = self.indent + 1 + self.passline = True + elif type == tokenize.DEDENT: + self.indent = self.indent - 1 + # the end of matching indent/dedent pairs end a block + # (note that this only works for "def"/"class" blocks, + # not e.g. for "if: else:" or "try: finally:" blocks) + if self.indent <= 0: + raise EndOfBlock + elif self.indent == 0 and type not in (tokenize.COMMENT, tokenize.NL): + # any other token on the same indentation level end the previous + # block as well, except the pseudo-tokens COMMENT and NL. + raise EndOfBlock + +def getblock(lines): + """Extract the block of code at the top of the given list of lines.""" + blockfinder = BlockFinder() + try: + tokenize.tokenize(iter(lines).next, blockfinder.tokeneater) + except (EndOfBlock, IndentationError): + pass + return lines[:blockfinder.last] + +def getsourcelines(object): + """Return a list of source lines and starting line number for an object. + + The argument may be a module, class, method, function, traceback, frame, + or code object. The source code is returned as a list of the lines + corresponding to the object and the line number indicates where in the + original source file the first line of code was found. An IOError is + raised if the source code cannot be retrieved.""" + lines, lnum = findsource(object) + + if ismodule(object): return lines, 0 + else: return getblock(lines[lnum:]), lnum + 1 + +def getsource(object): + """Return the text of the source code for an object. + + The argument may be a module, class, method, function, traceback, frame, + or code object. The source code is returned as a single string. An + IOError is raised if the source code cannot be retrieved.""" + lines, lnum = getsourcelines(object) + return string.join(lines, '') + +# --------------------------------------------------- class tree extraction +def walktree(classes, children, parent): + """Recursive helper function for getclasstree().""" + results = [] + classes.sort(key=attrgetter('__module__', '__name__')) + for c in classes: + results.append((c, c.__bases__)) + if c in children: + results.append(walktree(children[c], children, c)) + return results + +def getclasstree(classes, unique=0): + """Arrange the given list of classes into a hierarchy of nested lists. + + Where a nested list appears, it contains classes derived from the class + whose entry immediately precedes the list. Each entry is a 2-tuple + containing a class and a tuple of its base classes. If the 'unique' + argument is true, exactly one entry appears in the returned structure + for each class in the given list. Otherwise, classes using multiple + inheritance and their descendants will appear multiple times.""" + children = {} + roots = [] + for c in classes: + if c.__bases__: + for parent in c.__bases__: + if not parent in children: + children[parent] = [] + if c not in children[parent]: + children[parent].append(c) + if unique and parent in classes: break + elif c not in roots: + roots.append(c) + for parent in children: + if parent not in classes: + roots.append(parent) + return walktree(roots, children, None) + +# ------------------------------------------------ argument list extraction +Arguments = namedtuple('Arguments', 'args varargs keywords') + +def getargs(co): + """Get information about the arguments accepted by a code object. + + Three things are returned: (args, varargs, varkw), where 'args' is + a list of argument names (possibly containing nested lists), and + 'varargs' and 'varkw' are the names of the * and ** arguments or None.""" + + if not iscode(co): + raise TypeError('{!r} is not a code object'.format(co)) + + nargs = co.co_argcount + names = co.co_varnames + args = list(names[:nargs]) + step = 0 + + # The following acrobatics are for anonymous (tuple) arguments. + for i in range(nargs): + if args[i][:1] in ('', '.'): + stack, remain, count = [], [], [] + while step < len(co.co_code): + op = ord(co.co_code[step]) + step = step + 1 + if op >= dis.HAVE_ARGUMENT: + opname = dis.opname[op] + value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256 + step = step + 2 + if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'): + remain.append(value) + count.append(value) + elif opname == 'STORE_FAST': + stack.append(names[value]) + + # Special case for sublists of length 1: def foo((bar)) + # doesn't generate the UNPACK_TUPLE bytecode, so if + # `remain` is empty here, we have such a sublist. + if not remain: + stack[0] = [stack[0]] + break + else: + remain[-1] = remain[-1] - 1 + while remain[-1] == 0: + remain.pop() + size = count.pop() + stack[-size:] = [stack[-size:]] + if not remain: break + remain[-1] = remain[-1] - 1 + if not remain: break + args[i] = stack[0] + + varargs = None + if co.co_flags & CO_VARARGS: + varargs = co.co_varnames[nargs] + nargs = nargs + 1 + varkw = None + if co.co_flags & CO_VARKEYWORDS: + varkw = co.co_varnames[nargs] + return Arguments(args, varargs, varkw) + +ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults') + +def getargspec(func): + """Get the names and default values of a function's arguments. + + A tuple of four things is returned: (args, varargs, varkw, defaults). + 'args' is a list of the argument names (it may contain nested lists). + 'varargs' and 'varkw' are the names of the * and ** arguments or None. + 'defaults' is an n-tuple of the default values of the last n arguments. + """ + + if ismethod(func): + func = func.im_func + if not isfunction(func): + raise TypeError('{!r} is not a Python function'.format(func)) + args, varargs, varkw = getargs(func.func_code) + return ArgSpec(args, varargs, varkw, func.func_defaults) + +ArgInfo = namedtuple('ArgInfo', 'args varargs keywords locals') + +def getargvalues(frame): + """Get information about arguments passed into a particular frame. + + A tuple of four things is returned: (args, varargs, varkw, locals). + 'args' is a list of the argument names (it may contain nested lists). + 'varargs' and 'varkw' are the names of the * and ** arguments or None. + 'locals' is the locals dictionary of the given frame.""" + args, varargs, varkw = getargs(frame.f_code) + return ArgInfo(args, varargs, varkw, frame.f_locals) + +def joinseq(seq): + if len(seq) == 1: + return '(' + seq[0] + ',)' + else: + return '(' + string.join(seq, ', ') + ')' + +def strseq(object, convert, join=joinseq): + """Recursively walk a sequence, stringifying each element.""" + if type(object) in (list, tuple): + return join(map(lambda o, c=convert, j=join: strseq(o, c, j), object)) + else: + return convert(object) + +def formatargspec(args, varargs=None, varkw=None, defaults=None, + formatarg=str, + formatvarargs=lambda name: '*' + name, + formatvarkw=lambda name: '**' + name, + formatvalue=lambda value: '=' + repr(value), + join=joinseq): + """Format an argument spec from the 4 values returned by getargspec. + + The first four arguments are (args, varargs, varkw, defaults). The + other four arguments are the corresponding optional formatting functions + that are called to turn names and values into strings. The ninth + argument is an optional function to format the sequence of arguments.""" + specs = [] + if defaults: + firstdefault = len(args) - len(defaults) + for i, arg in enumerate(args): + spec = strseq(arg, formatarg, join) + if defaults and i >= firstdefault: + spec = spec + formatvalue(defaults[i - firstdefault]) + specs.append(spec) + if varargs is not None: + specs.append(formatvarargs(varargs)) + if varkw is not None: + specs.append(formatvarkw(varkw)) + return '(' + string.join(specs, ', ') + ')' + +def formatargvalues(args, varargs, varkw, locals, + formatarg=str, + formatvarargs=lambda name: '*' + name, + formatvarkw=lambda name: '**' + name, + formatvalue=lambda value: '=' + repr(value), + join=joinseq): + """Format an argument spec from the 4 values returned by getargvalues. + + The first four arguments are (args, varargs, varkw, locals). The + next four arguments are the corresponding optional formatting functions + that are called to turn names and values into strings. The ninth + argument is an optional function to format the sequence of arguments.""" + def convert(name, locals=locals, + formatarg=formatarg, formatvalue=formatvalue): + return formatarg(name) + formatvalue(locals[name]) + specs = [] + for i in range(len(args)): + specs.append(strseq(args[i], convert, join)) + if varargs: + specs.append(formatvarargs(varargs) + formatvalue(locals[varargs])) + if varkw: + specs.append(formatvarkw(varkw) + formatvalue(locals[varkw])) + return '(' + string.join(specs, ', ') + ')' + +def getcallargs(func, *positional, **named): + """Get the mapping of arguments to values. + + A dict is returned, with keys the function argument names (including the + names of the * and ** arguments, if any), and values the respective bound + values from 'positional' and 'named'.""" + args, varargs, varkw, defaults = getargspec(func) + f_name = func.__name__ + arg2value = {} + + # The following closures are basically because of tuple parameter unpacking. + assigned_tuple_params = [] + def assign(arg, value): + if isinstance(arg, str): + arg2value[arg] = value + else: + assigned_tuple_params.append(arg) + value = iter(value) + for i, subarg in enumerate(arg): + try: + subvalue = next(value) + except StopIteration: + raise ValueError('need more than %d %s to unpack' % + (i, 'values' if i > 1 else 'value')) + assign(subarg,subvalue) + try: + next(value) + except StopIteration: + pass + else: + raise ValueError('too many values to unpack') + def is_assigned(arg): + if isinstance(arg,str): + return arg in arg2value + return arg in assigned_tuple_params + if ismethod(func) and func.im_self is not None: + # implicit 'self' (or 'cls' for classmethods) argument + positional = (func.im_self,) + positional + num_pos = len(positional) + num_total = num_pos + len(named) + num_args = len(args) + num_defaults = len(defaults) if defaults else 0 + for arg, value in zip(args, positional): + assign(arg, value) + if varargs: + if num_pos > num_args: + assign(varargs, positional[-(num_pos-num_args):]) + else: + assign(varargs, ()) + elif 0 < num_args < num_pos: + raise TypeError('%s() takes %s %d %s (%d given)' % ( + f_name, 'at most' if defaults else 'exactly', num_args, + 'arguments' if num_args > 1 else 'argument', num_total)) + elif num_args == 0 and num_total: + if varkw: + if num_pos: + # XXX: We should use num_pos, but Python also uses num_total: + raise TypeError('%s() takes exactly 0 arguments ' + '(%d given)' % (f_name, num_total)) + else: + raise TypeError('%s() takes no arguments (%d given)' % + (f_name, num_total)) + for arg in args: + if isinstance(arg, str) and arg in named: + if is_assigned(arg): + raise TypeError("%s() got multiple values for keyword " + "argument '%s'" % (f_name, arg)) + else: + assign(arg, named.pop(arg)) + if defaults: # fill in any missing values with the defaults + for arg, value in zip(args[-num_defaults:], defaults): + if not is_assigned(arg): + assign(arg, value) + if varkw: + assign(varkw, named) + elif named: + unexpected = next(iter(named)) + if isinstance(unexpected, unicode): + unexpected = unexpected.encode(sys.getdefaultencoding(), 'replace') + raise TypeError("%s() got an unexpected keyword argument '%s'" % + (f_name, unexpected)) + unassigned = num_args - len([arg for arg in args if is_assigned(arg)]) + if unassigned: + num_required = num_args - num_defaults + raise TypeError('%s() takes %s %d %s (%d given)' % ( + f_name, 'at least' if defaults else 'exactly', num_required, + 'arguments' if num_required > 1 else 'argument', num_total)) + return arg2value + +# -------------------------------------------------- stack frame extraction + +Traceback = namedtuple('Traceback', 'filename lineno function code_context index') + +def getframeinfo(frame, context=1): + """Get information about a frame or traceback object. + + A tuple of five things is returned: the filename, the line number of + the current line, the function name, a list of lines of context from + the source code, and the index of the current line within that list. + The optional second argument specifies the number of lines of context + to return, which are centered around the current line.""" + if istraceback(frame): + lineno = frame.tb_lineno + frame = frame.tb_frame + else: + lineno = frame.f_lineno + if not isframe(frame): + raise TypeError('{!r} is not a frame or traceback object'.format(frame)) + + filename = getsourcefile(frame) or getfile(frame) + if context > 0: + start = lineno - 1 - context//2 + try: + lines, lnum = findsource(frame) + except IOError: + lines = index = None + else: + start = max(start, 1) + start = max(0, min(start, len(lines) - context)) + lines = lines[start:start+context] + index = lineno - 1 - start + else: + lines = index = None + + return Traceback(filename, lineno, frame.f_code.co_name, lines, index) + +def getlineno(frame): + """Get the line number from a frame object, allowing for optimization.""" + # FrameType.f_lineno is now a descriptor that grovels co_lnotab + return frame.f_lineno + +def getouterframes(frame, context=1): + """Get a list of records for a frame and all higher (calling) frames. + + Each record contains a frame object, filename, line number, function + name, a list of lines of context, and index within the context.""" + framelist = [] + while frame: + framelist.append((frame,) + getframeinfo(frame, context)) + frame = frame.f_back + return framelist + +def getinnerframes(tb, context=1): + """Get a list of records for a traceback's frame and all lower frames. + + Each record contains a frame object, filename, line number, function + name, a list of lines of context, and index within the context.""" + framelist = [] + while tb: + framelist.append((tb.tb_frame,) + getframeinfo(tb, context)) + tb = tb.tb_next + return framelist + +if hasattr(sys, '_getframe'): + currentframe = sys._getframe +else: + currentframe = lambda _=None: None + +def stack(context=1): + """Return a list of records for the stack above the caller's frame.""" + return getouterframes(sys._getframe(1), context) + +def trace(context=1): + """Return a list of records for the stack below the current exception.""" + return getinnerframes(sys.exc_info()[2], context) diff --git a/PythonHome/Lib/inspect.pyc b/PythonHome/Lib/inspect.pyc index d3162642a59a8d2643c580af6ab43506c32c79b2..ab0356b8d87d8293bbdde94bcaf53c57351b7eef 100644 GIT binary patch delta 4047 zcmbW3-%C?r7{_;}+ia0wdRCY;3$;Sq63w-&NVZxFZEF*>JhS|9a>Cl0=Nzq!Y_0|_ z=+`q7qUa{2n?QX7p^Pvhf{0e+MGd+rNw4~GQ5RkH{te%&_v*v<`#jJ0d3a~1^|xQ^ zr)6{99-U4n@0R-d)v(qrwZ+cb4hMZl0)Cg|)6_GXD!JuutxxiwQ^T?7q1b6zim-@T z5+Ly1>RLSllBv)p7+FK%!8{007VQ`E*~_9FW_zmGhJm>fBL=RB8!>RrIspU4^+{|r z_e-k;1AA2(#B|Hc=AfCfFVp=D!r`z%-l z{Y~#7tF+bi1{ot|-5W@BKL%L`zxD+OTA(IzX_4ZddVcYzJOfzOR&TvvVy)h*P`BxO zbC};mUkkPZbTgRd8&uZ16S`B>-oAjeos}Q!fV#y-k3SODDtY`T(JP-)4E*hhbSVls zrDenjZ3!h2j?ILeSOLE~RVZpK(lvuAR`hgY;8^b^ERzXEWR>BM2BfpI(JD;T>a{Re z+yOP063QZCmW5R8^F*Us2O>yInhbIN!IKa-HyDMunxP7Q)s7A|W5axK{t6_!V;C!Q zVz?jCW2Or)u)t+6-a`aQ9q|ZeHa~J1`tgt_^$?L|e^bw}I-iVv;yK8qKVv!ImxR*S o79h`o>*Ltn`*C9u0_o1J1mcu7({qShp|=Rf<}(>=nr#!g|3Xihx&QzG delta 1008 zcmbPsf@#wRrVXiF>;eo740n`dyvFv2E?2s-Ed`-Q}y&2nI=!wTL)7+xlI2njJK`)Qap zlh1fcPk!pL1&MFY$hw)u%NK6Yo@DQ795O)w}-DZ{eXt=4HHzllP6iw=#qD`8(5~0^1PHb|> zl*2$bNKCzja04(XCR@!s2-CM&Z`M>qpnaRY6waA^Zf+w?)#Rpm`{C@8`DbD5%_R$_ KAZ)Z=d>a5SBJ#cf diff --git a/PythonHome/Lib/io.py b/PythonHome/Lib/io.py new file mode 100644 index 0000000000..14384930c5 --- /dev/null +++ b/PythonHome/Lib/io.py @@ -0,0 +1,90 @@ +"""The io module provides the Python interfaces to stream handling. The +builtin open function is defined in this module. + +At the top of the I/O hierarchy is the abstract base class IOBase. It +defines the basic interface to a stream. Note, however, that there is no +separation between reading and writing to streams; implementations are +allowed to raise an IOError if they do not support a given operation. + +Extending IOBase is RawIOBase which deals simply with the reading and +writing of raw bytes to a stream. FileIO subclasses RawIOBase to provide +an interface to OS files. + +BufferedIOBase deals with buffering on a raw byte stream (RawIOBase). Its +subclasses, BufferedWriter, BufferedReader, and BufferedRWPair buffer +streams that are readable, writable, and both respectively. +BufferedRandom provides a buffered interface to random access +streams. BytesIO is a simple stream of in-memory bytes. + +Another IOBase subclass, TextIOBase, deals with the encoding and decoding +of streams into text. TextIOWrapper, which extends it, is a buffered text +interface to a buffered raw stream (`BufferedIOBase`). Finally, StringIO +is a in-memory stream for text. + +Argument names are not part of the specification, and only the arguments +of open() are intended to be used as keyword arguments. + +data: + +DEFAULT_BUFFER_SIZE + + An int containing the default buffer size used by the module's buffered + I/O classes. open() uses the file's blksize (as obtained by os.stat) if + possible. +""" +# New I/O library conforming to PEP 3116. + +__author__ = ("Guido van Rossum , " + "Mike Verdone , " + "Mark Russell , " + "Antoine Pitrou , " + "Amaury Forgeot d'Arc , " + "Benjamin Peterson ") + +__all__ = ["BlockingIOError", "open", "IOBase", "RawIOBase", "FileIO", + "BytesIO", "StringIO", "BufferedIOBase", + "BufferedReader", "BufferedWriter", "BufferedRWPair", + "BufferedRandom", "TextIOBase", "TextIOWrapper", + "UnsupportedOperation", "SEEK_SET", "SEEK_CUR", "SEEK_END"] + + +import _io +import abc + +from _io import (DEFAULT_BUFFER_SIZE, BlockingIOError, UnsupportedOperation, + open, FileIO, BytesIO, StringIO, BufferedReader, + BufferedWriter, BufferedRWPair, BufferedRandom, + IncrementalNewlineDecoder, TextIOWrapper) + +OpenWrapper = _io.open # for compatibility with _pyio + +# for seek() +SEEK_SET = 0 +SEEK_CUR = 1 +SEEK_END = 2 + +# Declaring ABCs in C is tricky so we do it here. +# Method descriptions and default implementations are inherited from the C +# version however. +class IOBase(_io._IOBase): + __metaclass__ = abc.ABCMeta + __doc__ = _io._IOBase.__doc__ + +class RawIOBase(_io._RawIOBase, IOBase): + __doc__ = _io._RawIOBase.__doc__ + +class BufferedIOBase(_io._BufferedIOBase, IOBase): + __doc__ = _io._BufferedIOBase.__doc__ + +class TextIOBase(_io._TextIOBase, IOBase): + __doc__ = _io._TextIOBase.__doc__ + +RawIOBase.register(FileIO) + +for klass in (BytesIO, BufferedReader, BufferedWriter, BufferedRandom, + BufferedRWPair): + BufferedIOBase.register(klass) + +for klass in (StringIO, TextIOWrapper): + TextIOBase.register(klass) +del klass diff --git a/PythonHome/Lib/io.pyc b/PythonHome/Lib/io.pyc index 77d175989aaea6e5d63ca1a7d8ebe32275d9b9fa..9f5e35872fa70bc53529e589ffc334abaca265ef 100644 GIT binary patch delta 277 zcmaDYJymwYSuR6!1_p*ytC;l6l8n-%nDG1xJ+EMYzn}o;82{3eg3^*0m(--v^q7Fk ml8pR3kNn)!$#=M#$ is a subset of +JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data +interchange format. + +:mod:`json` exposes an API familiar to users of the standard library +:mod:`marshal` and :mod:`pickle` modules. It is the externally maintained +version of the :mod:`json` library contained in Python 2.6, but maintains +compatibility with Python 2.4 and Python 2.5 and (currently) has +significant performance advantages, even without using the optional C +extension for speedups. + +Encoding basic Python object hierarchies:: + + >>> import json + >>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}]) + '["foo", {"bar": ["baz", null, 1.0, 2]}]' + >>> print json.dumps("\"foo\bar") + "\"foo\bar" + >>> print json.dumps(u'\u1234') + "\u1234" + >>> print json.dumps('\\') + "\\" + >>> print json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True) + {"a": 0, "b": 0, "c": 0} + >>> from StringIO import StringIO + >>> io = StringIO() + >>> json.dump(['streaming API'], io) + >>> io.getvalue() + '["streaming API"]' + +Compact encoding:: + + >>> import json + >>> json.dumps([1,2,3,{'4': 5, '6': 7}], sort_keys=True, separators=(',',':')) + '[1,2,3,{"4":5,"6":7}]' + +Pretty printing:: + + >>> import json + >>> print json.dumps({'4': 5, '6': 7}, sort_keys=True, + ... indent=4, separators=(',', ': ')) + { + "4": 5, + "6": 7 + } + +Decoding JSON:: + + >>> import json + >>> obj = [u'foo', {u'bar': [u'baz', None, 1.0, 2]}] + >>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]') == obj + True + >>> json.loads('"\\"foo\\bar"') == u'"foo\x08ar' + True + >>> from StringIO import StringIO + >>> io = StringIO('["streaming API"]') + >>> json.load(io)[0] == 'streaming API' + True + +Specializing JSON object decoding:: + + >>> import json + >>> def as_complex(dct): + ... if '__complex__' in dct: + ... return complex(dct['real'], dct['imag']) + ... return dct + ... + >>> json.loads('{"__complex__": true, "real": 1, "imag": 2}', + ... object_hook=as_complex) + (1+2j) + >>> from decimal import Decimal + >>> json.loads('1.1', parse_float=Decimal) == Decimal('1.1') + True + +Specializing JSON object encoding:: + + >>> import json + >>> def encode_complex(obj): + ... if isinstance(obj, complex): + ... return [obj.real, obj.imag] + ... raise TypeError(repr(o) + " is not JSON serializable") + ... + >>> json.dumps(2 + 1j, default=encode_complex) + '[2.0, 1.0]' + >>> json.JSONEncoder(default=encode_complex).encode(2 + 1j) + '[2.0, 1.0]' + >>> ''.join(json.JSONEncoder(default=encode_complex).iterencode(2 + 1j)) + '[2.0, 1.0]' + + +Using json.tool from the shell to validate and pretty-print:: + + $ echo '{"json":"obj"}' | python -m json.tool + { + "json": "obj" + } + $ echo '{ 1.2:3.4}' | python -m json.tool + Expecting property name enclosed in double quotes: line 1 column 3 (char 2) +""" +__version__ = '2.0.9' +__all__ = [ + 'dump', 'dumps', 'load', 'loads', + 'JSONDecoder', 'JSONEncoder', +] + +__author__ = 'Bob Ippolito ' + +from .decoder import JSONDecoder +from .encoder import JSONEncoder + +_default_encoder = JSONEncoder( + skipkeys=False, + ensure_ascii=True, + check_circular=True, + allow_nan=True, + indent=None, + separators=None, + encoding='utf-8', + default=None, +) + +def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, + allow_nan=True, cls=None, indent=None, separators=None, + encoding='utf-8', default=None, sort_keys=False, **kw): + """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a + ``.write()``-supporting file-like object). + + If ``skipkeys`` is true then ``dict`` keys that are not basic types + (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) + will be skipped instead of raising a ``TypeError``. + + If ``ensure_ascii`` is true (the default), all non-ASCII characters in the + output are escaped with ``\uXXXX`` sequences, and the result is a ``str`` + instance consisting of ASCII characters only. If ``ensure_ascii`` is + ``False``, some chunks written to ``fp`` may be ``unicode`` instances. + This usually happens because the input contains unicode strings or the + ``encoding`` parameter is used. Unless ``fp.write()`` explicitly + understands ``unicode`` (as in ``codecs.getwriter``) this is likely to + cause an error. + + If ``check_circular`` is false, then the circular reference check + for container types will be skipped and a circular reference will + result in an ``OverflowError`` (or worse). + + If ``allow_nan`` is false, then it will be a ``ValueError`` to + serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) + in strict compliance of the JSON specification, instead of using the + JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``). + + If ``indent`` is a non-negative integer, then JSON array elements and + object members will be pretty-printed with that indent level. An indent + level of 0 will only insert newlines. ``None`` is the most compact + representation. Since the default item separator is ``', '``, the + output might include trailing whitespace when ``indent`` is specified. + You can use ``separators=(',', ': ')`` to avoid this. + + If ``separators`` is an ``(item_separator, dict_separator)`` tuple + then it will be used instead of the default ``(', ', ': ')`` separators. + ``(',', ':')`` is the most compact JSON representation. + + ``encoding`` is the character encoding for str instances, default is UTF-8. + + ``default(obj)`` is a function that should return a serializable version + of obj or raise TypeError. The default simply raises TypeError. + + If *sort_keys* is ``True`` (default: ``False``), then the output of + dictionaries will be sorted by key. + + To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the + ``.default()`` method to serialize additional types), specify it with + the ``cls`` kwarg; otherwise ``JSONEncoder`` is used. + + """ + # cached encoder + if (not skipkeys and ensure_ascii and + check_circular and allow_nan and + cls is None and indent is None and separators is None and + encoding == 'utf-8' and default is None and not sort_keys and not kw): + iterable = _default_encoder.iterencode(obj) + else: + if cls is None: + cls = JSONEncoder + iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii, + check_circular=check_circular, allow_nan=allow_nan, indent=indent, + separators=separators, encoding=encoding, + default=default, sort_keys=sort_keys, **kw).iterencode(obj) + # could accelerate with writelines in some versions of Python, at + # a debuggability cost + for chunk in iterable: + fp.write(chunk) + + +def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, + allow_nan=True, cls=None, indent=None, separators=None, + encoding='utf-8', default=None, sort_keys=False, **kw): + """Serialize ``obj`` to a JSON formatted ``str``. + + If ``skipkeys`` is false then ``dict`` keys that are not basic types + (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) + will be skipped instead of raising a ``TypeError``. + + If ``ensure_ascii`` is false, all non-ASCII characters are not escaped, and + the return value may be a ``unicode`` instance. See ``dump`` for details. + + If ``check_circular`` is false, then the circular reference check + for container types will be skipped and a circular reference will + result in an ``OverflowError`` (or worse). + + If ``allow_nan`` is false, then it will be a ``ValueError`` to + serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in + strict compliance of the JSON specification, instead of using the + JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``). + + If ``indent`` is a non-negative integer, then JSON array elements and + object members will be pretty-printed with that indent level. An indent + level of 0 will only insert newlines. ``None`` is the most compact + representation. Since the default item separator is ``', '``, the + output might include trailing whitespace when ``indent`` is specified. + You can use ``separators=(',', ': ')`` to avoid this. + + If ``separators`` is an ``(item_separator, dict_separator)`` tuple + then it will be used instead of the default ``(', ', ': ')`` separators. + ``(',', ':')`` is the most compact JSON representation. + + ``encoding`` is the character encoding for str instances, default is UTF-8. + + ``default(obj)`` is a function that should return a serializable version + of obj or raise TypeError. The default simply raises TypeError. + + If *sort_keys* is ``True`` (default: ``False``), then the output of + dictionaries will be sorted by key. + + To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the + ``.default()`` method to serialize additional types), specify it with + the ``cls`` kwarg; otherwise ``JSONEncoder`` is used. + + """ + # cached encoder + if (not skipkeys and ensure_ascii and + check_circular and allow_nan and + cls is None and indent is None and separators is None and + encoding == 'utf-8' and default is None and not sort_keys and not kw): + return _default_encoder.encode(obj) + if cls is None: + cls = JSONEncoder + return cls( + skipkeys=skipkeys, ensure_ascii=ensure_ascii, + check_circular=check_circular, allow_nan=allow_nan, indent=indent, + separators=separators, encoding=encoding, default=default, + sort_keys=sort_keys, **kw).encode(obj) + + +_default_decoder = JSONDecoder(encoding=None, object_hook=None, + object_pairs_hook=None) + + +def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None, + parse_int=None, parse_constant=None, object_pairs_hook=None, **kw): + """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing + a JSON document) to a Python object. + + If the contents of ``fp`` is encoded with an ASCII based encoding other + than utf-8 (e.g. latin-1), then an appropriate ``encoding`` name must + be specified. Encodings that are not ASCII based (such as UCS-2) are + not allowed, and should be wrapped with + ``codecs.getreader(fp)(encoding)``, or simply decoded to a ``unicode`` + object and passed to ``loads()`` + + ``object_hook`` is an optional function that will be called with the + result of any object literal decode (a ``dict``). The return value of + ``object_hook`` will be used instead of the ``dict``. This feature + can be used to implement custom decoders (e.g. JSON-RPC class hinting). + + ``object_pairs_hook`` is an optional function that will be called with the + result of any object literal decoded with an ordered list of pairs. The + return value of ``object_pairs_hook`` will be used instead of the ``dict``. + This feature can be used to implement custom decoders that rely on the + order that the key and value pairs are decoded (for example, + collections.OrderedDict will remember the order of insertion). If + ``object_hook`` is also defined, the ``object_pairs_hook`` takes priority. + + To use a custom ``JSONDecoder`` subclass, specify it with the ``cls`` + kwarg; otherwise ``JSONDecoder`` is used. + + """ + return loads(fp.read(), + encoding=encoding, cls=cls, object_hook=object_hook, + parse_float=parse_float, parse_int=parse_int, + parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, + **kw) + + +def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, + parse_int=None, parse_constant=None, object_pairs_hook=None, **kw): + """Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON + document) to a Python object. + + If ``s`` is a ``str`` instance and is encoded with an ASCII based encoding + other than utf-8 (e.g. latin-1) then an appropriate ``encoding`` name + must be specified. Encodings that are not ASCII based (such as UCS-2) + are not allowed and should be decoded to ``unicode`` first. + + ``object_hook`` is an optional function that will be called with the + result of any object literal decode (a ``dict``). The return value of + ``object_hook`` will be used instead of the ``dict``. This feature + can be used to implement custom decoders (e.g. JSON-RPC class hinting). + + ``object_pairs_hook`` is an optional function that will be called with the + result of any object literal decoded with an ordered list of pairs. The + return value of ``object_pairs_hook`` will be used instead of the ``dict``. + This feature can be used to implement custom decoders that rely on the + order that the key and value pairs are decoded (for example, + collections.OrderedDict will remember the order of insertion). If + ``object_hook`` is also defined, the ``object_pairs_hook`` takes priority. + + ``parse_float``, if specified, will be called with the string + of every JSON float to be decoded. By default this is equivalent to + float(num_str). This can be used to use another datatype or parser + for JSON floats (e.g. decimal.Decimal). + + ``parse_int``, if specified, will be called with the string + of every JSON int to be decoded. By default this is equivalent to + int(num_str). This can be used to use another datatype or parser + for JSON integers (e.g. float). + + ``parse_constant``, if specified, will be called with one of the + following strings: -Infinity, Infinity, NaN, null, true, false. + This can be used to raise an exception if invalid JSON numbers + are encountered. + + To use a custom ``JSONDecoder`` subclass, specify it with the ``cls`` + kwarg; otherwise ``JSONDecoder`` is used. + + """ + if (cls is None and encoding is None and object_hook is None and + parse_int is None and parse_float is None and + parse_constant is None and object_pairs_hook is None and not kw): + return _default_decoder.decode(s) + if cls is None: + cls = JSONDecoder + if object_hook is not None: + kw['object_hook'] = object_hook + if object_pairs_hook is not None: + kw['object_pairs_hook'] = object_pairs_hook + if parse_float is not None: + kw['parse_float'] = parse_float + if parse_int is not None: + kw['parse_int'] = parse_int + if parse_constant is not None: + kw['parse_constant'] = parse_constant + return cls(encoding=encoding, **kw).decode(s) diff --git a/PythonHome/Lib/json/__init__.pyc b/PythonHome/Lib/json/__init__.pyc index 03736b742c99db33ce02dd285a41e203e6337741..6ef0af96e381b3f8319df073ed80a30904e52df3 100644 GIT binary patch delta 315 zcmaErGbL|>4j-f3W?jC^+=fmJ3=FAOG3l8l8Kp@v;rSJMUcvr;K>^M&{-q@ar6n;g zsY#{jF#(k&8Tol0`MIf+1x&>zt4bLF4G5E(%SoOAn 65535 and \ + 0xd800 <= uni <= 0xdbff and s[end:end + 2] == '\\u': + uni2 = _decode_uXXXX(s, end + 1) + if 0xdc00 <= uni2 <= 0xdfff: + uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00)) + end += 6 + char = unichr(uni) + # Append the unescaped character + _append(char) + return u''.join(chunks), end + + +# Use speedup if available +scanstring = c_scanstring or py_scanstring + +WHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS) +WHITESPACE_STR = ' \t\n\r' + +def JSONObject(s_and_end, encoding, strict, scan_once, object_hook, + object_pairs_hook, _w=WHITESPACE.match, _ws=WHITESPACE_STR): + s, end = s_and_end + pairs = [] + pairs_append = pairs.append + # Use a slice to prevent IndexError from being raised, the following + # check will raise a more specific ValueError if the string is empty + nextchar = s[end:end + 1] + # Normally we expect nextchar == '"' + if nextchar != '"': + if nextchar in _ws: + end = _w(s, end).end() + nextchar = s[end:end + 1] + # Trivial empty object + if nextchar == '}': + if object_pairs_hook is not None: + result = object_pairs_hook(pairs) + return result, end + 1 + pairs = {} + if object_hook is not None: + pairs = object_hook(pairs) + return pairs, end + 1 + elif nextchar != '"': + raise ValueError(errmsg( + "Expecting property name enclosed in double quotes", s, end)) + end += 1 + while True: + key, end = scanstring(s, end, encoding, strict) + + # To skip some function call overhead we optimize the fast paths where + # the JSON key separator is ": " or just ":". + if s[end:end + 1] != ':': + end = _w(s, end).end() + if s[end:end + 1] != ':': + raise ValueError(errmsg("Expecting ':' delimiter", s, end)) + end += 1 + + try: + if s[end] in _ws: + end += 1 + if s[end] in _ws: + end = _w(s, end + 1).end() + except IndexError: + pass + + try: + value, end = scan_once(s, end) + except StopIteration: + raise ValueError(errmsg("Expecting object", s, end)) + pairs_append((key, value)) + + try: + nextchar = s[end] + if nextchar in _ws: + end = _w(s, end + 1).end() + nextchar = s[end] + except IndexError: + nextchar = '' + end += 1 + + if nextchar == '}': + break + elif nextchar != ',': + raise ValueError(errmsg("Expecting ',' delimiter", s, end - 1)) + + try: + nextchar = s[end] + if nextchar in _ws: + end += 1 + nextchar = s[end] + if nextchar in _ws: + end = _w(s, end + 1).end() + nextchar = s[end] + except IndexError: + nextchar = '' + + end += 1 + if nextchar != '"': + raise ValueError(errmsg( + "Expecting property name enclosed in double quotes", s, end - 1)) + if object_pairs_hook is not None: + result = object_pairs_hook(pairs) + return result, end + pairs = dict(pairs) + if object_hook is not None: + pairs = object_hook(pairs) + return pairs, end + +def JSONArray(s_and_end, scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR): + s, end = s_and_end + values = [] + nextchar = s[end:end + 1] + if nextchar in _ws: + end = _w(s, end + 1).end() + nextchar = s[end:end + 1] + # Look-ahead for trivial empty array + if nextchar == ']': + return values, end + 1 + _append = values.append + while True: + try: + value, end = scan_once(s, end) + except StopIteration: + raise ValueError(errmsg("Expecting object", s, end)) + _append(value) + nextchar = s[end:end + 1] + if nextchar in _ws: + end = _w(s, end + 1).end() + nextchar = s[end:end + 1] + end += 1 + if nextchar == ']': + break + elif nextchar != ',': + raise ValueError(errmsg("Expecting ',' delimiter", s, end)) + try: + if s[end] in _ws: + end += 1 + if s[end] in _ws: + end = _w(s, end + 1).end() + except IndexError: + pass + + return values, end + +class JSONDecoder(object): + """Simple JSON decoder + + Performs the following translations in decoding by default: + + +---------------+-------------------+ + | JSON | Python | + +===============+===================+ + | object | dict | + +---------------+-------------------+ + | array | list | + +---------------+-------------------+ + | string | unicode | + +---------------+-------------------+ + | number (int) | int, long | + +---------------+-------------------+ + | number (real) | float | + +---------------+-------------------+ + | true | True | + +---------------+-------------------+ + | false | False | + +---------------+-------------------+ + | null | None | + +---------------+-------------------+ + + It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as + their corresponding ``float`` values, which is outside the JSON spec. + + """ + + def __init__(self, encoding=None, object_hook=None, parse_float=None, + parse_int=None, parse_constant=None, strict=True, + object_pairs_hook=None): + """``encoding`` determines the encoding used to interpret any ``str`` + objects decoded by this instance (utf-8 by default). It has no + effect when decoding ``unicode`` objects. + + Note that currently only encodings that are a superset of ASCII work, + strings of other encodings should be passed in as ``unicode``. + + ``object_hook``, if specified, will be called with the result + of every JSON object decoded and its return value will be used in + place of the given ``dict``. This can be used to provide custom + deserializations (e.g. to support JSON-RPC class hinting). + + ``object_pairs_hook``, if specified will be called with the result of + every JSON object decoded with an ordered list of pairs. The return + value of ``object_pairs_hook`` will be used instead of the ``dict``. + This feature can be used to implement custom decoders that rely on the + order that the key and value pairs are decoded (for example, + collections.OrderedDict will remember the order of insertion). If + ``object_hook`` is also defined, the ``object_pairs_hook`` takes + priority. + + ``parse_float``, if specified, will be called with the string + of every JSON float to be decoded. By default this is equivalent to + float(num_str). This can be used to use another datatype or parser + for JSON floats (e.g. decimal.Decimal). + + ``parse_int``, if specified, will be called with the string + of every JSON int to be decoded. By default this is equivalent to + int(num_str). This can be used to use another datatype or parser + for JSON integers (e.g. float). + + ``parse_constant``, if specified, will be called with one of the + following strings: -Infinity, Infinity, NaN. + This can be used to raise an exception if invalid JSON numbers + are encountered. + + If ``strict`` is false (true is the default), then control + characters will be allowed inside strings. Control characters in + this context are those with character codes in the 0-31 range, + including ``'\\t'`` (tab), ``'\\n'``, ``'\\r'`` and ``'\\0'``. + + """ + self.encoding = encoding + self.object_hook = object_hook + self.object_pairs_hook = object_pairs_hook + self.parse_float = parse_float or float + self.parse_int = parse_int or int + self.parse_constant = parse_constant or _CONSTANTS.__getitem__ + self.strict = strict + self.parse_object = JSONObject + self.parse_array = JSONArray + self.parse_string = scanstring + self.scan_once = scanner.make_scanner(self) + + def decode(self, s, _w=WHITESPACE.match): + """Return the Python representation of ``s`` (a ``str`` or ``unicode`` + instance containing a JSON document) + + """ + obj, end = self.raw_decode(s, idx=_w(s, 0).end()) + end = _w(s, end).end() + if end != len(s): + raise ValueError(errmsg("Extra data", s, end, len(s))) + return obj + + def raw_decode(self, s, idx=0): + """Decode a JSON document from ``s`` (a ``str`` or ``unicode`` + beginning with a JSON document) and return a 2-tuple of the Python + representation and the index in ``s`` where the document ended. + + This can be used to decode a JSON document from a string that may + have extraneous data at the end. + + """ + try: + obj, end = self.scan_once(s, idx) + except StopIteration: + raise ValueError("No JSON object could be decoded") + return obj, end diff --git a/PythonHome/Lib/json/decoder.pyc b/PythonHome/Lib/json/decoder.pyc index 386e699722ffedfe583ea26a4b7d62da47e48170..dde6fe535d8a2c36b78df56180039ee996304a07 100644 GIT binary patch delta 731 zcmZpQo0YgBliARbfq@~_DkeR%B%?GbCOp4F&nwv9FDSq{#=o?rptK~$B{iuuJtm;C zBqKl1BR@BFvVfMzne delta 315 zcmbQ0*c7)RlbK(hfq}u7qj&=DXeGWoP_2R8A|GxX9iO)@aZ0ste6Se^g? diff --git a/PythonHome/Lib/json/encoder.py b/PythonHome/Lib/json/encoder.py new file mode 100644 index 0000000000..f5eeed75f0 --- /dev/null +++ b/PythonHome/Lib/json/encoder.py @@ -0,0 +1,448 @@ +"""Implementation of JSONEncoder +""" +import re + +try: + from _json import encode_basestring_ascii as c_encode_basestring_ascii +except ImportError: + c_encode_basestring_ascii = None +try: + from _json import make_encoder as c_make_encoder +except ImportError: + c_make_encoder = None + +ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]') +ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])') +HAS_UTF8 = re.compile(r'[\x80-\xff]') +ESCAPE_DCT = { + '\\': '\\\\', + '"': '\\"', + '\b': '\\b', + '\f': '\\f', + '\n': '\\n', + '\r': '\\r', + '\t': '\\t', +} +for i in range(0x20): + ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i)) + #ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,)) + +INFINITY = float('inf') +FLOAT_REPR = repr + +def encode_basestring(s): + """Return a JSON representation of a Python string + + """ + def replace(match): + return ESCAPE_DCT[match.group(0)] + return '"' + ESCAPE.sub(replace, s) + '"' + + +def py_encode_basestring_ascii(s): + """Return an ASCII-only JSON representation of a Python string + + """ + if isinstance(s, str) and HAS_UTF8.search(s) is not None: + s = s.decode('utf-8') + def replace(match): + s = match.group(0) + try: + return ESCAPE_DCT[s] + except KeyError: + n = ord(s) + if n < 0x10000: + return '\\u{0:04x}'.format(n) + #return '\\u%04x' % (n,) + else: + # surrogate pair + n -= 0x10000 + s1 = 0xd800 | ((n >> 10) & 0x3ff) + s2 = 0xdc00 | (n & 0x3ff) + return '\\u{0:04x}\\u{1:04x}'.format(s1, s2) + #return '\\u%04x\\u%04x' % (s1, s2) + return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"' + + +encode_basestring_ascii = ( + c_encode_basestring_ascii or py_encode_basestring_ascii) + +class JSONEncoder(object): + """Extensible JSON encoder for Python data structures. + + Supports the following objects and types by default: + + +-------------------+---------------+ + | Python | JSON | + +===================+===============+ + | dict | object | + +-------------------+---------------+ + | list, tuple | array | + +-------------------+---------------+ + | str, unicode | string | + +-------------------+---------------+ + | int, long, float | number | + +-------------------+---------------+ + | True | true | + +-------------------+---------------+ + | False | false | + +-------------------+---------------+ + | None | null | + +-------------------+---------------+ + + To extend this to recognize other objects, subclass and implement a + ``.default()`` method with another method that returns a serializable + object for ``o`` if possible, otherwise it should call the superclass + implementation (to raise ``TypeError``). + + """ + item_separator = ', ' + key_separator = ': ' + def __init__(self, skipkeys=False, ensure_ascii=True, + check_circular=True, allow_nan=True, sort_keys=False, + indent=None, separators=None, encoding='utf-8', default=None): + """Constructor for JSONEncoder, with sensible defaults. + + If skipkeys is false, then it is a TypeError to attempt + encoding of keys that are not str, int, long, float or None. If + skipkeys is True, such items are simply skipped. + + If *ensure_ascii* is true (the default), all non-ASCII + characters in the output are escaped with \uXXXX sequences, + and the results are str instances consisting of ASCII + characters only. If ensure_ascii is False, a result may be a + unicode instance. This usually happens if the input contains + unicode strings or the *encoding* parameter is used. + + If check_circular is true, then lists, dicts, and custom encoded + objects will be checked for circular references during encoding to + prevent an infinite recursion (which would cause an OverflowError). + Otherwise, no such check takes place. + + If allow_nan is true, then NaN, Infinity, and -Infinity will be + encoded as such. This behavior is not JSON specification compliant, + but is consistent with most JavaScript based encoders and decoders. + Otherwise, it will be a ValueError to encode such floats. + + If sort_keys is true, then the output of dictionaries will be + sorted by key; this is useful for regression tests to ensure + that JSON serializations can be compared on a day-to-day basis. + + If indent is a non-negative integer, then JSON array + elements and object members will be pretty-printed with that + indent level. An indent level of 0 will only insert newlines. + None is the most compact representation. Since the default + item separator is ', ', the output might include trailing + whitespace when indent is specified. You can use + separators=(',', ': ') to avoid this. + + If specified, separators should be a (item_separator, key_separator) + tuple. The default is (', ', ': '). To get the most compact JSON + representation you should specify (',', ':') to eliminate whitespace. + + If specified, default is a function that gets called for objects + that can't otherwise be serialized. It should return a JSON encodable + version of the object or raise a ``TypeError``. + + If encoding is not None, then all input strings will be + transformed into unicode using that encoding prior to JSON-encoding. + The default is UTF-8. + + """ + + self.skipkeys = skipkeys + self.ensure_ascii = ensure_ascii + self.check_circular = check_circular + self.allow_nan = allow_nan + self.sort_keys = sort_keys + self.indent = indent + if separators is not None: + self.item_separator, self.key_separator = separators + if default is not None: + self.default = default + self.encoding = encoding + + def default(self, o): + """Implement this method in a subclass such that it returns + a serializable object for ``o``, or calls the base implementation + (to raise a ``TypeError``). + + For example, to support arbitrary iterators, you could + implement default like this:: + + def default(self, o): + try: + iterable = iter(o) + except TypeError: + pass + else: + return list(iterable) + # Let the base class default method raise the TypeError + return JSONEncoder.default(self, o) + + """ + raise TypeError(repr(o) + " is not JSON serializable") + + def encode(self, o): + """Return a JSON string representation of a Python data structure. + + >>> JSONEncoder().encode({"foo": ["bar", "baz"]}) + '{"foo": ["bar", "baz"]}' + + """ + # This is for extremely simple cases and benchmarks. + if isinstance(o, basestring): + if isinstance(o, str): + _encoding = self.encoding + if (_encoding is not None + and not (_encoding == 'utf-8')): + o = o.decode(_encoding) + if self.ensure_ascii: + return encode_basestring_ascii(o) + else: + return encode_basestring(o) + # This doesn't pass the iterator directly to ''.join() because the + # exceptions aren't as detailed. The list call should be roughly + # equivalent to the PySequence_Fast that ''.join() would do. + chunks = self.iterencode(o, _one_shot=True) + if not isinstance(chunks, (list, tuple)): + chunks = list(chunks) + return ''.join(chunks) + + def iterencode(self, o, _one_shot=False): + """Encode the given object and yield each string + representation as available. + + For example:: + + for chunk in JSONEncoder().iterencode(bigobject): + mysocket.write(chunk) + + """ + if self.check_circular: + markers = {} + else: + markers = None + if self.ensure_ascii: + _encoder = encode_basestring_ascii + else: + _encoder = encode_basestring + if self.encoding != 'utf-8': + def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding): + if isinstance(o, str): + o = o.decode(_encoding) + return _orig_encoder(o) + + def floatstr(o, allow_nan=self.allow_nan, + _repr=FLOAT_REPR, _inf=INFINITY, _neginf=-INFINITY): + # Check for specials. Note that this type of test is processor + # and/or platform-specific, so do tests which don't depend on the + # internals. + + if o != o: + text = 'NaN' + elif o == _inf: + text = 'Infinity' + elif o == _neginf: + text = '-Infinity' + else: + return _repr(o) + + if not allow_nan: + raise ValueError( + "Out of range float values are not JSON compliant: " + + repr(o)) + + return text + + + if (_one_shot and c_make_encoder is not None + and self.indent is None and not self.sort_keys): + _iterencode = c_make_encoder( + markers, self.default, _encoder, self.indent, + self.key_separator, self.item_separator, self.sort_keys, + self.skipkeys, self.allow_nan) + else: + _iterencode = _make_iterencode( + markers, self.default, _encoder, self.indent, floatstr, + self.key_separator, self.item_separator, self.sort_keys, + self.skipkeys, _one_shot) + return _iterencode(o, 0) + +def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, + _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot, + ## HACK: hand-optimized bytecode; turn globals into locals + ValueError=ValueError, + basestring=basestring, + dict=dict, + float=float, + id=id, + int=int, + isinstance=isinstance, + list=list, + long=long, + str=str, + tuple=tuple, + ): + + def _iterencode_list(lst, _current_indent_level): + if not lst: + yield '[]' + return + if markers is not None: + markerid = id(lst) + if markerid in markers: + raise ValueError("Circular reference detected") + markers[markerid] = lst + buf = '[' + if _indent is not None: + _current_indent_level += 1 + newline_indent = '\n' + (' ' * (_indent * _current_indent_level)) + separator = _item_separator + newline_indent + buf += newline_indent + else: + newline_indent = None + separator = _item_separator + first = True + for value in lst: + if first: + first = False + else: + buf = separator + if isinstance(value, basestring): + yield buf + _encoder(value) + elif value is None: + yield buf + 'null' + elif value is True: + yield buf + 'true' + elif value is False: + yield buf + 'false' + elif isinstance(value, (int, long)): + yield buf + str(value) + elif isinstance(value, float): + yield buf + _floatstr(value) + else: + yield buf + if isinstance(value, (list, tuple)): + chunks = _iterencode_list(value, _current_indent_level) + elif isinstance(value, dict): + chunks = _iterencode_dict(value, _current_indent_level) + else: + chunks = _iterencode(value, _current_indent_level) + for chunk in chunks: + yield chunk + if newline_indent is not None: + _current_indent_level -= 1 + yield '\n' + (' ' * (_indent * _current_indent_level)) + yield ']' + if markers is not None: + del markers[markerid] + + def _iterencode_dict(dct, _current_indent_level): + if not dct: + yield '{}' + return + if markers is not None: + markerid = id(dct) + if markerid in markers: + raise ValueError("Circular reference detected") + markers[markerid] = dct + yield '{' + if _indent is not None: + _current_indent_level += 1 + newline_indent = '\n' + (' ' * (_indent * _current_indent_level)) + item_separator = _item_separator + newline_indent + yield newline_indent + else: + newline_indent = None + item_separator = _item_separator + first = True + if _sort_keys: + items = sorted(dct.items(), key=lambda kv: kv[0]) + else: + items = dct.iteritems() + for key, value in items: + if isinstance(key, basestring): + pass + # JavaScript is weakly typed for these, so it makes sense to + # also allow them. Many encoders seem to do something like this. + elif isinstance(key, float): + key = _floatstr(key) + elif key is True: + key = 'true' + elif key is False: + key = 'false' + elif key is None: + key = 'null' + elif isinstance(key, (int, long)): + key = str(key) + elif _skipkeys: + continue + else: + raise TypeError("key " + repr(key) + " is not a string") + if first: + first = False + else: + yield item_separator + yield _encoder(key) + yield _key_separator + if isinstance(value, basestring): + yield _encoder(value) + elif value is None: + yield 'null' + elif value is True: + yield 'true' + elif value is False: + yield 'false' + elif isinstance(value, (int, long)): + yield str(value) + elif isinstance(value, float): + yield _floatstr(value) + else: + if isinstance(value, (list, tuple)): + chunks = _iterencode_list(value, _current_indent_level) + elif isinstance(value, dict): + chunks = _iterencode_dict(value, _current_indent_level) + else: + chunks = _iterencode(value, _current_indent_level) + for chunk in chunks: + yield chunk + if newline_indent is not None: + _current_indent_level -= 1 + yield '\n' + (' ' * (_indent * _current_indent_level)) + yield '}' + if markers is not None: + del markers[markerid] + + def _iterencode(o, _current_indent_level): + if isinstance(o, basestring): + yield _encoder(o) + elif o is None: + yield 'null' + elif o is True: + yield 'true' + elif o is False: + yield 'false' + elif isinstance(o, (int, long)): + yield str(o) + elif isinstance(o, float): + yield _floatstr(o) + elif isinstance(o, (list, tuple)): + for chunk in _iterencode_list(o, _current_indent_level): + yield chunk + elif isinstance(o, dict): + for chunk in _iterencode_dict(o, _current_indent_level): + yield chunk + else: + if markers is not None: + markerid = id(o) + if markerid in markers: + raise ValueError("Circular reference detected") + markers[markerid] = o + o = _default(o) + for chunk in _iterencode(o, _current_indent_level): + yield chunk + if markers is not None: + del markers[markerid] + + return _iterencode diff --git a/PythonHome/Lib/json/encoder.pyc b/PythonHome/Lib/json/encoder.pyc index b6e09d0ae6e199fa5aa244983787a9238e7f8ab8..1a7268839ff4f73e83b39b37ba0297f03fa8ce76 100644 GIT binary patch delta 1035 zcmdm)^*c|9`7fP&m()HDl!4d`WgDc?L*so~#hU zNS>c3^DF%$LnkPT43(FYr*rckWpP$AwVG?Hu#lnkpo!Gx7Ts8K0tx8V&8+%=$cY+| TR#hW2a&4_QHYP{wL6Zsq;i_TB delta 453 zcmeyJw=+wK`7^M&{-q@ar6n;g osY#{jF#(k&8Tol0`MIf^1K8LZN!Kt<8 delta 75 zcmeAXS|+&RG$SMX<}-|?Ed25e3=GazF#(k&8Tole=9`Py*cs6UC$D1vh#_`{!vO## CI2E`6 diff --git a/PythonHome/Lib/json/tool.py b/PythonHome/Lib/json/tool.py new file mode 100644 index 0000000000..fc5d74923d --- /dev/null +++ b/PythonHome/Lib/json/tool.py @@ -0,0 +1,40 @@ +r"""Command-line tool to validate and pretty-print JSON + +Usage:: + + $ echo '{"json":"obj"}' | python -m json.tool + { + "json": "obj" + } + $ echo '{ 1.2:3.4}' | python -m json.tool + Expecting property name enclosed in double quotes: line 1 column 3 (char 2) + +""" +import sys +import json + +def main(): + if len(sys.argv) == 1: + infile = sys.stdin + outfile = sys.stdout + elif len(sys.argv) == 2: + infile = open(sys.argv[1], 'rb') + outfile = sys.stdout + elif len(sys.argv) == 3: + infile = open(sys.argv[1], 'rb') + outfile = open(sys.argv[2], 'wb') + else: + raise SystemExit(sys.argv[0] + " [infile [outfile]]") + with infile: + try: + obj = json.load(infile) + except ValueError, e: + raise SystemExit(e) + with outfile: + json.dump(obj, outfile, sort_keys=True, + indent=4, separators=(',', ': ')) + outfile.write('\n') + + +if __name__ == '__main__': + main() diff --git a/PythonHome/Lib/json/tool.pyc b/PythonHome/Lib/json/tool.pyc deleted file mode 100644 index d2e584b19a534e27cca26aee0ceaa6ccb381e1fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1264 zcmaJ>OK%e~5FYQQuO+2G1raB#3PC_L5|2{^2!wh;sE7tA>O;#WHm%cLJM20@L~^0r zk@ye%2mTiaj_{2Wka~bsc6L0EZ$8i1iGM67-?v|PdNg|?d>`Pg9zrOh9Y{ecqFm4p zl&K!kPDCoE&j^S~*GSdqD5CNn>6ng*ghg6Jo#q@vofSlnTv23Jt>?yS>7C0Vp9It|f{2g=aJLy@n>O;C;l+ zx{qdg`~>wQIu0G@&R!3em?l$KjV6NZ*OQS^m_bHH^|TbsWK180yRMPlb|utmo|yfD)|NKFY+3WNkrTB64m??9VJx$Br%Ce z0AdV!AugX)hdMCHTI3c#CF}#v$DSrj&Qotr$>5Jfg^CN($*Uu zluy{J2U(eUS5}x4(T$2rv}MJMq{)k|aPp_-<}wVP%jZDhZv|Wi%gTdym=+9P;n;I2 zXkZe&IAb=H>mXbg8z0Qn&Zj&CM6+!NTDVbRKe`DA1yP-Y*4lewx_ex9k1tmX7mlHd%vkPqbp?XNd9ftwkQZk1 zV$=`|A{MJ+1-1ovmW5wLWSVkjnudReKq5_*>!s-y6WZc#Z8acf!F^@MQ<& diff --git a/PythonHome/Lib/keyword.py b/PythonHome/Lib/keyword.py new file mode 100644 index 0000000000..69794bda8c --- /dev/null +++ b/PythonHome/Lib/keyword.py @@ -0,0 +1,93 @@ +#! /usr/bin/env python + +"""Keywords (from "graminit.c") + +This file is automatically generated; please don't muck it up! + +To update the symbols in this file, 'cd' to the top directory of +the python source tree after building the interpreter and run: + + ./python Lib/keyword.py +""" + +__all__ = ["iskeyword", "kwlist"] + +kwlist = [ +#--start keywords-- + 'and', + 'as', + 'assert', + 'break', + 'class', + 'continue', + 'def', + 'del', + 'elif', + 'else', + 'except', + 'exec', + 'finally', + 'for', + 'from', + 'global', + 'if', + 'import', + 'in', + 'is', + 'lambda', + 'not', + 'or', + 'pass', + 'print', + 'raise', + 'return', + 'try', + 'while', + 'with', + 'yield', +#--end keywords-- + ] + +iskeyword = frozenset(kwlist).__contains__ + +def main(): + import sys, re + + args = sys.argv[1:] + iptfile = args and args[0] or "Python/graminit.c" + if len(args) > 1: optfile = args[1] + else: optfile = "Lib/keyword.py" + + # scan the source file for keywords + fp = open(iptfile) + strprog = re.compile('"([^"]+)"') + lines = [] + for line in fp: + if '{1, "' in line: + match = strprog.search(line) + if match: + lines.append(" '" + match.group(1) + "',\n") + fp.close() + lines.sort() + + # load the output skeleton from the target + fp = open(optfile) + format = fp.readlines() + fp.close() + + # insert the lines of keywords + try: + start = format.index("#--start keywords--\n") + 1 + end = format.index("#--end keywords--\n") + format[start:end] = lines + except ValueError: + sys.stderr.write("target does not contain format markers\n") + sys.exit(1) + + # write the output file + fp = open(optfile, 'w') + fp.write(''.join(format)) + fp.close() + +if __name__ == "__main__": + main() diff --git a/PythonHome/Lib/keyword.pyc b/PythonHome/Lib/keyword.pyc index ab1ea246459fb60d43d312f53139f915c5d15d89..82f48fe5554bb174b19526f28eac3be497bde3a7 100644 GIT binary patch delta 122 zcmZ24@L6C34>KeCW?trF%!W1$3=FAOG3l8l8Kp@v;rSJMUcvr;K>^M&{-q@ar6n;g dsY#{jF#(k&8Tol0`MIf+AF*8|L)RhpTmZrSD*XTe delta 54 vcmew?uwGyT4>Kd{W?trF%=}Ue3=GazF#(k&8Tole=95|2FJg$XapVF3iN_9W diff --git a/PythonHome/Lib/lib-tk/Canvas.py b/PythonHome/Lib/lib-tk/Canvas.py new file mode 100644 index 0000000000..34464ab979 --- /dev/null +++ b/PythonHome/Lib/lib-tk/Canvas.py @@ -0,0 +1,194 @@ +# This module exports classes for the various canvas item types + +# NOTE: This module was an experiment and is now obsolete. +# It's best to use the Tkinter.Canvas class directly. + +from warnings import warnpy3k +warnpy3k("the Canvas module has been removed in Python 3.0", stacklevel=2) +del warnpy3k + +from Tkinter import Canvas, _cnfmerge, _flatten + + +class CanvasItem: + def __init__(self, canvas, itemType, *args, **kw): + self.canvas = canvas + self.id = canvas._create(itemType, args, kw) + if not hasattr(canvas, 'items'): + canvas.items = {} + canvas.items[self.id] = self + def __str__(self): + return str(self.id) + def __repr__(self): + return '<%s, id=%d>' % (self.__class__.__name__, self.id) + def delete(self): + del self.canvas.items[self.id] + self.canvas.delete(self.id) + def __getitem__(self, key): + v = self.canvas.tk.split(self.canvas.tk.call( + self.canvas._w, 'itemconfigure', + self.id, '-' + key)) + return v[4] + cget = __getitem__ + def __setitem__(self, key, value): + self.canvas.itemconfig(self.id, {key: value}) + def keys(self): + if not hasattr(self, '_keys'): + self._keys = map(lambda x, tk=self.canvas.tk: + tk.splitlist(x)[0][1:], + self.canvas.tk.splitlist( + self.canvas._do( + 'itemconfigure', + (self.id,)))) + return self._keys + def has_key(self, key): + return key in self.keys() + def __contains__(self, key): + return key in self.keys() + def addtag(self, tag, option='withtag'): + self.canvas.addtag(tag, option, self.id) + def bbox(self): + x1, y1, x2, y2 = self.canvas.bbox(self.id) + return (x1, y1), (x2, y2) + def bind(self, sequence=None, command=None, add=None): + return self.canvas.tag_bind(self.id, sequence, command, add) + def unbind(self, sequence, funcid=None): + self.canvas.tag_unbind(self.id, sequence, funcid) + def config(self, cnf={}, **kw): + return self.canvas.itemconfig(self.id, _cnfmerge((cnf, kw))) + def coords(self, pts = ()): + flat = () + for x, y in pts: flat = flat + (x, y) + return self.canvas.coords(self.id, *flat) + def dchars(self, first, last=None): + self.canvas.dchars(self.id, first, last) + def dtag(self, ttd): + self.canvas.dtag(self.id, ttd) + def focus(self): + self.canvas.focus(self.id) + def gettags(self): + return self.canvas.gettags(self.id) + def icursor(self, index): + self.canvas.icursor(self.id, index) + def index(self, index): + return self.canvas.index(self.id, index) + def insert(self, beforethis, string): + self.canvas.insert(self.id, beforethis, string) + def lower(self, belowthis=None): + self.canvas.tag_lower(self.id, belowthis) + def move(self, xamount, yamount): + self.canvas.move(self.id, xamount, yamount) + def tkraise(self, abovethis=None): + self.canvas.tag_raise(self.id, abovethis) + raise_ = tkraise # BW compat + def scale(self, xorigin, yorigin, xscale, yscale): + self.canvas.scale(self.id, xorigin, yorigin, xscale, yscale) + def type(self): + return self.canvas.type(self.id) + +class Arc(CanvasItem): + def __init__(self, canvas, *args, **kw): + CanvasItem.__init__(self, canvas, 'arc', *args, **kw) + +class Bitmap(CanvasItem): + def __init__(self, canvas, *args, **kw): + CanvasItem.__init__(self, canvas, 'bitmap', *args, **kw) + +class ImageItem(CanvasItem): + def __init__(self, canvas, *args, **kw): + CanvasItem.__init__(self, canvas, 'image', *args, **kw) + +class Line(CanvasItem): + def __init__(self, canvas, *args, **kw): + CanvasItem.__init__(self, canvas, 'line', *args, **kw) + +class Oval(CanvasItem): + def __init__(self, canvas, *args, **kw): + CanvasItem.__init__(self, canvas, 'oval', *args, **kw) + +class Polygon(CanvasItem): + def __init__(self, canvas, *args, **kw): + CanvasItem.__init__(self, canvas, 'polygon', *args, **kw) + +class Rectangle(CanvasItem): + def __init__(self, canvas, *args, **kw): + CanvasItem.__init__(self, canvas, 'rectangle', *args, **kw) + +# XXX "Text" is taken by the Text widget... +class CanvasText(CanvasItem): + def __init__(self, canvas, *args, **kw): + CanvasItem.__init__(self, canvas, 'text', *args, **kw) + +class Window(CanvasItem): + def __init__(self, canvas, *args, **kw): + CanvasItem.__init__(self, canvas, 'window', *args, **kw) + +class Group: + def __init__(self, canvas, tag=None): + if not tag: + tag = 'Group%d' % id(self) + self.tag = self.id = tag + self.canvas = canvas + self.canvas.dtag(self.tag) + def str(self): + return self.tag + __str__ = str + def _do(self, cmd, *args): + return self.canvas._do(cmd, (self.tag,) + _flatten(args)) + def addtag_above(self, tagOrId): + self._do('addtag', 'above', tagOrId) + def addtag_all(self): + self._do('addtag', 'all') + def addtag_below(self, tagOrId): + self._do('addtag', 'below', tagOrId) + def addtag_closest(self, x, y, halo=None, start=None): + self._do('addtag', 'closest', x, y, halo, start) + def addtag_enclosed(self, x1, y1, x2, y2): + self._do('addtag', 'enclosed', x1, y1, x2, y2) + def addtag_overlapping(self, x1, y1, x2, y2): + self._do('addtag', 'overlapping', x1, y1, x2, y2) + def addtag_withtag(self, tagOrId): + self._do('addtag', 'withtag', tagOrId) + def bbox(self): + return self.canvas._getints(self._do('bbox')) + def bind(self, sequence=None, command=None, add=None): + return self.canvas.tag_bind(self.id, sequence, command, add) + def unbind(self, sequence, funcid=None): + self.canvas.tag_unbind(self.id, sequence, funcid) + def coords(self, *pts): + return self._do('coords', pts) + def dchars(self, first, last=None): + self._do('dchars', first, last) + def delete(self): + self._do('delete') + def dtag(self, tagToDelete=None): + self._do('dtag', tagToDelete) + def focus(self): + self._do('focus') + def gettags(self): + return self.canvas.tk.splitlist(self._do('gettags', self.tag)) + def icursor(self, index): + return self._do('icursor', index) + def index(self, index): + return self.canvas.tk.getint(self._do('index', index)) + def insert(self, beforeThis, string): + self._do('insert', beforeThis, string) + def config(self, cnf={}, **kw): + return self.canvas.itemconfigure(self.tag, _cnfmerge((cnf,kw))) + def lower(self, belowThis=None): + self._do('lower', belowThis) + def move(self, xAmount, yAmount): + self._do('move', xAmount, yAmount) + def tkraise(self, aboveThis=None): + self._do('raise', aboveThis) + lift = tkraise + def scale(self, xOrigin, yOrigin, xScale, yScale): + self._do('scale', xOrigin, yOrigin, xScale, yScale) + def select_adjust(self, index): + self.canvas._do('select', ('adjust', self.tag, index)) + def select_from(self, index): + self.canvas._do('select', ('from', self.tag, index)) + def select_to(self, index): + self.canvas._do('select', ('to', self.tag, index)) + def type(self): + return self._do('type') diff --git a/PythonHome/Lib/lib-tk/Canvas.pyc b/PythonHome/Lib/lib-tk/Canvas.pyc deleted file mode 100644 index cb32fd5d0f6d53ccae437f3459319cf0e9964779..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14364 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 diff --git a/PythonHome/Lib/lib-tk/FileDialog.py b/PythonHome/Lib/lib-tk/FileDialog.py new file mode 100644 index 0000000000..06ce2b9229 --- /dev/null +++ b/PythonHome/Lib/lib-tk/FileDialog.py @@ -0,0 +1,274 @@ +"""File selection dialog classes. + +Classes: + +- FileDialog +- LoadFileDialog +- SaveFileDialog + +""" + +from Tkinter import * +from Dialog import Dialog + +import os +import fnmatch + + +dialogstates = {} + + +class FileDialog: + + """Standard file selection dialog -- no checks on selected file. + + Usage: + + d = FileDialog(master) + fname = d.go(dir_or_file, pattern, default, key) + if fname is None: ...canceled... + else: ...open file... + + All arguments to go() are optional. + + The 'key' argument specifies a key in the global dictionary + 'dialogstates', which keeps track of the values for the directory + and pattern arguments, overriding the values passed in (it does + not keep track of the default argument!). If no key is specified, + the dialog keeps no memory of previous state. Note that memory is + kept even when the dialog is canceled. (All this emulates the + behavior of the Macintosh file selection dialogs.) + + """ + + title = "File Selection Dialog" + + def __init__(self, master, title=None): + if title is None: title = self.title + self.master = master + self.directory = None + + self.top = Toplevel(master) + self.top.title(title) + self.top.iconname(title) + + self.botframe = Frame(self.top) + self.botframe.pack(side=BOTTOM, fill=X) + + self.selection = Entry(self.top) + self.selection.pack(side=BOTTOM, fill=X) + self.selection.bind('', self.ok_event) + + self.filter = Entry(self.top) + self.filter.pack(side=TOP, fill=X) + self.filter.bind('', self.filter_command) + + self.midframe = Frame(self.top) + self.midframe.pack(expand=YES, fill=BOTH) + + self.filesbar = Scrollbar(self.midframe) + self.filesbar.pack(side=RIGHT, fill=Y) + self.files = Listbox(self.midframe, exportselection=0, + yscrollcommand=(self.filesbar, 'set')) + self.files.pack(side=RIGHT, expand=YES, fill=BOTH) + btags = self.files.bindtags() + self.files.bindtags(btags[1:] + btags[:1]) + self.files.bind('', self.files_select_event) + self.files.bind('', self.files_double_event) + self.filesbar.config(command=(self.files, 'yview')) + + self.dirsbar = Scrollbar(self.midframe) + self.dirsbar.pack(side=LEFT, fill=Y) + self.dirs = Listbox(self.midframe, exportselection=0, + yscrollcommand=(self.dirsbar, 'set')) + self.dirs.pack(side=LEFT, expand=YES, fill=BOTH) + self.dirsbar.config(command=(self.dirs, 'yview')) + btags = self.dirs.bindtags() + self.dirs.bindtags(btags[1:] + btags[:1]) + self.dirs.bind('', self.dirs_select_event) + self.dirs.bind('', self.dirs_double_event) + + self.ok_button = Button(self.botframe, + text="OK", + command=self.ok_command) + self.ok_button.pack(side=LEFT) + self.filter_button = Button(self.botframe, + text="Filter", + command=self.filter_command) + self.filter_button.pack(side=LEFT, expand=YES) + self.cancel_button = Button(self.botframe, + text="Cancel", + command=self.cancel_command) + self.cancel_button.pack(side=RIGHT) + + self.top.protocol('WM_DELETE_WINDOW', self.cancel_command) + # XXX Are the following okay for a general audience? + self.top.bind('', self.cancel_command) + self.top.bind('', self.cancel_command) + + def go(self, dir_or_file=os.curdir, pattern="*", default="", key=None): + if key and key in dialogstates: + self.directory, pattern = dialogstates[key] + else: + dir_or_file = os.path.expanduser(dir_or_file) + if os.path.isdir(dir_or_file): + self.directory = dir_or_file + else: + self.directory, default = os.path.split(dir_or_file) + self.set_filter(self.directory, pattern) + self.set_selection(default) + self.filter_command() + self.selection.focus_set() + self.top.wait_visibility() # window needs to be visible for the grab + self.top.grab_set() + self.how = None + self.master.mainloop() # Exited by self.quit(how) + if key: + directory, pattern = self.get_filter() + if self.how: + directory = os.path.dirname(self.how) + dialogstates[key] = directory, pattern + self.top.destroy() + return self.how + + def quit(self, how=None): + self.how = how + self.master.quit() # Exit mainloop() + + def dirs_double_event(self, event): + self.filter_command() + + def dirs_select_event(self, event): + dir, pat = self.get_filter() + subdir = self.dirs.get('active') + dir = os.path.normpath(os.path.join(self.directory, subdir)) + self.set_filter(dir, pat) + + def files_double_event(self, event): + self.ok_command() + + def files_select_event(self, event): + file = self.files.get('active') + self.set_selection(file) + + def ok_event(self, event): + self.ok_command() + + def ok_command(self): + self.quit(self.get_selection()) + + def filter_command(self, event=None): + dir, pat = self.get_filter() + try: + names = os.listdir(dir) + except os.error: + self.master.bell() + return + self.directory = dir + self.set_filter(dir, pat) + names.sort() + subdirs = [os.pardir] + matchingfiles = [] + for name in names: + fullname = os.path.join(dir, name) + if os.path.isdir(fullname): + subdirs.append(name) + elif fnmatch.fnmatch(name, pat): + matchingfiles.append(name) + self.dirs.delete(0, END) + for name in subdirs: + self.dirs.insert(END, name) + self.files.delete(0, END) + for name in matchingfiles: + self.files.insert(END, name) + head, tail = os.path.split(self.get_selection()) + if tail == os.curdir: tail = '' + self.set_selection(tail) + + def get_filter(self): + filter = self.filter.get() + filter = os.path.expanduser(filter) + if filter[-1:] == os.sep or os.path.isdir(filter): + filter = os.path.join(filter, "*") + return os.path.split(filter) + + def get_selection(self): + file = self.selection.get() + file = os.path.expanduser(file) + return file + + def cancel_command(self, event=None): + self.quit() + + def set_filter(self, dir, pat): + if not os.path.isabs(dir): + try: + pwd = os.getcwd() + except os.error: + pwd = None + if pwd: + dir = os.path.join(pwd, dir) + dir = os.path.normpath(dir) + self.filter.delete(0, END) + self.filter.insert(END, os.path.join(dir or os.curdir, pat or "*")) + + def set_selection(self, file): + self.selection.delete(0, END) + self.selection.insert(END, os.path.join(self.directory, file)) + + +class LoadFileDialog(FileDialog): + + """File selection dialog which checks that the file exists.""" + + title = "Load File Selection Dialog" + + def ok_command(self): + file = self.get_selection() + if not os.path.isfile(file): + self.master.bell() + else: + self.quit(file) + + +class SaveFileDialog(FileDialog): + + """File selection dialog which checks that the file may be created.""" + + title = "Save File Selection Dialog" + + def ok_command(self): + file = self.get_selection() + if os.path.exists(file): + if os.path.isdir(file): + self.master.bell() + return + d = Dialog(self.top, + title="Overwrite Existing File Question", + text="Overwrite existing file %r?" % (file,), + bitmap='questhead', + default=1, + strings=("Yes", "Cancel")) + if d.num != 0: + return + else: + head, tail = os.path.split(file) + if not os.path.isdir(head): + self.master.bell() + return + self.quit(file) + + +def test(): + """Simple test program.""" + root = Tk() + root.withdraw() + fd = LoadFileDialog(root) + loadfile = fd.go(key="test") + fd = SaveFileDialog(root) + savefile = fd.go(key="test") + print loadfile, savefile + + +if __name__ == '__main__': + test() diff --git a/PythonHome/Lib/lib-tk/FileDialog.pyc b/PythonHome/Lib/lib-tk/FileDialog.pyc deleted file mode 100644 index b38b60f3abc83411bcfb48025838fd3b8abc8c50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9394 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 V(sid^u9m0&IJ0-=SZz<;`7d0S30D9B diff --git a/PythonHome/Lib/lib-tk/FixTk.py b/PythonHome/Lib/lib-tk/FixTk.py new file mode 100644 index 0000000000..49960c74ca --- /dev/null +++ b/PythonHome/Lib/lib-tk/FixTk.py @@ -0,0 +1,78 @@ +import sys, os + +# Delay import _tkinter until we have set TCL_LIBRARY, +# so that Tcl_FindExecutable has a chance to locate its +# encoding directory. + +# Unfortunately, we cannot know the TCL_LIBRARY directory +# if we don't know the tcl version, which we cannot find out +# without import Tcl. Fortunately, Tcl will itself look in +# \..\tcl, so anything close to +# the real Tcl library will do. + +# Expand symbolic links on Vista +try: + import ctypes + ctypes.windll.kernel32.GetFinalPathNameByHandleW +except (ImportError, AttributeError): + def convert_path(s): + return s +else: + def convert_path(s): + assert isinstance(s, str) # sys.prefix contains only bytes + udir = s.decode("mbcs") + hdir = ctypes.windll.kernel32.\ + CreateFileW(udir, 0x80, # FILE_READ_ATTRIBUTES + 1, # FILE_SHARE_READ + None, 3, # OPEN_EXISTING + 0x02000000, # FILE_FLAG_BACKUP_SEMANTICS + None) + if hdir == -1: + # Cannot open directory, give up + return s + buf = ctypes.create_unicode_buffer(u"", 32768) + res = ctypes.windll.kernel32.\ + GetFinalPathNameByHandleW(hdir, buf, len(buf), + 0) # VOLUME_NAME_DOS + ctypes.windll.kernel32.CloseHandle(hdir) + if res == 0: + # Conversion failed (e.g. network location) + return s + s = buf[:res].encode("mbcs") + # Ignore leading \\?\ + if s.startswith("\\\\?\\"): + s = s[4:] + if s.startswith("UNC"): + s = "\\" + s[3:] + return s + +prefix = os.path.join(sys.prefix,"tcl") +if not os.path.exists(prefix): + # devdir/../tcltk/lib + prefix = os.path.join(sys.prefix, os.path.pardir, "tcltk", "lib") + prefix = os.path.abspath(prefix) +# if this does not exist, no further search is needed +if os.path.exists(prefix): + prefix = convert_path(prefix) + if "TCL_LIBRARY" not in os.environ: + for name in os.listdir(prefix): + if name.startswith("tcl"): + tcldir = os.path.join(prefix,name) + if os.path.isdir(tcldir): + os.environ["TCL_LIBRARY"] = tcldir + # Compute TK_LIBRARY, knowing that it has the same version + # as Tcl + import _tkinter + ver = str(_tkinter.TCL_VERSION) + if "TK_LIBRARY" not in os.environ: + v = os.path.join(prefix, 'tk'+ver) + if os.path.exists(os.path.join(v, "tclIndex")): + os.environ['TK_LIBRARY'] = v + # We don't know the Tix version, so we must search the entire + # directory + if "TIX_LIBRARY" not in os.environ: + for name in os.listdir(prefix): + if name.startswith("tix"): + tixdir = os.path.join(prefix,name) + if os.path.isdir(tixdir): + os.environ["TIX_LIBRARY"] = tixdir diff --git a/PythonHome/Lib/lib-tk/FixTk.pyc b/PythonHome/Lib/lib-tk/FixTk.pyc deleted file mode 100644 index af52d8cdbff8d249f1eae2ffb72e25650d1dde2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1956 zcma)6&2k$>5boKPB}s({2qU~nle*`OelGLm*&p4ECK?~EL| z%C1Ub9*F}Fz&S6$IVT9RsUmnk|vF!IA zQGmaqh^TifE9xn_{5ZSvsOORPDD)}JQMg2^8$YI;&XX?CiAUoSC0$ZV1s?s5ILj25 z=tbZ!4q8!Iq_9MqC|sc+M>mMLLJNJF^a|Z5vVUco%yMB+p{)Kzf}s zP7V|VwyY8`n&$`VT=Bn)looBRQ?E|?A?Z4W8|>8EqyV{z6X)~h9jKs4dXqM|L0cId zs=Dpq76m0vhSA}f+5mkS=x-FmrhQFoZF%plwJc%YzLUVB*6j=vwQh@9(}S?6bp>cm z@BFR8zkA;D7+29@qk@?-|KiskDTvwH!U$t|l0oCIWQ=g_NHH51|JXrsmt-$i5YvRf0 zYH*iQ>8qe3*ExE$aeIH*SVdFX$e8GCII`w71jB7NK5tl_ur`B)cZ2wH5J| ziGwI|%-dKev5vm@9DM_ci5@uJGLh~|=Iu$W9nZ!{E{W z;AnuAXQKbt>~^?ooW0$_Myjr=s;u(LmsM0{FQ?X^sj8w{m(#jeRTZ3TN^smLa-0)C z$7wxgDD@oe?jP^(J?%W{{49hV{cwBacLUbkTlnq8fu5%>doONnxEN>VjSu`E-}NI)1s1ErCa=xiV#jrEX|%K`ozrBzR!(y z=?qK<3HP;t_=BMpFP3$DVUkHK`Uu7u2{E|s@XIf8P#IrvbBtw)vp#lXAnK$eJ>z-e zHvROhbGY}sEoJgogh{zbgP1v78#vS5_MT4>V>Hhu!7S2WaunOdwpsB(VGRUU{NhKO fYR&sp)xDI~hoG_!ino0xxvI9*Cu-fVs!abM-UV^P diff --git a/PythonHome/Lib/lib-tk/ScrolledText.py b/PythonHome/Lib/lib-tk/ScrolledText.py new file mode 100644 index 0000000000..a1ef79ca74 --- /dev/null +++ b/PythonHome/Lib/lib-tk/ScrolledText.py @@ -0,0 +1,55 @@ +"""A ScrolledText widget feels like a text widget but also has a +vertical scroll bar on its right. (Later, options may be added to +add a horizontal bar as well, to make the bars disappear +automatically when not needed, to move them to the other side of the +window, etc.) + +Configuration options are passed to the Text widget. +A Frame widget is inserted between the master and the text, to hold +the Scrollbar widget. +Most methods calls are inherited from the Text widget; Pack, Grid and +Place methods are redirected to the Frame widget however. +""" + +__all__ = ['ScrolledText'] + +from Tkinter import Frame, Text, Scrollbar, Pack, Grid, Place +from Tkconstants import RIGHT, LEFT, Y, BOTH + +class ScrolledText(Text): + def __init__(self, master=None, **kw): + self.frame = Frame(master) + self.vbar = Scrollbar(self.frame) + self.vbar.pack(side=RIGHT, fill=Y) + + kw.update({'yscrollcommand': self.vbar.set}) + Text.__init__(self, self.frame, **kw) + self.pack(side=LEFT, fill=BOTH, expand=True) + self.vbar['command'] = self.yview + + # Copy geometry methods of self.frame without overriding Text + # methods -- hack! + text_meths = vars(Text).keys() + methods = vars(Pack).keys() + vars(Grid).keys() + vars(Place).keys() + methods = set(methods).difference(text_meths) + + for m in methods: + if m[0] != '_' and m != 'config' and m != 'configure': + setattr(self, m, getattr(self.frame, m)) + + def __str__(self): + return str(self.frame) + + +def example(): + import __main__ + from Tkconstants import END + + stext = ScrolledText(bg='white', height=10) + stext.insert(END, __main__.__doc__) + stext.pack(fill=BOTH, side=LEFT, expand=True) + stext.focus_set() + stext.mainloop() + +if __name__ == "__main__": + example() diff --git a/PythonHome/Lib/lib-tk/ScrolledText.pyc b/PythonHome/Lib/lib-tk/ScrolledText.pyc deleted file mode 100644 index 37f29e7599ff3c5bdac8a3859ad4c5f26eed936a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2589 zcma)7OHUj}5U!qG78tk~Q~hDulMeNXG|i^Q9HQ&(eetJ3KrInuj;%`%f|Uxg5G$FQpHZ&m35#TWpe znmpfx0S>?mKQ#Qp>CC!hJT^%kCKF#3iCmu_>FLmvx~#k|jRA6VvO18H1;a2xg{9Wc zW)KIg38%Kqs_CXSKJ9%Th7YT9VD~09U=hZd%SmnYIB`xK7N85c>V^09lR7EPS?;XU zwsc4g%y*5S8aT$67l}h6bW$R0Y&omq<*>@LkTp#qIQ*sxz3^q_ye^C%R+-aCGit)V z*b-q_#vjxbg2UMh4t=A4Ow!S&ep*{(w#>pG^CZRfGZ+S_O=fG8GQun~|A}B&O${pB z3;iH9? zE9hU#_Q4N3&r{o!*l6RM8SAn(n{3-ziSo>>C(32Li=JL6Qw^z=$H+X;b!u|x% z3v}ET)ipY9u>j@aPpo|O^GiCJqho~Ap$(n}Evnzie&K?=IFtRl1T#ne`dLVGbQ;iU zi`1|02!F3K)VLcWsasMfCX)yQo9F%#^heDsNUNei_aTKS+2NQ)F2_u5A(E6k7K>Df zCmqy?liGA|z$W6BkX9Km$s(?=+;;$?h%iQvMGPHr{|VY;oMGsAwspow+z!YQ${yR& z`Z$hw6LAoNuv1TrTyb<@&9p(stPx>kj$Fj;8gau%()xTbvx9-DO_>@A3)dvx*CJzp zvfR*wk2;eN#II%qp!0}EQ!n>}H!)Mw$k^ z_QpriCos5%$KAw2YE@lP8^KL=UENY^?JMezS`SuKSEZaye%OVFc-#sWX2uy6w!8d# zt1CH^1o}F<3YF+1%@UrE^h<(@W9REQ=3|awNo{pGnX{6VC~F)`HsZLbvPsTc&f8X1 z8i_3W47>AdKQbpcL+rU@td3f~ma>Lp;%<@X4BPlQ=bOcHx|QX^)Fa&HAw&f diff --git a/PythonHome/Lib/lib-tk/SimpleDialog.py b/PythonHome/Lib/lib-tk/SimpleDialog.py new file mode 100644 index 0000000000..cb08318dbd --- /dev/null +++ b/PythonHome/Lib/lib-tk/SimpleDialog.py @@ -0,0 +1,112 @@ +"""A simple but flexible modal dialog box.""" + + +from Tkinter import * + + +class SimpleDialog: + + def __init__(self, master, + text='', buttons=[], default=None, cancel=None, + title=None, class_=None): + if class_: + self.root = Toplevel(master, class_=class_) + else: + self.root = Toplevel(master) + if title: + self.root.title(title) + self.root.iconname(title) + self.message = Message(self.root, text=text, aspect=400) + self.message.pack(expand=1, fill=BOTH) + self.frame = Frame(self.root) + self.frame.pack() + self.num = default + self.cancel = cancel + self.default = default + self.root.bind('', self.return_event) + for num in range(len(buttons)): + s = buttons[num] + b = Button(self.frame, text=s, + command=(lambda self=self, num=num: self.done(num))) + if num == default: + b.config(relief=RIDGE, borderwidth=8) + b.pack(side=LEFT, fill=BOTH, expand=1) + self.root.protocol('WM_DELETE_WINDOW', self.wm_delete_window) + self._set_transient(master) + + def _set_transient(self, master, relx=0.5, rely=0.3): + widget = self.root + widget.withdraw() # Remain invisible while we figure out the geometry + widget.transient(master) + widget.update_idletasks() # Actualize geometry information + if master.winfo_ismapped(): + m_width = master.winfo_width() + m_height = master.winfo_height() + m_x = master.winfo_rootx() + m_y = master.winfo_rooty() + else: + m_width = master.winfo_screenwidth() + m_height = master.winfo_screenheight() + m_x = m_y = 0 + w_width = widget.winfo_reqwidth() + w_height = widget.winfo_reqheight() + x = m_x + (m_width - w_width) * relx + y = m_y + (m_height - w_height) * rely + if x+w_width > master.winfo_screenwidth(): + x = master.winfo_screenwidth() - w_width + elif x < 0: + x = 0 + if y+w_height > master.winfo_screenheight(): + y = master.winfo_screenheight() - w_height + elif y < 0: + y = 0 + widget.geometry("+%d+%d" % (x, y)) + widget.deiconify() # Become visible at the desired location + + def go(self): + self.root.wait_visibility() + self.root.grab_set() + self.root.mainloop() + self.root.destroy() + return self.num + + def return_event(self, event): + if self.default is None: + self.root.bell() + else: + self.done(self.default) + + def wm_delete_window(self): + if self.cancel is None: + self.root.bell() + else: + self.done(self.cancel) + + def done(self, num): + self.num = num + self.root.quit() + + +if __name__ == '__main__': + + def test(): + root = Tk() + def doit(root=root): + d = SimpleDialog(root, + text="This is a test dialog. " + "Would this have been an actual dialog, " + "the buttons below would have been glowing " + "in soft pink light.\n" + "Do you believe this?", + buttons=["Yes", "No", "Cancel"], + default=0, + cancel=2, + title="Test Dialog") + print d.go() + t = Button(root, text='Test', command=doit) + t.pack() + q = Button(root, text='Quit', command=t.quit) + q.pack() + t.mainloop() + + test() diff --git a/PythonHome/Lib/lib-tk/SimpleDialog.pyc b/PythonHome/Lib/lib-tk/SimpleDialog.pyc deleted file mode 100644 index f712ac77b8e64912c8ab8d54bb72ebe3ba295f24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4174 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 diff --git a/PythonHome/Lib/lib-tk/Tix.py b/PythonHome/Lib/lib-tk/Tix.py new file mode 100644 index 0000000000..1f28e56f74 --- /dev/null +++ b/PythonHome/Lib/lib-tk/Tix.py @@ -0,0 +1,1945 @@ +# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*- +# +# $Id$ +# +# Tix.py -- Tix widget wrappers. +# +# For Tix, see http://tix.sourceforge.net +# +# - Sudhir Shenoy (sshenoy@gol.com), Dec. 1995. +# based on an idea of Jean-Marc Lugrin (lugrin@ms.com) +# +# NOTE: In order to minimize changes to Tkinter.py, some of the code here +# (TixWidget.__init__) has been taken from Tkinter (Widget.__init__) +# and will break if there are major changes in Tkinter. +# +# The Tix widgets are represented by a class hierarchy in python with proper +# inheritance of base classes. +# +# As a result after creating a 'w = StdButtonBox', I can write +# w.ok['text'] = 'Who Cares' +# or w.ok['bg'] = w['bg'] +# or even w.ok.invoke() +# etc. +# +# Compare the demo tixwidgets.py to the original Tcl program and you will +# appreciate the advantages. +# + +from Tkinter import * +from Tkinter import _flatten, _cnfmerge, _default_root + +# WARNING - TkVersion is a limited precision floating point number +if TkVersion < 3.999: + raise ImportError, "This version of Tix.py requires Tk 4.0 or higher" + +import _tkinter # If this fails your Python may not be configured for Tk + +# Some more constants (for consistency with Tkinter) +WINDOW = 'window' +TEXT = 'text' +STATUS = 'status' +IMMEDIATE = 'immediate' +IMAGE = 'image' +IMAGETEXT = 'imagetext' +BALLOON = 'balloon' +AUTO = 'auto' +ACROSSTOP = 'acrosstop' + +# A few useful constants for the Grid widget +ASCII = 'ascii' +CELL = 'cell' +COLUMN = 'column' +DECREASING = 'decreasing' +INCREASING = 'increasing' +INTEGER = 'integer' +MAIN = 'main' +MAX = 'max' +REAL = 'real' +ROW = 'row' +S_REGION = 's-region' +X_REGION = 'x-region' +Y_REGION = 'y-region' + +# Some constants used by Tkinter dooneevent() +TCL_DONT_WAIT = 1 << 1 +TCL_WINDOW_EVENTS = 1 << 2 +TCL_FILE_EVENTS = 1 << 3 +TCL_TIMER_EVENTS = 1 << 4 +TCL_IDLE_EVENTS = 1 << 5 +TCL_ALL_EVENTS = 0 + +# BEWARE - this is implemented by copying some code from the Widget class +# in Tkinter (to override Widget initialization) and is therefore +# liable to break. +import Tkinter, os + +# Could probably add this to Tkinter.Misc +class tixCommand: + """The tix commands provide access to miscellaneous elements + of Tix's internal state and the Tix application context. + Most of the information manipulated by these commands pertains + to the application as a whole, or to a screen or + display, rather than to a particular window. + + This is a mixin class, assumed to be mixed to Tkinter.Tk + that supports the self.tk.call method. + """ + + def tix_addbitmapdir(self, directory): + """Tix maintains a list of directories under which + the tix_getimage and tix_getbitmap commands will + search for image files. The standard bitmap directory + is $TIX_LIBRARY/bitmaps. The addbitmapdir command + adds directory into this list. By using this + command, the image files of an applications can + also be located using the tix_getimage or tix_getbitmap + command. + """ + return self.tk.call('tix', 'addbitmapdir', directory) + + def tix_cget(self, option): + """Returns the current value of the configuration + option given by option. Option may be any of the + options described in the CONFIGURATION OPTIONS section. + """ + return self.tk.call('tix', 'cget', option) + + def tix_configure(self, cnf=None, **kw): + """Query or modify the configuration options of the Tix application + context. If no option is specified, returns a dictionary all of the + available options. If option is specified with no value, then the + command returns a list describing the one named option (this list + will be identical to the corresponding sublist of the value + returned if no option is specified). If one or more option-value + pairs are specified, then the command modifies the given option(s) + to have the given value(s); in this case the command returns an + empty string. Option may be any of the configuration options. + """ + # Copied from Tkinter.py + if kw: + cnf = _cnfmerge((cnf, kw)) + elif cnf: + cnf = _cnfmerge(cnf) + if cnf is None: + return self._getconfigure('tix', 'configure') + if isinstance(cnf, StringType): + return self._getconfigure1('tix', 'configure', '-'+cnf) + return self.tk.call(('tix', 'configure') + self._options(cnf)) + + def tix_filedialog(self, dlgclass=None): + """Returns the file selection dialog that may be shared among + different calls from this application. This command will create a + file selection dialog widget when it is called the first time. This + dialog will be returned by all subsequent calls to tix_filedialog. + An optional dlgclass parameter can be passed to specified what type + of file selection dialog widget is desired. Possible options are + tix FileSelectDialog or tixExFileSelectDialog. + """ + if dlgclass is not None: + return self.tk.call('tix', 'filedialog', dlgclass) + else: + return self.tk.call('tix', 'filedialog') + + def tix_getbitmap(self, name): + """Locates a bitmap file of the name name.xpm or name in one of the + bitmap directories (see the tix_addbitmapdir command above). By + using tix_getbitmap, you can avoid hard coding the pathnames of the + bitmap files in your application. When successful, it returns the + complete pathname of the bitmap file, prefixed with the character + '@'. The returned value can be used to configure the -bitmap + option of the TK and Tix widgets. + """ + return self.tk.call('tix', 'getbitmap', name) + + def tix_getimage(self, name): + """Locates an image file of the name name.xpm, name.xbm or name.ppm + in one of the bitmap directories (see the addbitmapdir command + above). If more than one file with the same name (but different + extensions) exist, then the image type is chosen according to the + depth of the X display: xbm images are chosen on monochrome + displays and color images are chosen on color displays. By using + tix_ getimage, you can avoid hard coding the pathnames of the + image files in your application. When successful, this command + returns the name of the newly created image, which can be used to + configure the -image option of the Tk and Tix widgets. + """ + return self.tk.call('tix', 'getimage', name) + + def tix_option_get(self, name): + """Gets the options maintained by the Tix + scheme mechanism. Available options include: + + active_bg active_fg bg + bold_font dark1_bg dark1_fg + dark2_bg dark2_fg disabled_fg + fg fixed_font font + inactive_bg inactive_fg input1_bg + input2_bg italic_font light1_bg + light1_fg light2_bg light2_fg + menu_font output1_bg output2_bg + select_bg select_fg selector + """ + # could use self.tk.globalgetvar('tixOption', name) + return self.tk.call('tix', 'option', 'get', name) + + def tix_resetoptions(self, newScheme, newFontSet, newScmPrio=None): + """Resets the scheme and fontset of the Tix application to + newScheme and newFontSet, respectively. This affects only those + widgets created after this call. Therefore, it is best to call the + resetoptions command before the creation of any widgets in a Tix + application. + + The optional parameter newScmPrio can be given to reset the + priority level of the Tk options set by the Tix schemes. + + Because of the way Tk handles the X option database, after Tix has + been has imported and inited, it is not possible to reset the color + schemes and font sets using the tix config command. Instead, the + tix_resetoptions command must be used. + """ + if newScmPrio is not None: + return self.tk.call('tix', 'resetoptions', newScheme, newFontSet, newScmPrio) + else: + return self.tk.call('tix', 'resetoptions', newScheme, newFontSet) + +class Tk(Tkinter.Tk, tixCommand): + """Toplevel widget of Tix which represents mostly the main window + of an application. It has an associated Tcl interpreter.""" + def __init__(self, screenName=None, baseName=None, className='Tix'): + Tkinter.Tk.__init__(self, screenName, baseName, className) + tixlib = os.environ.get('TIX_LIBRARY') + self.tk.eval('global auto_path; lappend auto_path [file dir [info nameof]]') + if tixlib is not None: + self.tk.eval('global auto_path; lappend auto_path {%s}' % tixlib) + self.tk.eval('global tcl_pkgPath; lappend tcl_pkgPath {%s}' % tixlib) + # Load Tix - this should work dynamically or statically + # If it's static, tcl/tix8.1/pkgIndex.tcl should have + # 'load {} Tix' + # If it's dynamic under Unix, tcl/tix8.1/pkgIndex.tcl should have + # 'load libtix8.1.8.3.so Tix' + self.tk.eval('package require Tix') + + def destroy(self): + # For safety, remove an delete_window binding before destroy + self.protocol("WM_DELETE_WINDOW", "") + Tkinter.Tk.destroy(self) + +# The Tix 'tixForm' geometry manager +class Form: + """The Tix Form geometry manager + + Widgets can be arranged by specifying attachments to other widgets. + See Tix documentation for complete details""" + + def config(self, cnf={}, **kw): + self.tk.call('tixForm', self._w, *self._options(cnf, kw)) + + form = config + + def __setitem__(self, key, value): + Form.form(self, {key: value}) + + def check(self): + return self.tk.call('tixForm', 'check', self._w) + + def forget(self): + self.tk.call('tixForm', 'forget', self._w) + + def grid(self, xsize=0, ysize=0): + if (not xsize) and (not ysize): + x = self.tk.call('tixForm', 'grid', self._w) + y = self.tk.splitlist(x) + z = () + for x in y: + z = z + (self.tk.getint(x),) + return z + return self.tk.call('tixForm', 'grid', self._w, xsize, ysize) + + def info(self, option=None): + if not option: + return self.tk.call('tixForm', 'info', self._w) + if option[0] != '-': + option = '-' + option + return self.tk.call('tixForm', 'info', self._w, option) + + def slaves(self): + return map(self._nametowidget, + self.tk.splitlist( + self.tk.call( + 'tixForm', 'slaves', self._w))) + + + +Tkinter.Widget.__bases__ = Tkinter.Widget.__bases__ + (Form,) + +class TixWidget(Tkinter.Widget): + """A TixWidget class is used to package all (or most) Tix widgets. + + Widget initialization is extended in two ways: + 1) It is possible to give a list of options which must be part of + the creation command (so called Tix 'static' options). These cannot be + given as a 'config' command later. + 2) It is possible to give the name of an existing TK widget. These are + child widgets created automatically by a Tix mega-widget. The Tk call + to create these widgets is therefore bypassed in TixWidget.__init__ + + Both options are for use by subclasses only. + """ + def __init__ (self, master=None, widgetName=None, + static_options=None, cnf={}, kw={}): + # Merge keywords and dictionary arguments + if kw: + cnf = _cnfmerge((cnf, kw)) + else: + cnf = _cnfmerge(cnf) + + # Move static options into extra. static_options must be + # a list of keywords (or None). + extra=() + + # 'options' is always a static option + if static_options: + static_options.append('options') + else: + static_options = ['options'] + + for k,v in cnf.items()[:]: + if k in static_options: + extra = extra + ('-' + k, v) + del cnf[k] + + self.widgetName = widgetName + Widget._setup(self, master, cnf) + + # If widgetName is None, this is a dummy creation call where the + # corresponding Tk widget has already been created by Tix + if widgetName: + self.tk.call(widgetName, self._w, *extra) + + # Non-static options - to be done via a 'config' command + if cnf: + Widget.config(self, cnf) + + # Dictionary to hold subwidget names for easier access. We can't + # use the children list because the public Tix names may not be the + # same as the pathname component + self.subwidget_list = {} + + # We set up an attribute access function so that it is possible to + # do w.ok['text'] = 'Hello' rather than w.subwidget('ok')['text'] = 'Hello' + # when w is a StdButtonBox. + # We can even do w.ok.invoke() because w.ok is subclassed from the + # Button class if you go through the proper constructors + def __getattr__(self, name): + if name in self.subwidget_list: + return self.subwidget_list[name] + raise AttributeError, name + + def set_silent(self, value): + """Set a variable without calling its action routine""" + self.tk.call('tixSetSilent', self._w, value) + + def subwidget(self, name): + """Return the named subwidget (which must have been created by + the sub-class).""" + n = self._subwidget_name(name) + if not n: + raise TclError, "Subwidget " + name + " not child of " + self._name + # Remove header of name and leading dot + n = n[len(self._w)+1:] + return self._nametowidget(n) + + def subwidgets_all(self): + """Return all subwidgets.""" + names = self._subwidget_names() + if not names: + return [] + retlist = [] + for name in names: + name = name[len(self._w)+1:] + try: + retlist.append(self._nametowidget(name)) + except: + # some of the widgets are unknown e.g. border in LabelFrame + pass + return retlist + + def _subwidget_name(self,name): + """Get a subwidget name (returns a String, not a Widget !)""" + try: + return self.tk.call(self._w, 'subwidget', name) + except TclError: + return None + + def _subwidget_names(self): + """Return the name of all subwidgets.""" + try: + x = self.tk.call(self._w, 'subwidgets', '-all') + return self.tk.splitlist(x) + except TclError: + return None + + def config_all(self, option, value): + """Set configuration options for all subwidgets (and self).""" + if option == '': + return + elif not isinstance(option, StringType): + option = repr(option) + if not isinstance(value, StringType): + value = repr(value) + names = self._subwidget_names() + for name in names: + self.tk.call(name, 'configure', '-' + option, value) + # 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' + if kw and cnf: cnf = _cnfmerge((cnf, kw)) + elif kw: cnf = kw + options = () + for k, v in cnf.items(): + if hasattr(v, '__call__'): + v = self._register(v) + options = options + ('-'+k, v) + return master.tk.call(('image', 'create', imgtype,) + options) + def image_delete(self, imgname): + try: + self.tk.call('image', 'delete', imgname) + except TclError: + # May happen if the root was destroyed + pass + +# Subwidgets are child widgets created automatically by mega-widgets. +# In python, we have to create these subwidgets manually to mirror their +# existence in Tk/Tix. +class TixSubWidget(TixWidget): + """Subwidget class. + + This is used to mirror child widgets automatically created + by Tix/Tk as part of a mega-widget in Python (which is not informed + of this)""" + + def __init__(self, master, name, + destroy_physically=1, check_intermediate=1): + if check_intermediate: + path = master._subwidget_name(name) + try: + path = path[len(master._w)+1:] + plist = path.split('.') + except: + plist = [] + + if not check_intermediate: + # immediate descendant + TixWidget.__init__(self, master, None, None, {'name' : name}) + else: + # Ensure that the intermediate widgets exist + parent = master + for i in range(len(plist) - 1): + n = '.'.join(plist[:i+1]) + try: + w = master._nametowidget(n) + parent = w + except KeyError: + # Create the intermediate widget + parent = TixSubWidget(parent, plist[i], + destroy_physically=0, + check_intermediate=0) + # The Tk widget name is in plist, not in name + if plist: + name = plist[-1] + TixWidget.__init__(self, parent, None, None, {'name' : name}) + self.destroy_physically = destroy_physically + + def destroy(self): + # For some widgets e.g., a NoteBook, when we call destructors, + # we must be careful not to destroy the frame widget since this + # also destroys the parent NoteBook thus leading to an exception + # in Tkinter when it finally calls Tcl to destroy the NoteBook + for c in self.children.values(): c.destroy() + if self._name in self.master.children: + del self.master.children[self._name] + if self._name in self.master.subwidget_list: + del self.master.subwidget_list[self._name] + if self.destroy_physically: + # This is bypassed only for a few widgets + self.tk.call('destroy', self._w) + + +# Useful class to create a display style - later shared by many items. +# Contributed by Steffen Kremser +class DisplayStyle: + """DisplayStyle - handle configuration options shared by + (multiple) Display Items""" + + def __init__(self, itemtype, cnf={}, **kw): + master = _default_root # global from Tkinter + if not master and 'refwindow' in cnf: master=cnf['refwindow'] + elif not master and 'refwindow' in kw: master= kw['refwindow'] + elif not master: raise RuntimeError, "Too early to create display style: no root window" + self.tk = master.tk + self.stylename = self.tk.call('tixDisplayStyle', itemtype, + *self._options(cnf,kw) ) + + def __str__(self): + return self.stylename + + def _options(self, cnf, kw): + if kw and cnf: + cnf = _cnfmerge((cnf, kw)) + elif kw: + cnf = kw + opts = () + for k, v in cnf.items(): + opts = opts + ('-'+k, v) + return opts + + def delete(self): + self.tk.call(self.stylename, 'delete') + + def __setitem__(self,key,value): + self.tk.call(self.stylename, 'configure', '-%s'%key, value) + + def config(self, cnf={}, **kw): + return self._getconfigure( + self.stylename, 'configure', *self._options(cnf,kw)) + + def __getitem__(self,key): + return self.tk.call(self.stylename, 'cget', '-%s'%key) + + +###################################################### +### The Tix Widget classes - in alphabetical order ### +###################################################### + +class Balloon(TixWidget): + """Balloon help widget. + + Subwidget Class + --------- ----- + label Label + message Message""" + + # FIXME: It should inherit -superclass tixShell + def __init__(self, master=None, cnf={}, **kw): + # static seem to be -installcolormap -initwait -statusbar -cursor + static = ['options', 'installcolormap', 'initwait', 'statusbar', + 'cursor'] + TixWidget.__init__(self, master, 'tixBalloon', static, cnf, kw) + self.subwidget_list['label'] = _dummyLabel(self, 'label', + destroy_physically=0) + self.subwidget_list['message'] = _dummyLabel(self, 'message', + destroy_physically=0) + + def bind_widget(self, widget, cnf={}, **kw): + """Bind balloon widget to another. + One balloon widget may be bound to several widgets at the same time""" + self.tk.call(self._w, 'bind', widget._w, *self._options(cnf, kw)) + + def unbind_widget(self, widget): + self.tk.call(self._w, 'unbind', widget._w) + +class ButtonBox(TixWidget): + """ButtonBox - A container for pushbuttons. + Subwidgets are the buttons added with the add method. + """ + def __init__(self, master=None, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixButtonBox', + ['orientation', 'options'], cnf, kw) + + def add(self, name, cnf={}, **kw): + """Add a button with given name to box.""" + + btn = self.tk.call(self._w, 'add', name, *self._options(cnf, kw)) + self.subwidget_list[name] = _dummyButton(self, name) + return btn + + def invoke(self, name): + if name in self.subwidget_list: + self.tk.call(self._w, 'invoke', name) + +class ComboBox(TixWidget): + """ComboBox - an Entry field with a dropdown menu. The user can select a + choice by either typing in the entry subwidget or selecting from the + listbox subwidget. + + Subwidget Class + --------- ----- + entry Entry + arrow Button + slistbox ScrolledListBox + tick Button + cross Button : present if created with the fancy option""" + + # FIXME: It should inherit -superclass tixLabelWidget + def __init__ (self, master=None, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixComboBox', + ['editable', 'dropdown', 'fancy', 'options'], + cnf, kw) + self.subwidget_list['label'] = _dummyLabel(self, 'label') + self.subwidget_list['entry'] = _dummyEntry(self, 'entry') + self.subwidget_list['arrow'] = _dummyButton(self, 'arrow') + self.subwidget_list['slistbox'] = _dummyScrolledListBox(self, + 'slistbox') + try: + self.subwidget_list['tick'] = _dummyButton(self, 'tick') + self.subwidget_list['cross'] = _dummyButton(self, 'cross') + except TypeError: + # unavailable when -fancy not specified + pass + + # align + + def add_history(self, str): + self.tk.call(self._w, 'addhistory', str) + + def append_history(self, str): + self.tk.call(self._w, 'appendhistory', str) + + def insert(self, index, str): + self.tk.call(self._w, 'insert', index, str) + + def pick(self, index): + self.tk.call(self._w, 'pick', index) + +class Control(TixWidget): + """Control - An entry field with value change arrows. The user can + adjust the value by pressing the two arrow buttons or by entering + the value directly into the entry. The new value will be checked + against the user-defined upper and lower limits. + + Subwidget Class + --------- ----- + incr Button + decr Button + entry Entry + label Label""" + + # FIXME: It should inherit -superclass tixLabelWidget + def __init__ (self, master=None, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixControl', ['options'], cnf, kw) + self.subwidget_list['incr'] = _dummyButton(self, 'incr') + self.subwidget_list['decr'] = _dummyButton(self, 'decr') + self.subwidget_list['label'] = _dummyLabel(self, 'label') + self.subwidget_list['entry'] = _dummyEntry(self, 'entry') + + def decrement(self): + self.tk.call(self._w, 'decr') + + def increment(self): + self.tk.call(self._w, 'incr') + + def invoke(self): + self.tk.call(self._w, 'invoke') + + def update(self): + self.tk.call(self._w, 'update') + +class DirList(TixWidget): + """DirList - displays a list view of a directory, its previous + directories and its sub-directories. The user can choose one of + the directories displayed in the list or change to another directory. + + Subwidget Class + --------- ----- + hlist HList + hsb Scrollbar + vsb Scrollbar""" + + # FIXME: It should inherit -superclass tixScrolledHList + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixDirList', ['options'], cnf, kw) + self.subwidget_list['hlist'] = _dummyHList(self, 'hlist') + self.subwidget_list['vsb'] = _dummyScrollbar(self, 'vsb') + self.subwidget_list['hsb'] = _dummyScrollbar(self, 'hsb') + + def chdir(self, dir): + self.tk.call(self._w, 'chdir', dir) + +class DirTree(TixWidget): + """DirTree - Directory Listing in a hierarchical view. + Displays a tree view of a directory, its previous directories and its + sub-directories. The user can choose one of the directories displayed + in the list or change to another directory. + + Subwidget Class + --------- ----- + hlist HList + hsb Scrollbar + vsb Scrollbar""" + + # FIXME: It should inherit -superclass tixScrolledHList + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixDirTree', ['options'], cnf, kw) + self.subwidget_list['hlist'] = _dummyHList(self, 'hlist') + self.subwidget_list['vsb'] = _dummyScrollbar(self, 'vsb') + self.subwidget_list['hsb'] = _dummyScrollbar(self, 'hsb') + + def chdir(self, dir): + self.tk.call(self._w, 'chdir', dir) + +class DirSelectBox(TixWidget): + """DirSelectBox - Motif style file select box. + It is generally used for + the user to choose a file. FileSelectBox stores the files mostly + recently selected into a ComboBox widget so that they can be quickly + selected again. + + Subwidget Class + --------- ----- + selection ComboBox + filter ComboBox + dirlist ScrolledListBox + filelist ScrolledListBox""" + + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixDirSelectBox', ['options'], cnf, kw) + self.subwidget_list['dirlist'] = _dummyDirList(self, 'dirlist') + self.subwidget_list['dircbx'] = _dummyFileComboBox(self, 'dircbx') + +class ExFileSelectBox(TixWidget): + """ExFileSelectBox - MS Windows style file select box. + It provides an convenient method for the user to select files. + + Subwidget Class + --------- ----- + cancel Button + ok Button + hidden Checkbutton + types ComboBox + dir ComboBox + file ComboBox + dirlist ScrolledListBox + filelist ScrolledListBox""" + + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixExFileSelectBox', ['options'], cnf, kw) + self.subwidget_list['cancel'] = _dummyButton(self, 'cancel') + self.subwidget_list['ok'] = _dummyButton(self, 'ok') + self.subwidget_list['hidden'] = _dummyCheckbutton(self, 'hidden') + self.subwidget_list['types'] = _dummyComboBox(self, 'types') + self.subwidget_list['dir'] = _dummyComboBox(self, 'dir') + self.subwidget_list['dirlist'] = _dummyDirList(self, 'dirlist') + self.subwidget_list['file'] = _dummyComboBox(self, 'file') + self.subwidget_list['filelist'] = _dummyScrolledListBox(self, 'filelist') + + def filter(self): + self.tk.call(self._w, 'filter') + + def invoke(self): + self.tk.call(self._w, 'invoke') + + +# Should inherit from a Dialog class +class DirSelectDialog(TixWidget): + """The DirSelectDialog widget presents the directories in the file + system in a dialog window. The user can use this dialog window to + navigate through the file system to select the desired directory. + + Subwidgets Class + ---------- ----- + dirbox DirSelectDialog""" + + # FIXME: It should inherit -superclass tixDialogShell + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixDirSelectDialog', + ['options'], cnf, kw) + self.subwidget_list['dirbox'] = _dummyDirSelectBox(self, 'dirbox') + # cancel and ok buttons are missing + + def popup(self): + self.tk.call(self._w, 'popup') + + def popdown(self): + self.tk.call(self._w, 'popdown') + + +# Should inherit from a Dialog class +class ExFileSelectDialog(TixWidget): + """ExFileSelectDialog - MS Windows style file select dialog. + It provides an convenient method for the user to select files. + + Subwidgets Class + ---------- ----- + fsbox ExFileSelectBox""" + + # FIXME: It should inherit -superclass tixDialogShell + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixExFileSelectDialog', + ['options'], cnf, kw) + self.subwidget_list['fsbox'] = _dummyExFileSelectBox(self, 'fsbox') + + def popup(self): + self.tk.call(self._w, 'popup') + + def popdown(self): + self.tk.call(self._w, 'popdown') + +class FileSelectBox(TixWidget): + """ExFileSelectBox - Motif style file select box. + It is generally used for + the user to choose a file. FileSelectBox stores the files mostly + recently selected into a ComboBox widget so that they can be quickly + selected again. + + Subwidget Class + --------- ----- + selection ComboBox + filter ComboBox + dirlist ScrolledListBox + filelist ScrolledListBox""" + + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixFileSelectBox', ['options'], cnf, kw) + self.subwidget_list['dirlist'] = _dummyScrolledListBox(self, 'dirlist') + self.subwidget_list['filelist'] = _dummyScrolledListBox(self, 'filelist') + self.subwidget_list['filter'] = _dummyComboBox(self, 'filter') + self.subwidget_list['selection'] = _dummyComboBox(self, 'selection') + + def apply_filter(self): # name of subwidget is same as command + self.tk.call(self._w, 'filter') + + def invoke(self): + self.tk.call(self._w, 'invoke') + +# Should inherit from a Dialog class +class FileSelectDialog(TixWidget): + """FileSelectDialog - Motif style file select dialog. + + Subwidgets Class + ---------- ----- + btns StdButtonBox + fsbox FileSelectBox""" + + # FIXME: It should inherit -superclass tixStdDialogShell + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixFileSelectDialog', + ['options'], cnf, kw) + self.subwidget_list['btns'] = _dummyStdButtonBox(self, 'btns') + self.subwidget_list['fsbox'] = _dummyFileSelectBox(self, 'fsbox') + + def popup(self): + self.tk.call(self._w, 'popup') + + def popdown(self): + self.tk.call(self._w, 'popdown') + +class FileEntry(TixWidget): + """FileEntry - Entry field with button that invokes a FileSelectDialog. + The user can type in the filename manually. Alternatively, the user can + press the button widget that sits next to the entry, which will bring + up a file selection dialog. + + Subwidgets Class + ---------- ----- + button Button + entry Entry""" + + # FIXME: It should inherit -superclass tixLabelWidget + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixFileEntry', + ['dialogtype', 'options'], cnf, kw) + self.subwidget_list['button'] = _dummyButton(self, 'button') + self.subwidget_list['entry'] = _dummyEntry(self, 'entry') + + def invoke(self): + self.tk.call(self._w, 'invoke') + + def file_dialog(self): + # FIXME: return python object + pass + +class HList(TixWidget, XView, YView): + """HList - Hierarchy display widget can be used to display any data + that have a hierarchical structure, for example, file system directory + trees. The list entries are indented and connected by branch lines + according to their places in the hierarchy. + + Subwidgets - None""" + + def __init__ (self,master=None,cnf={}, **kw): + TixWidget.__init__(self, master, 'tixHList', + ['columns', 'options'], cnf, kw) + + def add(self, entry, cnf={}, **kw): + return self.tk.call(self._w, 'add', entry, *self._options(cnf, kw)) + + def add_child(self, parent=None, cnf={}, **kw): + if not parent: + parent = '' + return self.tk.call( + self._w, 'addchild', parent, *self._options(cnf, kw)) + + def anchor_set(self, entry): + self.tk.call(self._w, 'anchor', 'set', entry) + + def anchor_clear(self): + self.tk.call(self._w, 'anchor', 'clear') + + def column_width(self, col=0, width=None, chars=None): + if not chars: + return self.tk.call(self._w, 'column', 'width', col, width) + else: + return self.tk.call(self._w, 'column', 'width', col, + '-char', chars) + + def delete_all(self): + self.tk.call(self._w, 'delete', 'all') + + def delete_entry(self, entry): + self.tk.call(self._w, 'delete', 'entry', entry) + + def delete_offsprings(self, entry): + self.tk.call(self._w, 'delete', 'offsprings', entry) + + def delete_siblings(self, entry): + self.tk.call(self._w, 'delete', 'siblings', entry) + + def dragsite_set(self, index): + self.tk.call(self._w, 'dragsite', 'set', index) + + def dragsite_clear(self): + self.tk.call(self._w, 'dragsite', 'clear') + + def dropsite_set(self, index): + self.tk.call(self._w, 'dropsite', 'set', index) + + def dropsite_clear(self): + self.tk.call(self._w, 'dropsite', 'clear') + + def header_create(self, col, cnf={}, **kw): + self.tk.call(self._w, 'header', 'create', col, *self._options(cnf, kw)) + + def header_configure(self, col, cnf={}, **kw): + if cnf is None: + return self._getconfigure(self._w, 'header', 'configure', col) + self.tk.call(self._w, 'header', 'configure', col, + *self._options(cnf, kw)) + + def header_cget(self, col, opt): + return self.tk.call(self._w, 'header', 'cget', col, opt) + + def header_exists(self, col): + return self.tk.call(self._w, 'header', 'exists', col) + + def header_delete(self, col): + self.tk.call(self._w, 'header', 'delete', col) + + def header_size(self, col): + return self.tk.call(self._w, 'header', 'size', col) + + def hide_entry(self, entry): + self.tk.call(self._w, 'hide', 'entry', entry) + + def indicator_create(self, entry, cnf={}, **kw): + self.tk.call( + self._w, 'indicator', 'create', entry, *self._options(cnf, kw)) + + def indicator_configure(self, entry, cnf={}, **kw): + if cnf is None: + return self._getconfigure( + self._w, 'indicator', 'configure', entry) + self.tk.call( + self._w, 'indicator', 'configure', entry, *self._options(cnf, kw)) + + def indicator_cget(self, entry, opt): + return self.tk.call(self._w, 'indicator', 'cget', entry, opt) + + def indicator_exists(self, entry): + return self.tk.call (self._w, 'indicator', 'exists', entry) + + def indicator_delete(self, entry): + self.tk.call(self._w, 'indicator', 'delete', entry) + + def indicator_size(self, entry): + return self.tk.call(self._w, 'indicator', 'size', entry) + + def info_anchor(self): + return self.tk.call(self._w, 'info', 'anchor') + + def info_bbox(self, entry): + return self._getints( + self.tk.call(self._w, 'info', 'bbox', entry)) or None + + def info_children(self, entry=None): + c = self.tk.call(self._w, 'info', 'children', entry) + return self.tk.splitlist(c) + + def info_data(self, entry): + return self.tk.call(self._w, 'info', 'data', entry) + + def info_dragsite(self): + return self.tk.call(self._w, 'info', 'dragsite') + + def info_dropsite(self): + return self.tk.call(self._w, 'info', 'dropsite') + + def info_exists(self, entry): + return self.tk.call(self._w, 'info', 'exists', entry) + + def info_hidden(self, entry): + return self.tk.call(self._w, 'info', 'hidden', entry) + + def info_next(self, entry): + return self.tk.call(self._w, 'info', 'next', entry) + + def info_parent(self, entry): + return self.tk.call(self._w, 'info', 'parent', entry) + + def info_prev(self, entry): + return self.tk.call(self._w, 'info', 'prev', entry) + + def info_selection(self): + c = self.tk.call(self._w, 'info', 'selection') + return self.tk.splitlist(c) + + def item_cget(self, entry, col, opt): + return self.tk.call(self._w, 'item', 'cget', entry, col, opt) + + def item_configure(self, entry, col, cnf={}, **kw): + if cnf is None: + return self._getconfigure(self._w, 'item', 'configure', entry, col) + self.tk.call(self._w, 'item', 'configure', entry, col, + *self._options(cnf, kw)) + + def item_create(self, entry, col, cnf={}, **kw): + self.tk.call( + self._w, 'item', 'create', entry, col, *self._options(cnf, kw)) + + def item_exists(self, entry, col): + return self.tk.call(self._w, 'item', 'exists', entry, col) + + def item_delete(self, entry, col): + self.tk.call(self._w, 'item', 'delete', entry, col) + + def entrycget(self, entry, opt): + return self.tk.call(self._w, 'entrycget', entry, opt) + + def entryconfigure(self, entry, cnf={}, **kw): + if cnf is None: + return self._getconfigure(self._w, 'entryconfigure', entry) + self.tk.call(self._w, 'entryconfigure', entry, + *self._options(cnf, kw)) + + def nearest(self, y): + return self.tk.call(self._w, 'nearest', y) + + def see(self, entry): + self.tk.call(self._w, 'see', entry) + + def selection_clear(self, cnf={}, **kw): + self.tk.call(self._w, 'selection', 'clear', *self._options(cnf, kw)) + + def selection_includes(self, entry): + return self.tk.call(self._w, 'selection', 'includes', entry) + + def selection_set(self, first, last=None): + self.tk.call(self._w, 'selection', 'set', first, last) + + def show_entry(self, entry): + return self.tk.call(self._w, 'show', 'entry', entry) + +class InputOnly(TixWidget): + """InputOnly - Invisible widget. Unix only. + + Subwidgets - None""" + + def __init__ (self,master=None,cnf={}, **kw): + TixWidget.__init__(self, master, 'tixInputOnly', None, cnf, kw) + +class LabelEntry(TixWidget): + """LabelEntry - Entry field with label. Packages an entry widget + and a label into one mega widget. It can beused be used to simplify + the creation of ``entry-form'' type of interface. + + Subwidgets Class + ---------- ----- + label Label + entry Entry""" + + def __init__ (self,master=None,cnf={}, **kw): + TixWidget.__init__(self, master, 'tixLabelEntry', + ['labelside','options'], cnf, kw) + self.subwidget_list['label'] = _dummyLabel(self, 'label') + self.subwidget_list['entry'] = _dummyEntry(self, 'entry') + +class LabelFrame(TixWidget): + """LabelFrame - Labelled Frame container. Packages a frame widget + and a label into one mega widget. To create widgets inside a + LabelFrame widget, one creates the new widgets relative to the + frame subwidget and manage them inside the frame subwidget. + + Subwidgets Class + ---------- ----- + label Label + frame Frame""" + + def __init__ (self,master=None,cnf={}, **kw): + TixWidget.__init__(self, master, 'tixLabelFrame', + ['labelside','options'], cnf, kw) + self.subwidget_list['label'] = _dummyLabel(self, 'label') + self.subwidget_list['frame'] = _dummyFrame(self, 'frame') + + +class ListNoteBook(TixWidget): + """A ListNoteBook widget is very similar to the TixNoteBook widget: + it can be used to display many windows in a limited space using a + notebook metaphor. The notebook is divided into a stack of pages + (windows). At one time only one of these pages can be shown. + The user can navigate through these pages by + choosing the name of the desired page in the hlist subwidget.""" + + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixListNoteBook', ['options'], cnf, kw) + # Is this necessary? It's not an exposed subwidget in Tix. + self.subwidget_list['pane'] = _dummyPanedWindow(self, 'pane', + destroy_physically=0) + self.subwidget_list['hlist'] = _dummyHList(self, 'hlist') + self.subwidget_list['shlist'] = _dummyScrolledHList(self, 'shlist') + + def add(self, name, cnf={}, **kw): + self.tk.call(self._w, 'add', name, *self._options(cnf, kw)) + self.subwidget_list[name] = TixSubWidget(self, name) + return self.subwidget_list[name] + + def page(self, name): + return self.subwidget(name) + + def pages(self): + # Can't call subwidgets_all directly because we don't want .nbframe + names = self.tk.split(self.tk.call(self._w, 'pages')) + ret = [] + for x in names: + ret.append(self.subwidget(x)) + return ret + + def raise_page(self, name): # raise is a python keyword + self.tk.call(self._w, 'raise', name) + +class Meter(TixWidget): + """The Meter widget can be used to show the progress of a background + job which may take a long time to execute. + """ + + def __init__(self, master=None, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixMeter', + ['options'], cnf, kw) + +class NoteBook(TixWidget): + """NoteBook - Multi-page container widget (tabbed notebook metaphor). + + Subwidgets Class + ---------- ----- + nbframe NoteBookFrame + page widgets added dynamically with the add method""" + + def __init__ (self,master=None,cnf={}, **kw): + TixWidget.__init__(self,master,'tixNoteBook', ['options'], cnf, kw) + self.subwidget_list['nbframe'] = TixSubWidget(self, 'nbframe', + destroy_physically=0) + + def add(self, name, cnf={}, **kw): + self.tk.call(self._w, 'add', name, *self._options(cnf, kw)) + self.subwidget_list[name] = TixSubWidget(self, name) + return self.subwidget_list[name] + + def delete(self, name): + self.tk.call(self._w, 'delete', name) + self.subwidget_list[name].destroy() + del self.subwidget_list[name] + + def page(self, name): + return self.subwidget(name) + + def pages(self): + # Can't call subwidgets_all directly because we don't want .nbframe + names = self.tk.split(self.tk.call(self._w, 'pages')) + ret = [] + for x in names: + ret.append(self.subwidget(x)) + return ret + + def raise_page(self, name): # raise is a python keyword + self.tk.call(self._w, 'raise', name) + + def raised(self): + return self.tk.call(self._w, 'raised') + +class NoteBookFrame(TixWidget): + # FIXME: This is dangerous to expose to be called on its own. + pass + +class OptionMenu(TixWidget): + """OptionMenu - creates a menu button of options. + + Subwidget Class + --------- ----- + menubutton Menubutton + menu Menu""" + + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixOptionMenu', + ['labelside', 'options'], cnf, kw) + self.subwidget_list['menubutton'] = _dummyMenubutton(self, 'menubutton') + self.subwidget_list['menu'] = _dummyMenu(self, 'menu') + + def add_command(self, name, cnf={}, **kw): + self.tk.call(self._w, 'add', 'command', name, *self._options(cnf, kw)) + + def add_separator(self, name, cnf={}, **kw): + self.tk.call(self._w, 'add', 'separator', name, *self._options(cnf, kw)) + + def delete(self, name): + self.tk.call(self._w, 'delete', name) + + def disable(self, name): + self.tk.call(self._w, 'disable', name) + + def enable(self, name): + self.tk.call(self._w, 'enable', name) + +class PanedWindow(TixWidget): + """PanedWindow - Multi-pane container widget + allows the user to interactively manipulate the sizes of several + panes. The panes can be arranged either vertically or horizontally.The + user changes the sizes of the panes by dragging the resize handle + between two panes. + + Subwidgets Class + ---------- ----- + g/p widgets added dynamically with the add method.""" + + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixPanedWindow', ['orientation', 'options'], cnf, kw) + + # add delete forget panecget paneconfigure panes setsize + def add(self, name, cnf={}, **kw): + self.tk.call(self._w, 'add', name, *self._options(cnf, kw)) + self.subwidget_list[name] = TixSubWidget(self, name, + check_intermediate=0) + return self.subwidget_list[name] + + def delete(self, name): + self.tk.call(self._w, 'delete', name) + self.subwidget_list[name].destroy() + del self.subwidget_list[name] + + def forget(self, name): + self.tk.call(self._w, 'forget', name) + + def panecget(self, entry, opt): + return self.tk.call(self._w, 'panecget', entry, opt) + + def paneconfigure(self, entry, cnf={}, **kw): + if cnf is None: + return self._getconfigure(self._w, 'paneconfigure', entry) + self.tk.call(self._w, 'paneconfigure', entry, *self._options(cnf, kw)) + + def panes(self): + names = self.tk.splitlist(self.tk.call(self._w, 'panes')) + return [self.subwidget(x) for x in names] + +class PopupMenu(TixWidget): + """PopupMenu widget can be used as a replacement of the tk_popup command. + The advantage of the Tix PopupMenu widget is it requires less application + code to manipulate. + + + Subwidgets Class + ---------- ----- + menubutton Menubutton + menu Menu""" + + # FIXME: It should inherit -superclass tixShell + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixPopupMenu', ['options'], cnf, kw) + self.subwidget_list['menubutton'] = _dummyMenubutton(self, 'menubutton') + self.subwidget_list['menu'] = _dummyMenu(self, 'menu') + + def bind_widget(self, widget): + self.tk.call(self._w, 'bind', widget._w) + + def unbind_widget(self, widget): + self.tk.call(self._w, 'unbind', widget._w) + + def post_widget(self, widget, x, y): + self.tk.call(self._w, 'post', widget._w, x, y) + +class ResizeHandle(TixWidget): + """Internal widget to draw resize handles on Scrolled widgets.""" + def __init__(self, master, cnf={}, **kw): + # There seems to be a Tix bug rejecting the configure method + # Let's try making the flags -static + flags = ['options', 'command', 'cursorfg', 'cursorbg', + 'handlesize', 'hintcolor', 'hintwidth', + 'x', 'y'] + # In fact, x y height width are configurable + TixWidget.__init__(self, master, 'tixResizeHandle', + flags, cnf, kw) + + def attach_widget(self, widget): + self.tk.call(self._w, 'attachwidget', widget._w) + + def detach_widget(self, widget): + self.tk.call(self._w, 'detachwidget', widget._w) + + def hide(self, widget): + self.tk.call(self._w, 'hide', widget._w) + + def show(self, widget): + self.tk.call(self._w, 'show', widget._w) + +class ScrolledHList(TixWidget): + """ScrolledHList - HList with automatic scrollbars.""" + + # FIXME: It should inherit -superclass tixScrolledWidget + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixScrolledHList', ['options'], + cnf, kw) + self.subwidget_list['hlist'] = _dummyHList(self, 'hlist') + self.subwidget_list['vsb'] = _dummyScrollbar(self, 'vsb') + self.subwidget_list['hsb'] = _dummyScrollbar(self, 'hsb') + +class ScrolledListBox(TixWidget): + """ScrolledListBox - Listbox with automatic scrollbars.""" + + # FIXME: It should inherit -superclass tixScrolledWidget + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixScrolledListBox', ['options'], cnf, kw) + self.subwidget_list['listbox'] = _dummyListbox(self, 'listbox') + self.subwidget_list['vsb'] = _dummyScrollbar(self, 'vsb') + self.subwidget_list['hsb'] = _dummyScrollbar(self, 'hsb') + +class ScrolledText(TixWidget): + """ScrolledText - Text with automatic scrollbars.""" + + # FIXME: It should inherit -superclass tixScrolledWidget + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixScrolledText', ['options'], cnf, kw) + self.subwidget_list['text'] = _dummyText(self, 'text') + self.subwidget_list['vsb'] = _dummyScrollbar(self, 'vsb') + self.subwidget_list['hsb'] = _dummyScrollbar(self, 'hsb') + +class ScrolledTList(TixWidget): + """ScrolledTList - TList with automatic scrollbars.""" + + # FIXME: It should inherit -superclass tixScrolledWidget + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixScrolledTList', ['options'], + cnf, kw) + self.subwidget_list['tlist'] = _dummyTList(self, 'tlist') + self.subwidget_list['vsb'] = _dummyScrollbar(self, 'vsb') + self.subwidget_list['hsb'] = _dummyScrollbar(self, 'hsb') + +class ScrolledWindow(TixWidget): + """ScrolledWindow - Window with automatic scrollbars.""" + + # FIXME: It should inherit -superclass tixScrolledWidget + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixScrolledWindow', ['options'], cnf, kw) + self.subwidget_list['window'] = _dummyFrame(self, 'window') + self.subwidget_list['vsb'] = _dummyScrollbar(self, 'vsb') + self.subwidget_list['hsb'] = _dummyScrollbar(self, 'hsb') + +class Select(TixWidget): + """Select - Container of button subwidgets. It can be used to provide + radio-box or check-box style of selection options for the user. + + Subwidgets are buttons added dynamically using the add method.""" + + # FIXME: It should inherit -superclass tixLabelWidget + def __init__(self, master, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixSelect', + ['allowzero', 'radio', 'orientation', 'labelside', + 'options'], + cnf, kw) + self.subwidget_list['label'] = _dummyLabel(self, 'label') + + def add(self, name, cnf={}, **kw): + self.tk.call(self._w, 'add', name, *self._options(cnf, kw)) + self.subwidget_list[name] = _dummyButton(self, name) + return self.subwidget_list[name] + + def invoke(self, name): + self.tk.call(self._w, 'invoke', name) + +class Shell(TixWidget): + """Toplevel window. + + Subwidgets - None""" + + def __init__ (self,master=None,cnf={}, **kw): + TixWidget.__init__(self, master, 'tixShell', ['options', 'title'], cnf, kw) + +class DialogShell(TixWidget): + """Toplevel window, with popup popdown and center methods. + It tells the window manager that it is a dialog window and should be + treated specially. The exact treatment depends on the treatment of + the window manager. + + Subwidgets - None""" + + # FIXME: It should inherit from Shell + def __init__ (self,master=None,cnf={}, **kw): + TixWidget.__init__(self, master, + 'tixDialogShell', + ['options', 'title', 'mapped', + 'minheight', 'minwidth', + 'parent', 'transient'], cnf, kw) + + def popdown(self): + self.tk.call(self._w, 'popdown') + + def popup(self): + self.tk.call(self._w, 'popup') + + def center(self): + self.tk.call(self._w, 'center') + +class StdButtonBox(TixWidget): + """StdButtonBox - Standard Button Box (OK, Apply, Cancel and Help) """ + + def __init__(self, master=None, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixStdButtonBox', + ['orientation', 'options'], cnf, kw) + self.subwidget_list['ok'] = _dummyButton(self, 'ok') + self.subwidget_list['apply'] = _dummyButton(self, 'apply') + self.subwidget_list['cancel'] = _dummyButton(self, 'cancel') + self.subwidget_list['help'] = _dummyButton(self, 'help') + + def invoke(self, name): + if name in self.subwidget_list: + self.tk.call(self._w, 'invoke', name) + +class TList(TixWidget, XView, YView): + """TList - Hierarchy display widget which can be + used to display data in a tabular format. The list entries of a TList + widget are similar to the entries in the Tk listbox widget. The main + differences are (1) the TList widget can display the list entries in a + two dimensional format and (2) you can use graphical images as well as + multiple colors and fonts for the list entries. + + Subwidgets - None""" + + def __init__ (self,master=None,cnf={}, **kw): + TixWidget.__init__(self, master, 'tixTList', ['options'], cnf, kw) + + def active_set(self, index): + self.tk.call(self._w, 'active', 'set', index) + + def active_clear(self): + self.tk.call(self._w, 'active', 'clear') + + def anchor_set(self, index): + self.tk.call(self._w, 'anchor', 'set', index) + + def anchor_clear(self): + self.tk.call(self._w, 'anchor', 'clear') + + def delete(self, from_, to=None): + self.tk.call(self._w, 'delete', from_, to) + + def dragsite_set(self, index): + self.tk.call(self._w, 'dragsite', 'set', index) + + def dragsite_clear(self): + self.tk.call(self._w, 'dragsite', 'clear') + + def dropsite_set(self, index): + self.tk.call(self._w, 'dropsite', 'set', index) + + def dropsite_clear(self): + self.tk.call(self._w, 'dropsite', 'clear') + + def insert(self, index, cnf={}, **kw): + self.tk.call(self._w, 'insert', index, *self._options(cnf, kw)) + + def info_active(self): + return self.tk.call(self._w, 'info', 'active') + + def info_anchor(self): + return self.tk.call(self._w, 'info', 'anchor') + + def info_down(self, index): + return self.tk.call(self._w, 'info', 'down', index) + + def info_left(self, index): + return self.tk.call(self._w, 'info', 'left', index) + + def info_right(self, index): + return self.tk.call(self._w, 'info', 'right', index) + + def info_selection(self): + c = self.tk.call(self._w, 'info', 'selection') + return self.tk.splitlist(c) + + def info_size(self): + return self.tk.call(self._w, 'info', 'size') + + def info_up(self, index): + return self.tk.call(self._w, 'info', 'up', index) + + def nearest(self, x, y): + return self.tk.call(self._w, 'nearest', x, y) + + def see(self, index): + self.tk.call(self._w, 'see', index) + + def selection_clear(self, cnf={}, **kw): + self.tk.call(self._w, 'selection', 'clear', *self._options(cnf, kw)) + + def selection_includes(self, index): + return self.tk.call(self._w, 'selection', 'includes', index) + + def selection_set(self, first, last=None): + self.tk.call(self._w, 'selection', 'set', first, last) + +class Tree(TixWidget): + """Tree - The tixTree widget can be used to display hierarchical + data in a tree form. The user can adjust + the view of the tree by opening or closing parts of the tree.""" + + # FIXME: It should inherit -superclass tixScrolledWidget + def __init__(self, master=None, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixTree', + ['options'], cnf, kw) + self.subwidget_list['hlist'] = _dummyHList(self, 'hlist') + self.subwidget_list['vsb'] = _dummyScrollbar(self, 'vsb') + self.subwidget_list['hsb'] = _dummyScrollbar(self, 'hsb') + + def autosetmode(self): + '''This command calls the setmode method for all the entries in this + Tree widget: if an entry has no child entries, its mode is set to + none. Otherwise, if the entry has any hidden child entries, its mode is + set to open; otherwise its mode is set to close.''' + self.tk.call(self._w, 'autosetmode') + + def close(self, entrypath): + '''Close the entry given by entryPath if its mode is close.''' + self.tk.call(self._w, 'close', entrypath) + + def getmode(self, entrypath): + '''Returns the current mode of the entry given by entryPath.''' + return self.tk.call(self._w, 'getmode', entrypath) + + def open(self, entrypath): + '''Open the entry given by entryPath if its mode is open.''' + self.tk.call(self._w, 'open', entrypath) + + def setmode(self, entrypath, mode='none'): + '''This command is used to indicate whether the entry given by + entryPath has children entries and whether the children are visible. mode + must be one of open, close or none. If mode is set to open, a (+) + indicator is drawn next to the entry. If mode is set to close, a (-) + indicator is drawn next to the entry. If mode is set to none, no + indicators will be drawn for this entry. The default mode is none. The + open mode indicates the entry has hidden children and this entry can be + opened by the user. The close mode indicates that all the children of the + entry are now visible and the entry can be closed by the user.''' + self.tk.call(self._w, 'setmode', entrypath, mode) + + +# Could try subclassing Tree for CheckList - would need another arg to init +class CheckList(TixWidget): + """The CheckList widget + displays a list of items to be selected by the user. CheckList acts + similarly to the Tk checkbutton or radiobutton widgets, except it is + capable of handling many more items than checkbuttons or radiobuttons. + """ + # FIXME: It should inherit -superclass tixTree + def __init__(self, master=None, cnf={}, **kw): + TixWidget.__init__(self, master, 'tixCheckList', + ['options', 'radio'], cnf, kw) + self.subwidget_list['hlist'] = _dummyHList(self, 'hlist') + self.subwidget_list['vsb'] = _dummyScrollbar(self, 'vsb') + self.subwidget_list['hsb'] = _dummyScrollbar(self, 'hsb') + + def autosetmode(self): + '''This command calls the setmode method for all the entries in this + Tree widget: if an entry has no child entries, its mode is set to + none. Otherwise, if the entry has any hidden child entries, its mode is + set to open; otherwise its mode is set to close.''' + self.tk.call(self._w, 'autosetmode') + + def close(self, entrypath): + '''Close the entry given by entryPath if its mode is close.''' + self.tk.call(self._w, 'close', entrypath) + + def getmode(self, entrypath): + '''Returns the current mode of the entry given by entryPath.''' + return self.tk.call(self._w, 'getmode', entrypath) + + def open(self, entrypath): + '''Open the entry given by entryPath if its mode is open.''' + self.tk.call(self._w, 'open', entrypath) + + def getselection(self, mode='on'): + '''Returns a list of items whose status matches status. If status is + not specified, the list of items in the "on" status will be returned. + Mode can be on, off, default''' + c = self.tk.split(self.tk.call(self._w, 'getselection', mode)) + return self.tk.splitlist(c) + + def getstatus(self, entrypath): + '''Returns the current status of entryPath.''' + return self.tk.call(self._w, 'getstatus', entrypath) + + def setstatus(self, entrypath, mode='on'): + '''Sets the status of entryPath to be status. A bitmap will be + displayed next to the entry its status is on, off or default.''' + self.tk.call(self._w, 'setstatus', entrypath, mode) + + +########################################################################### +### The subclassing below is used to instantiate the subwidgets in each ### +### mega widget. This allows us to access their methods directly. ### +########################################################################### + +class _dummyButton(Button, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + +class _dummyCheckbutton(Checkbutton, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + +class _dummyEntry(Entry, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + +class _dummyFrame(Frame, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + +class _dummyLabel(Label, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + +class _dummyListbox(Listbox, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + +class _dummyMenu(Menu, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + +class _dummyMenubutton(Menubutton, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + +class _dummyScrollbar(Scrollbar, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + +class _dummyText(Text, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + +class _dummyScrolledListBox(ScrolledListBox, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + self.subwidget_list['listbox'] = _dummyListbox(self, 'listbox') + self.subwidget_list['vsb'] = _dummyScrollbar(self, 'vsb') + self.subwidget_list['hsb'] = _dummyScrollbar(self, 'hsb') + +class _dummyHList(HList, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + +class _dummyScrolledHList(ScrolledHList, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + self.subwidget_list['hlist'] = _dummyHList(self, 'hlist') + self.subwidget_list['vsb'] = _dummyScrollbar(self, 'vsb') + self.subwidget_list['hsb'] = _dummyScrollbar(self, 'hsb') + +class _dummyTList(TList, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + +class _dummyComboBox(ComboBox, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, ['fancy',destroy_physically]) + self.subwidget_list['label'] = _dummyLabel(self, 'label') + self.subwidget_list['entry'] = _dummyEntry(self, 'entry') + self.subwidget_list['arrow'] = _dummyButton(self, 'arrow') + + self.subwidget_list['slistbox'] = _dummyScrolledListBox(self, + 'slistbox') + try: + self.subwidget_list['tick'] = _dummyButton(self, 'tick') + #cross Button : present if created with the fancy option + self.subwidget_list['cross'] = _dummyButton(self, 'cross') + except TypeError: + # unavailable when -fancy not specified + pass + +class _dummyDirList(DirList, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + self.subwidget_list['hlist'] = _dummyHList(self, 'hlist') + self.subwidget_list['vsb'] = _dummyScrollbar(self, 'vsb') + self.subwidget_list['hsb'] = _dummyScrollbar(self, 'hsb') + +class _dummyDirSelectBox(DirSelectBox, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + self.subwidget_list['dirlist'] = _dummyDirList(self, 'dirlist') + self.subwidget_list['dircbx'] = _dummyFileComboBox(self, 'dircbx') + +class _dummyExFileSelectBox(ExFileSelectBox, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + self.subwidget_list['cancel'] = _dummyButton(self, 'cancel') + self.subwidget_list['ok'] = _dummyButton(self, 'ok') + self.subwidget_list['hidden'] = _dummyCheckbutton(self, 'hidden') + self.subwidget_list['types'] = _dummyComboBox(self, 'types') + self.subwidget_list['dir'] = _dummyComboBox(self, 'dir') + self.subwidget_list['dirlist'] = _dummyScrolledListBox(self, 'dirlist') + self.subwidget_list['file'] = _dummyComboBox(self, 'file') + self.subwidget_list['filelist'] = _dummyScrolledListBox(self, 'filelist') + +class _dummyFileSelectBox(FileSelectBox, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + self.subwidget_list['dirlist'] = _dummyScrolledListBox(self, 'dirlist') + self.subwidget_list['filelist'] = _dummyScrolledListBox(self, 'filelist') + self.subwidget_list['filter'] = _dummyComboBox(self, 'filter') + self.subwidget_list['selection'] = _dummyComboBox(self, 'selection') + +class _dummyFileComboBox(ComboBox, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + self.subwidget_list['dircbx'] = _dummyComboBox(self, 'dircbx') + +class _dummyStdButtonBox(StdButtonBox, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + self.subwidget_list['ok'] = _dummyButton(self, 'ok') + self.subwidget_list['apply'] = _dummyButton(self, 'apply') + self.subwidget_list['cancel'] = _dummyButton(self, 'cancel') + self.subwidget_list['help'] = _dummyButton(self, 'help') + +class _dummyNoteBookFrame(NoteBookFrame, TixSubWidget): + def __init__(self, master, name, destroy_physically=0): + TixSubWidget.__init__(self, master, name, destroy_physically) + +class _dummyPanedWindow(PanedWindow, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) + +######################## +### Utility Routines ### +######################## + +#mike Should tixDestroy be exposed as a wrapper? - but not for widgets. + +def OptionName(widget): + '''Returns the qualified path name for the widget. Normally used to set + default options for subwidgets. See tixwidgets.py''' + return widget.tk.call('tixOptionName', widget._w) + +# Called with a dictionary argument of the form +# {'*.c':'C source files', '*.txt':'Text Files', '*':'All files'} +# returns a string which can be used to configure the fsbox file types +# in an ExFileSelectBox. i.e., +# '{{*} {* - All files}} {{*.c} {*.c - C source files}} {{*.txt} {*.txt - Text Files}}' +def FileTypeList(dict): + s = '' + for type in dict.keys(): + s = s + '{{' + type + '} {' + type + ' - ' + dict[type] + '}} ' + return s + +# Still to be done: +# tixIconView +class CObjView(TixWidget): + """This file implements the Canvas Object View widget. This is a base + class of IconView. It implements automatic placement/adjustment of the + scrollbars according to the canvas objects inside the canvas subwidget. + The scrollbars are adjusted so that the canvas is just large enough + to see all the objects. + """ + # FIXME: It should inherit -superclass tixScrolledWidget + pass + + +class Grid(TixWidget, XView, YView): + '''The Tix Grid command creates a new window and makes it into a + tixGrid widget. Additional options, may be specified on the command + line or in the option database to configure aspects such as its cursor + and relief. + + A Grid widget displays its contents in a two dimensional grid of cells. + Each cell may contain one Tix display item, which may be in text, + graphics or other formats. See the DisplayStyle class for more information + about Tix display items. Individual cells, or groups of cells, can be + formatted with a wide range of attributes, such as its color, relief and + border. + + Subwidgets - None''' + # valid specific resources as of Tk 8.4 + # editdonecmd, editnotifycmd, floatingcols, floatingrows, formatcmd, + # highlightbackground, highlightcolor, leftmargin, itemtype, selectmode, + # selectunit, topmargin, + def __init__(self, master=None, cnf={}, **kw): + static= [] + self.cnf= cnf + TixWidget.__init__(self, master, 'tixGrid', static, cnf, kw) + + # valid options as of Tk 8.4 + # anchor, bdtype, cget, configure, delete, dragsite, dropsite, entrycget, + # edit, entryconfigure, format, geometryinfo, info, index, move, nearest, + # selection, set, size, unset, xview, yview + def anchor_clear(self): + """Removes the selection anchor.""" + self.tk.call(self, 'anchor', 'clear') + + def anchor_get(self): + "Get the (x,y) coordinate of the current anchor cell" + return self._getints(self.tk.call(self, 'anchor', 'get')) + + def anchor_set(self, x, y): + """Set the selection anchor to the cell at (x, y).""" + self.tk.call(self, 'anchor', 'set', x, y) + + def delete_row(self, from_, to=None): + """Delete rows between from_ and to inclusive. + If to is not provided, delete only row at from_""" + if to is None: + self.tk.call(self, 'delete', 'row', from_) + else: + self.tk.call(self, 'delete', 'row', from_, to) + + def delete_column(self, from_, to=None): + """Delete columns between from_ and to inclusive. + If to is not provided, delete only column at from_""" + if to is None: + self.tk.call(self, 'delete', 'column', from_) + else: + self.tk.call(self, 'delete', 'column', from_, to) + + def edit_apply(self): + """If any cell is being edited, de-highlight the cell and applies + the changes.""" + self.tk.call(self, 'edit', 'apply') + + def edit_set(self, x, y): + """Highlights the cell at (x, y) for editing, if the -editnotify + command returns True for this cell.""" + self.tk.call(self, 'edit', 'set', x, y) + + def entrycget(self, x, y, option): + "Get the option value for cell at (x,y)" + if option and option[0] != '-': + option = '-' + option + return self.tk.call(self, 'entrycget', x, y, option) + + def entryconfigure(self, x, y, cnf=None, **kw): + return self._configure(('entryconfigure', x, y), cnf, kw) + + # def format + # def index + + def info_exists(self, x, y): + "Return True if display item exists at (x,y)" + return self._getboolean(self.tk.call(self, 'info', 'exists', x, y)) + + def info_bbox(self, x, y): + # This seems to always return '', at least for 'text' displayitems + return self.tk.call(self, 'info', 'bbox', x, y) + + def move_column(self, from_, to, offset): + """Moves the range of columns from position FROM through TO by + the distance indicated by OFFSET. For example, move_column(2, 4, 1) + moves the columns 2,3,4 to columns 3,4,5.""" + self.tk.call(self, 'move', 'column', from_, to, offset) + + def move_row(self, from_, to, offset): + """Moves the range of rows from position FROM through TO by + the distance indicated by OFFSET. + For example, move_row(2, 4, 1) moves the rows 2,3,4 to rows 3,4,5.""" + self.tk.call(self, 'move', 'row', from_, to, offset) + + def nearest(self, x, y): + "Return coordinate of cell nearest pixel coordinate (x,y)" + return self._getints(self.tk.call(self, 'nearest', x, y)) + + # def selection adjust + # def selection clear + # def selection includes + # def selection set + # def selection toggle + + def set(self, x, y, itemtype=None, **kw): + args= self._options(self.cnf, kw) + if itemtype is not None: + args= ('-itemtype', itemtype) + args + self.tk.call(self, 'set', x, y, *args) + + def size_column(self, index, **kw): + """Queries or sets the size of the column given by + INDEX. INDEX may be any non-negative + integer that gives the position of a given column. + INDEX can also be the string "default"; in this case, this command + queries or sets the default size of all columns. + When no option-value pair is given, this command returns a tuple + containing the current size setting of the given column. When + option-value pairs are given, the corresponding options of the + size setting of the given column are changed. Options may be one + of the follwing: + pad0 pixels + Specifies the paddings to the left of a column. + pad1 pixels + Specifies the paddings to the right of a column. + size val + Specifies the width of a column. Val may be: + "auto" -- the width of the column is set to the + width of the widest cell in the column; + a valid Tk screen distance unit; + or a real number following by the word chars + (e.g. 3.4chars) that sets the width of the column to the + given number of characters.""" + return self.tk.split(self.tk.call(self._w, 'size', 'column', index, + *self._options({}, kw))) + + def size_row(self, index, **kw): + """Queries or sets the size of the row given by + INDEX. INDEX may be any non-negative + integer that gives the position of a given row . + INDEX can also be the string "default"; in this case, this command + queries or sets the default size of all rows. + When no option-value pair is given, this command returns a list con- + taining the current size setting of the given row . When option-value + pairs are given, the corresponding options of the size setting of the + given row are changed. Options may be one of the follwing: + pad0 pixels + Specifies the paddings to the top of a row. + pad1 pixels + Specifies the paddings to the bottom of a row. + size val + Specifies the height of a row. Val may be: + "auto" -- the height of the row is set to the + height of the highest cell in the row; + a valid Tk screen distance unit; + or a real number following by the word chars + (e.g. 3.4chars) that sets the height of the row to the + given number of characters.""" + return self.tk.split(self.tk.call( + self, 'size', 'row', index, *self._options({}, kw))) + + def unset(self, x, y): + """Clears the cell at (x, y) by removing its display item.""" + self.tk.call(self._w, 'unset', x, y) + + +class ScrolledGrid(Grid): + '''Scrolled Grid widgets''' + + # FIXME: It should inherit -superclass tixScrolledWidget + def __init__(self, master=None, cnf={}, **kw): + static= [] + self.cnf= cnf + TixWidget.__init__(self, master, 'tixScrolledGrid', static, cnf, kw) diff --git a/PythonHome/Lib/lib-tk/Tix.pyc b/PythonHome/Lib/lib-tk/Tix.pyc deleted file mode 100644 index 2642bd6c400fdff68d41e5c9a7416c8cc76ce0e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91067 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 to a callback function that you write. The function +should call Tkdnd.dnd_start(source, event), where 'source' is the +object to be dragged, and 'event' is the event that invoked the call +(the argument to your callback function). Even though this is a class +instantiation, the returned instance should not be stored -- it will +be kept alive automatically for the duration of the drag-and-drop. + +When a drag-and-drop is already in process for the Tk interpreter, the +call is *ignored*; this normally averts starting multiple simultaneous +dnd processes, e.g. because different button callbacks all +dnd_start(). + +The object is *not* necessarily a widget -- it can be any +application-specific object that is meaningful to potential +drag-and-drop targets. + +Potential drag-and-drop targets are discovered as follows. Whenever +the mouse moves, and at the start and end of a drag-and-drop move, the +Tk widget directly under the mouse is inspected. This is the target +widget (not to be confused with the target object, yet to be +determined). If there is no target widget, there is no dnd target +object. If there is a target widget, and it has an attribute +dnd_accept, this should be a function (or any callable object). The +function is called as dnd_accept(source, event), where 'source' is the +object being dragged (the object passed to dnd_start() above), and +'event' is the most recent event object (generally a event; +it can also be or ). If the dnd_accept() +function returns something other than None, this is the new dnd target +object. If dnd_accept() returns None, or if the target widget has no +dnd_accept attribute, the target widget's parent is considered as the +target widget, and the search for a target object is repeated from +there. If necessary, the search is repeated all the way up to the +root widget. If none of the target widgets can produce a target +object, there is no target object (the target object is None). + +The target object thus produced, if any, is called the new target +object. It is compared with the old target object (or None, if there +was no old target widget). There are several cases ('source' is the +source object, and 'event' is the most recent event object): + +- Both the old and new target objects are None. Nothing happens. + +- The old and new target objects are the same object. Its method +dnd_motion(source, event) is called. + +- The old target object was None, and the new target object is not +None. The new target object's method dnd_enter(source, event) is +called. + +- The new target object is None, and the old target object is not +None. The old target object's method dnd_leave(source, event) is +called. + +- The old and new target objects differ and neither is None. The old +target object's method dnd_leave(source, event), and then the new +target object's method dnd_enter(source, event) is called. + +Once this is done, the new target object replaces the old one, and the +Tk mainloop proceeds. The return value of the methods mentioned above +is ignored; if they raise an exception, the normal exception handling +mechanisms take over. + +The drag-and-drop processes can end in two ways: a final target object +is selected, or no final target object is selected. When a final +target object is selected, it will always have been notified of the +potential drop by a call to its dnd_enter() method, as described +above, and possibly one or more calls to its dnd_motion() method; its +dnd_leave() method has not been called since the last call to +dnd_enter(). The target is notified of the drop by a call to its +method dnd_commit(source, event). + +If no final target object is selected, and there was an old target +object, its dnd_leave(source, event) method is called to complete the +dnd sequence. + +Finally, the source object is notified that the drag-and-drop process +is over, by a call to source.dnd_end(target, event), specifying either +the selected target object, or None if no target object was selected. +The source object can use this to implement the commit action; this is +sometimes simpler than to do it in the target's dnd_commit(). The +target's dnd_commit() method could then simply be aliased to +dnd_leave(). + +At any time during a dnd sequence, the application can cancel the +sequence by calling the cancel() method on the object returned by +dnd_start(). This will call dnd_leave() if a target is currently +active; it will never call dnd_commit(). + +""" + + +import Tkinter + + +# The factory function + +def dnd_start(source, event): + h = DndHandler(source, event) + if h.root: + return h + else: + return None + + +# The class that does the work + +class DndHandler: + + root = None + + def __init__(self, source, event): + if event.num > 5: + return + root = event.widget._root() + try: + root.__dnd + return # Don't start recursive dnd + except AttributeError: + root.__dnd = self + self.root = root + self.source = source + self.target = None + self.initial_button = button = event.num + self.initial_widget = widget = event.widget + self.release_pattern = "" % (button, button) + self.save_cursor = widget['cursor'] or "" + widget.bind(self.release_pattern, self.on_release) + widget.bind("", self.on_motion) + widget['cursor'] = "hand2" + + def __del__(self): + root = self.root + self.root = None + if root: + try: + del root.__dnd + except AttributeError: + pass + + def on_motion(self, event): + x, y = event.x_root, event.y_root + target_widget = self.initial_widget.winfo_containing(x, y) + source = self.source + new_target = None + while target_widget: + try: + attr = target_widget.dnd_accept + except AttributeError: + pass + else: + new_target = attr(source, event) + if new_target: + break + target_widget = target_widget.master + old_target = self.target + if old_target is new_target: + if old_target: + old_target.dnd_motion(source, event) + else: + if old_target: + self.target = None + old_target.dnd_leave(source, event) + if new_target: + new_target.dnd_enter(source, event) + self.target = new_target + + def on_release(self, event): + self.finish(event, 1) + + def cancel(self, event=None): + self.finish(event, 0) + + def finish(self, event, commit=0): + target = self.target + source = self.source + widget = self.initial_widget + root = self.root + try: + del root.__dnd + self.initial_widget.unbind(self.release_pattern) + self.initial_widget.unbind("") + widget['cursor'] = self.save_cursor + self.target = self.source = self.initial_widget = self.root = None + if target: + if commit: + target.dnd_commit(source, event) + else: + target.dnd_leave(source, event) + finally: + source.dnd_end(target, event) + + + +# ---------------------------------------------------------------------- +# The rest is here for testing and demonstration purposes only! + +class Icon: + + def __init__(self, name): + self.name = name + self.canvas = self.label = self.id = None + + def attach(self, canvas, x=10, y=10): + if canvas is self.canvas: + self.canvas.coords(self.id, x, y) + return + if self.canvas: + self.detach() + if not canvas: + return + label = Tkinter.Label(canvas, text=self.name, + borderwidth=2, relief="raised") + id = canvas.create_window(x, y, window=label, anchor="nw") + self.canvas = canvas + self.label = label + self.id = id + label.bind("", self.press) + + def detach(self): + canvas = self.canvas + if not canvas: + return + id = self.id + label = self.label + self.canvas = self.label = self.id = None + canvas.delete(id) + label.destroy() + + def press(self, event): + if dnd_start(self, event): + # where the pointer is relative to the label widget: + self.x_off = event.x + self.y_off = event.y + # where the widget is relative to the canvas: + self.x_orig, self.y_orig = self.canvas.coords(self.id) + + def move(self, event): + x, y = self.where(self.canvas, event) + self.canvas.coords(self.id, x, y) + + def putback(self): + self.canvas.coords(self.id, self.x_orig, self.y_orig) + + def where(self, canvas, event): + # where the corner of the canvas is relative to the screen: + x_org = canvas.winfo_rootx() + y_org = canvas.winfo_rooty() + # where the pointer is relative to the canvas widget: + x = event.x_root - x_org + y = event.y_root - y_org + # compensate for initial pointer offset + return x - self.x_off, y - self.y_off + + def dnd_end(self, target, event): + pass + +class Tester: + + def __init__(self, root): + self.top = Tkinter.Toplevel(root) + self.canvas = Tkinter.Canvas(self.top, width=100, height=100) + self.canvas.pack(fill="both", expand=1) + self.canvas.dnd_accept = self.dnd_accept + + def dnd_accept(self, source, event): + return self + + def dnd_enter(self, source, event): + self.canvas.focus_set() # Show highlight border + x, y = source.where(self.canvas, event) + x1, y1, x2, y2 = source.canvas.bbox(source.id) + dx, dy = x2-x1, y2-y1 + self.dndid = self.canvas.create_rectangle(x, y, x+dx, y+dy) + self.dnd_motion(source, event) + + def dnd_motion(self, source, event): + x, y = source.where(self.canvas, event) + x1, y1, x2, y2 = self.canvas.bbox(self.dndid) + self.canvas.move(self.dndid, x-x1, y-y1) + + def dnd_leave(self, source, event): + self.top.focus_set() # Hide highlight border + self.canvas.delete(self.dndid) + self.dndid = None + + def dnd_commit(self, source, event): + self.dnd_leave(source, event) + x, y = source.where(self.canvas, event) + source.attach(self.canvas, x, y) + +def test(): + root = Tkinter.Tk() + root.geometry("+1+1") + Tkinter.Button(command=root.quit, text="Quit").pack() + t1 = Tester(root) + t1.top.geometry("+1+60") + t2 = Tester(root) + t2.top.geometry("+120+60") + t3 = Tester(root) + t3.top.geometry("+240+60") + i1 = Icon("ICON1") + i2 = Icon("ICON2") + i3 = Icon("ICON3") + i1.attach(t1.canvas) + i2.attach(t2.canvas) + i3.attach(t3.canvas) + root.mainloop() + +if __name__ == '__main__': + test() diff --git a/PythonHome/Lib/lib-tk/Tkdnd.pyc b/PythonHome/Lib/lib-tk/Tkdnd.pyc deleted file mode 100644 index c50d19a10d1164b5802faa98c98a25db86f1fc6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12435 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 J@4U3$_&>(VdA9%n diff --git a/PythonHome/Lib/lib-tk/Tkinter.py b/PythonHome/Lib/lib-tk/Tkinter.py new file mode 100644 index 0000000000..d3d7d83959 --- /dev/null +++ b/PythonHome/Lib/lib-tk/Tkinter.py @@ -0,0 +1,3809 @@ +"""Wrapper functions for Tcl/Tk. + +Tkinter provides classes which allow the display, positioning and +control of widgets. Toplevel widgets are Tk and Toplevel. Other +widgets are Frame, Label, Entry, Text, Canvas, Button, Radiobutton, +Checkbutton, Scale, Listbox, Scrollbar, OptionMenu, Spinbox +LabelFrame and PanedWindow. + +Properties of the widgets are specified with keyword arguments. +Keyword arguments have the same name as the corresponding resource +under Tk. + +Widgets are positioned with one of the geometry managers Place, Pack +or Grid. These managers can be called with methods place, pack, grid +available in every Widget. + +Actions are bound to events by resources (e.g. keyword argument +command) or with the method bind. + +Example (Hello, World): +import Tkinter +from Tkconstants import * +tk = Tkinter.Tk() +frame = Tkinter.Frame(tk, relief=RIDGE, borderwidth=2) +frame.pack(fill=BOTH,expand=1) +label = Tkinter.Label(frame, text="Hello, World") +label.pack(fill=X, expand=1) +button = Tkinter.Button(frame,text="Exit",command=tk.destroy) +button.pack(side=BOTTOM) +tk.mainloop() +""" + +__version__ = "$Revision: 81008 $" + +import sys +if sys.platform == "win32": + # Attempt to configure Tcl/Tk without requiring PATH + import FixTk +import _tkinter # If this fails your Python may not be configured for Tk +tkinter = _tkinter # b/w compat for export +TclError = _tkinter.TclError +from types import * +from Tkconstants import * +import re + +wantobjects = 1 + +TkVersion = float(_tkinter.TK_VERSION) +TclVersion = float(_tkinter.TCL_VERSION) + +READABLE = _tkinter.READABLE +WRITABLE = _tkinter.WRITABLE +EXCEPTION = _tkinter.EXCEPTION + +# These are not always defined, e.g. not on Win32 with Tk 8.0 :-( +try: _tkinter.createfilehandler +except AttributeError: _tkinter.createfilehandler = None +try: _tkinter.deletefilehandler +except AttributeError: _tkinter.deletefilehandler = None + + +_magic_re = re.compile(r'([\\{}])') +_space_re = re.compile(r'([\s])') + +def _join(value): + """Internal function.""" + return ' '.join(map(_stringify, value)) + +def _stringify(value): + """Internal function.""" + if isinstance(value, (list, tuple)): + if len(value) == 1: + value = _stringify(value[0]) + if value[0] == '{': + value = '{%s}' % value + else: + value = '{%s}' % _join(value) + else: + if isinstance(value, str): + value = unicode(value, 'utf-8') + elif not isinstance(value, unicode): + value = str(value) + if not value: + value = '{}' + elif _magic_re.search(value): + # add '\' before special characters and spaces + value = _magic_re.sub(r'\\\1', value) + value = _space_re.sub(r'\\\1', value) + elif value[0] == '"' or _space_re.search(value): + value = '{%s}' % value + return value + +def _flatten(tuple): + """Internal function.""" + res = () + for item in tuple: + if type(item) in (TupleType, ListType): + res = res + _flatten(item) + elif item is not None: + res = res + (item,) + return res + +try: _flatten = _tkinter._flatten +except AttributeError: pass + +def _cnfmerge(cnfs): + """Internal function.""" + if type(cnfs) is DictionaryType: + return cnfs + elif type(cnfs) in (NoneType, StringType): + return cnfs + else: + cnf = {} + for c in _flatten(cnfs): + try: + cnf.update(c) + except (AttributeError, TypeError), msg: + print "_cnfmerge: fallback due to:", msg + for k, v in c.items(): + cnf[k] = v + return cnf + +try: _cnfmerge = _tkinter._cnfmerge +except AttributeError: pass + +class Event: + """Container for the properties of an event. + + Instances of this type are generated if one of the following events occurs: + + KeyPress, KeyRelease - for keyboard events + ButtonPress, ButtonRelease, Motion, Enter, Leave, MouseWheel - for mouse events + Visibility, Unmap, Map, Expose, FocusIn, FocusOut, Circulate, + Colormap, Gravity, Reparent, Property, Destroy, Activate, + Deactivate - for window events. + + If a callback function for one of these events is registered + using bind, bind_all, bind_class, or tag_bind, the callback is + called with an Event as first argument. It will have the + following attributes (in braces are the event types for which + the attribute is valid): + + serial - serial number of event + num - mouse button pressed (ButtonPress, ButtonRelease) + focus - whether the window has the focus (Enter, Leave) + height - height of the exposed window (Configure, Expose) + width - width of the exposed window (Configure, Expose) + keycode - keycode of the pressed key (KeyPress, KeyRelease) + state - state of the event as a number (ButtonPress, ButtonRelease, + Enter, KeyPress, KeyRelease, + Leave, Motion) + state - state as a string (Visibility) + time - when the event occurred + x - x-position of the mouse + y - y-position of the mouse + x_root - x-position of the mouse on the screen + (ButtonPress, ButtonRelease, KeyPress, KeyRelease, Motion) + y_root - y-position of the mouse on the screen + (ButtonPress, ButtonRelease, KeyPress, KeyRelease, Motion) + char - pressed character (KeyPress, KeyRelease) + send_event - see X/Windows documentation + keysym - keysym of the event as a string (KeyPress, KeyRelease) + keysym_num - keysym of the event as a number (KeyPress, KeyRelease) + type - type of the event as a number + widget - widget in which the event occurred + delta - delta of wheel movement (MouseWheel) + """ + pass + +_support_default_root = 1 +_default_root = None + +def NoDefaultRoot(): + """Inhibit setting of default root window. + + 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 + _default_root = None + del _default_root + +def _tkerror(err): + """Internal function.""" + pass + +def _exit(code=0): + """Internal function. Calling it will raise the exception SystemExit.""" + try: + code = int(code) + except ValueError: + pass + raise SystemExit, code + +_varnum = 0 +class Variable: + """Class to define value holders for e.g. buttons. + + Subclasses StringVar, IntVar, DoubleVar, BooleanVar are specializations + that constrain the type of the value returned from get().""" + _default = "" + def __init__(self, master=None, value=None, name=None): + """Construct a variable + + MASTER can be given as master widget. + VALUE is an optional value (defaults to "") + NAME is an optional Tcl name (defaults to PY_VARnum). + + If NAME matches an existing variable and VALUE is omitted + then the existing value is retained. + """ + global _varnum + if not master: + master = _default_root + self._master = master + self._tk = master.tk + if name: + self._name = name + else: + self._name = 'PY_VAR' + repr(_varnum) + _varnum += 1 + if value is not None: + self.set(value) + elif not self._tk.getboolean(self._tk.call("info", "exists", self._name)): + self.set(self._default) + def __del__(self): + """Unset the variable in Tcl.""" + if (self._tk is not None and + self._tk.getboolean(self._tk.call("info", "exists", self._name))): + self._tk.globalunsetvar(self._name) + def __str__(self): + """Return the name of the variable in Tcl.""" + return self._name + def set(self, value): + """Set the variable to VALUE.""" + return self._tk.globalsetvar(self._name, value) + def get(self): + """Return value of variable.""" + return self._tk.globalgetvar(self._name) + def trace_variable(self, mode, callback): + """Define a trace callback for the variable. + + MODE is one of "r", "w", "u" for read, write, undefine. + CALLBACK must be a function which is called when + the variable is read, written or undefined. + + Return the name of the callback. + """ + cbname = self._master._register(callback) + self._tk.call("trace", "variable", self._name, mode, cbname) + return cbname + trace = trace_variable + def trace_vdelete(self, mode, cbname): + """Delete the trace callback for a variable. + + MODE is one of "r", "w", "u" for read, write, undefine. + CBNAME is the name of the callback returned from trace_variable or trace. + """ + self._tk.call("trace", "vdelete", self._name, mode, cbname) + self._master.deletecommand(cbname) + def trace_vinfo(self): + """Return all trace callback information.""" + return map(self._tk.split, self._tk.splitlist( + 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 + """ + return self.__class__.__name__ == other.__class__.__name__ \ + and self._name == other._name + +class StringVar(Variable): + """Value holder for strings variables.""" + _default = "" + def __init__(self, master=None, value=None, name=None): + """Construct a string variable. + + MASTER can be given as master widget. + VALUE is an optional value (defaults to "") + NAME is an optional Tcl name (defaults to PY_VARnum). + + If NAME matches an existing variable and VALUE is omitted + then the existing value is retained. + """ + Variable.__init__(self, master, value, name) + + def get(self): + """Return value of variable as string.""" + value = self._tk.globalgetvar(self._name) + if isinstance(value, basestring): + return value + return str(value) + +class IntVar(Variable): + """Value holder for integer variables.""" + _default = 0 + def __init__(self, master=None, value=None, name=None): + """Construct an integer variable. + + MASTER can be given as master widget. + VALUE is an optional value (defaults to 0) + NAME is an optional Tcl name (defaults to PY_VARnum). + + If NAME matches an existing variable and VALUE is omitted + then the existing value is retained. + """ + Variable.__init__(self, master, value, name) + + def set(self, value): + """Set the variable to value, converting booleans to integers.""" + if isinstance(value, bool): + value = int(value) + return Variable.set(self, value) + + def get(self): + """Return the value of the variable as an integer.""" + return getint(self._tk.globalgetvar(self._name)) + +class DoubleVar(Variable): + """Value holder for float variables.""" + _default = 0.0 + def __init__(self, master=None, value=None, name=None): + """Construct a float variable. + + MASTER can be given as master widget. + VALUE is an optional value (defaults to 0.0) + NAME is an optional Tcl name (defaults to PY_VARnum). + + If NAME matches an existing variable and VALUE is omitted + then the existing value is retained. + """ + Variable.__init__(self, master, value, name) + + def get(self): + """Return the value of the variable as a float.""" + return getdouble(self._tk.globalgetvar(self._name)) + +class BooleanVar(Variable): + """Value holder for boolean variables.""" + _default = False + def __init__(self, master=None, value=None, name=None): + """Construct a boolean variable. + + MASTER can be given as master widget. + VALUE is an optional value (defaults to False) + NAME is an optional Tcl name (defaults to PY_VARnum). + + If NAME matches an existing variable and VALUE is omitted + then the existing value is retained. + """ + Variable.__init__(self, master, value, name) + + def get(self): + """Return the value of the variable as a bool.""" + return self._tk.getboolean(self._tk.globalgetvar(self._name)) + +def mainloop(n=0): + """Run the main loop of Tcl.""" + _default_root.tk.mainloop(n) + +getint = int + +getdouble = float + +def getboolean(s): + """Convert true and false to integer values 1 and 0.""" + return _default_root.tk.getboolean(s) + +# Methods defined on both toplevel and interior widgets +class Misc: + """Internal class. + + Base class which defines methods common for interior widgets.""" + + # XXX font command? + _tclCommands = None + def destroy(self): + """Internal function. + + Delete all Tcl commands created for + this widget in the Tcl interpreter.""" + if self._tclCommands is not None: + for name in self._tclCommands: + #print '- Tkinter: deleted command', name + self.tk.deletecommand(name) + self._tclCommands = None + def deletecommand(self, name): + """Internal function. + + Delete the Tcl command provided in NAME.""" + #print '- Tkinter: deleted command', name + self.tk.deletecommand(name) + try: + self._tclCommands.remove(name) + except ValueError: + pass + def tk_strictMotif(self, boolean=None): + """Set Tcl internal variable, whether the look and feel + should adhere to Motif. + + A parameter of 1 means adhere to Motif (e.g. no color + change if mouse passes over slider). + Returns the set value.""" + return self.tk.getboolean(self.tk.call( + 'set', 'tk_strictMotif', boolean)) + def tk_bisque(self): + """Change the color scheme to light brown as used in Tk 3.6 and before.""" + self.tk.call('tk_bisque') + def tk_setPalette(self, *args, **kw): + """Set a new color scheme for all widget elements. + + A single color as argument will cause that all colors of Tk + widget elements are derived from this. + Alternatively several keyword parameters and its associated + colors can be given. The following keywords are valid: + activeBackground, foreground, selectColor, + activeForeground, highlightBackground, selectBackground, + background, highlightColor, selectForeground, + disabledForeground, insertBackground, troughColor.""" + self.tk.call(('tk_setPalette',) + + _flatten(args) + _flatten(kw.items())) + def tk_menuBar(self, *args): + """Do not use. Needed in Tk 3.6 and earlier.""" + pass # obsolete since Tk 4.0 + def wait_variable(self, name='PY_VAR'): + """Wait until the variable is modified. + + A parameter of type IntVar, StringVar, DoubleVar or + BooleanVar must be given.""" + self.tk.call('tkwait', 'variable', name) + waitvar = wait_variable # XXX b/w compat + def wait_window(self, window=None): + """Wait until a WIDGET is destroyed. + + If no parameter is given self is used.""" + if window is None: + window = self + self.tk.call('tkwait', 'window', window._w) + def wait_visibility(self, window=None): + """Wait until the visibility of a WIDGET changes + (e.g. it appears). + + If no parameter is given self is used.""" + if window is None: + window = self + self.tk.call('tkwait', 'visibility', window._w) + def setvar(self, name='PY_VAR', value='1'): + """Set Tcl variable NAME to VALUE.""" + self.tk.setvar(name, value) + def getvar(self, name='PY_VAR'): + """Return value of Tcl variable NAME.""" + return self.tk.getvar(name) + getint = int + getdouble = float + def getboolean(self, s): + """Return a boolean value for Tcl boolean values true and false given as parameter.""" + return self.tk.getboolean(s) + def focus_set(self): + """Direct input focus to this widget. + + If the application currently does not have the focus + this widget will get the focus if the application gets + the focus through the window manager.""" + self.tk.call('focus', self._w) + focus = focus_set # XXX b/w compat? + def focus_force(self): + """Direct input focus to this widget even if the + application does not have the focus. Use with + caution!""" + self.tk.call('focus', '-force', self._w) + def focus_get(self): + """Return the widget which has currently the focus in the + application. + + Use focus_displayof to allow working with several + displays. Return None if application does not have + the focus.""" + name = self.tk.call('focus') + if name == 'none' or not name: return None + return self._nametowidget(name) + def focus_displayof(self): + """Return the widget which has currently the focus on the + display where this widget is located. + + Return None if the application does not have the focus.""" + name = self.tk.call('focus', '-displayof', self._w) + if name == 'none' or not name: return None + return self._nametowidget(name) + def focus_lastfor(self): + """Return the widget which would have the focus if top level + for this widget gets the focus from the window manager.""" + name = self.tk.call('focus', '-lastfor', self._w) + if name == 'none' or not name: return None + return self._nametowidget(name) + def tk_focusFollowsMouse(self): + """The widget under mouse will get automatically focus. Can not + be disabled easily.""" + self.tk.call('tk_focusFollowsMouse') + def tk_focusNext(self): + """Return the next widget in the focus order which follows + widget which has currently the focus. + + The focus order first goes to the next child, then to + the children of the child recursively and then to the + next sibling which is higher in the stacking order. A + widget is omitted if it has the takefocus resource set + to 0.""" + name = self.tk.call('tk_focusNext', self._w) + if not name: return None + return self._nametowidget(name) + def tk_focusPrev(self): + """Return previous widget in the focus order. See tk_focusNext for details.""" + name = self.tk.call('tk_focusPrev', self._w) + if not name: return None + return self._nametowidget(name) + def after(self, ms, func=None, *args): + """Call function once after given time. + + MS specifies the time in milliseconds. FUNC gives the + function which shall be called. Additional parameters + are given as parameters to the function call. Return + identifier to cancel scheduling with after_cancel.""" + if not func: + # I'd rather use time.sleep(ms*0.001) + self.tk.call('after', ms) + else: + def callit(): + try: + func(*args) + finally: + try: + self.deletecommand(name) + except TclError: + pass + name = self._register(callit) + return self.tk.call('after', ms, name) + def after_idle(self, func, *args): + """Call FUNC once if the Tcl main loop has no event to + process. + + Return an identifier to cancel the scheduling with + after_cancel.""" + return self.after('idle', func, *args) + def after_cancel(self, id): + """Cancel scheduling of function identified with ID. + + Identifier returned by after or after_idle must be + given as first parameter.""" + try: + data = self.tk.call('after', 'info', id) + # In Tk 8.3, splitlist returns: (script, type) + # In Tk 8.4, splitlist may return (script, type) or (script,) + script = self.tk.splitlist(data)[0] + self.deletecommand(script) + except TclError: + pass + self.tk.call('after', 'cancel', id) + def bell(self, displayof=0): + """Ring a display's bell.""" + self.tk.call(('bell',) + self._displayof(displayof)) + + # Clipboard handling: + def clipboard_get(self, **kw): + """Retrieve data from the clipboard on window's display. + + The window keyword defaults to the root window of the Tkinter + application. + + The type keyword specifies the form in which the data is + to be returned and should be an atom name such as STRING + or FILE_NAME. Type defaults to STRING, except on X11, where the default + is to try UTF8_STRING and fall back to STRING. + + This command is equivalent to: + + selection_get(CLIPBOARD) + """ + if 'type' not in kw and self._windowingsystem == 'x11': + try: + kw['type'] = 'UTF8_STRING' + return self.tk.call(('clipboard', 'get') + self._options(kw)) + except TclError: + del kw['type'] + return self.tk.call(('clipboard', 'get') + self._options(kw)) + + def clipboard_clear(self, **kw): + """Clear the data in the Tk clipboard. + + A widget specified for the optional displayof keyword + argument specifies the target display.""" + if 'displayof' not in kw: kw['displayof'] = self._w + self.tk.call(('clipboard', 'clear') + self._options(kw)) + def clipboard_append(self, string, **kw): + """Append STRING to the Tk clipboard. + + A widget specified at the optional displayof keyword + argument specifies the target display. The clipboard + can be retrieved with selection_get.""" + if 'displayof' not in kw: kw['displayof'] = self._w + self.tk.call(('clipboard', 'append') + self._options(kw) + + ('--', string)) + # XXX grab current w/o window argument + def grab_current(self): + """Return widget which has currently the grab in this application + or None.""" + name = self.tk.call('grab', 'current', self._w) + if not name: return None + return self._nametowidget(name) + def grab_release(self): + """Release grab for this widget if currently set.""" + self.tk.call('grab', 'release', self._w) + def grab_set(self): + """Set grab for this widget. + + A grab directs all events to this and descendant + widgets in the application.""" + self.tk.call('grab', 'set', self._w) + def grab_set_global(self): + """Set global grab for this widget. + + A global grab directs all events to this and + descendant widgets on the display. Use with caution - + other applications do not get events anymore.""" + self.tk.call('grab', 'set', '-global', self._w) + def grab_status(self): + """Return None, "local" or "global" if this widget has + no, a local or a global grab.""" + status = self.tk.call('grab', 'status', self._w) + if status == 'none': status = None + return status + def option_add(self, pattern, value, priority = None): + """Set a VALUE (second parameter) for an option + PATTERN (first parameter). + + An optional third parameter gives the numeric priority + (defaults to 80).""" + self.tk.call('option', 'add', pattern, value, priority) + def option_clear(self): + """Clear the option database. + + It will be reloaded if option_add is called.""" + self.tk.call('option', 'clear') + def option_get(self, name, className): + """Return the value for an option NAME for this widget + with CLASSNAME. + + Values with higher priority override lower values.""" + return self.tk.call('option', 'get', self._w, name, className) + def option_readfile(self, fileName, priority = None): + """Read file FILENAME into the option database. + + An optional second parameter gives the numeric + priority.""" + self.tk.call('option', 'readfile', fileName, priority) + def selection_clear(self, **kw): + """Clear the current X selection.""" + if 'displayof' not in kw: kw['displayof'] = self._w + self.tk.call(('selection', 'clear') + self._options(kw)) + def selection_get(self, **kw): + """Return the contents of the current X selection. + + A keyword parameter selection specifies the name of + the selection and defaults to PRIMARY. A keyword + parameter displayof specifies a widget on the display + to use. A keyword parameter type specifies the form of data to be + fetched, defaulting to STRING except on X11, where UTF8_STRING is tried + before STRING.""" + if 'displayof' not in kw: kw['displayof'] = self._w + if 'type' not in kw and self._windowingsystem == 'x11': + try: + kw['type'] = 'UTF8_STRING' + return self.tk.call(('selection', 'get') + self._options(kw)) + except TclError: + del kw['type'] + return self.tk.call(('selection', 'get') + self._options(kw)) + def selection_handle(self, command, **kw): + """Specify a function COMMAND to call if the X + selection owned by this widget is queried by another + application. + + This function must return the contents of the + selection. The function will be called with the + arguments OFFSET and LENGTH which allows the chunking + of very long selections. The following keyword + parameters can be provided: + selection - name of the selection (default PRIMARY), + type - type of the selection (e.g. STRING, FILE_NAME).""" + name = self._register(command) + self.tk.call(('selection', 'handle') + self._options(kw) + + (self._w, name)) + def selection_own(self, **kw): + """Become owner of X selection. + + A keyword parameter selection specifies the name of + the selection (default PRIMARY).""" + self.tk.call(('selection', 'own') + + self._options(kw) + (self._w,)) + def selection_own_get(self, **kw): + """Return owner of X selection. + + The following keyword parameter can + be provided: + selection - name of the selection (default PRIMARY), + type - type of the selection (e.g. STRING, FILE_NAME).""" + if 'displayof' not in kw: kw['displayof'] = self._w + name = self.tk.call(('selection', 'own') + self._options(kw)) + if not name: return None + return self._nametowidget(name) + def send(self, interp, cmd, *args): + """Send Tcl command CMD to different interpreter INTERP to be executed.""" + return self.tk.call(('send', interp, cmd) + args) + def lower(self, belowThis=None): + """Lower this widget in the stacking order.""" + self.tk.call('lower', self._w, belowThis) + def tkraise(self, aboveThis=None): + """Raise this widget in the stacking order.""" + self.tk.call('raise', self._w, aboveThis) + lift = tkraise + def colormodel(self, value=None): + """Useless. Not implemented in Tk.""" + return self.tk.call('tk', 'colormodel', self._w, value) + def winfo_atom(self, name, displayof=0): + """Return integer which represents atom NAME.""" + args = ('winfo', 'atom') + self._displayof(displayof) + (name,) + return getint(self.tk.call(args)) + def winfo_atomname(self, id, displayof=0): + """Return name of atom with identifier ID.""" + args = ('winfo', 'atomname') \ + + self._displayof(displayof) + (id,) + return self.tk.call(args) + def winfo_cells(self): + """Return number of cells in the colormap for this widget.""" + return getint( + self.tk.call('winfo', 'cells', self._w)) + def winfo_children(self): + """Return a list of all widgets which are children of this widget.""" + result = [] + for child in self.tk.splitlist( + self.tk.call('winfo', 'children', self._w)): + try: + # Tcl sometimes returns extra windows, e.g. for + # menus; those need to be skipped + result.append(self._nametowidget(child)) + except KeyError: + pass + return result + + def winfo_class(self): + """Return window class name of this widget.""" + return self.tk.call('winfo', 'class', self._w) + def winfo_colormapfull(self): + """Return true if at the last color request the colormap was full.""" + return self.tk.getboolean( + self.tk.call('winfo', 'colormapfull', self._w)) + def winfo_containing(self, rootX, rootY, displayof=0): + """Return the widget which is at the root coordinates ROOTX, ROOTY.""" + args = ('winfo', 'containing') \ + + self._displayof(displayof) + (rootX, rootY) + name = self.tk.call(args) + if not name: return None + return self._nametowidget(name) + def winfo_depth(self): + """Return the number of bits per pixel.""" + return getint(self.tk.call('winfo', 'depth', self._w)) + def winfo_exists(self): + """Return true if this widget exists.""" + return getint( + self.tk.call('winfo', 'exists', self._w)) + def winfo_fpixels(self, number): + """Return the number of pixels for the given distance NUMBER + (e.g. "3c") as float.""" + return getdouble(self.tk.call( + 'winfo', 'fpixels', self._w, number)) + def winfo_geometry(self): + """Return geometry string for this widget in the form "widthxheight+X+Y".""" + return self.tk.call('winfo', 'geometry', self._w) + def winfo_height(self): + """Return height of this widget.""" + return getint( + self.tk.call('winfo', 'height', self._w)) + def winfo_id(self): + """Return identifier ID for this widget.""" + return self.tk.getint( + self.tk.call('winfo', 'id', self._w)) + def winfo_interps(self, displayof=0): + """Return the name of all Tcl interpreters for this display.""" + args = ('winfo', 'interps') + self._displayof(displayof) + return self.tk.splitlist(self.tk.call(args)) + def winfo_ismapped(self): + """Return true if this widget is mapped.""" + return getint( + self.tk.call('winfo', 'ismapped', self._w)) + def winfo_manager(self): + """Return the window mananger name for this widget.""" + return self.tk.call('winfo', 'manager', self._w) + def winfo_name(self): + """Return the name of this widget.""" + return self.tk.call('winfo', 'name', self._w) + def winfo_parent(self): + """Return the name of the parent of this widget.""" + return self.tk.call('winfo', 'parent', self._w) + def winfo_pathname(self, id, displayof=0): + """Return the pathname of the widget given by ID.""" + args = ('winfo', 'pathname') \ + + self._displayof(displayof) + (id,) + return self.tk.call(args) + def winfo_pixels(self, number): + """Rounded integer value of winfo_fpixels.""" + return getint( + self.tk.call('winfo', 'pixels', self._w, number)) + def winfo_pointerx(self): + """Return the x coordinate of the pointer on the root window.""" + return getint( + self.tk.call('winfo', 'pointerx', self._w)) + def winfo_pointerxy(self): + """Return a tuple of x and y coordinates of the pointer on the root window.""" + return self._getints( + self.tk.call('winfo', 'pointerxy', self._w)) + def winfo_pointery(self): + """Return the y coordinate of the pointer on the root window.""" + return getint( + self.tk.call('winfo', 'pointery', self._w)) + def winfo_reqheight(self): + """Return requested height of this widget.""" + return getint( + self.tk.call('winfo', 'reqheight', self._w)) + def winfo_reqwidth(self): + """Return requested width of this widget.""" + return getint( + 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 self._getints( + self.tk.call('winfo', 'rgb', self._w, color)) + def winfo_rootx(self): + """Return x coordinate of upper left corner of this widget on the + root window.""" + return getint( + self.tk.call('winfo', 'rootx', self._w)) + def winfo_rooty(self): + """Return y coordinate of upper left corner of this widget on the + root window.""" + return getint( + self.tk.call('winfo', 'rooty', self._w)) + def winfo_screen(self): + """Return the screen name of this widget.""" + return self.tk.call('winfo', 'screen', self._w) + def winfo_screencells(self): + """Return the number of the cells in the colormap of the screen + of this widget.""" + return getint( + self.tk.call('winfo', 'screencells', self._w)) + def winfo_screendepth(self): + """Return the number of bits per pixel of the root window of the + screen of this widget.""" + return getint( + self.tk.call('winfo', 'screendepth', self._w)) + def winfo_screenheight(self): + """Return the number of pixels of the height of the screen of this widget + in pixel.""" + return getint( + self.tk.call('winfo', 'screenheight', self._w)) + def winfo_screenmmheight(self): + """Return the number of pixels of the height of the screen of + this widget in mm.""" + return getint( + self.tk.call('winfo', 'screenmmheight', self._w)) + def winfo_screenmmwidth(self): + """Return the number of pixels of the width of the screen of + this widget in mm.""" + return getint( + self.tk.call('winfo', 'screenmmwidth', self._w)) + def winfo_screenvisual(self): + """Return one of the strings directcolor, grayscale, pseudocolor, + staticcolor, staticgray, or truecolor for the default + colormodel of this screen.""" + return self.tk.call('winfo', 'screenvisual', self._w) + def winfo_screenwidth(self): + """Return the number of pixels of the width of the screen of + this widget in pixel.""" + return getint( + self.tk.call('winfo', 'screenwidth', self._w)) + def winfo_server(self): + """Return information of the X-Server of the screen of this widget in + the form "XmajorRminor vendor vendorVersion".""" + return self.tk.call('winfo', 'server', self._w) + def winfo_toplevel(self): + """Return the toplevel widget of this widget.""" + return self._nametowidget(self.tk.call( + 'winfo', 'toplevel', self._w)) + def winfo_viewable(self): + """Return true if the widget and all its higher ancestors are mapped.""" + return getint( + self.tk.call('winfo', 'viewable', self._w)) + def winfo_visual(self): + """Return one of the strings directcolor, grayscale, pseudocolor, + staticcolor, staticgray, or truecolor for the + colormodel of this widget.""" + return self.tk.call('winfo', 'visual', self._w) + def winfo_visualid(self): + """Return the X identifier for the visual for this widget.""" + return self.tk.call('winfo', 'visualid', self._w) + def winfo_visualsavailable(self, includeids=0): + """Return a list of all visuals available for the screen + of this widget. + + Each item in the list consists of a visual name (see winfo_visual), a + depth and if INCLUDEIDS=1 is given also the X identifier.""" + data = self.tk.split( + self.tk.call('winfo', 'visualsavailable', self._w, + includeids and 'includeids' or None)) + if type(data) is StringType: + data = [self.tk.split(data)] + return map(self.__winfo_parseitem, data) + def __winfo_parseitem(self, t): + """Internal function.""" + return t[:1] + tuple(map(self.__winfo_getint, t[1:])) + def __winfo_getint(self, x): + """Internal function.""" + return int(x, 0) + def winfo_vrootheight(self): + """Return the height of the virtual root window associated with this + widget in pixels. If there is no virtual root window return the + height of the screen.""" + return getint( + self.tk.call('winfo', 'vrootheight', self._w)) + def winfo_vrootwidth(self): + """Return the width of the virtual root window associated with this + widget in pixel. If there is no virtual root window return the + width of the screen.""" + return getint( + self.tk.call('winfo', 'vrootwidth', self._w)) + def winfo_vrootx(self): + """Return the x offset of the virtual root relative to the root + window of the screen of this widget.""" + return getint( + self.tk.call('winfo', 'vrootx', self._w)) + def winfo_vrooty(self): + """Return the y offset of the virtual root relative to the root + window of the screen of this widget.""" + return getint( + self.tk.call('winfo', 'vrooty', self._w)) + def winfo_width(self): + """Return the width of this widget.""" + return getint( + self.tk.call('winfo', 'width', self._w)) + def winfo_x(self): + """Return the x coordinate of the upper left corner of this widget + in the parent.""" + return getint( + self.tk.call('winfo', 'x', self._w)) + def winfo_y(self): + """Return the y coordinate of the upper left corner of this widget + in the parent.""" + return getint( + self.tk.call('winfo', 'y', self._w)) + def update(self): + """Enter event loop until all pending events have been processed by Tcl.""" + self.tk.call('update') + def update_idletasks(self): + """Enter event loop until all idle callbacks have been called. This + will update the display of windows but not process events caused by + the user.""" + self.tk.call('update', 'idletasks') + def bindtags(self, tagList=None): + """Set or get the list of bindtags for this widget. + + With no argument return the list of all bindtags associated with + this widget. With a list of strings as argument the bindtags are + set to this list. The bindtags determine in which order events are + processed (see bind).""" + if tagList is None: + return self.tk.splitlist( + self.tk.call('bindtags', self._w)) + else: + self.tk.call('bindtags', self._w, tagList) + def _bind(self, what, sequence, func, add, needcleanup=1): + """Internal function.""" + if type(func) is StringType: + self.tk.call(what + (sequence, func)) + elif func: + funcid = self._register(func, self._substitute, + needcleanup) + cmd = ('%sif {"[%s %s]" == "break"} break\n' + % + (add and '+' or '', + funcid, self._subst_format_str)) + self.tk.call(what + (sequence, cmd)) + return funcid + elif sequence: + return self.tk.call(what + (sequence,)) + else: + return self.tk.splitlist(self.tk.call(what)) + def bind(self, sequence=None, func=None, add=None): + """Bind to this widget at event SEQUENCE a call to function FUNC. + + SEQUENCE is a string of concatenated event + patterns. An event pattern is of the form + where MODIFIER is one + of Control, Mod2, M2, Shift, Mod3, M3, Lock, Mod4, M4, + Button1, B1, Mod5, M5 Button2, B2, Meta, M, Button3, + B3, Alt, Button4, B4, Double, Button5, B5 Triple, + Mod1, M1. TYPE is one of Activate, Enter, Map, + ButtonPress, Button, Expose, Motion, ButtonRelease + FocusIn, MouseWheel, Circulate, FocusOut, Property, + Colormap, Gravity Reparent, Configure, KeyPress, Key, + Unmap, Deactivate, KeyRelease Visibility, Destroy, + Leave and DETAIL is the button number for ButtonPress, + ButtonRelease and DETAIL is the Keysym for KeyPress and + KeyRelease. Examples are + for pressing Control and mouse button 1 or + for pressing A and the Alt key (KeyPress can be omitted). + An event pattern can also be a virtual event of the form + <> where AString can be arbitrary. This + event can be generated by event_generate. + If events are concatenated they must appear shortly + after each other. + + FUNC will be called if the event sequence occurs with an + instance of Event as argument. If the return value of FUNC is + "break" no further bound function is invoked. + + An additional boolean parameter ADD specifies whether FUNC will + be called additionally to the other bound function or whether + it will replace the previous function. + + Bind will return an identifier to allow deletion of the bound function with + unbind without memory leak. + + If FUNC or SEQUENCE is omitted the bound function or list + of bound events are returned.""" + + return self._bind(('bind', self._w), sequence, func, add) + def unbind(self, sequence, funcid=None): + """Unbind for this widget for event SEQUENCE the + function identified with FUNCID.""" + self.tk.call('bind', self._w, sequence, '') + if funcid: + self.deletecommand(funcid) + def bind_all(self, sequence=None, func=None, add=None): + """Bind to all widgets at an event SEQUENCE a call to function FUNC. + An additional boolean parameter ADD specifies whether FUNC will + be called additionally to the other bound function or whether + it will replace the previous function. See bind for the return value.""" + return self._bind(('bind', 'all'), sequence, func, add, 0) + def unbind_all(self, sequence): + """Unbind for all widgets for event SEQUENCE all functions.""" + self.tk.call('bind', 'all' , sequence, '') + def bind_class(self, className, sequence=None, func=None, add=None): + + """Bind to widgets with bindtag CLASSNAME at event + SEQUENCE a call of function FUNC. An additional + boolean parameter ADD specifies whether FUNC will be + called additionally to the other bound function or + whether it will replace the previous function. See bind for + the return value.""" + + return self._bind(('bind', className), sequence, func, add, 0) + def unbind_class(self, className, sequence): + """Unbind for a all widgets with bindtag CLASSNAME for event SEQUENCE + all functions.""" + self.tk.call('bind', className , sequence, '') + def mainloop(self, n=0): + """Call the mainloop of Tk.""" + self.tk.mainloop(n) + def quit(self): + """Quit the Tcl interpreter. All widgets will be destroyed.""" + self.tk.quit() + def _getints(self, string): + """Internal function.""" + if string: + return tuple(map(getint, self.tk.splitlist(string))) + def _getdoubles(self, string): + """Internal function.""" + if string: + return tuple(map(getdouble, self.tk.splitlist(string))) + def _getboolean(self, string): + """Internal function.""" + if string: + return self.tk.getboolean(string) + def _displayof(self, displayof): + """Internal function.""" + if displayof: + return ('-displayof', displayof) + if displayof is None: + return ('-displayof', self._w) + return () + @property + def _windowingsystem(self): + """Internal function.""" + try: + return self._root()._windowingsystem_cached + except AttributeError: + ws = self._root()._windowingsystem_cached = \ + self.tk.call('tk', 'windowingsystem') + return ws + def _options(self, cnf, kw = None): + """Internal function.""" + if kw: + cnf = _cnfmerge((cnf, kw)) + else: + cnf = _cnfmerge(cnf) + res = () + for k, v in cnf.items(): + if v is not None: + if k[-1] == '_': k = k[:-1] + if hasattr(v, '__call__'): + v = self._register(v) + elif isinstance(v, (tuple, list)): + nv = [] + for item in v: + if not isinstance(item, (basestring, int)): + break + elif isinstance(item, int): + nv.append('%d' % item) + else: + # format it to proper Tcl code if it contains space + nv.append(_stringify(item)) + else: + v = ' '.join(nv) + res = res + ('-'+k, v) + return res + def nametowidget(self, name): + """Return the Tkinter instance of a widget identified by + its Tcl name NAME.""" + name = str(name).split('.') + w = self + + if not name[0]: + w = w._root() + name = name[1:] + + for n in name: + if not n: + break + w = w.children[n] + + return w + _nametowidget = nametowidget + def _register(self, func, subst=None, needcleanup=1): + """Return a newly created Tcl function. If this + function is called, the Python function FUNC will + be executed. An optional function SUBST can + be given which will be executed before FUNC.""" + f = CallWrapper(func, subst, self).__call__ + name = repr(id(f)) + try: + func = func.im_func + except AttributeError: + pass + try: + name = name + func.__name__ + except AttributeError: + pass + self.tk.createcommand(name, f) + if needcleanup: + if self._tclCommands is None: + self._tclCommands = [] + self._tclCommands.append(name) + return name + register = _register + def _root(self): + """Internal function.""" + w = self + while w.master: w = w.master + return w + _subst_format = ('%#', '%b', '%f', '%h', '%k', + '%s', '%t', '%w', '%x', '%y', + '%A', '%E', '%K', '%N', '%W', '%T', '%X', '%Y', '%D') + _subst_format_str = " ".join(_subst_format) + def _substitute(self, *args): + """Internal function.""" + if len(args) != len(self._subst_format): return args + getboolean = self.tk.getboolean + + getint = int + def getint_event(s): + """Tk changed behavior in 8.4.2, returning "??" rather more often.""" + try: + return int(s) + except ValueError: + return s + + nsign, b, f, h, k, s, t, w, x, y, A, E, K, N, W, T, X, Y, D = args + # Missing: (a, c, d, m, o, v, B, R) + e = Event() + # serial field: valid vor all events + # number of button: ButtonPress and ButtonRelease events only + # height field: Configure, ConfigureRequest, Create, + # ResizeRequest, and Expose events only + # keycode field: KeyPress and KeyRelease events only + # time field: "valid for events that contain a time field" + # width field: Configure, ConfigureRequest, Create, ResizeRequest, + # and Expose events only + # x field: "valid for events that contain a x field" + # y field: "valid for events that contain a y field" + # keysym as decimal: KeyPress and KeyRelease events only + # x_root, y_root fields: ButtonPress, ButtonRelease, KeyPress, + # KeyRelease,and Motion events + e.serial = getint(nsign) + e.num = getint_event(b) + try: e.focus = getboolean(f) + except TclError: pass + e.height = getint_event(h) + e.keycode = getint_event(k) + e.state = getint_event(s) + e.time = getint_event(t) + e.width = getint_event(w) + e.x = getint_event(x) + e.y = getint_event(y) + e.char = A + try: e.send_event = getboolean(E) + except TclError: pass + e.keysym = K + e.keysym_num = getint_event(N) + e.type = T + try: + e.widget = self._nametowidget(W) + except KeyError: + e.widget = W + e.x_root = getint_event(X) + e.y_root = getint_event(Y) + try: + e.delta = getint(D) + except ValueError: + e.delta = 0 + return (e,) + def _report_exception(self): + """Internal function.""" + import sys + exc, val, tb = sys.exc_type, sys.exc_value, sys.exc_traceback + root = self._root() + root.report_callback_exception(exc, val, tb) + + def _getconfigure(self, *args): + """Call Tcl configure command and return the result as a dict.""" + cnf = {} + for x in self.tk.splitlist(self.tk.call(*args)): + x = self.tk.splitlist(x) + cnf[x[0][1:]] = (x[0][1:],) + x[1:] + return cnf + + def _getconfigure1(self, *args): + x = self.tk.splitlist(self.tk.call(*args)) + return (x[0][1:],) + x[1:] + + def _configure(self, cmd, cnf, kw): + """Internal function.""" + if kw: + cnf = _cnfmerge((cnf, kw)) + elif cnf: + cnf = _cnfmerge(cnf) + if cnf is None: + return self._getconfigure(_flatten((self._w, cmd))) + if type(cnf) is StringType: + return self._getconfigure1(_flatten((self._w, cmd, '-'+cnf))) + self.tk.call(_flatten((self._w, cmd)) + self._options(cnf)) + # These used to be defined in Widget: + def configure(self, cnf=None, **kw): + """Configure resources of a widget. + + The values for resources are specified as keyword + arguments. To get an overview about + the allowed keyword arguments call the method keys. + """ + return self._configure('configure', cnf, kw) + config = configure + def cget(self, key): + """Return the resource value for a KEY given as string.""" + return self.tk.call(self._w, 'cget', '-' + key) + __getitem__ = cget + def __setitem__(self, key, value): + self.configure({key: value}) + def __contains__(self, key): + raise TypeError("Tkinter objects don't support 'in' tests.") + def keys(self): + """Return a list of all resource names of this widget.""" + return [x[0][1:] for x in + self.tk.splitlist(self.tk.call(self._w, 'configure'))] + def __str__(self): + """Return the window path name of this widget.""" + return self._w + # Pack methods that apply to the master + _noarg_ = ['_noarg_'] + def pack_propagate(self, flag=_noarg_): + """Set or get the status for propagation of geometry information. + + A boolean argument specifies whether the geometry information + of the slaves will determine the size of this widget. If no argument + is given the current setting will be returned. + """ + if flag is Misc._noarg_: + return self._getboolean(self.tk.call( + 'pack', 'propagate', self._w)) + else: + self.tk.call('pack', 'propagate', self._w, flag) + propagate = pack_propagate + def pack_slaves(self): + """Return a list of all slaves of this widget + in its packing order.""" + return map(self._nametowidget, + self.tk.splitlist( + self.tk.call('pack', 'slaves', self._w))) + slaves = pack_slaves + # Place method that applies to the master + def place_slaves(self): + """Return a list of all slaves of this widget + in its packing order.""" + return map(self._nametowidget, + self.tk.splitlist( + self.tk.call( + 'place', 'slaves', self._w))) + # Grid methods that apply to the master + def grid_bbox(self, column=None, row=None, col2=None, row2=None): + """Return a tuple of integer coordinates for the bounding + box of this widget controlled by the geometry manager grid. + + If COLUMN, ROW is given the bounding box applies from + the cell with row and column 0 to the specified + cell. If COL2 and ROW2 are given the bounding box + starts at that cell. + + The returned integers specify the offset of the upper left + corner in the master widget and the width and height. + """ + args = ('grid', 'bbox', self._w) + if column is not None and row is not None: + args = args + (column, row) + if col2 is not None and row2 is not None: + args = args + (col2, row2) + return self._getints(self.tk.call(*args)) or None + + bbox = grid_bbox + + def _gridconvvalue(self, value): + if isinstance(value, (str, _tkinter.Tcl_Obj)): + try: + svalue = str(value) + if not svalue: + return None + elif '.' in svalue: + return getdouble(svalue) + else: + return getint(svalue) + except ValueError: + pass + return value + + def _grid_configure(self, command, index, cnf, kw): + """Internal function.""" + if type(cnf) is StringType and not kw: + if cnf[-1:] == '_': + cnf = cnf[:-1] + if cnf[:1] != '-': + cnf = '-'+cnf + options = (cnf,) + else: + options = self._options(cnf, kw) + if not options: + res = self.tk.call('grid', + command, self._w, index) + words = self.tk.splitlist(res) + dict = {} + for i in range(0, len(words), 2): + key = words[i][1:] + value = words[i+1] + dict[key] = self._gridconvvalue(value) + return dict + res = self.tk.call( + ('grid', command, self._w, index) + + options) + if len(options) == 1: + return self._gridconvvalue(res) + + def grid_columnconfigure(self, index, cnf={}, **kw): + """Configure column INDEX of a grid. + + Valid resources are minsize (minimum size of the column), + weight (how much does additional space propagate to this column) + and pad (how much space to let additionally).""" + return self._grid_configure('columnconfigure', index, cnf, kw) + columnconfigure = grid_columnconfigure + def grid_location(self, x, y): + """Return a tuple of column and row which identify the cell + at which the pixel at position X and Y inside the master + widget is located.""" + return self._getints( + self.tk.call( + 'grid', 'location', self._w, x, y)) or None + def grid_propagate(self, flag=_noarg_): + """Set or get the status for propagation of geometry information. + + A boolean argument specifies whether the geometry information + of the slaves will determine the size of this widget. If no argument + is given, the current setting will be returned. + """ + if flag is Misc._noarg_: + return self._getboolean(self.tk.call( + 'grid', 'propagate', self._w)) + else: + self.tk.call('grid', 'propagate', self._w, flag) + def grid_rowconfigure(self, index, cnf={}, **kw): + """Configure row INDEX of a grid. + + Valid resources are minsize (minimum size of the row), + weight (how much does additional space propagate to this row) + and pad (how much space to let additionally).""" + return self._grid_configure('rowconfigure', index, cnf, kw) + rowconfigure = grid_rowconfigure + def grid_size(self): + """Return a tuple of the number of column and rows in the grid.""" + return self._getints( + self.tk.call('grid', 'size', self._w)) or None + size = grid_size + def grid_slaves(self, row=None, column=None): + """Return a list of all slaves of this widget + in its packing order.""" + args = () + if row is not None: + args = args + ('-row', row) + if column is not None: + args = args + ('-column', column) + return map(self._nametowidget, + self.tk.splitlist(self.tk.call( + ('grid', 'slaves', self._w) + args))) + + # Support for the "event" command, new in Tk 4.2. + # By Case Roole. + + def event_add(self, virtual, *sequences): + """Bind a virtual event VIRTUAL (of the form <>) + to an event SEQUENCE such that the virtual event is triggered + whenever SEQUENCE occurs.""" + args = ('event', 'add', virtual) + sequences + self.tk.call(args) + + def event_delete(self, virtual, *sequences): + """Unbind a virtual event VIRTUAL from SEQUENCE.""" + args = ('event', 'delete', virtual) + sequences + self.tk.call(args) + + def event_generate(self, sequence, **kw): + """Generate an event SEQUENCE. Additional + keyword arguments specify parameter of the event + (e.g. x, y, rootx, rooty).""" + args = ('event', 'generate', self._w, sequence) + for k, v in kw.items(): + args = args + ('-%s' % k, str(v)) + self.tk.call(args) + + def event_info(self, virtual=None): + """Return a list of all virtual events or the information + about the SEQUENCE bound to the virtual event VIRTUAL.""" + return self.tk.splitlist( + self.tk.call('event', 'info', virtual)) + + # Image related commands + + def image_names(self): + """Return a list of all existing image names.""" + return self.tk.splitlist(self.tk.call('image', 'names')) + + def image_types(self): + """Return a list of all available image types (e.g. phote bitmap).""" + return self.tk.splitlist(self.tk.call('image', 'types')) + + +class CallWrapper: + """Internal class. Stores function to call when some user + defined Tcl function is called e.g. after an event occurred.""" + def __init__(self, func, subst, widget): + """Store FUNC, SUBST and WIDGET as members.""" + self.func = func + self.subst = subst + self.widget = widget + def __call__(self, *args): + """Apply first function SUBST to arguments, than FUNC.""" + try: + if self.subst: + args = self.subst(*args) + return self.func(*args) + except SystemExit, msg: + raise SystemExit, msg + except: + self.widget._report_exception() + + +class XView: + """Mix-in class for querying and changing the horizontal position + of a widget's window.""" + + def xview(self, *args): + """Query and change the horizontal position of the view.""" + res = self.tk.call(self._w, 'xview', *args) + if not args: + return self._getdoubles(res) + + def xview_moveto(self, fraction): + """Adjusts the view in the window so that FRACTION of the + total width of the canvas is off-screen to the left.""" + self.tk.call(self._w, 'xview', 'moveto', fraction) + + def xview_scroll(self, number, what): + """Shift the x-view according to NUMBER which is measured in "units" + or "pages" (WHAT).""" + self.tk.call(self._w, 'xview', 'scroll', number, what) + + +class YView: + """Mix-in class for querying and changing the vertical position + of a widget's window.""" + + def yview(self, *args): + """Query and change the vertical position of the view.""" + res = self.tk.call(self._w, 'yview', *args) + if not args: + return self._getdoubles(res) + + def yview_moveto(self, fraction): + """Adjusts the view in the window so that FRACTION of the + total height of the canvas is off-screen to the top.""" + self.tk.call(self._w, 'yview', 'moveto', fraction) + + def yview_scroll(self, number, what): + """Shift the y-view according to NUMBER which is measured in + "units" or "pages" (WHAT).""" + self.tk.call(self._w, 'yview', 'scroll', number, what) + + +class Wm: + """Provides functions for the communication with the window manager.""" + + def wm_aspect(self, + minNumer=None, minDenom=None, + maxNumer=None, maxDenom=None): + """Instruct the window manager to set the aspect ratio (width/height) + of this widget to be between MINNUMER/MINDENOM and MAXNUMER/MAXDENOM. Return a tuple + of the actual values if no argument is given.""" + return self._getints( + self.tk.call('wm', 'aspect', self._w, + minNumer, minDenom, + maxNumer, maxDenom)) + aspect = wm_aspect + + def wm_attributes(self, *args): + """This subcommand returns or sets platform specific attributes + + The first form returns a list of the platform specific flags and + their values. The second form returns the value for the specific + option. The third form sets one or more of the values. The values + are as follows: + + On Windows, -disabled gets or sets whether the window is in a + disabled state. -toolwindow gets or sets the style of the window + to toolwindow (as defined in the MSDN). -topmost gets or sets + whether this is a topmost window (displays above all other + windows). + + On Macintosh, XXXXX + + On Unix, there are currently no special attribute values. + """ + args = ('wm', 'attributes', self._w) + args + return self.tk.call(args) + attributes=wm_attributes + + def wm_client(self, name=None): + """Store NAME in WM_CLIENT_MACHINE property of this widget. Return + current value.""" + return self.tk.call('wm', 'client', self._w, name) + client = wm_client + def wm_colormapwindows(self, *wlist): + """Store list of window names (WLIST) into WM_COLORMAPWINDOWS property + of this widget. This list contains windows whose colormaps differ from their + parents. Return current list of widgets if WLIST is empty.""" + if len(wlist) > 1: + wlist = (wlist,) # Tk needs a list of windows here + args = ('wm', 'colormapwindows', self._w) + wlist + if wlist: + self.tk.call(args) + else: + return map(self._nametowidget, self.tk.splitlist(self.tk.call(args))) + colormapwindows = wm_colormapwindows + def wm_command(self, value=None): + """Store VALUE in WM_COMMAND property. It is the command + which shall be used to invoke the application. Return current + command if VALUE is None.""" + return self.tk.call('wm', 'command', self._w, value) + command = wm_command + def wm_deiconify(self): + """Deiconify this widget. If it was never mapped it will not be mapped. + On Windows it will raise this widget and give it the focus.""" + return self.tk.call('wm', 'deiconify', self._w) + deiconify = wm_deiconify + def wm_focusmodel(self, model=None): + """Set focus model to MODEL. "active" means that this widget will claim + the focus itself, "passive" means that the window manager shall give + the focus. Return current focus model if MODEL is None.""" + return self.tk.call('wm', 'focusmodel', self._w, model) + focusmodel = wm_focusmodel + def wm_frame(self): + """Return identifier for decorative frame of this widget if present.""" + return self.tk.call('wm', 'frame', self._w) + frame = wm_frame + def wm_geometry(self, newGeometry=None): + """Set geometry to NEWGEOMETRY of the form =widthxheight+x+y. Return + current value if None is given.""" + return self.tk.call('wm', 'geometry', self._w, newGeometry) + geometry = wm_geometry + def wm_grid(self, + baseWidth=None, baseHeight=None, + widthInc=None, heightInc=None): + """Instruct the window manager that this widget shall only be + resized on grid boundaries. WIDTHINC and HEIGHTINC are the width and + height of a grid unit in pixels. BASEWIDTH and BASEHEIGHT are the + number of grid units requested in Tk_GeometryRequest.""" + return self._getints(self.tk.call( + 'wm', 'grid', self._w, + baseWidth, baseHeight, widthInc, heightInc)) + grid = wm_grid + def wm_group(self, pathName=None): + """Set the group leader widgets for related widgets to PATHNAME. Return + the group leader of this widget if None is given.""" + return self.tk.call('wm', 'group', self._w, pathName) + group = wm_group + def wm_iconbitmap(self, bitmap=None, default=None): + """Set bitmap for the iconified widget to BITMAP. Return + the bitmap if None is given. + + Under Windows, the DEFAULT parameter can be used to set the icon + for the widget and any descendents that don't have an icon set + explicitly. DEFAULT can be the relative path to a .ico file + (example: root.iconbitmap(default='myicon.ico') ). See Tk + documentation for more information.""" + if default: + return self.tk.call('wm', 'iconbitmap', self._w, '-default', default) + else: + return self.tk.call('wm', 'iconbitmap', self._w, bitmap) + iconbitmap = wm_iconbitmap + def wm_iconify(self): + """Display widget as icon.""" + return self.tk.call('wm', 'iconify', self._w) + iconify = wm_iconify + def wm_iconmask(self, bitmap=None): + """Set mask for the icon bitmap of this widget. Return the + mask if None is given.""" + return self.tk.call('wm', 'iconmask', self._w, bitmap) + iconmask = wm_iconmask + def wm_iconname(self, newName=None): + """Set the name of the icon for this widget. Return the name if + None is given.""" + return self.tk.call('wm', 'iconname', self._w, newName) + iconname = wm_iconname + def wm_iconposition(self, x=None, y=None): + """Set the position of the icon of this widget to X and Y. Return + a tuple of the current values of X and X if None is given.""" + return self._getints(self.tk.call( + 'wm', 'iconposition', self._w, x, y)) + iconposition = wm_iconposition + def wm_iconwindow(self, pathName=None): + """Set widget PATHNAME to be displayed instead of icon. Return the current + value if None is given.""" + return self.tk.call('wm', 'iconwindow', self._w, pathName) + iconwindow = wm_iconwindow + def wm_maxsize(self, width=None, height=None): + """Set max WIDTH and HEIGHT for this widget. If the window is gridded + the values are given in grid units. Return the current values if None + is given.""" + return self._getints(self.tk.call( + 'wm', 'maxsize', self._w, width, height)) + maxsize = wm_maxsize + def wm_minsize(self, width=None, height=None): + """Set min WIDTH and HEIGHT for this widget. If the window is gridded + the values are given in grid units. Return the current values if None + is given.""" + return self._getints(self.tk.call( + 'wm', 'minsize', self._w, width, height)) + minsize = wm_minsize + def wm_overrideredirect(self, boolean=None): + """Instruct the window manager to ignore this widget + if BOOLEAN is given with 1. Return the current value if None + is given.""" + return self._getboolean(self.tk.call( + 'wm', 'overrideredirect', self._w, boolean)) + overrideredirect = wm_overrideredirect + def wm_positionfrom(self, who=None): + """Instruct the window manager that the position of this widget shall + be defined by the user if WHO is "user", and by its own policy if WHO is + "program".""" + return self.tk.call('wm', 'positionfrom', self._w, who) + positionfrom = wm_positionfrom + def wm_protocol(self, name=None, func=None): + """Bind function FUNC to command NAME for this widget. + Return the function bound to NAME if None is given. NAME could be + e.g. "WM_SAVE_YOURSELF" or "WM_DELETE_WINDOW".""" + if hasattr(func, '__call__'): + command = self._register(func) + else: + command = func + return self.tk.call( + 'wm', 'protocol', self._w, name, command) + protocol = wm_protocol + def wm_resizable(self, width=None, height=None): + """Instruct the window manager whether this width can be resized + in WIDTH or HEIGHT. Both values are boolean values.""" + return self.tk.call('wm', 'resizable', self._w, width, height) + resizable = wm_resizable + def wm_sizefrom(self, who=None): + """Instruct the window manager that the size of this widget shall + be defined by the user if WHO is "user", and by its own policy if WHO is + "program".""" + return self.tk.call('wm', 'sizefrom', self._w, who) + sizefrom = wm_sizefrom + def wm_state(self, newstate=None): + """Query or set the state of this widget as one of normal, icon, + iconic (see wm_iconwindow), withdrawn, or zoomed (Windows only).""" + return self.tk.call('wm', 'state', self._w, newstate) + state = wm_state + def wm_title(self, string=None): + """Set the title of this widget.""" + return self.tk.call('wm', 'title', self._w, string) + title = wm_title + def wm_transient(self, master=None): + """Instruct the window manager that this widget is transient + with regard to widget MASTER.""" + return self.tk.call('wm', 'transient', self._w, master) + transient = wm_transient + def wm_withdraw(self): + """Withdraw this widget from the screen such that it is unmapped + and forgotten by the window manager. Re-draw it with wm_deiconify.""" + return self.tk.call('wm', 'withdraw', self._w) + withdraw = wm_withdraw + + +class Tk(Misc, Wm): + """Toplevel widget of Tk which represents mostly the main window + of an application. It has an associated Tcl interpreter.""" + _w = '.' + def __init__(self, screenName=None, baseName=None, className='Tk', + useTk=1, sync=0, use=None): + """Return a new Toplevel widget on screen SCREENNAME. A new Tcl interpreter will + be created. BASENAME will be used for the identification of the profile file (see + readprofile). + It is constructed from sys.argv[0] without extensions if None is given. CLASSNAME + is the name of the widget class.""" + self.master = None + self.children = {} + self._tkloaded = 0 + # to avoid recursions in the getattr code in case of failure, we + # ensure that self.tk is always _something_. + self.tk = None + if baseName is None: + import os + baseName = os.path.basename(sys.argv[0]) + baseName, ext = os.path.splitext(baseName) + if ext not in ('.py', '.pyc', '.pyo'): + baseName = baseName + ext + interactive = 0 + self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use) + if useTk: + self._loadtk() + if not sys.flags.ignore_environment: + # Issue #16248: Honor the -E flag to avoid code injection. + self.readprofile(baseName, className) + def loadtk(self): + if not self._tkloaded: + self.tk.loadtk() + self._loadtk() + def _loadtk(self): + self._tkloaded = 1 + global _default_root + # Version sanity checks + tk_version = self.tk.getvar('tk_version') + if tk_version != _tkinter.TK_VERSION: + raise RuntimeError, \ + "tk.h version (%s) doesn't match libtk.a version (%s)" \ + % (_tkinter.TK_VERSION, tk_version) + # Under unknown circumstances, tcl_version gets coerced to float + tcl_version = str(self.tk.getvar('tcl_version')) + if tcl_version != _tkinter.TCL_VERSION: + raise RuntimeError, \ + "tcl.h version (%s) doesn't match libtcl.a version (%s)" \ + % (_tkinter.TCL_VERSION, tcl_version) + if TkVersion < 4.0: + raise RuntimeError, \ + "Tk 4.0 or higher is required; found Tk %s" \ + % str(TkVersion) + # Create and register the tkerror and exit commands + # We need to inline parts of _register here, _ register + # would register differently-named commands. + if self._tclCommands is None: + self._tclCommands = [] + self.tk.createcommand('tkerror', _tkerror) + self.tk.createcommand('exit', _exit) + self._tclCommands.append('tkerror') + self._tclCommands.append('exit') + if _support_default_root and not _default_root: + _default_root = self + self.protocol("WM_DELETE_WINDOW", self.destroy) + def destroy(self): + """Destroy this and all descendants widgets. This will + end the application of this Tcl interpreter.""" + for c in self.children.values(): c.destroy() + self.tk.call('destroy', self._w) + Misc.destroy(self) + global _default_root + if _support_default_root and _default_root is self: + _default_root = None + def readprofile(self, baseName, className): + """Internal function. It reads BASENAME.tcl and CLASSNAME.tcl into + the Tcl Interpreter and calls execfile on BASENAME.py and CLASSNAME.py if + such a file exists in the home directory.""" + import os + if 'HOME' in os.environ: home = os.environ['HOME'] + else: home = os.curdir + class_tcl = os.path.join(home, '.%s.tcl' % className) + class_py = os.path.join(home, '.%s.py' % className) + base_tcl = os.path.join(home, '.%s.tcl' % baseName) + base_py = os.path.join(home, '.%s.py' % baseName) + dir = {'self': self} + exec 'from Tkinter import *' in dir + if os.path.isfile(class_tcl): + self.tk.call('source', class_tcl) + if os.path.isfile(class_py): + execfile(class_py, dir) + if os.path.isfile(base_tcl): + self.tk.call('source', base_tcl) + if os.path.isfile(base_py): + execfile(base_py, dir) + def report_callback_exception(self, exc, val, tb): + """Internal function. It reports exception on sys.stderr.""" + import traceback, sys + sys.stderr.write("Exception in Tkinter callback\n") + sys.last_type = exc + sys.last_value = val + sys.last_traceback = tb + traceback.print_exception(exc, val, tb) + def __getattr__(self, attr): + "Delegate attribute access to the interpreter object" + return getattr(self.tk, attr) + +# Ideally, the classes Pack, Place and Grid disappear, the +# pack/place/grid methods are defined on the Widget class, and +# everybody uses w.pack_whatever(...) instead of Pack.whatever(w, +# ...), with pack(), place() and grid() being short for +# pack_configure(), place_configure() and grid_columnconfigure(), and +# forget() being short for pack_forget(). As a practical matter, I'm +# afraid that there is too much code out there that may be using the +# Pack, Place or Grid class, so I leave them intact -- but only as +# backwards compatibility features. Also note that those methods that +# take a master as argument (e.g. pack_propagate) have been moved to +# the Misc class (which now incorporates all methods common between +# toplevel and interior widgets). Again, for compatibility, these are +# copied into the Pack, Place or Grid class. + + +def Tcl(screenName=None, baseName=None, className='Tk', useTk=0): + return Tk(screenName, baseName, className, useTk) + +class Pack: + """Geometry manager Pack. + + Base class to use the methods pack_* in every widget.""" + def pack_configure(self, cnf={}, **kw): + """Pack a widget in the parent widget. Use as options: + after=widget - pack it after you have packed widget + anchor=NSEW (or subset) - position widget according to + given direction + before=widget - pack it before you will pack widget + expand=bool - expand widget if parent size grows + fill=NONE or X or Y or BOTH - fill widget if widget grows + in=master - use master to contain this widget + in_=master - see 'in' option description + ipadx=amount - add internal padding in x direction + ipady=amount - add internal padding in y direction + padx=amount - add padding in x direction + pady=amount - add padding in y direction + side=TOP or BOTTOM or LEFT or RIGHT - where to add this widget. + """ + self.tk.call( + ('pack', 'configure', self._w) + + self._options(cnf, kw)) + pack = configure = config = pack_configure + def pack_forget(self): + """Unmap this widget and do not use it for the packing order.""" + self.tk.call('pack', 'forget', self._w) + forget = pack_forget + def pack_info(self): + """Return information about the packing options + for this widget.""" + words = self.tk.splitlist( + self.tk.call('pack', 'info', self._w)) + dict = {} + for i in range(0, len(words), 2): + key = words[i][1:] + value = words[i+1] + if str(value)[:1] == '.': + value = self._nametowidget(value) + dict[key] = value + return dict + info = pack_info + propagate = pack_propagate = Misc.pack_propagate + slaves = pack_slaves = Misc.pack_slaves + +class Place: + """Geometry manager Place. + + Base class to use the methods place_* in every widget.""" + def place_configure(self, cnf={}, **kw): + """Place a widget in the parent widget. Use as options: + in=master - master relative to which the widget is placed + in_=master - see 'in' option description + x=amount - locate anchor of this widget at position x of master + y=amount - locate anchor of this widget at position y of master + relx=amount - locate anchor of this widget between 0.0 and 1.0 + relative to width of master (1.0 is right edge) + rely=amount - locate anchor of this widget between 0.0 and 1.0 + relative to height of master (1.0 is bottom edge) + anchor=NSEW (or subset) - position anchor according to given direction + width=amount - width of this widget in pixel + height=amount - height of this widget in pixel + relwidth=amount - width of this widget between 0.0 and 1.0 + relative to width of master (1.0 is the same width + as the master) + relheight=amount - height of this widget between 0.0 and 1.0 + relative to height of master (1.0 is the same + height as the master) + bordermode="inside" or "outside" - whether to take border width of + master widget into account + """ + self.tk.call( + ('place', 'configure', self._w) + + self._options(cnf, kw)) + place = configure = config = place_configure + def place_forget(self): + """Unmap this widget.""" + self.tk.call('place', 'forget', self._w) + forget = place_forget + def place_info(self): + """Return information about the placing options + for this widget.""" + words = self.tk.splitlist( + self.tk.call('place', 'info', self._w)) + dict = {} + for i in range(0, len(words), 2): + key = words[i][1:] + value = words[i+1] + if str(value)[:1] == '.': + value = self._nametowidget(value) + dict[key] = value + return dict + info = place_info + slaves = place_slaves = Misc.place_slaves + +class Grid: + """Geometry manager Grid. + + Base class to use the methods grid_* in every widget.""" + # Thanks to Masazumi Yoshikawa (yosikawa@isi.edu) + def grid_configure(self, cnf={}, **kw): + """Position a widget in the parent widget in a grid. Use as options: + column=number - use cell identified with given column (starting with 0) + columnspan=number - this widget will span several columns + in=master - use master to contain this widget + in_=master - see 'in' option description + ipadx=amount - add internal padding in x direction + ipady=amount - add internal padding in y direction + padx=amount - add padding in x direction + pady=amount - add padding in y direction + row=number - use cell identified with given row (starting with 0) + rowspan=number - this widget will span several rows + sticky=NSEW - if cell is larger on which sides will this + widget stick to the cell boundary + """ + self.tk.call( + ('grid', 'configure', self._w) + + self._options(cnf, kw)) + grid = configure = config = grid_configure + bbox = grid_bbox = Misc.grid_bbox + columnconfigure = grid_columnconfigure = Misc.grid_columnconfigure + def grid_forget(self): + """Unmap this widget.""" + self.tk.call('grid', 'forget', self._w) + forget = grid_forget + def grid_remove(self): + """Unmap this widget but remember the grid options.""" + self.tk.call('grid', 'remove', self._w) + def grid_info(self): + """Return information about the options + for positioning this widget in a grid.""" + words = self.tk.splitlist( + self.tk.call('grid', 'info', self._w)) + dict = {} + for i in range(0, len(words), 2): + key = words[i][1:] + value = words[i+1] + if str(value)[:1] == '.': + value = self._nametowidget(value) + dict[key] = value + return dict + info = grid_info + location = grid_location = Misc.grid_location + propagate = grid_propagate = Misc.grid_propagate + rowconfigure = grid_rowconfigure = Misc.grid_rowconfigure + size = grid_size = Misc.grid_size + slaves = grid_slaves = Misc.grid_slaves + +class BaseWidget(Misc): + """Internal class.""" + 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 + self.master = master + self.tk = master.tk + name = None + if 'name' in cnf: + name = cnf['name'] + del cnf['name'] + if not name: + name = repr(id(self)) + self._name = name + if master._w=='.': + self._w = '.' + name + else: + self._w = master._w + '.' + name + self.children = {} + if self._name in self.master.children: + self.master.children[self._name].destroy() + self.master.children[self._name] = self + def __init__(self, master, widgetName, cnf={}, kw={}, extra=()): + """Construct a widget with the parent widget MASTER, a name WIDGETNAME + and appropriate options.""" + if kw: + cnf = _cnfmerge((cnf, kw)) + self.widgetName = widgetName + BaseWidget._setup(self, master, cnf) + if self._tclCommands is None: + self._tclCommands = [] + classes = [] + for k in cnf.keys(): + if type(k) is ClassType: + classes.append((k, cnf[k])) + del cnf[k] + self.tk.call( + (widgetName, self._w) + extra + self._options(cnf)) + for k, v in classes: + k.configure(self, v) + def destroy(self): + """Destroy this and all descendants widgets.""" + for c in self.children.values(): c.destroy() + self.tk.call('destroy', self._w) + if self._name in self.master.children: + del self.master.children[self._name] + Misc.destroy(self) + def _do(self, name, args=()): + # XXX Obsolete -- better use self.tk.call directly! + return self.tk.call((self._w, name) + args) + +class Widget(BaseWidget, Pack, Place, Grid): + """Internal class. + + Base class for a widget which can be positioned with the geometry managers + Pack, Place or Grid.""" + pass + +class Toplevel(BaseWidget, Wm): + """Toplevel widget, e.g. for dialogs.""" + def __init__(self, master=None, cnf={}, **kw): + """Construct a toplevel widget with the parent MASTER. + + Valid resource names: background, bd, bg, borderwidth, class, + colormap, container, cursor, height, highlightbackground, + highlightcolor, highlightthickness, menu, relief, screen, takefocus, + use, visual, width.""" + if kw: + cnf = _cnfmerge((cnf, kw)) + extra = () + for wmkey in ['screen', 'class_', 'class', 'visual', + 'colormap']: + if wmkey in cnf: + val = cnf[wmkey] + # TBD: a hack needed because some keys + # are not valid as keyword arguments + if wmkey[-1] == '_': opt = '-'+wmkey[:-1] + else: opt = '-'+wmkey + extra = extra + (opt, val) + del cnf[wmkey] + BaseWidget.__init__(self, master, 'toplevel', cnf, {}, extra) + root = self._root() + self.iconname(root.iconname()) + self.title(root.title()) + self.protocol("WM_DELETE_WINDOW", self.destroy) + +class Button(Widget): + """Button widget.""" + def __init__(self, master=None, cnf={}, **kw): + """Construct a button widget with the parent MASTER. + + STANDARD OPTIONS + + activebackground, activeforeground, anchor, + background, bitmap, borderwidth, cursor, + disabledforeground, font, foreground + highlightbackground, highlightcolor, + highlightthickness, image, justify, + padx, pady, relief, repeatdelay, + repeatinterval, takefocus, text, + textvariable, underline, wraplength + + WIDGET-SPECIFIC OPTIONS + + command, compound, default, height, + overrelief, state, width + """ + Widget.__init__(self, master, 'button', cnf, kw) + + def tkButtonEnter(self, *dummy): + self.tk.call('tkButtonEnter', self._w) + + def tkButtonLeave(self, *dummy): + self.tk.call('tkButtonLeave', self._w) + + def tkButtonDown(self, *dummy): + self.tk.call('tkButtonDown', self._w) + + def tkButtonUp(self, *dummy): + self.tk.call('tkButtonUp', self._w) + + def tkButtonInvoke(self, *dummy): + self.tk.call('tkButtonInvoke', self._w) + + def flash(self): + """Flash the button. + + This is accomplished by redisplaying + the button several times, alternating between active and + normal colors. At the end of the flash the button is left + in the same normal/active state as when the command was + invoked. This command is ignored if the button's state is + disabled. + """ + self.tk.call(self._w, 'flash') + + def invoke(self): + """Invoke the command associated with the button. + + The return value is the return value from the command, + or an empty string if there is no command associated with + the button. This command is ignored if the button's state + is disabled. + """ + return self.tk.call(self._w, 'invoke') + +# Indices: +# XXX I don't like these -- take them away +def AtEnd(): + return 'end' +def AtInsert(*args): + s = 'insert' + for a in args: + if a: s = s + (' ' + a) + return s +def AtSelFirst(): + return 'sel.first' +def AtSelLast(): + return 'sel.last' +def At(x, y=None): + if y is None: + return '@%r' % (x,) + else: + return '@%r,%r' % (x, y) + +class Canvas(Widget, XView, YView): + """Canvas widget to display graphical elements like lines or text.""" + def __init__(self, master=None, cnf={}, **kw): + """Construct a canvas widget with the parent MASTER. + + Valid resource names: background, bd, bg, borderwidth, closeenough, + confine, cursor, height, highlightbackground, highlightcolor, + highlightthickness, insertbackground, insertborderwidth, + insertofftime, insertontime, insertwidth, offset, relief, + scrollregion, selectbackground, selectborderwidth, selectforeground, + state, takefocus, width, xscrollcommand, xscrollincrement, + yscrollcommand, yscrollincrement.""" + Widget.__init__(self, master, 'canvas', cnf, kw) + def addtag(self, *args): + """Internal function.""" + self.tk.call((self._w, 'addtag') + args) + def addtag_above(self, newtag, tagOrId): + """Add tag NEWTAG to all items above TAGORID.""" + self.addtag(newtag, 'above', tagOrId) + def addtag_all(self, newtag): + """Add tag NEWTAG to all items.""" + self.addtag(newtag, 'all') + def addtag_below(self, newtag, tagOrId): + """Add tag NEWTAG to all items below TAGORID.""" + self.addtag(newtag, 'below', tagOrId) + def addtag_closest(self, newtag, x, y, halo=None, start=None): + """Add tag NEWTAG to item which is closest to pixel at X, Y. + If several match take the top-most. + All items closer than HALO are considered overlapping (all are + closests). If START is specified the next below this tag is taken.""" + self.addtag(newtag, 'closest', x, y, halo, start) + def addtag_enclosed(self, newtag, x1, y1, x2, y2): + """Add tag NEWTAG to all items in the rectangle defined + by X1,Y1,X2,Y2.""" + self.addtag(newtag, 'enclosed', x1, y1, x2, y2) + def addtag_overlapping(self, newtag, x1, y1, x2, y2): + """Add tag NEWTAG to all items which overlap the rectangle + defined by X1,Y1,X2,Y2.""" + self.addtag(newtag, 'overlapping', x1, y1, x2, y2) + def addtag_withtag(self, newtag, tagOrId): + """Add tag NEWTAG to all items with TAGORID.""" + self.addtag(newtag, 'withtag', tagOrId) + def bbox(self, *args): + """Return a tuple of X1,Y1,X2,Y2 coordinates for a rectangle + which encloses all items with tags specified as arguments.""" + return self._getints( + self.tk.call((self._w, 'bbox') + args)) or None + def tag_unbind(self, tagOrId, sequence, funcid=None): + """Unbind for all items with TAGORID for event SEQUENCE the + function identified with FUNCID.""" + self.tk.call(self._w, 'bind', tagOrId, sequence, '') + if funcid: + self.deletecommand(funcid) + def tag_bind(self, tagOrId, sequence=None, func=None, add=None): + """Bind to all items with TAGORID at event SEQUENCE a call to function FUNC. + + An additional boolean parameter ADD specifies whether FUNC will be + called additionally to the other bound function or whether it will + replace the previous function. See bind for the return value.""" + return self._bind((self._w, 'bind', tagOrId), + sequence, func, add) + def canvasx(self, screenx, gridspacing=None): + """Return the canvas x coordinate of pixel position SCREENX rounded + to nearest multiple of GRIDSPACING units.""" + return getdouble(self.tk.call( + self._w, 'canvasx', screenx, gridspacing)) + def canvasy(self, screeny, gridspacing=None): + """Return the canvas y coordinate of pixel position SCREENY rounded + to nearest multiple of GRIDSPACING units.""" + return getdouble(self.tk.call( + self._w, 'canvasy', screeny, gridspacing)) + def coords(self, *args): + """Return a list of coordinates for the item given in ARGS.""" + # XXX Should use _flatten on args + return map(getdouble, + self.tk.splitlist( + self.tk.call((self._w, 'coords') + args))) + def _create(self, itemType, args, kw): # Args: (val, val, ..., cnf={}) + """Internal function.""" + args = _flatten(args) + cnf = args[-1] + if type(cnf) in (DictionaryType, TupleType): + args = args[:-1] + else: + cnf = {} + return getint(self.tk.call( + self._w, 'create', itemType, + *(args + self._options(cnf, kw)))) + def create_arc(self, *args, **kw): + """Create arc shaped region with coordinates x1,y1,x2,y2.""" + return self._create('arc', args, kw) + def create_bitmap(self, *args, **kw): + """Create bitmap with coordinates x1,y1.""" + return self._create('bitmap', args, kw) + def create_image(self, *args, **kw): + """Create image item with coordinates x1,y1.""" + return self._create('image', args, kw) + def create_line(self, *args, **kw): + """Create line with coordinates x1,y1,...,xn,yn.""" + return self._create('line', args, kw) + def create_oval(self, *args, **kw): + """Create oval with coordinates x1,y1,x2,y2.""" + return self._create('oval', args, kw) + def create_polygon(self, *args, **kw): + """Create polygon with coordinates x1,y1,...,xn,yn.""" + return self._create('polygon', args, kw) + def create_rectangle(self, *args, **kw): + """Create rectangle with coordinates x1,y1,x2,y2.""" + return self._create('rectangle', args, kw) + def create_text(self, *args, **kw): + """Create text with coordinates x1,y1.""" + return self._create('text', args, kw) + def create_window(self, *args, **kw): + """Create window with coordinates x1,y1,x2,y2.""" + return self._create('window', args, kw) + def dchars(self, *args): + """Delete characters of text items identified by tag or id in ARGS (possibly + several times) from FIRST to LAST character (including).""" + self.tk.call((self._w, 'dchars') + args) + def delete(self, *args): + """Delete items identified by all tag or ids contained in ARGS.""" + self.tk.call((self._w, 'delete') + args) + def dtag(self, *args): + """Delete tag or id given as last arguments in ARGS from items + identified by first argument in ARGS.""" + self.tk.call((self._w, 'dtag') + args) + def find(self, *args): + """Internal function.""" + return self._getints( + self.tk.call((self._w, 'find') + args)) or () + def find_above(self, tagOrId): + """Return items above TAGORID.""" + return self.find('above', tagOrId) + def find_all(self): + """Return all items.""" + return self.find('all') + def find_below(self, tagOrId): + """Return all items below TAGORID.""" + return self.find('below', tagOrId) + def find_closest(self, x, y, halo=None, start=None): + """Return item which is closest to pixel at X, Y. + If several match take the top-most. + All items closer than HALO are considered overlapping (all are + closests). If START is specified the next below this tag is taken.""" + return self.find('closest', x, y, halo, start) + def find_enclosed(self, x1, y1, x2, y2): + """Return all items in rectangle defined + by X1,Y1,X2,Y2.""" + return self.find('enclosed', x1, y1, x2, y2) + def find_overlapping(self, x1, y1, x2, y2): + """Return all items which overlap the rectangle + defined by X1,Y1,X2,Y2.""" + return self.find('overlapping', x1, y1, x2, y2) + def find_withtag(self, tagOrId): + """Return all items with TAGORID.""" + return self.find('withtag', tagOrId) + def focus(self, *args): + """Set focus to the first item specified in ARGS.""" + return self.tk.call((self._w, 'focus') + args) + def gettags(self, *args): + """Return tags associated with the first item specified in ARGS.""" + return self.tk.splitlist( + self.tk.call((self._w, 'gettags') + args)) + def icursor(self, *args): + """Set cursor at position POS in the item identified by TAGORID. + In ARGS TAGORID must be first.""" + self.tk.call((self._w, 'icursor') + args) + def index(self, *args): + """Return position of cursor as integer in item specified in ARGS.""" + return getint(self.tk.call((self._w, 'index') + args)) + def insert(self, *args): + """Insert TEXT in item TAGORID at position POS. ARGS must + be TAGORID POS TEXT.""" + self.tk.call((self._w, 'insert') + args) + def itemcget(self, tagOrId, option): + """Return the resource value for an OPTION for item TAGORID.""" + return self.tk.call( + (self._w, 'itemcget') + (tagOrId, '-'+option)) + def itemconfigure(self, tagOrId, cnf=None, **kw): + """Configure resources of an item TAGORID. + + The values for resources are specified as keyword + arguments. To get an overview about + the allowed keyword arguments call the method without arguments. + """ + return self._configure(('itemconfigure', tagOrId), cnf, kw) + itemconfig = itemconfigure + # lower, tkraise/lift hide Misc.lower, Misc.tkraise/lift, + # so the preferred name for them is tag_lower, tag_raise + # (similar to tag_bind, and similar to the Text widget); + # unfortunately can't delete the old ones yet (maybe in 1.6) + def tag_lower(self, *args): + """Lower an item TAGORID given in ARGS + (optional below another item).""" + self.tk.call((self._w, 'lower') + args) + lower = tag_lower + def move(self, *args): + """Move an item TAGORID given in ARGS.""" + self.tk.call((self._w, 'move') + args) + def postscript(self, cnf={}, **kw): + """Print the contents of the canvas to a postscript + file. Valid options: colormap, colormode, file, fontmap, + height, pageanchor, pageheight, pagewidth, pagex, pagey, + rotate, witdh, x, y.""" + return self.tk.call((self._w, 'postscript') + + self._options(cnf, kw)) + def tag_raise(self, *args): + """Raise an item TAGORID given in ARGS + (optional above another item).""" + self.tk.call((self._w, 'raise') + args) + lift = tkraise = tag_raise + def scale(self, *args): + """Scale item TAGORID with XORIGIN, YORIGIN, XSCALE, YSCALE.""" + self.tk.call((self._w, 'scale') + args) + def scan_mark(self, x, y): + """Remember the current X, Y coordinates.""" + self.tk.call(self._w, 'scan', 'mark', x, y) + def scan_dragto(self, x, y, gain=10): + """Adjust the view of the canvas to GAIN times the + difference between X and Y and the coordinates given in + scan_mark.""" + self.tk.call(self._w, 'scan', 'dragto', x, y, gain) + def select_adjust(self, tagOrId, index): + """Adjust the end of the selection near the cursor of an item TAGORID to index.""" + self.tk.call(self._w, 'select', 'adjust', tagOrId, index) + def select_clear(self): + """Clear the selection if it is in this widget.""" + self.tk.call(self._w, 'select', 'clear') + def select_from(self, tagOrId, index): + """Set the fixed end of a selection in item TAGORID to INDEX.""" + self.tk.call(self._w, 'select', 'from', tagOrId, index) + def select_item(self): + """Return the item which has the selection.""" + return self.tk.call(self._w, 'select', 'item') or None + def select_to(self, tagOrId, index): + """Set the variable end of a selection in item TAGORID to INDEX.""" + self.tk.call(self._w, 'select', 'to', tagOrId, index) + def type(self, tagOrId): + """Return the type of the item TAGORID.""" + return self.tk.call(self._w, 'type', tagOrId) or None + +class Checkbutton(Widget): + """Checkbutton widget which is either in on- or off-state.""" + def __init__(self, master=None, cnf={}, **kw): + """Construct a checkbutton widget with the parent MASTER. + + Valid resource names: activebackground, activeforeground, anchor, + background, bd, bg, bitmap, borderwidth, command, cursor, + disabledforeground, fg, font, foreground, height, + highlightbackground, highlightcolor, highlightthickness, image, + indicatoron, justify, offvalue, onvalue, padx, pady, relief, + selectcolor, selectimage, state, takefocus, text, textvariable, + underline, variable, width, wraplength.""" + Widget.__init__(self, master, 'checkbutton', cnf, kw) + def deselect(self): + """Put the button in off-state.""" + self.tk.call(self._w, 'deselect') + def flash(self): + """Flash the button.""" + self.tk.call(self._w, 'flash') + def invoke(self): + """Toggle the button and invoke a command if given as resource.""" + return self.tk.call(self._w, 'invoke') + def select(self): + """Put the button in on-state.""" + self.tk.call(self._w, 'select') + def toggle(self): + """Toggle the button.""" + self.tk.call(self._w, 'toggle') + +class Entry(Widget, XView): + """Entry widget which allows to display simple text.""" + def __init__(self, master=None, cnf={}, **kw): + """Construct an entry widget with the parent MASTER. + + Valid resource names: background, bd, bg, borderwidth, cursor, + exportselection, fg, font, foreground, highlightbackground, + highlightcolor, highlightthickness, insertbackground, + insertborderwidth, insertofftime, insertontime, insertwidth, + invalidcommand, invcmd, justify, relief, selectbackground, + selectborderwidth, selectforeground, show, state, takefocus, + textvariable, validate, validatecommand, vcmd, width, + xscrollcommand.""" + Widget.__init__(self, master, 'entry', cnf, kw) + def delete(self, first, last=None): + """Delete text from FIRST to LAST (not included).""" + self.tk.call(self._w, 'delete', first, last) + def get(self): + """Return the text.""" + return self.tk.call(self._w, 'get') + def icursor(self, index): + """Insert cursor at INDEX.""" + self.tk.call(self._w, 'icursor', index) + def index(self, index): + """Return position of cursor.""" + return getint(self.tk.call( + self._w, 'index', index)) + def insert(self, index, string): + """Insert STRING at INDEX.""" + self.tk.call(self._w, 'insert', index, string) + def scan_mark(self, x): + """Remember the current X, Y coordinates.""" + self.tk.call(self._w, 'scan', 'mark', x) + def scan_dragto(self, x): + """Adjust the view of the canvas to 10 times the + difference between X and Y and the coordinates given in + scan_mark.""" + self.tk.call(self._w, 'scan', 'dragto', x) + def selection_adjust(self, index): + """Adjust the end of the selection near the cursor to INDEX.""" + self.tk.call(self._w, 'selection', 'adjust', index) + select_adjust = selection_adjust + def selection_clear(self): + """Clear the selection if it is in this widget.""" + self.tk.call(self._w, 'selection', 'clear') + select_clear = selection_clear + def selection_from(self, index): + """Set the fixed end of a selection to INDEX.""" + self.tk.call(self._w, 'selection', 'from', index) + select_from = selection_from + def selection_present(self): + """Return True if there are characters selected in the entry, False + otherwise.""" + return self.tk.getboolean( + self.tk.call(self._w, 'selection', 'present')) + select_present = selection_present + def selection_range(self, start, end): + """Set the selection from START to END (not included).""" + self.tk.call(self._w, 'selection', 'range', start, end) + select_range = selection_range + def selection_to(self, index): + """Set the variable end of a selection to INDEX.""" + self.tk.call(self._w, 'selection', 'to', index) + select_to = selection_to + +class Frame(Widget): + """Frame widget which may contain other widgets and can have a 3D border.""" + def __init__(self, master=None, cnf={}, **kw): + """Construct a frame widget with the parent MASTER. + + Valid resource names: background, bd, bg, borderwidth, class, + colormap, container, cursor, height, highlightbackground, + highlightcolor, highlightthickness, relief, takefocus, visual, width.""" + cnf = _cnfmerge((cnf, kw)) + extra = () + if 'class_' in cnf: + extra = ('-class', cnf['class_']) + del cnf['class_'] + elif 'class' in cnf: + extra = ('-class', cnf['class']) + del cnf['class'] + Widget.__init__(self, master, 'frame', cnf, {}, extra) + +class Label(Widget): + """Label widget which can display text and bitmaps.""" + def __init__(self, master=None, cnf={}, **kw): + """Construct a label widget with the parent MASTER. + + STANDARD OPTIONS + + activebackground, activeforeground, anchor, + background, bitmap, borderwidth, cursor, + disabledforeground, font, foreground, + highlightbackground, highlightcolor, + highlightthickness, image, justify, + padx, pady, relief, takefocus, text, + textvariable, underline, wraplength + + WIDGET-SPECIFIC OPTIONS + + height, state, width + + """ + Widget.__init__(self, master, 'label', cnf, kw) + +class Listbox(Widget, XView, YView): + """Listbox widget which can display a list of strings.""" + def __init__(self, master=None, cnf={}, **kw): + """Construct a listbox widget with the parent MASTER. + + Valid resource names: background, bd, bg, borderwidth, cursor, + exportselection, fg, font, foreground, height, highlightbackground, + highlightcolor, highlightthickness, relief, selectbackground, + selectborderwidth, selectforeground, selectmode, setgrid, takefocus, + width, xscrollcommand, yscrollcommand, listvariable.""" + Widget.__init__(self, master, 'listbox', cnf, kw) + def activate(self, index): + """Activate item identified by INDEX.""" + self.tk.call(self._w, 'activate', index) + def bbox(self, index): + """Return a tuple of X1,Y1,X2,Y2 coordinates for a rectangle + which encloses the item identified by the given index.""" + return self._getints(self.tk.call(self._w, 'bbox', index)) or None + def curselection(self): + """Return the indices of currently selected item.""" + return self._getints(self.tk.call(self._w, 'curselection')) or () + def delete(self, first, last=None): + """Delete items from FIRST to LAST (included).""" + self.tk.call(self._w, 'delete', first, last) + def get(self, first, last=None): + """Get list of items from FIRST to LAST (included).""" + if last is not None: + return self.tk.splitlist(self.tk.call( + self._w, 'get', first, last)) + else: + return self.tk.call(self._w, 'get', first) + def index(self, index): + """Return index of item identified with INDEX.""" + i = self.tk.call(self._w, 'index', index) + if i == 'none': return None + return getint(i) + def insert(self, index, *elements): + """Insert ELEMENTS at INDEX.""" + self.tk.call((self._w, 'insert', index) + elements) + def nearest(self, y): + """Get index of item which is nearest to y coordinate Y.""" + return getint(self.tk.call( + self._w, 'nearest', y)) + def scan_mark(self, x, y): + """Remember the current X, Y coordinates.""" + self.tk.call(self._w, 'scan', 'mark', x, y) + def scan_dragto(self, x, y): + """Adjust the view of the listbox to 10 times the + difference between X and Y and the coordinates given in + scan_mark.""" + self.tk.call(self._w, 'scan', 'dragto', x, y) + def see(self, index): + """Scroll such that INDEX is visible.""" + self.tk.call(self._w, 'see', index) + def selection_anchor(self, index): + """Set the fixed end oft the selection to INDEX.""" + self.tk.call(self._w, 'selection', 'anchor', index) + select_anchor = selection_anchor + def selection_clear(self, first, last=None): + """Clear the selection from FIRST to LAST (included).""" + self.tk.call(self._w, + 'selection', 'clear', first, last) + select_clear = selection_clear + def selection_includes(self, index): + """Return 1 if INDEX is part of the selection.""" + return self.tk.getboolean(self.tk.call( + self._w, 'selection', 'includes', index)) + select_includes = selection_includes + def selection_set(self, first, last=None): + """Set the selection from FIRST to LAST (included) without + changing the currently selected elements.""" + self.tk.call(self._w, 'selection', 'set', first, last) + select_set = selection_set + def size(self): + """Return the number of elements in the listbox.""" + return getint(self.tk.call(self._w, 'size')) + def itemcget(self, index, option): + """Return the resource value for an ITEM and an OPTION.""" + return self.tk.call( + (self._w, 'itemcget') + (index, '-'+option)) + def itemconfigure(self, index, cnf=None, **kw): + """Configure resources of an ITEM. + + The values for resources are specified as keyword arguments. + To get an overview about the allowed keyword arguments + call the method without arguments. + Valid resource names: background, bg, foreground, fg, + selectbackground, selectforeground.""" + return self._configure(('itemconfigure', index), cnf, kw) + itemconfig = itemconfigure + +class Menu(Widget): + """Menu widget which allows to display menu bars, pull-down menus and pop-up menus.""" + def __init__(self, master=None, cnf={}, **kw): + """Construct menu widget with the parent MASTER. + + Valid resource names: activebackground, activeborderwidth, + activeforeground, background, bd, bg, borderwidth, cursor, + disabledforeground, fg, font, foreground, postcommand, relief, + selectcolor, takefocus, tearoff, tearoffcommand, title, type.""" + Widget.__init__(self, master, 'menu', cnf, kw) + def tk_bindForTraversal(self): + pass # obsolete since Tk 4.0 + def tk_mbPost(self): + self.tk.call('tk_mbPost', self._w) + def tk_mbUnpost(self): + self.tk.call('tk_mbUnpost') + def tk_traverseToMenu(self, char): + self.tk.call('tk_traverseToMenu', self._w, char) + def tk_traverseWithinMenu(self, char): + self.tk.call('tk_traverseWithinMenu', self._w, char) + def tk_getMenuButtons(self): + return self.tk.call('tk_getMenuButtons', self._w) + def tk_nextMenu(self, count): + self.tk.call('tk_nextMenu', count) + def tk_nextMenuEntry(self, count): + self.tk.call('tk_nextMenuEntry', count) + def tk_invokeMenu(self): + self.tk.call('tk_invokeMenu', self._w) + def tk_firstMenu(self): + self.tk.call('tk_firstMenu', self._w) + def tk_mbButtonDown(self): + self.tk.call('tk_mbButtonDown', self._w) + def tk_popup(self, x, y, entry=""): + """Post the menu at position X,Y with entry ENTRY.""" + self.tk.call('tk_popup', self._w, x, y, entry) + def activate(self, index): + """Activate entry at INDEX.""" + self.tk.call(self._w, 'activate', index) + def add(self, itemType, cnf={}, **kw): + """Internal function.""" + self.tk.call((self._w, 'add', itemType) + + self._options(cnf, kw)) + def add_cascade(self, cnf={}, **kw): + """Add hierarchical menu item.""" + self.add('cascade', cnf or kw) + def add_checkbutton(self, cnf={}, **kw): + """Add checkbutton menu item.""" + self.add('checkbutton', cnf or kw) + def add_command(self, cnf={}, **kw): + """Add command menu item.""" + self.add('command', cnf or kw) + def add_radiobutton(self, cnf={}, **kw): + """Addd radio menu item.""" + self.add('radiobutton', cnf or kw) + def add_separator(self, cnf={}, **kw): + """Add separator.""" + self.add('separator', cnf or kw) + def insert(self, index, itemType, cnf={}, **kw): + """Internal function.""" + self.tk.call((self._w, 'insert', index, itemType) + + self._options(cnf, kw)) + def insert_cascade(self, index, cnf={}, **kw): + """Add hierarchical menu item at INDEX.""" + self.insert(index, 'cascade', cnf or kw) + def insert_checkbutton(self, index, cnf={}, **kw): + """Add checkbutton menu item at INDEX.""" + self.insert(index, 'checkbutton', cnf or kw) + def insert_command(self, index, cnf={}, **kw): + """Add command menu item at INDEX.""" + self.insert(index, 'command', cnf or kw) + def insert_radiobutton(self, index, cnf={}, **kw): + """Addd radio menu item at INDEX.""" + self.insert(index, 'radiobutton', cnf or kw) + def insert_separator(self, index, cnf={}, **kw): + """Add separator at INDEX.""" + self.insert(index, 'separator', cnf or kw) + def delete(self, index1, index2=None): + """Delete menu items between INDEX1 and INDEX2 (included).""" + if index2 is None: + index2 = index1 + + num_index1, num_index2 = self.index(index1), self.index(index2) + if (num_index1 is None) or (num_index2 is None): + num_index1, num_index2 = 0, -1 + + for i in range(num_index1, num_index2 + 1): + if 'command' in self.entryconfig(i): + c = str(self.entrycget(i, 'command')) + if c: + self.deletecommand(c) + self.tk.call(self._w, 'delete', index1, index2) + def entrycget(self, index, option): + """Return the resource value of an menu item for OPTION at INDEX.""" + return self.tk.call(self._w, 'entrycget', index, '-' + option) + def entryconfigure(self, index, cnf=None, **kw): + """Configure a menu item at INDEX.""" + return self._configure(('entryconfigure', index), cnf, kw) + entryconfig = entryconfigure + def index(self, index): + """Return the index of a menu item identified by INDEX.""" + i = self.tk.call(self._w, 'index', index) + if i == 'none': return None + return getint(i) + def invoke(self, index): + """Invoke a menu item identified by INDEX and execute + the associated command.""" + return self.tk.call(self._w, 'invoke', index) + def post(self, x, y): + """Display a menu at position X,Y.""" + self.tk.call(self._w, 'post', x, y) + def type(self, index): + """Return the type of the menu item at INDEX.""" + return self.tk.call(self._w, 'type', index) + def unpost(self): + """Unmap a menu.""" + self.tk.call(self._w, 'unpost') + def yposition(self, index): + """Return the y-position of the topmost pixel of the menu item at INDEX.""" + return getint(self.tk.call( + self._w, 'yposition', index)) + +class Menubutton(Widget): + """Menubutton widget, obsolete since Tk8.0.""" + def __init__(self, master=None, cnf={}, **kw): + Widget.__init__(self, master, 'menubutton', cnf, kw) + +class Message(Widget): + """Message widget to display multiline text. Obsolete since Label does it too.""" + def __init__(self, master=None, cnf={}, **kw): + Widget.__init__(self, master, 'message', cnf, kw) + +class Radiobutton(Widget): + """Radiobutton widget which shows only one of several buttons in on-state.""" + def __init__(self, master=None, cnf={}, **kw): + """Construct a radiobutton widget with the parent MASTER. + + Valid resource names: activebackground, activeforeground, anchor, + background, bd, bg, bitmap, borderwidth, command, cursor, + disabledforeground, fg, font, foreground, height, + highlightbackground, highlightcolor, highlightthickness, image, + indicatoron, justify, padx, pady, relief, selectcolor, selectimage, + state, takefocus, text, textvariable, underline, value, variable, + width, wraplength.""" + Widget.__init__(self, master, 'radiobutton', cnf, kw) + def deselect(self): + """Put the button in off-state.""" + + self.tk.call(self._w, 'deselect') + def flash(self): + """Flash the button.""" + self.tk.call(self._w, 'flash') + def invoke(self): + """Toggle the button and invoke a command if given as resource.""" + return self.tk.call(self._w, 'invoke') + def select(self): + """Put the button in on-state.""" + self.tk.call(self._w, 'select') + +class Scale(Widget): + """Scale widget which can display a numerical scale.""" + def __init__(self, master=None, cnf={}, **kw): + """Construct a scale widget with the parent MASTER. + + Valid resource names: activebackground, background, bigincrement, bd, + bg, borderwidth, command, cursor, digits, fg, font, foreground, from, + highlightbackground, highlightcolor, highlightthickness, label, + length, orient, relief, repeatdelay, repeatinterval, resolution, + showvalue, sliderlength, sliderrelief, state, takefocus, + tickinterval, to, troughcolor, variable, width.""" + Widget.__init__(self, master, 'scale', cnf, kw) + def get(self): + """Get the current value as integer or float.""" + value = self.tk.call(self._w, 'get') + try: + return getint(value) + except ValueError: + return getdouble(value) + def set(self, value): + """Set the value to VALUE.""" + self.tk.call(self._w, 'set', value) + def coords(self, value=None): + """Return a tuple (X,Y) of the point along the centerline of the + trough that corresponds to VALUE or the current value if None is + given.""" + + return self._getints(self.tk.call(self._w, 'coords', value)) + def identify(self, x, y): + """Return where the point X,Y lies. Valid return values are "slider", + "though1" and "though2".""" + return self.tk.call(self._w, 'identify', x, y) + +class Scrollbar(Widget): + """Scrollbar widget which displays a slider at a certain position.""" + def __init__(self, master=None, cnf={}, **kw): + """Construct a scrollbar widget with the parent MASTER. + + Valid resource names: activebackground, activerelief, + background, bd, bg, borderwidth, command, cursor, + elementborderwidth, highlightbackground, + highlightcolor, highlightthickness, jump, orient, + relief, repeatdelay, repeatinterval, takefocus, + troughcolor, width.""" + Widget.__init__(self, master, 'scrollbar', cnf, kw) + def activate(self, index): + """Display the element at INDEX with activebackground and activerelief. + INDEX can be "arrow1","slider" or "arrow2".""" + self.tk.call(self._w, 'activate', index) + def delta(self, deltax, deltay): + """Return the fractional change of the scrollbar setting if it + would be moved by DELTAX or DELTAY pixels.""" + return getdouble( + self.tk.call(self._w, 'delta', deltax, deltay)) + def fraction(self, x, y): + """Return the fractional value which corresponds to a slider + position of X,Y.""" + return getdouble(self.tk.call(self._w, 'fraction', x, y)) + def identify(self, x, y): + """Return the element under position X,Y as one of + "arrow1","slider","arrow2" or "".""" + return self.tk.call(self._w, 'identify', x, y) + def get(self): + """Return the current fractional values (upper and lower end) + of the slider position.""" + return self._getdoubles(self.tk.call(self._w, 'get')) + def set(self, *args): + """Set the fractional values of the slider position (upper and + lower ends as value between 0 and 1).""" + self.tk.call((self._w, 'set') + args) + + + +class Text(Widget, XView, YView): + """Text widget which can display text in various forms.""" + def __init__(self, master=None, cnf={}, **kw): + """Construct a text widget with the parent MASTER. + + STANDARD OPTIONS + + background, borderwidth, cursor, + exportselection, font, foreground, + highlightbackground, highlightcolor, + highlightthickness, insertbackground, + insertborderwidth, insertofftime, + insertontime, insertwidth, padx, pady, + relief, selectbackground, + selectborderwidth, selectforeground, + setgrid, takefocus, + xscrollcommand, yscrollcommand, + + WIDGET-SPECIFIC OPTIONS + + autoseparators, height, maxundo, + spacing1, spacing2, spacing3, + state, tabs, undo, width, wrap, + + """ + Widget.__init__(self, master, 'text', cnf, kw) + def bbox(self, *args): + """Return a tuple of (x,y,width,height) which gives the bounding + box of the visible part of the character at the index in ARGS.""" + return self._getints( + self.tk.call((self._w, 'bbox') + args)) or None + def tk_textSelectTo(self, index): + self.tk.call('tk_textSelectTo', self._w, index) + def tk_textBackspace(self): + self.tk.call('tk_textBackspace', self._w) + def tk_textIndexCloser(self, a, b, c): + self.tk.call('tk_textIndexCloser', self._w, a, b, c) + def tk_textResetAnchor(self, index): + self.tk.call('tk_textResetAnchor', self._w, index) + def compare(self, index1, op, index2): + """Return whether between index INDEX1 and index INDEX2 the + relation OP is satisfied. OP is one of <, <=, ==, >=, >, or !=.""" + return self.tk.getboolean(self.tk.call( + self._w, 'compare', index1, op, index2)) + def debug(self, boolean=None): + """Turn on the internal consistency checks of the B-Tree inside the text + widget according to BOOLEAN.""" + if boolean is None: + return self.tk.getboolean(self.tk.call(self._w, 'debug')) + self.tk.call(self._w, 'debug', boolean) + def delete(self, index1, index2=None): + """Delete the characters between INDEX1 and INDEX2 (not included).""" + self.tk.call(self._w, 'delete', index1, index2) + def dlineinfo(self, index): + """Return tuple (x,y,width,height,baseline) giving the bounding box + and baseline position of the visible part of the line containing + the character at INDEX.""" + return self._getints(self.tk.call(self._w, 'dlineinfo', index)) + def dump(self, index1, index2=None, command=None, **kw): + """Return the contents of the widget between index1 and index2. + + The type of contents returned in filtered based on the keyword + parameters; if 'all', 'image', 'mark', 'tag', 'text', or 'window' are + given and true, then the corresponding items are returned. The result + is a list of triples of the form (key, value, index). If none of the + keywords are true then 'all' is used by default. + + If the 'command' argument is given, it is called once for each element + of the list of triples, with the values of each triple serving as the + arguments to the function. In this case the list is not returned.""" + args = [] + func_name = None + result = None + if not command: + # Never call the dump command without the -command flag, since the + # output could involve Tcl quoting and would be a pain to parse + # right. Instead just set the command to build a list of triples + # as if we had done the parsing. + result = [] + def append_triple(key, value, index, result=result): + result.append((key, value, index)) + command = append_triple + try: + if not isinstance(command, str): + func_name = command = self._register(command) + args += ["-command", command] + for key in kw: + if kw[key]: args.append("-" + key) + args.append(index1) + if index2: + args.append(index2) + self.tk.call(self._w, "dump", *args) + return result + finally: + if func_name: + self.deletecommand(func_name) + + ## new in tk8.4 + def edit(self, *args): + """Internal method + + This method controls the undo mechanism and + the modified flag. The exact behavior of the + command depends on the option argument that + follows the edit argument. The following forms + of the command are currently supported: + + edit_modified, edit_redo, edit_reset, edit_separator + and edit_undo + + """ + return self.tk.call(self._w, 'edit', *args) + + def edit_modified(self, arg=None): + """Get or Set the modified flag + + If arg is not specified, returns the modified + flag of the widget. The insert, delete, edit undo and + edit redo commands or the user can set or clear the + modified flag. If boolean is specified, sets the + modified flag of the widget to arg. + """ + return self.edit("modified", arg) + + def edit_redo(self): + """Redo the last undone edit + + When the undo option is true, reapplies the last + undone edits provided no other edits were done since + then. Generates an error when the redo stack is empty. + Does nothing when the undo option is false. + """ + return self.edit("redo") + + def edit_reset(self): + """Clears the undo and redo stacks + """ + return self.edit("reset") + + def edit_separator(self): + """Inserts a separator (boundary) on the undo stack. + + Does nothing when the undo option is false + """ + return self.edit("separator") + + def edit_undo(self): + """Undoes the last edit action + + If the undo option is true. An edit action is defined + as all the insert and delete commands that are recorded + on the undo stack in between two separators. Generates + an error when the undo stack is empty. Does nothing + when the undo option is false + """ + return self.edit("undo") + + def get(self, index1, index2=None): + """Return the text from INDEX1 to INDEX2 (not included).""" + return self.tk.call(self._w, 'get', index1, index2) + # (Image commands are new in 8.0) + def image_cget(self, index, option): + """Return the value of OPTION of an embedded image at INDEX.""" + if option[:1] != "-": + option = "-" + option + if option[-1:] == "_": + option = option[:-1] + return self.tk.call(self._w, "image", "cget", index, option) + def image_configure(self, index, cnf=None, **kw): + """Configure an embedded image at INDEX.""" + return self._configure(('image', 'configure', index), cnf, kw) + def image_create(self, index, cnf={}, **kw): + """Create an embedded image at INDEX.""" + return self.tk.call( + self._w, "image", "create", index, + *self._options(cnf, kw)) + def image_names(self): + """Return all names of embedded images in this widget.""" + return self.tk.call(self._w, "image", "names") + def index(self, index): + """Return the index in the form line.char for INDEX.""" + return str(self.tk.call(self._w, 'index', index)) + def insert(self, index, chars, *args): + """Insert CHARS before the characters at INDEX. An additional + tag can be given in ARGS. Additional CHARS and tags can follow in ARGS.""" + self.tk.call((self._w, 'insert', index, chars) + args) + def mark_gravity(self, markName, direction=None): + """Change the gravity of a mark MARKNAME to DIRECTION (LEFT or RIGHT). + Return the current value if None is given for DIRECTION.""" + return self.tk.call( + (self._w, 'mark', 'gravity', markName, direction)) + def mark_names(self): + """Return all mark names.""" + return self.tk.splitlist(self.tk.call( + self._w, 'mark', 'names')) + def mark_set(self, markName, index): + """Set mark MARKNAME before the character at INDEX.""" + self.tk.call(self._w, 'mark', 'set', markName, index) + def mark_unset(self, *markNames): + """Delete all marks in MARKNAMES.""" + self.tk.call((self._w, 'mark', 'unset') + markNames) + def mark_next(self, index): + """Return the name of the next mark after INDEX.""" + return self.tk.call(self._w, 'mark', 'next', index) or None + def mark_previous(self, index): + """Return the name of the previous mark before INDEX.""" + return self.tk.call(self._w, 'mark', 'previous', index) or None + def scan_mark(self, x, y): + """Remember the current X, Y coordinates.""" + self.tk.call(self._w, 'scan', 'mark', x, y) + def scan_dragto(self, x, y): + """Adjust the view of the text to 10 times the + difference between X and Y and the coordinates given in + scan_mark.""" + self.tk.call(self._w, 'scan', 'dragto', x, y) + def search(self, pattern, index, stopindex=None, + forwards=None, backwards=None, exact=None, + regexp=None, nocase=None, count=None, elide=None): + """Search PATTERN beginning from INDEX until STOPINDEX. + Return the index of the first character of a match or an + empty string.""" + args = [self._w, 'search'] + if forwards: args.append('-forwards') + if backwards: args.append('-backwards') + if exact: args.append('-exact') + if regexp: args.append('-regexp') + if nocase: args.append('-nocase') + if elide: args.append('-elide') + if count: args.append('-count'); args.append(count) + if pattern and pattern[0] == '-': args.append('--') + args.append(pattern) + args.append(index) + if stopindex: args.append(stopindex) + return str(self.tk.call(tuple(args))) + def see(self, index): + """Scroll such that the character at INDEX is visible.""" + self.tk.call(self._w, 'see', index) + def tag_add(self, tagName, index1, *args): + """Add tag TAGNAME to all characters between INDEX1 and index2 in ARGS. + Additional pairs of indices may follow in ARGS.""" + self.tk.call( + (self._w, 'tag', 'add', tagName, index1) + args) + def tag_unbind(self, tagName, sequence, funcid=None): + """Unbind for all characters with TAGNAME for event SEQUENCE the + function identified with FUNCID.""" + self.tk.call(self._w, 'tag', 'bind', tagName, sequence, '') + if funcid: + self.deletecommand(funcid) + def tag_bind(self, tagName, sequence, func, add=None): + """Bind to all characters with TAGNAME at event SEQUENCE a call to function FUNC. + + An additional boolean parameter ADD specifies whether FUNC will be + called additionally to the other bound function or whether it will + replace the previous function. See bind for the return value.""" + return self._bind((self._w, 'tag', 'bind', tagName), + sequence, func, add) + def tag_cget(self, tagName, option): + """Return the value of OPTION for tag TAGNAME.""" + if option[:1] != '-': + option = '-' + option + if option[-1:] == '_': + option = option[:-1] + return self.tk.call(self._w, 'tag', 'cget', tagName, option) + def tag_configure(self, tagName, cnf=None, **kw): + """Configure a tag TAGNAME.""" + return self._configure(('tag', 'configure', tagName), cnf, kw) + tag_config = tag_configure + def tag_delete(self, *tagNames): + """Delete all tags in TAGNAMES.""" + self.tk.call((self._w, 'tag', 'delete') + tagNames) + def tag_lower(self, tagName, belowThis=None): + """Change the priority of tag TAGNAME such that it is lower + than the priority of BELOWTHIS.""" + self.tk.call(self._w, 'tag', 'lower', tagName, belowThis) + def tag_names(self, index=None): + """Return a list of all tag names.""" + return self.tk.splitlist( + self.tk.call(self._w, 'tag', 'names', index)) + def tag_nextrange(self, tagName, index1, index2=None): + """Return a list of start and end index for the first sequence of + characters between INDEX1 and INDEX2 which all have tag TAGNAME. + The text is searched forward from INDEX1.""" + return self.tk.splitlist(self.tk.call( + self._w, 'tag', 'nextrange', tagName, index1, index2)) + def tag_prevrange(self, tagName, index1, index2=None): + """Return a list of start and end index for the first sequence of + characters between INDEX1 and INDEX2 which all have tag TAGNAME. + The text is searched backwards from INDEX1.""" + return self.tk.splitlist(self.tk.call( + self._w, 'tag', 'prevrange', tagName, index1, index2)) + def tag_raise(self, tagName, aboveThis=None): + """Change the priority of tag TAGNAME such that it is higher + than the priority of ABOVETHIS.""" + self.tk.call( + self._w, 'tag', 'raise', tagName, aboveThis) + def tag_ranges(self, tagName): + """Return a list of ranges of text which have tag TAGNAME.""" + return self.tk.splitlist(self.tk.call( + self._w, 'tag', 'ranges', tagName)) + def tag_remove(self, tagName, index1, index2=None): + """Remove tag TAGNAME from all characters between INDEX1 and INDEX2.""" + self.tk.call( + self._w, 'tag', 'remove', tagName, index1, index2) + def window_cget(self, index, option): + """Return the value of OPTION of an embedded window at INDEX.""" + if option[:1] != '-': + option = '-' + option + if option[-1:] == '_': + option = option[:-1] + return self.tk.call(self._w, 'window', 'cget', index, option) + def window_configure(self, index, cnf=None, **kw): + """Configure an embedded window at INDEX.""" + return self._configure(('window', 'configure', index), cnf, kw) + window_config = window_configure + def window_create(self, index, cnf={}, **kw): + """Create a window at INDEX.""" + self.tk.call( + (self._w, 'window', 'create', index) + + self._options(cnf, kw)) + def window_names(self): + """Return all names of embedded windows in this widget.""" + return self.tk.splitlist( + self.tk.call(self._w, 'window', 'names')) + def yview_pickplace(self, *what): + """Obsolete function, use see.""" + self.tk.call((self._w, 'yview', '-pickplace') + what) + + +class _setit: + """Internal class. It wraps the command in the widget OptionMenu.""" + def __init__(self, var, value, callback=None): + self.__value = value + self.__var = var + self.__callback = callback + def __call__(self, *args): + self.__var.set(self.__value) + if self.__callback: + self.__callback(self.__value, *args) + +class OptionMenu(Menubutton): + """OptionMenu which allows the user to select a value from a menu.""" + def __init__(self, master, variable, value, *values, **kwargs): + """Construct an optionmenu widget with the parent MASTER, with + the resource textvariable set to VARIABLE, the initially selected + value VALUE, the other menu values VALUES and an additional + keyword argument command.""" + kw = {"borderwidth": 2, "textvariable": variable, + "indicatoron": 1, "relief": RAISED, "anchor": "c", + "highlightthickness": 2} + Widget.__init__(self, master, "menubutton", kw) + self.widgetName = 'tk_optionMenu' + menu = self.__menu = Menu(self, name="menu", tearoff=0) + self.menuname = menu._w + # 'command' is the only supported keyword + callback = kwargs.get('command') + if 'command' in kwargs: + del kwargs['command'] + if kwargs: + raise TclError, 'unknown option -'+kwargs.keys()[0] + menu.add_command(label=value, + command=_setit(variable, value, callback)) + for v in values: + menu.add_command(label=v, + command=_setit(variable, v, callback)) + self["menu"] = menu + + def __getitem__(self, name): + if name == 'menu': + return self.__menu + return Widget.__getitem__(self, name) + + def destroy(self): + """Destroy this widget and the associated menu.""" + Menubutton.destroy(self) + self.__menu = None + +class Image: + """Base class for images.""" + _last_id = 0 + 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' + self.tk = master.tk + if not name: + Image._last_id += 1 + name = "pyimage%r" % (Image._last_id,) # tk itself would use image + # The following is needed for systems where id(x) + # can return a negative number, such as Linux/m68k: + if name[0] == '-': name = '_' + name[1:] + if kw and cnf: cnf = _cnfmerge((cnf, kw)) + elif kw: cnf = kw + options = () + for k, v in cnf.items(): + if hasattr(v, '__call__'): + v = self._register(v) + options = options + ('-'+k, v) + self.tk.call(('image', 'create', imgtype, name,) + options) + self.name = name + def __str__(self): return self.name + def __del__(self): + if self.name: + try: + self.tk.call('image', 'delete', self.name) + except TclError: + # May happen if the root was destroyed + pass + def __setitem__(self, key, value): + self.tk.call(self.name, 'configure', '-'+key, value) + def __getitem__(self, key): + return self.tk.call(self.name, 'configure', '-'+key) + def configure(self, **kw): + """Configure the image.""" + res = () + for k, v in _cnfmerge(kw).items(): + if v is not None: + if k[-1] == '_': k = k[:-1] + if hasattr(v, '__call__'): + v = self._register(v) + res = res + ('-'+k, v) + self.tk.call((self.name, 'config') + res) + config = configure + def height(self): + """Return the height of the image.""" + return getint( + self.tk.call('image', 'height', self.name)) + def type(self): + """Return the type of the imgage, e.g. "photo" or "bitmap".""" + return self.tk.call('image', 'type', self.name) + def width(self): + """Return the width of the image.""" + return getint( + self.tk.call('image', 'width', self.name)) + +class PhotoImage(Image): + """Widget which can display colored images in GIF, PPM/PGM format.""" + def __init__(self, name=None, cnf={}, master=None, **kw): + """Create an image with NAME. + + Valid resource names: data, format, file, gamma, height, palette, + width.""" + Image.__init__(self, 'photo', name, cnf, master, **kw) + def blank(self): + """Display a transparent image.""" + self.tk.call(self.name, 'blank') + def cget(self, option): + """Return the value of OPTION.""" + return self.tk.call(self.name, 'cget', '-' + option) + # XXX config + def __getitem__(self, key): + return self.tk.call(self.name, 'cget', '-' + key) + # XXX copy -from, -to, ...? + def copy(self): + """Return a new PhotoImage with the same image as this widget.""" + destImage = PhotoImage() + self.tk.call(destImage, 'copy', self.name) + return destImage + def zoom(self,x,y=''): + """Return a new PhotoImage with the same image as this widget + but zoom it with X and Y.""" + destImage = PhotoImage() + if y=='': y=x + self.tk.call(destImage, 'copy', self.name, '-zoom',x,y) + return destImage + def subsample(self,x,y=''): + """Return a new PhotoImage based on the same image as this widget + but use only every Xth or Yth pixel.""" + destImage = PhotoImage() + if y=='': y=x + self.tk.call(destImage, 'copy', self.name, '-subsample',x,y) + return destImage + def get(self, x, y): + """Return the color (red, green, blue) of the pixel at X,Y.""" + return self.tk.call(self.name, 'get', x, y) + def put(self, data, to=None): + """Put row formatted colors to image starting from + position TO, e.g. image.put("{red green} {blue yellow}", to=(4,6))""" + args = (self.name, 'put', data) + if to: + if to[0] == '-to': + to = to[1:] + args = args + ('-to',) + tuple(to) + self.tk.call(args) + # XXX read + def write(self, filename, format=None, from_coords=None): + """Write image to file FILENAME in FORMAT starting from + position FROM_COORDS.""" + args = (self.name, 'write', filename) + if format: + args = args + ('-format', format) + if from_coords: + args = args + ('-from',) + tuple(from_coords) + self.tk.call(args) + +class BitmapImage(Image): + """Widget which can display a bitmap.""" + def __init__(self, name=None, cnf={}, master=None, **kw): + """Create a bitmap with NAME. + + Valid resource names: background, data, file, foreground, maskdata, maskfile.""" + Image.__init__(self, 'bitmap', name, cnf, master, **kw) + +def image_names(): + return _default_root.tk.splitlist(_default_root.tk.call('image', 'names')) + +def image_types(): + return _default_root.tk.splitlist(_default_root.tk.call('image', 'types')) + + +class Spinbox(Widget, XView): + """spinbox widget.""" + def __init__(self, master=None, cnf={}, **kw): + """Construct a spinbox widget with the parent MASTER. + + STANDARD OPTIONS + + activebackground, background, borderwidth, + cursor, exportselection, font, foreground, + highlightbackground, highlightcolor, + highlightthickness, insertbackground, + insertborderwidth, insertofftime, + insertontime, insertwidth, justify, relief, + repeatdelay, repeatinterval, + selectbackground, selectborderwidth + selectforeground, takefocus, textvariable + xscrollcommand. + + WIDGET-SPECIFIC OPTIONS + + buttonbackground, buttoncursor, + buttondownrelief, buttonuprelief, + command, disabledbackground, + disabledforeground, format, from, + invalidcommand, increment, + readonlybackground, state, to, + validate, validatecommand values, + width, wrap, + """ + Widget.__init__(self, master, 'spinbox', cnf, kw) + + def bbox(self, index): + """Return a tuple of X1,Y1,X2,Y2 coordinates for a + rectangle which encloses the character given by index. + + The first two elements of the list give the x and y + coordinates of the upper-left corner of the screen + area covered by the character (in pixels relative + to the widget) and the last two elements give the + width and height of the character, in pixels. The + bounding box may refer to a region outside the + visible area of the window. + """ + return self._getints(self.tk.call(self._w, 'bbox', index)) or None + + def delete(self, first, last=None): + """Delete one or more elements of the spinbox. + + First is the index of the first character to delete, + and last is the index of the character just after + the last one to delete. If last isn't specified it + defaults to first+1, i.e. a single character is + deleted. This command returns an empty string. + """ + return self.tk.call(self._w, 'delete', first, last) + + def get(self): + """Returns the spinbox's string""" + return self.tk.call(self._w, 'get') + + def icursor(self, index): + """Alter the position of the insertion cursor. + + The insertion cursor will be displayed just before + the character given by index. Returns an empty string + """ + return self.tk.call(self._w, 'icursor', index) + + def identify(self, x, y): + """Returns the name of the widget at position x, y + + Return value is one of: none, buttondown, buttonup, entry + """ + return self.tk.call(self._w, 'identify', x, y) + + def index(self, index): + """Returns the numerical index corresponding to index + """ + return self.tk.call(self._w, 'index', index) + + def insert(self, index, s): + """Insert string s at index + + Returns an empty string. + """ + return self.tk.call(self._w, 'insert', index, s) + + def invoke(self, element): + """Causes the specified element to be invoked + + The element could be buttondown or buttonup + triggering the action associated with it. + """ + return self.tk.call(self._w, 'invoke', element) + + def scan(self, *args): + """Internal function.""" + return self._getints( + self.tk.call((self._w, 'scan') + args)) or () + + def scan_mark(self, x): + """Records x and the current view in the spinbox window; + + used in conjunction with later scan dragto commands. + Typically this command is associated with a mouse button + press in the widget. It returns an empty string. + """ + return self.scan("mark", x) + + def scan_dragto(self, x): + """Compute the difference between the given x argument + and the x argument to the last scan mark command + + It then adjusts the view left or right by 10 times the + difference in x-coordinates. This command is typically + associated with mouse motion events in the widget, to + produce the effect of dragging the spinbox at high speed + through the window. The return value is an empty string. + """ + return self.scan("dragto", x) + + def selection(self, *args): + """Internal function.""" + return self._getints( + self.tk.call((self._w, 'selection') + args)) or () + + def selection_adjust(self, index): + """Locate the end of the selection nearest to the character + given by index, + + Then adjust that end of the selection to be at index + (i.e including but not going beyond index). The other + end of the selection is made the anchor point for future + select to commands. If the selection isn't currently in + the spinbox, then a new selection is created to include + the characters between index and the most recent selection + anchor point, inclusive. Returns an empty string. + """ + return self.selection("adjust", index) + + def selection_clear(self): + """Clear the selection + + If the selection isn't in this widget then the + command has no effect. Returns an empty string. + """ + return self.selection("clear") + + def selection_element(self, element=None): + """Sets or gets the currently selected element. + + If a spinbutton element is specified, it will be + displayed depressed + """ + return self.selection("element", element) + +########################################################################### + +class LabelFrame(Widget): + """labelframe widget.""" + def __init__(self, master=None, cnf={}, **kw): + """Construct a labelframe widget with the parent MASTER. + + STANDARD OPTIONS + + borderwidth, cursor, font, foreground, + highlightbackground, highlightcolor, + highlightthickness, padx, pady, relief, + takefocus, text + + WIDGET-SPECIFIC OPTIONS + + background, class, colormap, container, + height, labelanchor, labelwidget, + visual, width + """ + Widget.__init__(self, master, 'labelframe', cnf, kw) + +######################################################################## + +class PanedWindow(Widget): + """panedwindow widget.""" + def __init__(self, master=None, cnf={}, **kw): + """Construct a panedwindow widget with the parent MASTER. + + STANDARD OPTIONS + + background, borderwidth, cursor, height, + orient, relief, width + + WIDGET-SPECIFIC OPTIONS + + handlepad, handlesize, opaqueresize, + sashcursor, sashpad, sashrelief, + sashwidth, showhandle, + """ + Widget.__init__(self, master, 'panedwindow', cnf, kw) + + def add(self, child, **kw): + """Add a child widget to the panedwindow in a new pane. + + The child argument is the name of the child widget + followed by pairs of arguments that specify how to + manage the windows. The possible options and values + are the ones accepted by the paneconfigure method. + """ + self.tk.call((self._w, 'add', child) + self._options(kw)) + + def remove(self, child): + """Remove the pane containing child from the panedwindow + + All geometry management options for child will be forgotten. + """ + self.tk.call(self._w, 'forget', child) + forget=remove + + def identify(self, x, y): + """Identify the panedwindow component at point x, y + + If the point is over a sash or a sash handle, the result + is a two element list containing the index of the sash or + handle, and a word indicating whether it is over a sash + or a handle, such as {0 sash} or {2 handle}. If the point + is over any other part of the panedwindow, the result is + an empty list. + """ + return self.tk.call(self._w, 'identify', x, y) + + def proxy(self, *args): + """Internal function.""" + return self._getints( + self.tk.call((self._w, 'proxy') + args)) or () + + def proxy_coord(self): + """Return the x and y pair of the most recent proxy location + """ + return self.proxy("coord") + + def proxy_forget(self): + """Remove the proxy from the display. + """ + return self.proxy("forget") + + def proxy_place(self, x, y): + """Place the proxy at the given x and y coordinates. + """ + return self.proxy("place", x, y) + + def sash(self, *args): + """Internal function.""" + return self._getints( + self.tk.call((self._w, 'sash') + args)) or () + + def sash_coord(self, index): + """Return the current x and y pair for the sash given by index. + + Index must be an integer between 0 and 1 less than the + number of panes in the panedwindow. The coordinates given are + those of the top left corner of the region containing the sash. + pathName sash dragto index x y This command computes the + difference between the given coordinates and the coordinates + given to the last sash coord command for the given sash. It then + moves that sash the computed difference. The return value is the + empty string. + """ + return self.sash("coord", index) + + def sash_mark(self, index): + """Records x and y for the sash given by index; + + Used in conjunction with later dragto commands to move the sash. + """ + return self.sash("mark", index) + + def sash_place(self, index, x, y): + """Place the sash given by index at the given coordinates + """ + return self.sash("place", index, x, y) + + def panecget(self, child, option): + """Query a management option for window. + + Option may be any value allowed by the paneconfigure subcommand + """ + return self.tk.call( + (self._w, 'panecget') + (child, '-'+option)) + + def paneconfigure(self, tagOrId, cnf=None, **kw): + """Query or modify the management options for window. + + If no option is specified, returns a list describing all + of the available options for pathName. If option is + specified with no value, then the command returns a list + describing the one named option (this list will be identical + to the corresponding sublist of the value returned if no + option is specified). If one or more option-value pairs are + specified, then the command modifies the given widget + option(s) to have the given value(s); in this case the + command returns an empty string. The following options + are supported: + + after window + Insert the window after the window specified. window + should be the name of a window already managed by pathName. + before window + Insert the window before the window specified. window + should be the name of a window already managed by pathName. + height size + Specify a height for the window. The height will be the + outer dimension of the window including its border, if + any. If size is an empty string, or if -height is not + specified, then the height requested internally by the + window will be used initially; the height may later be + adjusted by the movement of sashes in the panedwindow. + Size may be any value accepted by Tk_GetPixels. + minsize n + Specifies that the size of the window cannot be made + less than n. This constraint only affects the size of + the widget in the paned dimension -- the x dimension + for horizontal panedwindows, the y dimension for + vertical panedwindows. May be any value accepted by + Tk_GetPixels. + padx n + Specifies a non-negative value indicating how much + extra space to leave on each side of the window in + the X-direction. The value may have any of the forms + accepted by Tk_GetPixels. + pady n + Specifies a non-negative value indicating how much + extra space to leave on each side of the window in + the Y-direction. The value may have any of the forms + accepted by Tk_GetPixels. + sticky style + If a window's pane is larger than the requested + dimensions of the window, this option may be used + to position (or stretch) the window within its pane. + Style is a string that contains zero or more of the + characters n, s, e or w. The string can optionally + contains spaces or commas, but they are ignored. Each + letter refers to a side (north, south, east, or west) + that the window will "stick" to. If both n and s + (or e and w) are specified, the window will be + stretched to fill the entire height (or width) of + its cavity. + width size + Specify a width for the window. The width will be + the outer dimension of the window including its + border, if any. If size is an empty string, or + if -width is not specified, then the width requested + internally by the window will be used initially; the + width may later be adjusted by the movement of sashes + in the panedwindow. Size may be any value accepted by + Tk_GetPixels. + + """ + if cnf is None and not kw: + return self._getconfigure(self._w, 'paneconfigure', tagOrId) + if type(cnf) == StringType and not kw: + return self._getconfigure1( + self._w, 'paneconfigure', tagOrId, '-'+cnf) + self.tk.call((self._w, 'paneconfigure', tagOrId) + + self._options(cnf, kw)) + paneconfig = paneconfigure + + def panes(self): + """Returns an ordered list of the child panes.""" + return self.tk.splitlist(self.tk.call(self._w, 'panes')) + +###################################################################### +# Extensions: + +class Studbutton(Button): + def __init__(self, master=None, cnf={}, **kw): + Widget.__init__(self, master, 'studbutton', cnf, kw) + self.bind('', self.tkButtonEnter) + self.bind('', self.tkButtonLeave) + self.bind('<1>', self.tkButtonDown) + self.bind('', self.tkButtonUp) + +class Tributton(Button): + def __init__(self, master=None, cnf={}, **kw): + Widget.__init__(self, master, 'tributton', cnf, kw) + self.bind('', self.tkButtonEnter) + self.bind('', self.tkButtonLeave) + self.bind('<1>', self.tkButtonDown) + self.bind('', self.tkButtonUp) + self['fg'] = self['bg'] + self['activebackground'] = self['bg'] + +###################################################################### +# Test: + +def _test(): + root = Tk() + text = "This is Tcl/Tk version %s" % TclVersion + if TclVersion >= 8.1: + try: + text = text + unicode("\nThis should be a cedilla: \347", + "iso-8859-1") + except NameError: + pass # no unicode support + label = Label(root, text=text) + label.pack() + test = Button(root, text="Click me!", + command=lambda root=root: root.test.configure( + text="[%s]" % root.test['text'])) + test.pack() + root.test = test + quit = Button(root, text="QUIT", command=root.destroy) + quit.pack() + # The following three commands are needed so the window pops + # up on top on Windows... + root.iconify() + root.update() + root.deiconify() + root.mainloop() + +if __name__ == '__main__': + _test() diff --git a/PythonHome/Lib/lib-tk/Tkinter.pyc b/PythonHome/Lib/lib-tk/Tkinter.pyc deleted file mode 100644 index 0fa768839c1757ff8ca0b38f0d9041a612767a62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 189968 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 diff --git a/PythonHome/Lib/lib-tk/tkCommonDialog.py b/PythonHome/Lib/lib-tk/tkCommonDialog.py new file mode 100644 index 0000000000..2cd9be4eac --- /dev/null +++ b/PythonHome/Lib/lib-tk/tkCommonDialog.py @@ -0,0 +1,60 @@ +# base class for tk common dialogues +# +# this module provides a base class for accessing the common +# dialogues available in Tk 4.2 and newer. use tkFileDialog, +# tkColorChooser, and tkMessageBox to access the individual +# dialogs. +# +# written by Fredrik Lundh, May 1997 +# + +from Tkinter import * + +class Dialog: + + command = None + + def __init__(self, master=None, **options): + + # FIXME: should this be placed on the module level instead? + if TkVersion < 4.2: + raise TclError, "this module requires Tk 4.2 or newer" + + self.master = master + self.options = options + if not master and options.get('parent'): + self.master = options['parent'] + + def _fixoptions(self): + pass # hook + + def _fixresult(self, widget, result): + return result # hook + + def show(self, **options): + + # update instance options + for k, v in options.items(): + self.options[k] = v + + self._fixoptions() + + # we need a dummy widget to properly process the options + # (at least as long as we use Tkinter 1.63) + w = Frame(self.master) + + try: + + s = w.tk.call(self.command, *w._options(self.options)) + + s = self._fixresult(w, s) + + finally: + + try: + # get rid of the widget + w.destroy() + except: + pass + + return s diff --git a/PythonHome/Lib/lib-tk/tkCommonDialog.pyc b/PythonHome/Lib/lib-tk/tkCommonDialog.pyc deleted file mode 100644 index ef5a85265b4d6a46b339bf18a042512626610dab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1426 zcmb7D&2G~`5T0Gwqy!Sd;K`vdt{@&jkeSAI8E~IZycRTK+g-4(0bkq z)J=`eotmoYimIqpHRPFHoo&|OkUqD7Z(DgdW?fExzUYgv@b<&gS!uT+8Xg^~Ay>zT zJzs~#VEzfq3KCY@IthLBMObwHB)0Pvw#NbtV% zp-z2G=Xe1kyhI~_OVj4@5_MV9ycP<6XwQxf_dR?y;9KEa@Rn)B}LvDuQ1l4$+l_`4p7D8lStuzVTTVPyXHfewq z;?^PlO-;D}*cq4Mz>P2*tE5Z1wpej0&TJK=m)xRG6eieRQJ+7GRJEDc@to%kuNVrE<}F4?@3gW*wfyzqSu$GJm?)S zdP@>b3?xhzy<-whv9Vv4=!RCtC8}s;LZWGjX5=OIpVa!S)~6(zlW1P+HzZon$rXt) zc~Oo%>Hft;OR_(s8Z1kDR`zG5_rpPRPWI;{o|D$RmJ1TC$b~0{U5nbaBp29nM)uO1 zQi_))UXi9J$5YZ>Gk8)Xzlw3(n-blXLjxqt{!QtvOMFXWbWT&;{;I^Q(z;EY%wBp& zurRtUkDtV|(z?Um=#H#DenMfccso;>l+C0ayIv=@RUa)!;qJ79 zKAt!0xFk!hn?U`uxc9Kz&APc_CG^<1-K^qQw6JTaeR!~)JUeJ7&+fb919$ug!gG~B z?DX6XOsF-J7k#PUMblEU7~i{VrcHwV561ysK0>%K#s=2M}Ch4J@LC*t+`m<9PD{zi7J9T%YAlptmaUr`DU5ZNU zCvlbfhb&as^CUWqomRWCJ#D*?rwOMy&b4|1{9e@rTul??!bl*y!sVvyRXiUynD$EM z7Jlcy91Ly<0|;iG`bUZWLE@+nJ+Q|?GwTNRU;t>~vLJ(4HHbT|0Z#7n2zV>sr~=;K&%?rR8dX@nRF=|0!@?>wb{4jTO;B=>VN^D-<> zrxE29t_~5s8ZBE8XvuU&*M4mEG_GEz`uF>4e9|yXpl8WCgO^VPdcub4<$`q&|u_l2S_+vmIlbq;AwHBLkUeC-a;`n=>Gr? z+4PDr?Mw7&?2z)53GbrS;HFf&fap7D5Evr`3;XxxxAbCF|K)849CL@YpJ2%_d<+aR zKl~oFBGQg~3Crjfz>17K!O{}C2$<*sGn{i|W zj6b58r?vh9?joeMgn=&4SDCVnN&!P3fG12dkYBv`CZpBX=WCijAd5AMjApJt2DiQW z@}BG=`@q6HZS6bqpCEOB)Youp2vh-+f~5TDU)?$JayUncN6d6`(4QDE$4dV@2QQH? z52k8+-jnqXq($L-sOFdR2dL#Sm{WIE@NsCNWU=W(*HnLky zJ)ZwxIQkRF9w2`?^Xy;TSE6YVuoRl`eF)8wEAY8C6#PyA6vH6)H*{PkCpz@2@(MQv z^Yx*c#a%h7oKlNs3-n`#Lc@1hynP_=SblO0A` z3AwrDtzK`pmAqC>{+?wXxS5@{qae)?SIO;1IP#B!JW7(7`Inr=ehrwH<%Az&N|hn5 zpOI}MiOkacOE*NfXu_-4W~gRW48F|)MwXDi5E9PtBNpFh@dFl1C>+BjzJv7F_Htin zXN@{O%BhZxUB5+d+TN@^*xuG0JZ;z7_4F`Fo0+Dzn@_hM?mqmbj{W?klXabbhicB_ z2>~;gi zoVT*Rva~Y3vOGD4zZ;c_%6w&Fa=cPTTJQTv?HA1o-co77_-5A3pd2%c-a={8{0Bcy B!y*6x diff --git a/PythonHome/Lib/lib-tk/tkFont.py b/PythonHome/Lib/lib-tk/tkFont.py new file mode 100644 index 0000000000..61c2f86abd --- /dev/null +++ b/PythonHome/Lib/lib-tk/tkFont.py @@ -0,0 +1,217 @@ +# Tkinter font wrapper +# +# written by Fredrik Lundh, February 1998 +# +# FIXME: should add 'displayof' option where relevant (actual, families, +# measure, and metrics) +# + +__version__ = "0.9" + +import Tkinter + +# weight/slant +NORMAL = "normal" +ROMAN = "roman" +BOLD = "bold" +ITALIC = "italic" + +def nametofont(name): + """Given the name of a tk named font, returns a Font representation. + """ + return Font(name=name, exists=True) + +class Font: + + """Represents a named font. + + Constructor options are: + + font -- font specifier (name, system font, or (family, size, style)-tuple) + name -- name to use for this font configuration (defaults to a unique name) + exists -- does a named font by this name already exist? + Creates a new named font if False, points to the existing font if True. + Raises _Tkinter.TclError if the assertion is false. + + the following are ignored if font is specified: + + family -- font 'family', e.g. Courier, Times, Helvetica + size -- font size in points + weight -- font thickness: NORMAL, BOLD + slant -- font slant: ROMAN, ITALIC + underline -- font underlining: false (0), true (1) + overstrike -- font strikeout: false (0), true (1) + + """ + + def _set(self, kw): + options = [] + for k, v in kw.items(): + options.append("-"+k) + options.append(str(v)) + return tuple(options) + + def _get(self, args): + options = [] + for k in args: + options.append("-"+k) + return tuple(options) + + def _mkdict(self, args): + options = {} + for i in range(0, len(args), 2): + options[args[i][1:]] = args[i+1] + return options + + def __init__(self, root=None, font=None, name=None, exists=False, **options): + if not root: + root = Tkinter._default_root + if font: + # get actual settings corresponding to the given font + font = root.tk.splitlist(root.tk.call("font", "actual", font)) + else: + font = self._set(options) + if not name: + name = "font" + str(id(self)) + self.name = name + + if exists: + self.delete_font = False + # confirm font exists + if self.name not in root.tk.splitlist( + root.tk.call("font", "names")): + raise Tkinter._tkinter.TclError, "named font %s does not already exist" % (self.name,) + # if font config info supplied, apply it + if font: + root.tk.call("font", "configure", self.name, *font) + else: + # create new font (raises TclError if the font exists) + root.tk.call("font", "create", self.name, *font) + self.delete_font = True + # backlinks! + self._root = root + self._split = root.tk.splitlist + self._call = root.tk.call + + def __str__(self): + return self.name + + def __eq__(self, other): + return self.name == other.name and isinstance(other, Font) + + def __getitem__(self, key): + return self.cget(key) + + def __setitem__(self, key, value): + self.configure(**{key: value}) + + def __del__(self): + try: + if self.delete_font: + self._call("font", "delete", self.name) + except (KeyboardInterrupt, SystemExit): + raise + except Exception: + pass + + def copy(self): + "Return a distinct copy of the current font" + return Font(self._root, **self.actual()) + + def actual(self, option=None): + "Return actual font attributes" + if option: + return self._call("font", "actual", self.name, "-"+option) + else: + return self._mkdict( + self._split(self._call("font", "actual", self.name)) + ) + + def cget(self, option): + "Get font attribute" + return self._call("font", "config", self.name, "-"+option) + + def config(self, **options): + "Modify font attributes" + if options: + self._call("font", "config", self.name, + *self._set(options)) + else: + return self._mkdict( + self._split(self._call("font", "config", self.name)) + ) + + configure = config + + def measure(self, text): + "Return text width" + return int(self._call("font", "measure", self.name, text)) + + def metrics(self, *options): + """Return font metrics. + + For best performance, create a dummy widget + using this font before calling this method.""" + + if options: + return int( + self._call("font", "metrics", self.name, self._get(options)) + ) + else: + res = self._split(self._call("font", "metrics", self.name)) + options = {} + for i in range(0, len(res), 2): + options[res[i][1:]] = int(res[i+1]) + return options + +def families(root=None): + "Get font families (as a tuple)" + if not root: + root = Tkinter._default_root + return root.tk.splitlist(root.tk.call("font", "families")) + +def names(root=None): + "Get names of defined fonts (as a tuple)" + if not root: + root = Tkinter._default_root + return root.tk.splitlist(root.tk.call("font", "names")) + +# -------------------------------------------------------------------- +# test stuff + +if __name__ == "__main__": + + root = Tkinter.Tk() + + # create a font + f = Font(family="times", size=30, weight=NORMAL) + + print f.actual() + print f.actual("family") + print f.actual("weight") + + print f.config() + print f.cget("family") + print f.cget("weight") + + print names() + + print f.measure("hello"), f.metrics("linespace") + + print f.metrics() + + f = Font(font=("Courier", 20, "bold")) + print f.measure("hello"), f.metrics("linespace") + + w = Tkinter.Label(root, text="Hello, world", font=f) + w.pack() + + w = Tkinter.Button(root, text="Quit!", command=root.destroy) + w.pack() + + fb = Font(font=w["font"]).copy() + fb.config(weight=BOLD) + + w.config(font=fb) + + Tkinter.mainloop() diff --git a/PythonHome/Lib/lib-tk/tkFont.pyc b/PythonHome/Lib/lib-tk/tkFont.pyc deleted file mode 100644 index 2d0daf3d5c3a90fd8c231620b18b3ceb4879c29e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6815 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 diff --git a/PythonHome/Lib/lib-tk/tkMessageBox.py b/PythonHome/Lib/lib-tk/tkMessageBox.py new file mode 100644 index 0000000000..9ee923576f --- /dev/null +++ b/PythonHome/Lib/lib-tk/tkMessageBox.py @@ -0,0 +1,134 @@ +# tk common message boxes +# +# this module provides an interface to the native message boxes +# available in Tk 4.2 and newer. +# +# written by Fredrik Lundh, May 1997 +# + +# +# options (all have default values): +# +# - default: which button to make default (one of the reply codes) +# +# - icon: which icon to display (see below) +# +# - message: the message to display +# +# - parent: which window to place the dialog on top of +# +# - title: dialog title +# +# - type: dialog type; that is, which buttons to display (see below) +# + +from tkCommonDialog import Dialog + +# +# constants + +# icons +ERROR = "error" +INFO = "info" +QUESTION = "question" +WARNING = "warning" + +# types +ABORTRETRYIGNORE = "abortretryignore" +OK = "ok" +OKCANCEL = "okcancel" +RETRYCANCEL = "retrycancel" +YESNO = "yesno" +YESNOCANCEL = "yesnocancel" + +# replies +ABORT = "abort" +RETRY = "retry" +IGNORE = "ignore" +OK = "ok" +CANCEL = "cancel" +YES = "yes" +NO = "no" + + +# +# message dialog class + +class Message(Dialog): + "A message box" + + command = "tk_messageBox" + + +# +# convenience stuff + +# Rename _icon and _type options to allow overriding them in options +def _show(title=None, message=None, _icon=None, _type=None, **options): + if _icon and "icon" not in options: options["icon"] = _icon + if _type and "type" not in options: options["type"] = _type + if title: options["title"] = title + if message: options["message"] = message + res = Message(**options).show() + # In some Tcl installations, yes/no is converted into a boolean. + if isinstance(res, bool): + if res: + return YES + return NO + # In others we get a Tcl_Obj. + return str(res) + +def showinfo(title=None, message=None, **options): + "Show an info message" + return _show(title, message, INFO, OK, **options) + +def showwarning(title=None, message=None, **options): + "Show a warning message" + return _show(title, message, WARNING, OK, **options) + +def showerror(title=None, message=None, **options): + "Show an error message" + return _show(title, message, ERROR, OK, **options) + +def askquestion(title=None, message=None, **options): + "Ask a question" + return _show(title, message, QUESTION, YESNO, **options) + +def askokcancel(title=None, message=None, **options): + "Ask if operation should proceed; return true if the answer is ok" + s = _show(title, message, QUESTION, OKCANCEL, **options) + return s == OK + +def askyesno(title=None, message=None, **options): + "Ask a question; return true if the answer is yes" + s = _show(title, message, QUESTION, YESNO, **options) + return s == YES + +def askyesnocancel(title=None, message=None, **options): + "Ask a question; return true if the answer is yes, None if cancelled." + s = _show(title, message, QUESTION, YESNOCANCEL, **options) + # s might be a Tcl index object, so convert it to a string + s = str(s) + if s == CANCEL: + return None + return s == YES + +def askretrycancel(title=None, message=None, **options): + "Ask if operation should be retried; return true if the answer is yes" + s = _show(title, message, WARNING, RETRYCANCEL, **options) + return s == RETRY + + +# -------------------------------------------------------------------- +# test stuff + +if __name__ == "__main__": + + print "info", showinfo("Spam", "Egg Information") + print "warning", showwarning("Spam", "Egg Warning") + print "error", showerror("Spam", "Egg Alert") + print "question", askquestion("Spam", "Question?") + print "proceed", askokcancel("Spam", "Proceed?") + print "yes/no", askyesno("Spam", "Got it?") + print "yes/no/cancel", askyesnocancel("Spam", "Want it?") + print "try again", askretrycancel("Spam", "Try again?") diff --git a/PythonHome/Lib/lib-tk/tkMessageBox.pyc b/PythonHome/Lib/lib-tk/tkMessageBox.pyc deleted file mode 100644 index df1ab0679254005e9948a264eb8dd125819eaaa5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3729 zcmb_fS#uLd5bl*^`M|b}!R9hy0|CTka*%_BvN1+6E{GJbOu5)1rK~k;vyrsx?2HRs zWuD-b%0r&>KX}N$$`44s?wtigIUxp1yRGSOj_&DeM#aBIhF-4x+-#Hm^x^j=Uj3&- zr0_V@CF(ikJLISW`2|u%@{6QO5wEOn#YEKl%Nn2FM>EHAwy-sUh-*NF5;m z0I6Z}he?f)KSFAh{Ly@Th5QPsG4jVq9VGuCsc{M&T60JpqUS`8PJz;w z4$QF-LiR_bPSLXhE!=@o7D9*z;#vf72n~RIY>^TWC;{ZOMa}?$9zZ^^$XOsz1;{yz zoCgAJfK)AV0mzgf7c(S=(=Ji7dKq4f{>G;YPm(Ev+>U~7vToSNVVWkXDe;(iEinUV z{JI%x6D6_f2lF^c<0xJ?V`vAf7@CGA-HO)Z1dRf~q$87(PCJO(Vb>f0CSxqmLbgI3 zC(&tyUcL!dA-+0co{*iQ4Qk%ko<-m9%ZU zo%DJ^3{T+mn&>I8(+}@Os}H-;>J`&@XgXGFNSWT)@(yCab-bD-mYs5;Ee$Zd;k(@P z2go+U>lE)}yF{ISZUaFZ$PGAoyGZE_Ati113?tlK$hzTPN|AF>a)zSQ`!?!B>-{3&}|MT2q`}ZwRYRTII0tjxjk7B4Sz* zOJ+q{hDEcGWP?Lk%d|AqdvHs(5UVzib;OJ0jMIp`W&H9xUZ^-_r{t6hZH_C}l@$}8 zO`^f}#N&{`14|a@1xzOyC=uGk@@^2joOF3OR(TcgEYD^uF4n(q$mSb&vz}L*_RgSt zFFP8*c-|08TjDnBOz)vOZ!J^ZwS{39<=Olzb6$P1zTlll`$M(oio)7kiT9a(-wjM) za&CJmeY@z-fmHLnhPN-;4_fU-+Jg_#eH4@DbjJkL&kIxGs3W=m-bVNoi@fR2ckCI5=Ubchrm=?i5lGhYW{L1V z;|{zTdFO#7Cd6LlkY2;I|JdjZy8q4Fa5Wr`)4_Tk#}>|zYkXieITFfQBybMv+aP;2 z!ezIf#1a$P{h%AF>3VjwaP`c>f&C^qU?ai>FV~BVmlDg%?4R{GKXdD4igkc!zC0jU z3d7DY4vY^AncP~t<;`ly8IwluOr1Bw=mNBptC?3@_8wT{a0wKCU&6{7X6LOC>%R&v zd)Mj(QH%=}r&Dty=;;a?we@v(5rS`h?B#Vt!#rZxxcdOwoiJ6_ZRm%G xf7Rkfb}63W!lUnijFoYb", self.ok) + self.bind("", self.cancel) + + box.pack() + + # + # standard button semantics + + def ok(self, event=None): + + if not self.validate(): + self.initial_focus.focus_set() # put focus back + return + + self.withdraw() + self.update_idletasks() + + try: + self.apply() + finally: + self.cancel() + + def cancel(self, event=None): + + # put focus back to the parent window + if self.parent is not None: + self.parent.focus_set() + self.destroy() + + # + # command hooks + + def validate(self): + '''validate the data + + This method is called automatically to validate the data before the + dialog is destroyed. By default, it always validates OK. + ''' + + return 1 # override + + def apply(self): + '''process the data + + This method is called automatically to process the data, *after* + the dialog is destroyed. By default, it does nothing. + ''' + + pass # override + + +# -------------------------------------------------------------------- +# convenience dialogues + +class _QueryDialog(Dialog): + + def __init__(self, title, prompt, + initialvalue=None, + minvalue = None, maxvalue = None, + parent = None): + + if not parent: + import Tkinter + parent = Tkinter._default_root + + self.prompt = prompt + self.minvalue = minvalue + self.maxvalue = maxvalue + + self.initialvalue = initialvalue + + Dialog.__init__(self, parent, title) + + def destroy(self): + self.entry = None + Dialog.destroy(self) + + def body(self, master): + + w = Label(master, text=self.prompt, justify=LEFT) + w.grid(row=0, padx=5, sticky=W) + + self.entry = Entry(master, name="entry") + self.entry.grid(row=1, padx=5, sticky=W+E) + + if self.initialvalue is not None: + self.entry.insert(0, self.initialvalue) + self.entry.select_range(0, END) + + return self.entry + + def validate(self): + + import tkMessageBox + + try: + result = self.getresult() + except ValueError: + tkMessageBox.showwarning( + "Illegal value", + self.errormessage + "\nPlease try again", + parent = self + ) + return 0 + + if self.minvalue is not None and result < self.minvalue: + tkMessageBox.showwarning( + "Too small", + "The allowed minimum value is %s. " + "Please try again." % self.minvalue, + parent = self + ) + return 0 + + if self.maxvalue is not None and result > self.maxvalue: + tkMessageBox.showwarning( + "Too large", + "The allowed maximum value is %s. " + "Please try again." % self.maxvalue, + parent = self + ) + return 0 + + self.result = result + + return 1 + + +class _QueryInteger(_QueryDialog): + errormessage = "Not an integer." + def getresult(self): + return int(self.entry.get()) + +def askinteger(title, prompt, **kw): + '''get an integer from the user + + Arguments: + + title -- the dialog title + prompt -- the label text + **kw -- see SimpleDialog class + + Return value is an integer + ''' + d = _QueryInteger(title, prompt, **kw) + return d.result + +class _QueryFloat(_QueryDialog): + errormessage = "Not a floating point value." + def getresult(self): + return float(self.entry.get()) + +def askfloat(title, prompt, **kw): + '''get a float from the user + + Arguments: + + title -- the dialog title + prompt -- the label text + **kw -- see SimpleDialog class + + Return value is a float + ''' + d = _QueryFloat(title, prompt, **kw) + return d.result + +class _QueryString(_QueryDialog): + def __init__(self, *args, **kw): + if "show" in kw: + self.__show = kw["show"] + del kw["show"] + else: + self.__show = None + _QueryDialog.__init__(self, *args, **kw) + + def body(self, master): + entry = _QueryDialog.body(self, master) + if self.__show is not None: + entry.configure(show=self.__show) + return entry + + def getresult(self): + return self.entry.get() + +def askstring(title, prompt, **kw): + '''get a string from the user + + Arguments: + + title -- the dialog title + prompt -- the label text + **kw -- see SimpleDialog class + + Return value is a string + ''' + d = _QueryString(title, prompt, **kw) + return d.result + +if __name__ == "__main__": + + root = Tk() + root.update() + + print askinteger("Spam", "Egg count", initialvalue=12*12) + print askfloat("Spam", "Egg weight\n(in tons)", minvalue=1, maxvalue=100) + print askstring("Spam", "Egg label") diff --git a/PythonHome/Lib/lib-tk/tkSimpleDialog.pyc b/PythonHome/Lib/lib-tk/tkSimpleDialog.pyc deleted file mode 100644 index f247a08765f4a820525ba5984c1ba79f42ccb2c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8723 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 diff --git a/PythonHome/Lib/lib-tk/ttk.py b/PythonHome/Lib/lib-tk/ttk.py new file mode 100644 index 0000000000..77f1d3a9b5 --- /dev/null +++ b/PythonHome/Lib/lib-tk/ttk.py @@ -0,0 +1,1624 @@ +"""Ttk wrapper. + +This module provides classes to allow using Tk themed widget set. + +Ttk is based on a revised and enhanced version of +TIP #48 (http://tip.tcl.tk/48) specified style engine. + +Its basic idea is to separate, to the extent possible, the code +implementing a widget's behavior from the code implementing its +appearance. Widget class bindings are primarily responsible for +maintaining the widget state and invoking callbacks, all aspects +of the widgets appearance lies at Themes. +""" + +__version__ = "0.3.1" + +__author__ = "Guilherme Polo " + +__all__ = ["Button", "Checkbutton", "Combobox", "Entry", "Frame", "Label", + "Labelframe", "LabelFrame", "Menubutton", "Notebook", "Panedwindow", + "PanedWindow", "Progressbar", "Radiobutton", "Scale", "Scrollbar", + "Separator", "Sizegrip", "Style", "Treeview", + # Extensions + "LabeledScale", "OptionMenu", + # functions + "tclobjs_to_py", "setup_master"] + +import Tkinter +from Tkinter import _flatten, _join, _stringify + +# Verify if Tk is new enough to not need the Tile package +_REQUIRE_TILE = True if Tkinter.TkVersion < 8.5 else False + +def _load_tile(master): + if _REQUIRE_TILE: + import os + tilelib = os.environ.get('TILE_LIBRARY') + if tilelib: + # append custom tile path to the list of directories that + # Tcl uses when attempting to resolve packages with the package + # command + master.tk.eval( + 'global auto_path; ' + 'lappend auto_path {%s}' % tilelib) + + master.tk.eval('package require tile') # TclError may be raised here + master._tile_loaded = True + +def _format_optvalue(value, script=False): + """Internal function.""" + if script: + # if caller passes a Tcl script to tk.call, all the values need to + # be grouped into words (arguments to a command in Tcl dialect) + value = _stringify(value) + elif isinstance(value, (list, tuple)): + value = _join(value) + return value + +def _format_optdict(optdict, script=False, ignore=None): + """Formats optdict to a tuple to pass it to tk.call. + + E.g. (script=False): + {'foreground': 'blue', 'padding': [1, 2, 3, 4]} returns: + ('-foreground', 'blue', '-padding', '1 2 3 4')""" + + opts = [] + for opt, value in optdict.iteritems(): + if not ignore or opt not in ignore: + opts.append("-%s" % opt) + if value is not None: + opts.append(_format_optvalue(value, script)) + + return _flatten(opts) + +def _mapdict_values(items): + # each value in mapdict is expected to be a sequence, where each item + # is another sequence containing a state (or several) and a value + # E.g. (script=False): + # [('active', 'selected', 'grey'), ('focus', [1, 2, 3, 4])] + # returns: + # ['active selected', 'grey', 'focus', [1, 2, 3, 4]] + opt_val = [] + for item in items: + state = item[:-1] + val = item[-1] + # hacks for bakward compatibility + state[0] # raise IndexError if empty + if len(state) == 1: + # if it is empty (something that evaluates to False), then + # format it to Tcl code to denote the "normal" state + state = state[0] or '' + else: + # group multiple states + state = ' '.join(state) # raise TypeError if not str + opt_val.append(state) + if val is not None: + opt_val.append(val) + return opt_val + +def _format_mapdict(mapdict, script=False): + """Formats mapdict to pass it to tk.call. + + E.g. (script=False): + {'expand': [('active', 'selected', 'grey'), ('focus', [1, 2, 3, 4])]} + + returns: + + ('-expand', '{active selected} grey focus {1, 2, 3, 4}')""" + + opts = [] + for opt, value in mapdict.iteritems(): + opts.extend(("-%s" % opt, + _format_optvalue(_mapdict_values(value), script))) + + return _flatten(opts) + +def _format_elemcreate(etype, script=False, *args, **kw): + """Formats args and kw according to the given element factory etype.""" + spec = None + opts = () + if etype in ("image", "vsapi"): + if etype == "image": # define an element based on an image + # first arg should be the default image name + iname = args[0] + # next args, if any, are statespec/value pairs which is almost + # a mapdict, but we just need the value + imagespec = _join(_mapdict_values(args[1:])) + spec = "%s %s" % (iname, imagespec) + + else: + # define an element whose visual appearance is drawn using the + # Microsoft Visual Styles API which is responsible for the + # themed styles on Windows XP and Vista. + # Availability: Tk 8.6, Windows XP and Vista. + class_name, part_id = args[:2] + statemap = _join(_mapdict_values(args[2:])) + spec = "%s %s %s" % (class_name, part_id, statemap) + + opts = _format_optdict(kw, script) + + elif etype == "from": # clone an element + # it expects a themename and optionally an element to clone from, + # otherwise it will clone {} (empty element) + spec = args[0] # theme name + if len(args) > 1: # elementfrom specified + opts = (_format_optvalue(args[1], script),) + + if script: + spec = '{%s}' % spec + opts = ' '.join(opts) + + return spec, opts + +def _format_layoutlist(layout, indent=0, indent_size=2): + """Formats a layout list so we can pass the result to ttk::style + layout and ttk::style settings. Note that the layout doesn't has to + be a list necessarily. + + E.g.: + [("Menubutton.background", None), + ("Menubutton.button", {"children": + [("Menubutton.focus", {"children": + [("Menubutton.padding", {"children": + [("Menubutton.label", {"side": "left", "expand": 1})] + })] + })] + }), + ("Menubutton.indicator", {"side": "right"}) + ] + + returns: + + Menubutton.background + Menubutton.button -children { + Menubutton.focus -children { + Menubutton.padding -children { + Menubutton.label -side left -expand 1 + } + } + } + Menubutton.indicator -side right""" + script = [] + + for layout_elem in layout: + elem, opts = layout_elem + opts = opts or {} + fopts = ' '.join(_format_optdict(opts, True, ("children",))) + head = "%s%s%s" % (' ' * indent, elem, (" %s" % fopts) if fopts else '') + + if "children" in opts: + script.append(head + " -children {") + indent += indent_size + newscript, indent = _format_layoutlist(opts['children'], indent, + indent_size) + script.append(newscript) + indent -= indent_size + script.append('%s}' % (' ' * indent)) + else: + script.append(head) + + return '\n'.join(script), indent + +def _script_from_settings(settings): + """Returns an appropriate script, based on settings, according to + theme_settings definition to be used by theme_settings and + theme_create.""" + script = [] + # a script will be generated according to settings passed, which + # will then be evaluated by Tcl + for name, opts in settings.iteritems(): + # will format specific keys according to Tcl code + if opts.get('configure'): # format 'configure' + s = ' '.join(_format_optdict(opts['configure'], True)) + script.append("ttk::style configure %s %s;" % (name, s)) + + if opts.get('map'): # format 'map' + s = ' '.join(_format_mapdict(opts['map'], True)) + script.append("ttk::style map %s %s;" % (name, s)) + + if 'layout' in opts: # format 'layout' which may be empty + if not opts['layout']: + s = 'null' # could be any other word, but this one makes sense + else: + s, _ = _format_layoutlist(opts['layout']) + script.append("ttk::style layout %s {\n%s\n}" % (name, s)) + + if opts.get('element create'): # format 'element create' + eopts = opts['element create'] + etype = eopts[0] + + # find where args end, and where kwargs start + argc = 1 # etype was the first one + while argc < len(eopts) and not hasattr(eopts[argc], 'iteritems'): + argc += 1 + + elemargs = eopts[1:argc] + elemkw = eopts[argc] if argc < len(eopts) and eopts[argc] else {} + spec, opts = _format_elemcreate(etype, True, *elemargs, **elemkw) + + script.append("ttk::style element create %s %s %s %s" % ( + name, etype, spec, opts)) + + return '\n'.join(script) + +def _dict_from_tcltuple(ttuple, cut_minus=True): + """Break tuple in pairs, format it properly, then build the return + dict. If cut_minus is True, the supposed '-' prefixing options will + be removed. + + ttuple is expected to contain an even number of elements.""" + opt_start = 1 if cut_minus else 0 + + retdict = {} + it = iter(ttuple) + for opt, val in zip(it, it): + retdict[str(opt)[opt_start:]] = val + + return tclobjs_to_py(retdict) + +def _list_from_statespec(stuple): + """Construct a list from the given statespec tuple according to the + accepted statespec accepted by _format_mapdict.""" + nval = [] + for val in stuple: + typename = getattr(val, 'typename', None) + if typename is None: + nval.append(val) + else: # this is a Tcl object + val = str(val) + if typename == 'StateSpec': + val = val.split() + nval.append(val) + + it = iter(nval) + return [_flatten(spec) for spec in zip(it, it)] + +def _list_from_layouttuple(tk, ltuple): + """Construct a list from the tuple returned by ttk::layout, this is + somewhat the reverse of _format_layoutlist.""" + ltuple = tk.splitlist(ltuple) + res = [] + + indx = 0 + while indx < len(ltuple): + name = ltuple[indx] + opts = {} + res.append((name, opts)) + indx += 1 + + while indx < len(ltuple): # grab name's options + opt, val = ltuple[indx:indx + 2] + if not opt.startswith('-'): # found next name + break + + opt = opt[1:] # remove the '-' from the option + indx += 2 + + if opt == 'children': + val = _list_from_layouttuple(tk, val) + + opts[opt] = val + + return res + +def _val_or_dict(tk, options, *args): + """Format options then call Tk command with args and options and return + the appropriate result. + + If no option is specified, a dict is returned. If a option is + specified with the None value, the value for that option is returned. + Otherwise, the function just sets the passed options and the caller + shouldn't be expecting a return value anyway.""" + options = _format_optdict(options) + res = tk.call(*(args + options)) + + if len(options) % 2: # option specified without a value, return its value + return res + + return _dict_from_tcltuple(tk.splitlist(res)) + +def _convert_stringval(value): + """Converts a value to, hopefully, a more appropriate Python object.""" + value = unicode(value) + try: + value = int(value) + except (ValueError, TypeError): + pass + + return value + +def _to_number(x): + if isinstance(x, str): + if '.' in x: + x = float(x) + else: + x = int(x) + return x + +def tclobjs_to_py(adict): + """Returns adict with its values converted from Tcl objects to Python + objects.""" + for opt, val in adict.iteritems(): + if val and hasattr(val, '__len__') and not isinstance(val, basestring): + if getattr(val[0], 'typename', None) == 'StateSpec': + val = _list_from_statespec(val) + else: + val = map(_convert_stringval, val) + + elif hasattr(val, 'typename'): # some other (single) Tcl object + val = _convert_stringval(val) + + adict[opt] = val + + return adict + +def setup_master(master=None): + """If master is not None, itself is returned. If master is None, + the default master is returned if there is one, otherwise a new + master is created and returned. + + 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") + return master + + +class Style(object): + """Manipulate style database.""" + + _name = "ttk::style" + + def __init__(self, master=None): + master = setup_master(master) + + if not getattr(master, '_tile_loaded', False): + # Load tile now, if needed + _load_tile(master) + + self.master = master + self.tk = self.master.tk + + + def configure(self, style, query_opt=None, **kw): + """Query or sets the default value of the specified option(s) in + style. + + Each key in kw is an option and each value is either a string or + a sequence identifying the value for that option.""" + if query_opt is not None: + kw[query_opt] = None + return _val_or_dict(self.tk, kw, self._name, "configure", style) + + + def map(self, style, query_opt=None, **kw): + """Query or sets dynamic values of the specified option(s) in + style. + + Each key in kw is an option and each value should be a list or a + tuple (usually) containing statespecs grouped in tuples, or list, + or something else of your preference. A statespec is compound of + one or more states and then a value.""" + if query_opt is not None: + return _list_from_statespec(self.tk.splitlist( + self.tk.call(self._name, "map", style, '-%s' % query_opt))) + + return _dict_from_tcltuple(self.tk.splitlist( + self.tk.call(self._name, "map", style, *(_format_mapdict(kw))))) + + + def lookup(self, style, option, state=None, default=None): + """Returns the value specified for option in style. + + If state is specified it is expected to be a sequence of one + or more states. If the default argument is set, it is used as + a fallback value in case no specification for option is found.""" + state = ' '.join(state) if state else '' + + return self.tk.call(self._name, "lookup", style, '-%s' % option, + state, default) + + + def layout(self, style, layoutspec=None): + """Define the widget layout for given style. If layoutspec is + omitted, return the layout specification for given style. + + layoutspec is expected to be a list or an object different than + None that evaluates to False if you want to "turn off" that style. + If it is a list (or tuple, or something else), each item should be + a tuple where the first item is the layout name and the second item + should have the format described below: + + LAYOUTS + + A layout can contain the value None, if takes no options, or + a dict of options specifying how to arrange the element. + The layout mechanism uses a simplified version of the pack + geometry manager: given an initial cavity, each element is + allocated a parcel. Valid options/values are: + + side: whichside + Specifies which side of the cavity to place the + element; one of top, right, bottom or left. If + omitted, the element occupies the entire cavity. + + sticky: nswe + Specifies where the element is placed inside its + allocated parcel. + + children: [sublayout... ] + Specifies a list of elements to place inside the + element. Each element is a tuple (or other sequence) + where the first item is the layout name, and the other + is a LAYOUT.""" + lspec = None + if layoutspec: + lspec = _format_layoutlist(layoutspec)[0] + elif layoutspec is not None: # will disable the layout ({}, '', etc) + lspec = "null" # could be any other word, but this may make sense + # when calling layout(style) later + + return _list_from_layouttuple(self.tk, + self.tk.call(self._name, "layout", style, lspec)) + + + def element_create(self, elementname, etype, *args, **kw): + """Create a new element in the current theme of given etype.""" + spec, opts = _format_elemcreate(etype, False, *args, **kw) + self.tk.call(self._name, "element", "create", elementname, etype, + spec, *opts) + + + def element_names(self): + """Returns the list of elements defined in the current theme.""" + return self.tk.splitlist(self.tk.call(self._name, "element", "names")) + + + def element_options(self, elementname): + """Return the list of elementname's options.""" + return self.tk.splitlist(self.tk.call(self._name, "element", "options", elementname)) + + + def theme_create(self, themename, parent=None, settings=None): + """Creates a new theme. + + It is an error if themename already exists. If parent is + specified, the new theme will inherit styles, elements and + layouts from the specified parent theme. If settings are present, + they are expected to have the same syntax used for theme_settings.""" + script = _script_from_settings(settings) if settings else '' + + if parent: + self.tk.call(self._name, "theme", "create", themename, + "-parent", parent, "-settings", script) + else: + self.tk.call(self._name, "theme", "create", themename, + "-settings", script) + + + def theme_settings(self, themename, settings): + """Temporarily sets the current theme to themename, apply specified + settings and then restore the previous theme. + + Each key in settings is a style and each value may contain the + keys 'configure', 'map', 'layout' and 'element create' and they + are expected to have the same format as specified by the methods + configure, map, layout and element_create respectively.""" + script = _script_from_settings(settings) + self.tk.call(self._name, "theme", "settings", themename, script) + + + def theme_names(self): + """Returns a list of all known themes.""" + return self.tk.splitlist(self.tk.call(self._name, "theme", "names")) + + + def theme_use(self, themename=None): + """If themename is None, returns the theme in use, otherwise, set + the current theme to themename, refreshes all widgets and emits + a <> event.""" + if themename is None: + # Starting on Tk 8.6, checking this global is no longer needed + # since it allows doing self.tk.call(self._name, "theme", "use") + return self.tk.eval("return $ttk::currentTheme") + + # using "ttk::setTheme" instead of "ttk::style theme use" causes + # the variable currentTheme to be updated, also, ttk::setTheme calls + # "ttk::style theme use" in order to change theme. + self.tk.call("ttk::setTheme", themename) + + +class Widget(Tkinter.Widget): + """Base class for Tk themed widgets.""" + + def __init__(self, master, widgetname, kw=None): + """Constructs a Ttk Widget with the parent master. + + STANDARD OPTIONS + + class, cursor, takefocus, style + + SCROLLABLE WIDGET OPTIONS + + xscrollcommand, yscrollcommand + + LABEL WIDGET OPTIONS + + text, textvariable, underline, image, compound, width + + WIDGET STATES + + active, disabled, focus, pressed, selected, background, + readonly, alternate, invalid + """ + master = setup_master(master) + if not getattr(master, '_tile_loaded', False): + # Load tile now, if needed + _load_tile(master) + Tkinter.Widget.__init__(self, master, widgetname, kw=kw) + + + def identify(self, x, y): + """Returns the name of the element at position x, y, or the empty + string if the point does not lie within any element. + + x and y are pixel coordinates relative to the widget.""" + return self.tk.call(self._w, "identify", x, y) + + + def instate(self, statespec, callback=None, *args, **kw): + """Test the widget's state. + + If callback is not specified, returns True if the widget state + matches statespec and False otherwise. If callback is specified, + then it will be invoked with *args, **kw if the widget state + matches statespec. statespec is expected to be a sequence.""" + ret = self.tk.getboolean( + self.tk.call(self._w, "instate", ' '.join(statespec))) + if ret and callback: + return callback(*args, **kw) + + return bool(ret) + + + def state(self, statespec=None): + """Modify or inquire widget state. + + Widget state is returned if statespec is None, otherwise it is + set according to the statespec flags and then a new state spec + is returned indicating which flags were changed. statespec is + expected to be a sequence.""" + if statespec is not None: + statespec = ' '.join(statespec) + + return self.tk.splitlist(str(self.tk.call(self._w, "state", statespec))) + + +class Button(Widget): + """Ttk Button widget, displays a textual label and/or image, and + evaluates a command when pressed.""" + + def __init__(self, master=None, **kw): + """Construct a Ttk Button widget with the parent master. + + STANDARD OPTIONS + + class, compound, cursor, image, state, style, takefocus, + text, textvariable, underline, width + + WIDGET-SPECIFIC OPTIONS + + command, default, width + """ + Widget.__init__(self, master, "ttk::button", kw) + + + def invoke(self): + """Invokes the command associated with the button.""" + return self.tk.call(self._w, "invoke") + + +class Checkbutton(Widget): + """Ttk Checkbutton widget which is either in on- or off-state.""" + + def __init__(self, master=None, **kw): + """Construct a Ttk Checkbutton widget with the parent master. + + STANDARD OPTIONS + + class, compound, cursor, image, state, style, takefocus, + text, textvariable, underline, width + + WIDGET-SPECIFIC OPTIONS + + command, offvalue, onvalue, variable + """ + Widget.__init__(self, master, "ttk::checkbutton", kw) + + + def invoke(self): + """Toggles between the selected and deselected states and + invokes the associated command. If the widget is currently + selected, sets the option variable to the offvalue option + and deselects the widget; otherwise, sets the option variable + to the option onvalue. + + Returns the result of the associated command.""" + return self.tk.call(self._w, "invoke") + + +class Entry(Widget, Tkinter.Entry): + """Ttk Entry widget displays a one-line text string and allows that + string to be edited by the user.""" + + def __init__(self, master=None, widget=None, **kw): + """Constructs a Ttk Entry widget with the parent master. + + STANDARD OPTIONS + + class, cursor, style, takefocus, xscrollcommand + + WIDGET-SPECIFIC OPTIONS + + exportselection, invalidcommand, justify, show, state, + textvariable, validate, validatecommand, width + + VALIDATION MODES + + none, key, focus, focusin, focusout, all + """ + Widget.__init__(self, master, widget or "ttk::entry", kw) + + + def bbox(self, index): + """Return a tuple of (x, y, width, height) which describes the + bounding box of the character given by index.""" + return self._getints(self.tk.call(self._w, "bbox", index)) + + + def identify(self, x, y): + """Returns the name of the element at position x, y, or the + empty string if the coordinates are outside the window.""" + return self.tk.call(self._w, "identify", x, y) + + + def validate(self): + """Force revalidation, independent of the conditions specified + by the validate option. Returns False if validation fails, True + if it succeeds. Sets or clears the invalid state accordingly.""" + return bool(self.tk.getboolean(self.tk.call(self._w, "validate"))) + + +class Combobox(Entry): + """Ttk Combobox widget combines a text field with a pop-down list of + values.""" + + def __init__(self, master=None, **kw): + """Construct a Ttk Combobox widget with the parent master. + + STANDARD OPTIONS + + class, cursor, style, takefocus + + WIDGET-SPECIFIC OPTIONS + + exportselection, justify, height, postcommand, state, + textvariable, values, width + """ + Entry.__init__(self, master, "ttk::combobox", **kw) + + + def current(self, newindex=None): + """If newindex is supplied, sets the combobox value to the + element at position newindex in the list of values. Otherwise, + returns the index of the current value in the list of values + or -1 if the current value does not appear in the list.""" + if newindex is None: + return self.tk.getint(self.tk.call(self._w, "current")) + return self.tk.call(self._w, "current", newindex) + + + def set(self, value): + """Sets the value of the combobox to value.""" + self.tk.call(self._w, "set", value) + + +class Frame(Widget): + """Ttk Frame widget is a container, used to group other widgets + together.""" + + def __init__(self, master=None, **kw): + """Construct a Ttk Frame with parent master. + + STANDARD OPTIONS + + class, cursor, style, takefocus + + WIDGET-SPECIFIC OPTIONS + + borderwidth, relief, padding, width, height + """ + Widget.__init__(self, master, "ttk::frame", kw) + + +class Label(Widget): + """Ttk Label widget displays a textual label and/or image.""" + + def __init__(self, master=None, **kw): + """Construct a Ttk Label with parent master. + + STANDARD OPTIONS + + class, compound, cursor, image, style, takefocus, text, + textvariable, underline, width + + WIDGET-SPECIFIC OPTIONS + + anchor, background, font, foreground, justify, padding, + relief, text, wraplength + """ + Widget.__init__(self, master, "ttk::label", kw) + + +class Labelframe(Widget): + """Ttk Labelframe widget is a container used to group other widgets + together. It has an optional label, which may be a plain text string + or another widget.""" + + def __init__(self, master=None, **kw): + """Construct a Ttk Labelframe with parent master. + + STANDARD OPTIONS + + class, cursor, style, takefocus + + WIDGET-SPECIFIC OPTIONS + labelanchor, text, underline, padding, labelwidget, width, + height + """ + Widget.__init__(self, master, "ttk::labelframe", kw) + +LabelFrame = Labelframe # Tkinter name compatibility + + +class Menubutton(Widget): + """Ttk Menubutton widget displays a textual label and/or image, and + displays a menu when pressed.""" + + def __init__(self, master=None, **kw): + """Construct a Ttk Menubutton with parent master. + + STANDARD OPTIONS + + class, compound, cursor, image, state, style, takefocus, + text, textvariable, underline, width + + WIDGET-SPECIFIC OPTIONS + + direction, menu + """ + Widget.__init__(self, master, "ttk::menubutton", kw) + + +class Notebook(Widget): + """Ttk Notebook widget manages a collection of windows and displays + a single one at a time. Each child window is associated with a tab, + which the user may select to change the currently-displayed window.""" + + def __init__(self, master=None, **kw): + """Construct a Ttk Notebook with parent master. + + STANDARD OPTIONS + + class, cursor, style, takefocus + + WIDGET-SPECIFIC OPTIONS + + height, padding, width + + TAB OPTIONS + + state, sticky, padding, text, image, compound, underline + + TAB IDENTIFIERS (tab_id) + + The tab_id argument found in several methods may take any of + the following forms: + + * An integer between zero and the number of tabs + * The name of a child window + * A positional specification of the form "@x,y", which + defines the tab + * The string "current", which identifies the + currently-selected tab + * The string "end", which returns the number of tabs (only + valid for method index) + """ + Widget.__init__(self, master, "ttk::notebook", kw) + + + def add(self, child, **kw): + """Adds a new tab to the notebook. + + If window is currently managed by the notebook but hidden, it is + restored to its previous position.""" + self.tk.call(self._w, "add", child, *(_format_optdict(kw))) + + + def forget(self, tab_id): + """Removes the tab specified by tab_id, unmaps and unmanages the + associated window.""" + self.tk.call(self._w, "forget", tab_id) + + + def hide(self, tab_id): + """Hides the tab specified by tab_id. + + The tab will not be displayed, but the associated window remains + managed by the notebook and its configuration remembered. Hidden + tabs may be restored with the add command.""" + self.tk.call(self._w, "hide", tab_id) + + + def identify(self, x, y): + """Returns the name of the tab element at position x, y, or the + empty string if none.""" + return self.tk.call(self._w, "identify", x, y) + + + def index(self, tab_id): + """Returns the numeric index of the tab specified by tab_id, or + the total number of tabs if tab_id is the string "end".""" + return self.tk.getint(self.tk.call(self._w, "index", tab_id)) + + + def insert(self, pos, child, **kw): + """Inserts a pane at the specified position. + + pos is either the string end, an integer index, or the name of + a managed child. If child is already managed by the notebook, + moves it to the specified position.""" + self.tk.call(self._w, "insert", pos, child, *(_format_optdict(kw))) + + + def select(self, tab_id=None): + """Selects the specified tab. + + The associated child window will be displayed, and the + previously-selected window (if different) is unmapped. If tab_id + is omitted, returns the widget name of the currently selected + pane.""" + return self.tk.call(self._w, "select", tab_id) + + + def tab(self, tab_id, option=None, **kw): + """Query or modify the options of the specific tab_id. + + If kw is not given, returns a dict of the tab option values. If option + is specified, returns the value of that option. Otherwise, sets the + options to the corresponding values.""" + if option is not None: + kw[option] = None + return _val_or_dict(self.tk, kw, self._w, "tab", tab_id) + + + def tabs(self): + """Returns a list of windows managed by the notebook.""" + return self.tk.splitlist(self.tk.call(self._w, "tabs") or ()) + + + def enable_traversal(self): + """Enable keyboard traversal for a toplevel window containing + this notebook. + + This will extend the bindings for the toplevel window containing + this notebook as follows: + + Control-Tab: selects the tab following the currently selected + one + + Shift-Control-Tab: selects the tab preceding the currently + selected one + + Alt-K: where K is the mnemonic (underlined) character of any + tab, will select that tab. + + Multiple notebooks in a single toplevel may be enabled for + traversal, including nested notebooks. However, notebook traversal + only works properly if all panes are direct children of the + notebook.""" + # The only, and good, difference I see is about mnemonics, which works + # after calling this method. Control-Tab and Shift-Control-Tab always + # works (here at least). + self.tk.call("ttk::notebook::enableTraversal", self._w) + + +class Panedwindow(Widget, Tkinter.PanedWindow): + """Ttk Panedwindow widget displays a number of subwindows, stacked + either vertically or horizontally.""" + + def __init__(self, master=None, **kw): + """Construct a Ttk Panedwindow with parent master. + + STANDARD OPTIONS + + class, cursor, style, takefocus + + WIDGET-SPECIFIC OPTIONS + + orient, width, height + + PANE OPTIONS + + weight + """ + Widget.__init__(self, master, "ttk::panedwindow", kw) + + + forget = Tkinter.PanedWindow.forget # overrides Pack.forget + + + def insert(self, pos, child, **kw): + """Inserts a pane at the specified positions. + + pos is either the string end, and integer index, or the name + of a child. If child is already managed by the paned window, + moves it to the specified position.""" + self.tk.call(self._w, "insert", pos, child, *(_format_optdict(kw))) + + + def pane(self, pane, option=None, **kw): + """Query or modify the options of the specified pane. + + pane is either an integer index or the name of a managed subwindow. + If kw is not given, returns a dict of the pane option values. If + option is specified then the value for that option is returned. + Otherwise, sets the options to the corresponding values.""" + if option is not None: + kw[option] = None + return _val_or_dict(self.tk, kw, self._w, "pane", pane) + + + def sashpos(self, index, newpos=None): + """If newpos is specified, sets the position of sash number index. + + May adjust the positions of adjacent sashes to ensure that + positions are monotonically increasing. Sash positions are further + constrained to be between 0 and the total size of the widget. + + Returns the new position of sash number index.""" + return self.tk.getint(self.tk.call(self._w, "sashpos", index, newpos)) + +PanedWindow = Panedwindow # Tkinter name compatibility + + +class Progressbar(Widget): + """Ttk Progressbar widget shows the status of a long-running + operation. They can operate in two modes: determinate mode shows the + amount completed relative to the total amount of work to be done, and + indeterminate mode provides an animated display to let the user know + that something is happening.""" + + def __init__(self, master=None, **kw): + """Construct a Ttk Progressbar with parent master. + + STANDARD OPTIONS + + class, cursor, style, takefocus + + WIDGET-SPECIFIC OPTIONS + + orient, length, mode, maximum, value, variable, phase + """ + Widget.__init__(self, master, "ttk::progressbar", kw) + + + def start(self, interval=None): + """Begin autoincrement mode: schedules a recurring timer event + that calls method step every interval milliseconds. + + interval defaults to 50 milliseconds (20 steps/second) if ommited.""" + self.tk.call(self._w, "start", interval) + + + def step(self, amount=None): + """Increments the value option by amount. + + amount defaults to 1.0 if omitted.""" + self.tk.call(self._w, "step", amount) + + + def stop(self): + """Stop autoincrement mode: cancels any recurring timer event + initiated by start.""" + self.tk.call(self._w, "stop") + + +class Radiobutton(Widget): + """Ttk Radiobutton widgets are used in groups to show or change a + set of mutually-exclusive options.""" + + def __init__(self, master=None, **kw): + """Construct a Ttk Radiobutton with parent master. + + STANDARD OPTIONS + + class, compound, cursor, image, state, style, takefocus, + text, textvariable, underline, width + + WIDGET-SPECIFIC OPTIONS + + command, value, variable + """ + Widget.__init__(self, master, "ttk::radiobutton", kw) + + + def invoke(self): + """Sets the option variable to the option value, selects the + widget, and invokes the associated command. + + Returns the result of the command, or an empty string if + no command is specified.""" + return self.tk.call(self._w, "invoke") + + +class Scale(Widget, Tkinter.Scale): + """Ttk Scale widget is typically used to control the numeric value of + a linked variable that varies uniformly over some range.""" + + def __init__(self, master=None, **kw): + """Construct a Ttk Scale with parent master. + + STANDARD OPTIONS + + class, cursor, style, takefocus + + WIDGET-SPECIFIC OPTIONS + + command, from, length, orient, to, value, variable + """ + Widget.__init__(self, master, "ttk::scale", kw) + + + def configure(self, cnf=None, **kw): + """Modify or query scale options. + + Setting a value for any of the "from", "from_" or "to" options + generates a <> event.""" + if cnf: + kw.update(cnf) + Widget.configure(self, **kw) + if any(['from' in kw, 'from_' in kw, 'to' in kw]): + self.event_generate('<>') + + + def get(self, x=None, y=None): + """Get the current value of the value option, or the value + corresponding to the coordinates x, y if they are specified. + + x and y are pixel coordinates relative to the scale widget + origin.""" + return self.tk.call(self._w, 'get', x, y) + + +class Scrollbar(Widget, Tkinter.Scrollbar): + """Ttk Scrollbar controls the viewport of a scrollable widget.""" + + def __init__(self, master=None, **kw): + """Construct a Ttk Scrollbar with parent master. + + STANDARD OPTIONS + + class, cursor, style, takefocus + + WIDGET-SPECIFIC OPTIONS + + command, orient + """ + Widget.__init__(self, master, "ttk::scrollbar", kw) + + +class Separator(Widget): + """Ttk Separator widget displays a horizontal or vertical separator + bar.""" + + def __init__(self, master=None, **kw): + """Construct a Ttk Separator with parent master. + + STANDARD OPTIONS + + class, cursor, style, takefocus + + WIDGET-SPECIFIC OPTIONS + + orient + """ + Widget.__init__(self, master, "ttk::separator", kw) + + +class Sizegrip(Widget): + """Ttk Sizegrip allows the user to resize the containing toplevel + window by pressing and dragging the grip.""" + + def __init__(self, master=None, **kw): + """Construct a Ttk Sizegrip with parent master. + + STANDARD OPTIONS + + class, cursor, state, style, takefocus + """ + Widget.__init__(self, master, "ttk::sizegrip", kw) + + +class Treeview(Widget, Tkinter.XView, Tkinter.YView): + """Ttk Treeview widget displays a hierarchical collection of items. + + Each item has a textual label, an optional image, and an optional list + of data values. The data values are displayed in successive columns + after the tree label.""" + + def __init__(self, master=None, **kw): + """Construct a Ttk Treeview with parent master. + + STANDARD OPTIONS + + class, cursor, style, takefocus, xscrollcommand, + yscrollcommand + + WIDGET-SPECIFIC OPTIONS + + columns, displaycolumns, height, padding, selectmode, show + + ITEM OPTIONS + + text, image, values, open, tags + + TAG OPTIONS + + foreground, background, font, image + """ + Widget.__init__(self, master, "ttk::treeview", kw) + + + def bbox(self, item, column=None): + """Returns the bounding box (relative to the treeview widget's + window) of the specified item in the form x y width height. + + If column is specified, returns the bounding box of that cell. + If the item is not visible (i.e., if it is a descendant of a + closed item or is scrolled offscreen), returns an empty string.""" + return self._getints(self.tk.call(self._w, "bbox", item, column)) or '' + + + def get_children(self, item=None): + """Returns a tuple of children belonging to item. + + If item is not specified, returns root children.""" + return self.tk.splitlist( + self.tk.call(self._w, "children", item or '') or ()) + + + def set_children(self, item, *newchildren): + """Replaces item's child with newchildren. + + Children present in item that are not present in newchildren + are detached from tree. No items in newchildren may be an + ancestor of item.""" + self.tk.call(self._w, "children", item, newchildren) + + + def column(self, column, option=None, **kw): + """Query or modify the options for the specified column. + + If kw is not given, returns a dict of the column option values. If + option is specified then the value for that option is returned. + Otherwise, sets the options to the corresponding values.""" + if option is not None: + kw[option] = None + return _val_or_dict(self.tk, kw, self._w, "column", column) + + + def delete(self, *items): + """Delete all specified items and all their descendants. The root + item may not be deleted.""" + self.tk.call(self._w, "delete", items) + + + def detach(self, *items): + """Unlinks all of the specified items from the tree. + + The items and all of their descendants are still present, and may + be reinserted at another point in the tree, but will not be + displayed. The root item may not be detached.""" + self.tk.call(self._w, "detach", items) + + + def exists(self, item): + """Returns True if the specified item is present in the tree, + False otherwise.""" + return bool(self.tk.getboolean(self.tk.call(self._w, "exists", item))) + + + def focus(self, item=None): + """If item is specified, sets the focus item to item. Otherwise, + returns the current focus item, or '' if there is none.""" + return self.tk.call(self._w, "focus", item) + + + def heading(self, column, option=None, **kw): + """Query or modify the heading options for the specified column. + + If kw is not given, returns a dict of the heading option values. If + option is specified then the value for that option is returned. + Otherwise, sets the options to the corresponding values. + + Valid options/values are: + text: text + The text to display in the column heading + image: image_name + Specifies an image to display to the right of the column + heading + anchor: anchor + Specifies how the heading text should be aligned. One of + the standard Tk anchor values + command: callback + A callback to be invoked when the heading label is + pressed. + + To configure the tree column heading, call this with column = "#0" """ + cmd = kw.get('command') + if cmd and not isinstance(cmd, basestring): + # callback not registered yet, do it now + kw['command'] = self.master.register(cmd, self._substitute) + + if option is not None: + kw[option] = None + + return _val_or_dict(self.tk, kw, self._w, 'heading', column) + + + def identify(self, component, x, y): + """Returns a description of the specified component under the + point given by x and y, or the empty string if no such component + is present at that position.""" + return self.tk.call(self._w, "identify", component, x, y) + + + def identify_row(self, y): + """Returns the item ID of the item at position y.""" + return self.identify("row", 0, y) + + + def identify_column(self, x): + """Returns the data column identifier of the cell at position x. + + The tree column has ID #0.""" + return self.identify("column", x, 0) + + + def identify_region(self, x, y): + """Returns one of: + + heading: Tree heading area. + separator: Space between two columns headings; + tree: The tree area. + cell: A data cell. + + * Availability: Tk 8.6""" + return self.identify("region", x, y) + + + def identify_element(self, x, y): + """Returns the element at position x, y. + + * Availability: Tk 8.6""" + return self.identify("element", x, y) + + + def index(self, item): + """Returns the integer index of item within its parent's list + of children.""" + return self.tk.getint(self.tk.call(self._w, "index", item)) + + + def insert(self, parent, index, iid=None, **kw): + """Creates a new item and return the item identifier of the newly + created item. + + parent is the item ID of the parent item, or the empty string + to create a new top-level item. index is an integer, or the value + end, specifying where in the list of parent's children to insert + the new item. If index is less than or equal to zero, the new node + is inserted at the beginning, if index is greater than or equal to + the current number of children, it is inserted at the end. If iid + is specified, it is used as the item identifier, iid must not + already exist in the tree. Otherwise, a new unique identifier + is generated.""" + opts = _format_optdict(kw) + if iid: + res = self.tk.call(self._w, "insert", parent, index, + "-id", iid, *opts) + else: + res = self.tk.call(self._w, "insert", parent, index, *opts) + + return res + + + def item(self, item, option=None, **kw): + """Query or modify the options for the specified item. + + If no options are given, a dict with options/values for the item + is returned. If option is specified then the value for that option + is returned. Otherwise, sets the options to the corresponding + values as given by kw.""" + if option is not None: + kw[option] = None + return _val_or_dict(self.tk, kw, self._w, "item", item) + + + def move(self, item, parent, index): + """Moves item to position index in parent's list of children. + + It is illegal to move an item under one of its descendants. If + index is less than or equal to zero, item is moved to the + beginning, if greater than or equal to the number of children, + it is moved to the end. If item was detached it is reattached.""" + self.tk.call(self._w, "move", item, parent, index) + + reattach = move # A sensible method name for reattaching detached items + + + def next(self, item): + """Returns the identifier of item's next sibling, or '' if item + is the last child of its parent.""" + return self.tk.call(self._w, "next", item) + + + def parent(self, item): + """Returns the ID of the parent of item, or '' if item is at the + top level of the hierarchy.""" + return self.tk.call(self._w, "parent", item) + + + def prev(self, item): + """Returns the identifier of item's previous sibling, or '' if + item is the first child of its parent.""" + return self.tk.call(self._w, "prev", item) + + + def see(self, item): + """Ensure that item is visible. + + Sets all of item's ancestors open option to True, and scrolls + the widget if necessary so that item is within the visible + portion of the tree.""" + self.tk.call(self._w, "see", item) + + + def selection(self, selop=None, items=None): + """If selop is not specified, returns selected items.""" + return self.tk.call(self._w, "selection", selop, items) + + + def selection_set(self, items): + """items becomes the new selection.""" + self.selection("set", items) + + + def selection_add(self, items): + """Add items to the selection.""" + self.selection("add", items) + + + def selection_remove(self, items): + """Remove items from the selection.""" + self.selection("remove", items) + + + def selection_toggle(self, items): + """Toggle the selection state of each item in items.""" + self.selection("toggle", items) + + + def set(self, item, column=None, value=None): + """With one argument, returns a dictionary of column/value pairs + for the specified item. With two arguments, returns the current + value of the specified column. With three arguments, sets the + value of given column in given item to the specified value.""" + res = self.tk.call(self._w, "set", item, column, value) + if column is None and value is None: + return _dict_from_tcltuple(self.tk.splitlist(res), False) + else: + return res + + + def tag_bind(self, tagname, sequence=None, callback=None): + """Bind a callback for the given event sequence to the tag tagname. + When an event is delivered to an item, the callbacks for each + of the item's tags option are called.""" + self._bind((self._w, "tag", "bind", tagname), sequence, callback, add=0) + + + def tag_configure(self, tagname, option=None, **kw): + """Query or modify the options for the specified tagname. + + If kw is not given, returns a dict of the option settings for tagname. + If option is specified, returns the value for that option for the + specified tagname. Otherwise, sets the options to the corresponding + values for the given tagname.""" + if option is not None: + kw[option] = None + return _val_or_dict(self.tk, kw, self._w, "tag", "configure", + tagname) + + + def tag_has(self, tagname, item=None): + """If item is specified, returns 1 or 0 depending on whether the + specified item has the given tagname. Otherwise, returns a list of + all items which have the specified tag. + + * Availability: Tk 8.6""" + return self.tk.getboolean( + self.tk.call(self._w, "tag", "has", tagname, item)) + + +# Extensions + +class LabeledScale(Frame, object): + """A Ttk Scale widget with a Ttk Label widget indicating its + current value. + + The Ttk Scale can be accessed through instance.scale, and Ttk Label + can be accessed through instance.label""" + + def __init__(self, master=None, variable=None, from_=0, to=10, **kw): + """Construct an horizontal LabeledScale with parent master, a + variable to be associated with the Ttk Scale widget and its range. + If variable is not specified, a Tkinter.IntVar is created. + + WIDGET-SPECIFIC OPTIONS + + compound: 'top' or 'bottom' + Specifies how to display the label relative to the scale. + Defaults to 'top'. + """ + self._label_top = kw.pop('compound', 'top') == 'top' + + Frame.__init__(self, master, **kw) + self._variable = variable or Tkinter.IntVar(master) + self._variable.set(from_) + self._last_valid = from_ + + self.label = Label(self) + self.scale = Scale(self, variable=self._variable, from_=from_, to=to) + self.scale.bind('<>', self._adjust) + + # position scale and label according to the compound option + 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 + self.label.place(anchor='n' if label_side == 'top' else 's') + + # update the label as scale or variable changes + self.__tracecb = self._variable.trace_variable('w', self._adjust) + self.bind('', self._adjust) + self.bind('', self._adjust) + + + def destroy(self): + """Destroy this widget and possibly its associated variable.""" + try: + self._variable.trace_vdelete('w', self.__tracecb) + except AttributeError: + # widget has been destroyed already + pass + else: + del self._variable + Frame.destroy(self) + + + def _adjust(self, *args): + """Adjust the label position according to the scale.""" + def adjust_label(): + self.update_idletasks() # "force" scale redraw + + x, y = self.scale.coords() + if self._label_top: + y = self.scale.winfo_y() - self.label.winfo_reqheight() + else: + y = self.scale.winfo_reqheight() + self.label.winfo_reqheight() + + self.label.place_configure(x=x, y=y) + + from_ = _to_number(self.scale['from']) + to = _to_number(self.scale['to']) + if to < from_: + from_, to = to, from_ + newval = self._variable.get() + if not from_ <= newval <= to: + # value outside range, set value back to the last valid one + self.value = self._last_valid + return + + self._last_valid = newval + self.label['text'] = newval + self.after_idle(adjust_label) + + + def _get_value(self): + """Return current scale value.""" + return self._variable.get() + + + def _set_value(self, val): + """Set new scale value.""" + self._variable.set(val) + + + value = property(_get_value, _set_value) + + +class OptionMenu(Menubutton): + """Themed OptionMenu, based after Tkinter's OptionMenu, which allows + the user to select a value from a menu.""" + + def __init__(self, master, variable, default=None, *values, **kwargs): + """Construct a themed OptionMenu widget with master as the parent, + the resource textvariable set to variable, the initially selected + value specified by the default parameter, the menu values given by + *values and additional keywords. + + WIDGET-SPECIFIC OPTIONS + + style: stylename + Menubutton style. + direction: 'above', 'below', 'left', 'right', or 'flush' + Menubutton direction. + command: callback + A callback that will be invoked after selecting an item. + """ + kw = {'textvariable': variable, 'style': kwargs.pop('style', None), + 'direction': kwargs.pop('direction', None)} + Menubutton.__init__(self, master, **kw) + self['menu'] = Tkinter.Menu(self, tearoff=False) + + self._variable = variable + self._callback = kwargs.pop('command', None) + if kwargs: + raise Tkinter.TclError('unknown option -%s' % ( + kwargs.iterkeys().next())) + + self.set_menu(default, *values) + + + def __getitem__(self, item): + if item == 'menu': + return self.nametowidget(Menubutton.__getitem__(self, item)) + + return Menubutton.__getitem__(self, item) + + + def set_menu(self, default=None, *values): + """Build a new menu of radiobuttons with *values and optionally + a default value.""" + menu = self['menu'] + menu.delete(0, 'end') + for val in values: + menu.add_radiobutton(label=val, + command=Tkinter._setit(self._variable, val, self._callback)) + + if default: + self._variable.set(default) + + + def destroy(self): + """Destroy this widget and its associated variable.""" + del self._variable + Menubutton.destroy(self) diff --git a/PythonHome/Lib/lib-tk/ttk.pyc b/PythonHome/Lib/lib-tk/ttk.pyc deleted file mode 100644 index 505fd54ceb6010932a9db5708c1f2fbbb7f35f8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60597 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"EGg{vwB} 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', self.onResize) + + def reset(self, canvwidth=None, canvheight=None, bg = None): + """Adjust canvas and scrollbars according to given canvas size.""" + if canvwidth: + self.canvwidth = canvwidth + if canvheight: + self.canvheight = canvheight + if bg: + self.bg = bg + self._canvas.config(bg=bg, + scrollregion=(-self.canvwidth//2, -self.canvheight//2, + self.canvwidth//2, self.canvheight//2)) + self._canvas.xview_moveto(0.5*(self.canvwidth - self.width + 30) / + self.canvwidth) + self._canvas.yview_moveto(0.5*(self.canvheight- self.height + 30) / + self.canvheight) + self.adjustScrolls() + + + def adjustScrolls(self): + """ Adjust scrollbars according to window- and canvas-size. + """ + cwidth = self._canvas.winfo_width() + cheight = self._canvas.winfo_height() + self._canvas.xview_moveto(0.5*(self.canvwidth-cwidth)/self.canvwidth) + self._canvas.yview_moveto(0.5*(self.canvheight-cheight)/self.canvheight) + if cwidth < self.canvwidth or cheight < self.canvheight: + self.hscroll.grid(padx=1, in_ = self, pady=1, row=1, + column=0, rowspan=1, columnspan=1, sticky='news') + self.vscroll.grid(padx=1, in_ = self, pady=1, row=0, + column=1, rowspan=1, columnspan=1, sticky='news') + else: + self.hscroll.grid_forget() + self.vscroll.grid_forget() + + def onResize(self, event): + """self-explanatory""" + self.adjustScrolls() + + def bbox(self, *args): + """ 'forward' method, which canvas itself has inherited... + """ + return self._canvas.bbox(*args) + + def cget(self, *args, **kwargs): + """ 'forward' method, which canvas itself has inherited... + """ + return self._canvas.cget(*args, **kwargs) + + def config(self, *args, **kwargs): + """ 'forward' method, which canvas itself has inherited... + """ + self._canvas.config(*args, **kwargs) + + def bind(self, *args, **kwargs): + """ 'forward' method, which canvas itself has inherited... + """ + self._canvas.bind(*args, **kwargs) + + def unbind(self, *args, **kwargs): + """ 'forward' method, which canvas itself has inherited... + """ + self._canvas.unbind(*args, **kwargs) + + def focus_force(self): + """ 'forward' method, which canvas itself has inherited... + """ + self._canvas.focus_force() + +__forwardmethods(ScrolledCanvas, TK.Canvas, '_canvas') + + +class _Root(TK.Tk): + """Root class for Screen based on Tkinter.""" + def __init__(self): + TK.Tk.__init__(self) + + def setupcanvas(self, width, height, cwidth, cheight): + self._canvas = ScrolledCanvas(self, width, height, cwidth, cheight) + self._canvas.pack(expand=1, fill="both") + + def _getcanvas(self): + return self._canvas + + def set_geometry(self, width, height, startx, starty): + self.geometry("%dx%d%+d%+d"%(width, height, startx, starty)) + + def ondestroy(self, destroy): + self.wm_protocol("WM_DELETE_WINDOW", destroy) + + def win_width(self): + return self.winfo_screenwidth() + + def win_height(self): + return self.winfo_screenheight() + +Canvas = TK.Canvas + + +class TurtleScreenBase(object): + """Provide the basic graphics functionality. + Interface between Tkinter and turtle.py. + + To port turtle.py to some different graphics toolkit + a corresponding TurtleScreenBase class has to be implemented. + """ + + @staticmethod + def _blankimage(): + """return a blank image object + """ + img = TK.PhotoImage(width=1, height=1) + img.blank() + return img + + @staticmethod + def _image(filename): + """return an image object containing the + imagedata from a gif-file named filename. + """ + return TK.PhotoImage(file=filename) + + def __init__(self, cv): + self.cv = cv + if isinstance(cv, ScrolledCanvas): + w = self.cv.canvwidth + h = self.cv.canvheight + else: # expected: ordinary TK.Canvas + w = int(self.cv.cget("width")) + h = int(self.cv.cget("height")) + self.cv.config(scrollregion = (-w//2, -h//2, w//2, h//2 )) + self.canvwidth = w + self.canvheight = h + self.xscale = self.yscale = 1.0 + + def _createpoly(self): + """Create an invisible polygon item on canvas self.cv) + """ + return self.cv.create_polygon((0, 0, 0, 0, 0, 0), fill="", outline="") + + def _drawpoly(self, polyitem, coordlist, fill=None, + outline=None, width=None, top=False): + """Configure polygonitem polyitem according to provided + arguments: + coordlist is sequence of coordinates + fill is filling color + outline is outline color + top is a boolean value, which specifies if polyitem + will be put on top of the canvas' displaylist so it + will not be covered by other items. + """ + cl = [] + for x, y in coordlist: + cl.append(x * self.xscale) + cl.append(-y * self.yscale) + self.cv.coords(polyitem, *cl) + if fill is not None: + self.cv.itemconfigure(polyitem, fill=fill) + if outline is not None: + self.cv.itemconfigure(polyitem, outline=outline) + if width is not None: + self.cv.itemconfigure(polyitem, width=width) + if top: + self.cv.tag_raise(polyitem) + + def _createline(self): + """Create an invisible line item on canvas self.cv) + """ + return self.cv.create_line(0, 0, 0, 0, fill="", width=2, + capstyle = TK.ROUND) + + def _drawline(self, lineitem, coordlist=None, + fill=None, width=None, top=False): + """Configure lineitem according to provided arguments: + coordlist is sequence of coordinates + fill is drawing color + width is width of drawn line. + top is a boolean value, which specifies if polyitem + will be put on top of the canvas' displaylist so it + will not be covered by other items. + """ + if coordlist is not None: + cl = [] + for x, y in coordlist: + cl.append(x * self.xscale) + cl.append(-y * self.yscale) + self.cv.coords(lineitem, *cl) + if fill is not None: + self.cv.itemconfigure(lineitem, fill=fill) + if width is not None: + self.cv.itemconfigure(lineitem, width=width) + if top: + self.cv.tag_raise(lineitem) + + def _delete(self, item): + """Delete graphics item from canvas. + If item is"all" delete all graphics items. + """ + self.cv.delete(item) + + def _update(self): + """Redraw graphics items on canvas + """ + self.cv.update() + + def _delay(self, delay): + """Delay subsequent canvas actions for delay ms.""" + self.cv.after(delay) + + def _iscolorstring(self, color): + """Check if the string color is a legal Tkinter color string. + """ + try: + rgb = self.cv.winfo_rgb(color) + ok = True + except TK.TclError: + ok = False + return ok + + def _bgcolor(self, color=None): + """Set canvas' backgroundcolor if color is not None, + else return backgroundcolor.""" + if color is not None: + self.cv.config(bg = color) + self._update() + else: + return self.cv.cget("bg") + + def _write(self, pos, txt, align, font, pencolor): + """Write txt at pos in canvas with specified font + and color. + Return text item and x-coord of right bottom corner + of text's bounding box.""" + x, y = pos + x = x * self.xscale + y = y * self.yscale + anchor = {"left":"sw", "center":"s", "right":"se" } + item = self.cv.create_text(x-1, -y, text = txt, anchor = anchor[align], + fill = pencolor, font = font) + x0, y0, x1, y1 = self.cv.bbox(item) + self.cv.update() + return item, x1-1 + +## def _dot(self, pos, size, color): +## """may be implemented for some other graphics toolkit""" + + def _onclick(self, item, fun, num=1, add=None): + """Bind fun to mouse-click event on turtle. + fun must be a function with two arguments, the coordinates + of the clicked point on the canvas. + num, the number of the mouse-button defaults to 1 + """ + if fun is None: + self.cv.tag_unbind(item, "" % num) + else: + def eventfun(event): + x, y = (self.cv.canvasx(event.x)/self.xscale, + -self.cv.canvasy(event.y)/self.yscale) + fun(x, y) + self.cv.tag_bind(item, "" % num, eventfun, add) + + def _onrelease(self, item, fun, num=1, add=None): + """Bind fun to mouse-button-release event on turtle. + fun must be a function with two arguments, the coordinates + of the point on the canvas where mouse button is released. + num, the number of the mouse-button defaults to 1 + + If a turtle is clicked, first _onclick-event will be performed, + then _onscreensclick-event. + """ + if fun is None: + self.cv.tag_unbind(item, "" % num) + else: + def eventfun(event): + x, y = (self.cv.canvasx(event.x)/self.xscale, + -self.cv.canvasy(event.y)/self.yscale) + fun(x, y) + self.cv.tag_bind(item, "" % num, + eventfun, add) + + def _ondrag(self, item, fun, num=1, add=None): + """Bind fun to mouse-move-event (with pressed mouse button) on turtle. + fun must be a function with two arguments, the coordinates of the + actual mouse position on the canvas. + num, the number of the mouse-button defaults to 1 + + Every sequence of mouse-move-events on a turtle is preceded by a + mouse-click event on that turtle. + """ + if fun is None: + self.cv.tag_unbind(item, "" % num) + else: + def eventfun(event): + try: + x, y = (self.cv.canvasx(event.x)/self.xscale, + -self.cv.canvasy(event.y)/self.yscale) + fun(x, y) + except: + pass + self.cv.tag_bind(item, "" % num, eventfun, add) + + def _onscreenclick(self, fun, num=1, add=None): + """Bind fun to mouse-click event on canvas. + fun must be a function with two arguments, the coordinates + of the clicked point on the canvas. + num, the number of the mouse-button defaults to 1 + + If a turtle is clicked, first _onclick-event will be performed, + then _onscreensclick-event. + """ + if fun is None: + self.cv.unbind("" % num) + else: + def eventfun(event): + x, y = (self.cv.canvasx(event.x)/self.xscale, + -self.cv.canvasy(event.y)/self.yscale) + fun(x, y) + self.cv.bind("" % num, eventfun, add) + + def _onkey(self, fun, key): + """Bind fun to key-release event of key. + Canvas must have focus. See method listen + """ + if fun is None: + self.cv.unbind("" % key, None) + else: + def eventfun(event): + fun() + self.cv.bind("" % key, eventfun) + + def _listen(self): + """Set focus on canvas (in order to collect key-events) + """ + self.cv.focus_force() + + def _ontimer(self, fun, t): + """Install a timer, which calls fun after t milliseconds. + """ + if t == 0: + self.cv.after_idle(fun) + else: + self.cv.after(t, fun) + + def _createimage(self, image): + """Create and return image item on canvas. + """ + return self.cv.create_image(0, 0, image=image) + + def _drawimage(self, item, (x, y), image): + """Configure image item as to draw image object + at position (x,y) on canvas) + """ + self.cv.coords(item, (x * self.xscale, -y * self.yscale)) + self.cv.itemconfig(item, image=image) + + def _setbgpic(self, item, image): + """Configure image item as to draw image object + at center of canvas. Set item to the first item + in the displaylist, so it will be drawn below + any other item .""" + self.cv.itemconfig(item, image=image) + self.cv.tag_lower(item) + + def _type(self, item): + """Return 'line' or 'polygon' or 'image' depending on + type of item. + """ + return self.cv.type(item) + + def _pointlist(self, item): + """returns list of coordinate-pairs of points of item + Example (for insiders): + >>> from turtle import * + >>> getscreen()._pointlist(getturtle().turtle._item) + [(0.0, 9.9999999999999982), (0.0, -9.9999999999999982), + (9.9999999999999982, 0.0)] + >>> """ + cl = self.cv.coords(item) + pl = [(cl[i], -cl[i+1]) for i in range(0, len(cl), 2)] + return pl + + def _setscrollregion(self, srx1, sry1, srx2, sry2): + self.cv.config(scrollregion=(srx1, sry1, srx2, sry2)) + + def _rescale(self, xscalefactor, yscalefactor): + items = self.cv.find_all() + for item in items: + coordinates = self.cv.coords(item) + newcoordlist = [] + while coordinates: + x, y = coordinates[:2] + newcoordlist.append(x * xscalefactor) + newcoordlist.append(y * yscalefactor) + coordinates = coordinates[2:] + self.cv.coords(item, *newcoordlist) + + def _resize(self, canvwidth=None, canvheight=None, bg=None): + """Resize the canvas the turtles are drawing on. Does + not alter the drawing window. + """ + # needs amendment + if not isinstance(self.cv, ScrolledCanvas): + return self.canvwidth, self.canvheight + if canvwidth is canvheight is bg is None: + return self.cv.canvwidth, self.cv.canvheight + if canvwidth is not None: + self.canvwidth = canvwidth + if canvheight is not None: + self.canvheight = canvheight + self.cv.reset(canvwidth, canvheight, bg) + + def _window_size(self): + """ Return the width and height of the turtle window. + """ + width = self.cv.winfo_width() + if width <= 1: # the window isn't managed by a geometry manager + width = self.cv['width'] + height = self.cv.winfo_height() + if height <= 1: # the window isn't managed by a geometry manager + height = self.cv['height'] + return width, height + + +############################################################################## +### End of Tkinter - interface ### +############################################################################## + + +class Terminator (Exception): + """Will be raised in TurtleScreen.update, if _RUNNING becomes False. + + This stops execution of a turtle graphics script. + Main purpose: use in the Demo-Viewer turtle.Demo.py. + """ + pass + + +class TurtleGraphicsError(Exception): + """Some TurtleGraphics Error + """ + + +class Shape(object): + """Data structure modeling shapes. + + attribute _type is one of "polygon", "image", "compound" + attribute _data is - depending on _type a poygon-tuple, + an image or a list constructed using the addcomponent method. + """ + def __init__(self, type_, data=None): + self._type = type_ + if type_ == "polygon": + if isinstance(data, list): + data = tuple(data) + elif type_ == "image": + if isinstance(data, basestring): + if data.lower().endswith(".gif") and isfile(data): + data = TurtleScreen._image(data) + # else data assumed to be Photoimage + elif type_ == "compound": + data = [] + else: + raise TurtleGraphicsError("There is no shape type %s" % type_) + self._data = data + + def addcomponent(self, poly, fill, outline=None): + """Add component to a shape of type compound. + + Arguments: poly is a polygon, i. e. a tuple of number pairs. + fill is the fillcolor of the component, + outline is the outline color of the component. + + call (for a Shapeobject namend s): + -- s.addcomponent(((0,0), (10,10), (-10,10)), "red", "blue") + + Example: + >>> poly = ((0,0),(10,-5),(0,10),(-10,-5)) + >>> s = Shape("compound") + >>> s.addcomponent(poly, "red", "blue") + >>> # .. add more components and then use register_shape() + """ + if self._type != "compound": + raise TurtleGraphicsError("Cannot add component to %s Shape" + % self._type) + if outline is None: + outline = fill + self._data.append([poly, fill, outline]) + + +class Tbuffer(object): + """Ring buffer used as undobuffer for RawTurtle objects.""" + def __init__(self, bufsize=10): + self.bufsize = bufsize + self.buffer = [[None]] * bufsize + self.ptr = -1 + self.cumulate = False + def reset(self, bufsize=None): + if bufsize is None: + for i in range(self.bufsize): + self.buffer[i] = [None] + else: + self.bufsize = bufsize + self.buffer = [[None]] * bufsize + self.ptr = -1 + def push(self, item): + if self.bufsize > 0: + if not self.cumulate: + self.ptr = (self.ptr + 1) % self.bufsize + self.buffer[self.ptr] = item + else: + self.buffer[self.ptr].append(item) + def pop(self): + if self.bufsize > 0: + item = self.buffer[self.ptr] + if item is None: + return None + else: + self.buffer[self.ptr] = [None] + self.ptr = (self.ptr - 1) % self.bufsize + return (item) + def nr_of_items(self): + return self.bufsize - self.buffer.count([None]) + def __repr__(self): + return str(self.buffer) + " " + str(self.ptr) + + + +class TurtleScreen(TurtleScreenBase): + """Provides screen oriented methods like setbg etc. + + Only relies upon the methods of TurtleScreenBase and NOT + upon components of the underlying graphics toolkit - + which is Tkinter in this case. + """ +# _STANDARD_DELAY = 5 + _RUNNING = True + + def __init__(self, cv, mode=_CFG["mode"], + colormode=_CFG["colormode"], delay=_CFG["delay"]): + self._shapes = { + "arrow" : Shape("polygon", ((-10,0), (10,0), (0,10))), + "turtle" : Shape("polygon", ((0,16), (-2,14), (-1,10), (-4,7), + (-7,9), (-9,8), (-6,5), (-7,1), (-5,-3), (-8,-6), + (-6,-8), (-4,-5), (0,-7), (4,-5), (6,-8), (8,-6), + (5,-3), (7,1), (6,5), (9,8), (7,9), (4,7), (1,10), + (2,14))), + "circle" : Shape("polygon", ((10,0), (9.51,3.09), (8.09,5.88), + (5.88,8.09), (3.09,9.51), (0,10), (-3.09,9.51), + (-5.88,8.09), (-8.09,5.88), (-9.51,3.09), (-10,0), + (-9.51,-3.09), (-8.09,-5.88), (-5.88,-8.09), + (-3.09,-9.51), (-0.00,-10.00), (3.09,-9.51), + (5.88,-8.09), (8.09,-5.88), (9.51,-3.09))), + "square" : Shape("polygon", ((10,-10), (10,10), (-10,10), + (-10,-10))), + "triangle" : Shape("polygon", ((10,-5.77), (0,11.55), + (-10,-5.77))), + "classic": Shape("polygon", ((0,0),(-5,-9),(0,-7),(5,-9))), + "blank" : Shape("image", self._blankimage()) + } + + self._bgpics = {"nopic" : ""} + + TurtleScreenBase.__init__(self, cv) + self._mode = mode + self._delayvalue = delay + self._colormode = _CFG["colormode"] + self._keys = [] + self.clear() + + def clear(self): + """Delete all drawings and all turtles from the TurtleScreen. + + Reset empty TurtleScreen to its initial state: white background, + no backgroundimage, no eventbindings and tracing on. + + No argument. + + Example (for a TurtleScreen instance named screen): + >>> screen.clear() + + Note: this method is not available as function. + """ + self._delayvalue = _CFG["delay"] + self._colormode = _CFG["colormode"] + self._delete("all") + self._bgpic = self._createimage("") + self._bgpicname = "nopic" + self._tracing = 1 + self._updatecounter = 0 + self._turtles = [] + self.bgcolor("white") + for btn in 1, 2, 3: + self.onclick(None, btn) + for key in self._keys[:]: + self.onkey(None, key) + Turtle._pen = None + + def mode(self, mode=None): + """Set turtle-mode ('standard', 'logo' or 'world') and perform reset. + + Optional argument: + mode -- on of the strings 'standard', 'logo' or 'world' + + Mode 'standard' is compatible with turtle.py. + Mode 'logo' is compatible with most Logo-Turtle-Graphics. + Mode 'world' uses userdefined 'worldcoordinates'. *Attention*: in + this mode angles appear distorted if x/y unit-ratio doesn't equal 1. + If mode is not given, return the current mode. + + Mode Initial turtle heading positive angles + ------------|-------------------------|------------------- + 'standard' to the right (east) counterclockwise + 'logo' upward (north) clockwise + + Examples: + >>> mode('logo') # resets turtle heading to north + >>> mode() + 'logo' + """ + if mode is None: + return self._mode + mode = mode.lower() + if mode not in ["standard", "logo", "world"]: + raise TurtleGraphicsError("No turtle-graphics-mode %s" % mode) + self._mode = mode + if mode in ["standard", "logo"]: + self._setscrollregion(-self.canvwidth//2, -self.canvheight//2, + self.canvwidth//2, self.canvheight//2) + self.xscale = self.yscale = 1.0 + self.reset() + + def setworldcoordinates(self, llx, lly, urx, ury): + """Set up a user defined coordinate-system. + + Arguments: + llx -- a number, x-coordinate of lower left corner of canvas + lly -- a number, y-coordinate of lower left corner of canvas + urx -- a number, x-coordinate of upper right corner of canvas + ury -- a number, y-coordinate of upper right corner of canvas + + Set up user coodinat-system and switch to mode 'world' if necessary. + This performs a screen.reset. If mode 'world' is already active, + all drawings are redrawn according to the new coordinates. + + But ATTENTION: in user-defined coordinatesystems angles may appear + distorted. (see Screen.mode()) + + Example (for a TurtleScreen instance named screen): + >>> screen.setworldcoordinates(-10,-0.5,50,1.5) + >>> for _ in range(36): + ... left(10) + ... forward(0.5) + """ + if self.mode() != "world": + self.mode("world") + xspan = float(urx - llx) + yspan = float(ury - lly) + wx, wy = self._window_size() + self.screensize(wx-20, wy-20) + oldxscale, oldyscale = self.xscale, self.yscale + self.xscale = self.canvwidth / xspan + self.yscale = self.canvheight / yspan + srx1 = llx * self.xscale + sry1 = -ury * self.yscale + srx2 = self.canvwidth + srx1 + sry2 = self.canvheight + sry1 + self._setscrollregion(srx1, sry1, srx2, sry2) + self._rescale(self.xscale/oldxscale, self.yscale/oldyscale) + self.update() + + def register_shape(self, name, shape=None): + """Adds a turtle shape to TurtleScreen's shapelist. + + Arguments: + (1) name is the name of a gif-file and shape is None. + Installs the corresponding image shape. + !! Image-shapes DO NOT rotate when turning the turtle, + !! so they do not display the heading of the turtle! + (2) name is an arbitrary string and shape is a tuple + of pairs of coordinates. Installs the corresponding + polygon shape + (3) name is an arbitrary string and shape is a + (compound) Shape object. Installs the corresponding + compound shape. + To use a shape, you have to issue the command shape(shapename). + + call: register_shape("turtle.gif") + --or: register_shape("tri", ((0,0), (10,10), (-10,10))) + + Example (for a TurtleScreen instance named screen): + >>> screen.register_shape("triangle", ((5,-3),(0,5),(-5,-3))) + + """ + if shape is None: + # image + if name.lower().endswith(".gif"): + shape = Shape("image", self._image(name)) + else: + raise TurtleGraphicsError("Bad arguments for register_shape.\n" + + "Use help(register_shape)" ) + elif isinstance(shape, tuple): + shape = Shape("polygon", shape) + ## else shape assumed to be Shape-instance + self._shapes[name] = shape + # print "shape added:" , self._shapes + + def _colorstr(self, color): + """Return color string corresponding to args. + + Argument may be a string or a tuple of three + numbers corresponding to actual colormode, + i.e. in the range 0<=n<=colormode. + + If the argument doesn't represent a color, + an error is raised. + """ + if len(color) == 1: + color = color[0] + if isinstance(color, basestring): + if self._iscolorstring(color) or color == "": + return color + else: + raise TurtleGraphicsError("bad color string: %s" % str(color)) + try: + r, g, b = color + except: + raise TurtleGraphicsError("bad color arguments: %s" % str(color)) + if self._colormode == 1.0: + r, g, b = [round(255.0*x) for x in (r, g, b)] + if not ((0 <= r <= 255) and (0 <= g <= 255) and (0 <= b <= 255)): + raise TurtleGraphicsError("bad color sequence: %s" % str(color)) + return "#%02x%02x%02x" % (r, g, b) + + def _color(self, cstr): + if not cstr.startswith("#"): + return cstr + if len(cstr) == 7: + cl = [int(cstr[i:i+2], 16) for i in (1, 3, 5)] + elif len(cstr) == 4: + cl = [16*int(cstr[h], 16) for h in cstr[1:]] + else: + raise TurtleGraphicsError("bad colorstring: %s" % cstr) + return tuple([c * self._colormode/255 for c in cl]) + + def colormode(self, cmode=None): + """Return the colormode or set it to 1.0 or 255. + + Optional argument: + cmode -- one of the values 1.0 or 255 + + r, g, b values of colortriples have to be in range 0..cmode. + + Example (for a TurtleScreen instance named screen): + >>> screen.colormode() + 1.0 + >>> screen.colormode(255) + >>> pencolor(240,160,80) + """ + if cmode is None: + return self._colormode + if cmode == 1.0: + self._colormode = float(cmode) + elif cmode == 255: + self._colormode = int(cmode) + + def reset(self): + """Reset all Turtles on the Screen to their initial state. + + No argument. + + Example (for a TurtleScreen instance named screen): + >>> screen.reset() + """ + for turtle in self._turtles: + turtle._setmode(self._mode) + turtle.reset() + + def turtles(self): + """Return the list of turtles on the screen. + + Example (for a TurtleScreen instance named screen): + >>> screen.turtles() + [] + """ + return self._turtles + + def bgcolor(self, *args): + """Set or return backgroundcolor of the TurtleScreen. + + Arguments (if given): a color string or three numbers + in the range 0..colormode or a 3-tuple of such numbers. + + Example (for a TurtleScreen instance named screen): + >>> screen.bgcolor("orange") + >>> screen.bgcolor() + 'orange' + >>> screen.bgcolor(0.5,0,0.5) + >>> screen.bgcolor() + '#800080' + """ + if args: + color = self._colorstr(args) + else: + color = None + color = self._bgcolor(color) + if color is not None: + color = self._color(color) + return color + + def tracer(self, n=None, delay=None): + """Turns turtle animation on/off and set delay for update drawings. + + Optional arguments: + n -- nonnegative integer + delay -- nonnegative integer + + If n is given, only each n-th regular screen update is really performed. + (Can be used to accelerate the drawing of complex graphics.) + Second arguments sets delay value (see RawTurtle.delay()) + + Example (for a TurtleScreen instance named screen): + >>> screen.tracer(8, 25) + >>> dist = 2 + >>> for i in range(200): + ... fd(dist) + ... rt(90) + ... dist += 2 + """ + if n is None: + return self._tracing + self._tracing = int(n) + self._updatecounter = 0 + if delay is not None: + self._delayvalue = int(delay) + if self._tracing: + self.update() + + def delay(self, delay=None): + """ Return or set the drawing delay in milliseconds. + + Optional argument: + delay -- positive integer + + Example (for a TurtleScreen instance named screen): + >>> screen.delay(15) + >>> screen.delay() + 15 + """ + if delay is None: + return self._delayvalue + self._delayvalue = int(delay) + + def _incrementudc(self): + """Increment update counter.""" + if not TurtleScreen._RUNNING: + TurtleScreen._RUNNNING = True + raise Terminator + if self._tracing > 0: + self._updatecounter += 1 + self._updatecounter %= self._tracing + + def update(self): + """Perform a TurtleScreen update. + """ + tracing = self._tracing + self._tracing = True + for t in self.turtles(): + t._update_data() + t._drawturtle() + self._tracing = tracing + self._update() + + def window_width(self): + """ Return the width of the turtle window. + + Example (for a TurtleScreen instance named screen): + >>> screen.window_width() + 640 + """ + return self._window_size()[0] + + def window_height(self): + """ Return the height of the turtle window. + + Example (for a TurtleScreen instance named screen): + >>> screen.window_height() + 480 + """ + return self._window_size()[1] + + def getcanvas(self): + """Return the Canvas of this TurtleScreen. + + No argument. + + Example (for a Screen instance named screen): + >>> cv = screen.getcanvas() + >>> cv + + """ + return self.cv + + def getshapes(self): + """Return a list of names of all currently available turtle shapes. + + No argument. + + Example (for a TurtleScreen instance named screen): + >>> screen.getshapes() + ['arrow', 'blank', 'circle', ... , 'turtle'] + """ + return sorted(self._shapes.keys()) + + def onclick(self, fun, btn=1, add=None): + """Bind fun to mouse-click event on canvas. + + Arguments: + fun -- a function with two arguments, the coordinates of the + clicked point on the canvas. + num -- the number of the mouse-button, defaults to 1 + + Example (for a TurtleScreen instance named screen + and a Turtle instance named turtle): + + >>> screen.onclick(goto) + >>> # Subsequently clicking into the TurtleScreen will + >>> # make the turtle move to the clicked point. + >>> screen.onclick(None) + """ + self._onscreenclick(fun, btn, add) + + def onkey(self, fun, key): + """Bind fun to key-release event of key. + + Arguments: + fun -- a function with no arguments + key -- a string: key (e.g. "a") or key-symbol (e.g. "space") + + In order to be able to register key-events, TurtleScreen + must have focus. (See method listen.) + + Example (for a TurtleScreen instance named screen): + + >>> def f(): + ... fd(50) + ... lt(60) + ... + >>> screen.onkey(f, "Up") + >>> screen.listen() + + Subsequently the turtle can be moved by repeatedly pressing + the up-arrow key, consequently drawing a hexagon + + """ + if fun is None: + if key in self._keys: + self._keys.remove(key) + elif key not in self._keys: + self._keys.append(key) + self._onkey(fun, key) + + def listen(self, xdummy=None, ydummy=None): + """Set focus on TurtleScreen (in order to collect key-events) + + No arguments. + Dummy arguments are provided in order + to be able to pass listen to the onclick method. + + Example (for a TurtleScreen instance named screen): + >>> screen.listen() + """ + self._listen() + + def ontimer(self, fun, t=0): + """Install a timer, which calls fun after t milliseconds. + + Arguments: + fun -- a function with no arguments. + t -- a number >= 0 + + Example (for a TurtleScreen instance named screen): + + >>> running = True + >>> def f(): + ... if running: + ... fd(50) + ... lt(60) + ... screen.ontimer(f, 250) + ... + >>> f() # makes the turtle marching around + >>> running = False + """ + self._ontimer(fun, t) + + def bgpic(self, picname=None): + """Set background image or return name of current backgroundimage. + + Optional argument: + picname -- a string, name of a gif-file or "nopic". + + If picname is a filename, set the corresponding image as background. + If picname is "nopic", delete backgroundimage, if present. + If picname is None, return the filename of the current backgroundimage. + + Example (for a TurtleScreen instance named screen): + >>> screen.bgpic() + 'nopic' + >>> screen.bgpic("landscape.gif") + >>> screen.bgpic() + 'landscape.gif' + """ + if picname is None: + return self._bgpicname + if picname not in self._bgpics: + self._bgpics[picname] = self._image(picname) + self._setbgpic(self._bgpic, self._bgpics[picname]) + self._bgpicname = picname + + def screensize(self, canvwidth=None, canvheight=None, bg=None): + """Resize the canvas the turtles are drawing on. + + Optional arguments: + canvwidth -- positive integer, new width of canvas in pixels + canvheight -- positive integer, new height of canvas in pixels + bg -- colorstring or color-tuple, new backgroundcolor + If no arguments are given, return current (canvaswidth, canvasheight) + + Do not alter the drawing window. To observe hidden parts of + the canvas use the scrollbars. (Can make visible those parts + of a drawing, which were outside the canvas before!) + + Example (for a Turtle instance named turtle): + >>> turtle.screensize(2000,1500) + >>> # e. g. to search for an erroneously escaped turtle ;-) + """ + return self._resize(canvwidth, canvheight, bg) + + onscreenclick = onclick + resetscreen = reset + clearscreen = clear + addshape = register_shape + +class TNavigator(object): + """Navigation part of the RawTurtle. + Implements methods for turtle movement. + """ + START_ORIENTATION = { + "standard": Vec2D(1.0, 0.0), + "world" : Vec2D(1.0, 0.0), + "logo" : Vec2D(0.0, 1.0) } + DEFAULT_MODE = "standard" + DEFAULT_ANGLEOFFSET = 0 + DEFAULT_ANGLEORIENT = 1 + + def __init__(self, mode=DEFAULT_MODE): + self._angleOffset = self.DEFAULT_ANGLEOFFSET + self._angleOrient = self.DEFAULT_ANGLEORIENT + self._mode = mode + self.undobuffer = None + self.degrees() + self._mode = None + self._setmode(mode) + TNavigator.reset(self) + + def reset(self): + """reset turtle to its initial values + + Will be overwritten by parent class + """ + self._position = Vec2D(0.0, 0.0) + self._orient = TNavigator.START_ORIENTATION[self._mode] + + def _setmode(self, mode=None): + """Set turtle-mode to 'standard', 'world' or 'logo'. + """ + if mode is None: + return self._mode + if mode not in ["standard", "logo", "world"]: + return + self._mode = mode + if mode in ["standard", "world"]: + self._angleOffset = 0 + self._angleOrient = 1 + else: # mode == "logo": + self._angleOffset = self._fullcircle/4. + self._angleOrient = -1 + + def _setDegreesPerAU(self, fullcircle): + """Helper function for degrees() and radians()""" + self._fullcircle = fullcircle + self._degreesPerAU = 360/fullcircle + if self._mode == "standard": + self._angleOffset = 0 + else: + self._angleOffset = fullcircle/4. + + def degrees(self, fullcircle=360.0): + """ Set angle measurement units to degrees. + + Optional argument: + fullcircle - a number + + Set angle measurement units, i. e. set number + of 'degrees' for a full circle. Dafault value is + 360 degrees. + + Example (for a Turtle instance named turtle): + >>> turtle.left(90) + >>> turtle.heading() + 90 + + Change angle measurement unit to grad (also known as gon, + grade, or gradian and equals 1/100-th of the right angle.) + >>> turtle.degrees(400.0) + >>> turtle.heading() + 100 + + """ + self._setDegreesPerAU(fullcircle) + + def radians(self): + """ Set the angle measurement units to radians. + + No arguments. + + Example (for a Turtle instance named turtle): + >>> turtle.heading() + 90 + >>> turtle.radians() + >>> turtle.heading() + 1.5707963267948966 + """ + self._setDegreesPerAU(2*math.pi) + + def _go(self, distance): + """move turtle forward by specified distance""" + ende = self._position + self._orient * distance + self._goto(ende) + + def _rotate(self, angle): + """Turn turtle counterclockwise by specified angle if angle > 0.""" + angle *= self._degreesPerAU + self._orient = self._orient.rotate(angle) + + def _goto(self, end): + """move turtle to position end.""" + self._position = end + + def forward(self, distance): + """Move the turtle forward by the specified distance. + + Aliases: forward | fd + + Argument: + distance -- a number (integer or float) + + Move the turtle forward by the specified distance, in the direction + the turtle is headed. + + Example (for a Turtle instance named turtle): + >>> turtle.position() + (0.00, 0.00) + >>> turtle.forward(25) + >>> turtle.position() + (25.00,0.00) + >>> turtle.forward(-75) + >>> turtle.position() + (-50.00,0.00) + """ + self._go(distance) + + def back(self, distance): + """Move the turtle backward by distance. + + Aliases: back | backward | bk + + Argument: + distance -- a number + + Move the turtle backward by distance ,opposite to the direction the + turtle is headed. Do not change the turtle's heading. + + Example (for a Turtle instance named turtle): + >>> turtle.position() + (0.00, 0.00) + >>> turtle.backward(30) + >>> turtle.position() + (-30.00, 0.00) + """ + self._go(-distance) + + def right(self, angle): + """Turn turtle right by angle units. + + Aliases: right | rt + + Argument: + angle -- a number (integer or float) + + Turn turtle right by angle units. (Units are by default degrees, + but can be set via the degrees() and radians() functions.) + Angle orientation depends on mode. (See this.) + + Example (for a Turtle instance named turtle): + >>> turtle.heading() + 22.0 + >>> turtle.right(45) + >>> turtle.heading() + 337.0 + """ + self._rotate(-angle) + + def left(self, angle): + """Turn turtle left by angle units. + + Aliases: left | lt + + Argument: + angle -- a number (integer or float) + + Turn turtle left by angle units. (Units are by default degrees, + but can be set via the degrees() and radians() functions.) + Angle orientation depends on mode. (See this.) + + Example (for a Turtle instance named turtle): + >>> turtle.heading() + 22.0 + >>> turtle.left(45) + >>> turtle.heading() + 67.0 + """ + self._rotate(angle) + + def pos(self): + """Return the turtle's current location (x,y), as a Vec2D-vector. + + Aliases: pos | position + + No arguments. + + Example (for a Turtle instance named turtle): + >>> turtle.pos() + (0.00, 240.00) + """ + return self._position + + def xcor(self): + """ Return the turtle's x coordinate. + + No arguments. + + Example (for a Turtle instance named turtle): + >>> reset() + >>> turtle.left(60) + >>> turtle.forward(100) + >>> print turtle.xcor() + 50.0 + """ + return self._position[0] + + def ycor(self): + """ Return the turtle's y coordinate + --- + No arguments. + + Example (for a Turtle instance named turtle): + >>> reset() + >>> turtle.left(60) + >>> turtle.forward(100) + >>> print turtle.ycor() + 86.6025403784 + """ + return self._position[1] + + + def goto(self, x, y=None): + """Move turtle to an absolute position. + + Aliases: setpos | setposition | goto: + + Arguments: + x -- a number or a pair/vector of numbers + y -- a number None + + call: goto(x, y) # two coordinates + --or: goto((x, y)) # a pair (tuple) of coordinates + --or: goto(vec) # e.g. as returned by pos() + + Move turtle to an absolute position. If the pen is down, + a line will be drawn. The turtle's orientation does not change. + + Example (for a Turtle instance named turtle): + >>> tp = turtle.pos() + >>> tp + (0.00, 0.00) + >>> turtle.setpos(60,30) + >>> turtle.pos() + (60.00,30.00) + >>> turtle.setpos((20,80)) + >>> turtle.pos() + (20.00,80.00) + >>> turtle.setpos(tp) + >>> turtle.pos() + (0.00,0.00) + """ + if y is None: + self._goto(Vec2D(*x)) + else: + self._goto(Vec2D(x, y)) + + def home(self): + """Move turtle to the origin - coordinates (0,0). + + No arguments. + + Move turtle to the origin - coordinates (0,0) and set its + heading to its start-orientation (which depends on mode). + + Example (for a Turtle instance named turtle): + >>> turtle.home() + """ + self.goto(0, 0) + self.setheading(0) + + def setx(self, x): + """Set the turtle's first coordinate to x + + Argument: + x -- a number (integer or float) + + Set the turtle's first coordinate to x, leave second coordinate + unchanged. + + Example (for a Turtle instance named turtle): + >>> turtle.position() + (0.00, 240.00) + >>> turtle.setx(10) + >>> turtle.position() + (10.00, 240.00) + """ + self._goto(Vec2D(x, self._position[1])) + + def sety(self, y): + """Set the turtle's second coordinate to y + + Argument: + y -- a number (integer or float) + + Set the turtle's first coordinate to x, second coordinate remains + unchanged. + + Example (for a Turtle instance named turtle): + >>> turtle.position() + (0.00, 40.00) + >>> turtle.sety(-10) + >>> turtle.position() + (0.00, -10.00) + """ + self._goto(Vec2D(self._position[0], y)) + + def distance(self, x, y=None): + """Return the distance from the turtle to (x,y) in turtle step units. + + Arguments: + x -- a number or a pair/vector of numbers or a turtle instance + y -- a number None None + + call: distance(x, y) # two coordinates + --or: distance((x, y)) # a pair (tuple) of coordinates + --or: distance(vec) # e.g. as returned by pos() + --or: distance(mypen) # where mypen is another turtle + + Example (for a Turtle instance named turtle): + >>> turtle.pos() + (0.00, 0.00) + >>> turtle.distance(30,40) + 50.0 + >>> pen = Turtle() + >>> pen.forward(77) + >>> turtle.distance(pen) + 77.0 + """ + if y is not None: + pos = Vec2D(x, y) + if isinstance(x, Vec2D): + pos = x + elif isinstance(x, tuple): + pos = Vec2D(*x) + elif isinstance(x, TNavigator): + pos = x._position + return abs(pos - self._position) + + def towards(self, x, y=None): + """Return the angle of the line from the turtle's position to (x, y). + + Arguments: + x -- a number or a pair/vector of numbers or a turtle instance + y -- a number None None + + call: distance(x, y) # two coordinates + --or: distance((x, y)) # a pair (tuple) of coordinates + --or: distance(vec) # e.g. as returned by pos() + --or: distance(mypen) # where mypen is another turtle + + Return the angle, between the line from turtle-position to position + specified by x, y and the turtle's start orientation. (Depends on + modes - "standard" or "logo") + + Example (for a Turtle instance named turtle): + >>> turtle.pos() + (10.00, 10.00) + >>> turtle.towards(0,0) + 225.0 + """ + if y is not None: + pos = Vec2D(x, y) + if isinstance(x, Vec2D): + pos = x + elif isinstance(x, tuple): + pos = Vec2D(*x) + elif isinstance(x, TNavigator): + pos = x._position + x, y = pos - self._position + result = round(math.atan2(y, x)*180.0/math.pi, 10) % 360.0 + result /= self._degreesPerAU + return (self._angleOffset + self._angleOrient*result) % self._fullcircle + + def heading(self): + """ Return the turtle's current heading. + + No arguments. + + Example (for a Turtle instance named turtle): + >>> turtle.left(67) + >>> turtle.heading() + 67.0 + """ + x, y = self._orient + result = round(math.atan2(y, x)*180.0/math.pi, 10) % 360.0 + result /= self._degreesPerAU + return (self._angleOffset + self._angleOrient*result) % self._fullcircle + + def setheading(self, to_angle): + """Set the orientation of the turtle to to_angle. + + Aliases: setheading | seth + + Argument: + to_angle -- a number (integer or float) + + Set the orientation of the turtle to to_angle. + Here are some common directions in degrees: + + standard - mode: logo-mode: + -------------------|-------------------- + 0 - east 0 - north + 90 - north 90 - east + 180 - west 180 - south + 270 - south 270 - west + + Example (for a Turtle instance named turtle): + >>> turtle.setheading(90) + >>> turtle.heading() + 90 + """ + angle = (to_angle - self.heading())*self._angleOrient + full = self._fullcircle + angle = (angle+full/2.)%full - full/2. + self._rotate(angle) + + def circle(self, radius, extent = None, steps = None): + """ Draw a circle with given radius. + + Arguments: + radius -- a number + extent (optional) -- a number + steps (optional) -- an integer + + Draw a circle with given radius. The center is radius units left + of the turtle; extent - an angle - determines which part of the + circle is drawn. If extent is not given, draw the entire circle. + If extent is not a full circle, one endpoint of the arc is the + current pen position. Draw the arc in counterclockwise direction + if radius is positive, otherwise in clockwise direction. Finally + the direction of the turtle is changed by the amount of extent. + + As the circle is approximated by an inscribed regular polygon, + steps determines the number of steps to use. If not given, + it will be calculated automatically. Maybe used to draw regular + polygons. + + call: circle(radius) # full circle + --or: circle(radius, extent) # arc + --or: circle(radius, extent, steps) + --or: circle(radius, steps=6) # 6-sided polygon + + Example (for a Turtle instance named turtle): + >>> turtle.circle(50) + >>> turtle.circle(120, 180) # semicircle + """ + if self.undobuffer: + self.undobuffer.push(["seq"]) + self.undobuffer.cumulate = True + speed = self.speed() + if extent is None: + extent = self._fullcircle + if steps is None: + frac = abs(extent)/self._fullcircle + steps = 1+int(min(11+abs(radius)/6.0, 59.0)*frac) + w = 1.0 * extent / steps + w2 = 0.5 * w + l = 2.0 * radius * math.sin(w2*math.pi/180.0*self._degreesPerAU) + if radius < 0: + l, w, w2 = -l, -w, -w2 + tr = self.tracer() + dl = self._delay() + if speed == 0: + self.tracer(0, 0) + else: + self.speed(0) + self._rotate(w2) + for i in range(steps): + self.speed(speed) + self._go(l) + self.speed(0) + self._rotate(w) + self._rotate(-w2) + if speed == 0: + self.tracer(tr, dl) + self.speed(speed) + if self.undobuffer: + self.undobuffer.cumulate = False + +## three dummy methods to be implemented by child class: + + def speed(self, s=0): + """dummy method - to be overwritten by child class""" + def tracer(self, a=None, b=None): + """dummy method - to be overwritten by child class""" + def _delay(self, n=None): + """dummy method - to be overwritten by child class""" + + fd = forward + bk = back + backward = back + rt = right + lt = left + position = pos + setpos = goto + setposition = goto + seth = setheading + + +class TPen(object): + """Drawing part of the RawTurtle. + Implements drawing properties. + """ + def __init__(self, resizemode=_CFG["resizemode"]): + self._resizemode = resizemode # or "user" or "noresize" + self.undobuffer = None + TPen._reset(self) + + def _reset(self, pencolor=_CFG["pencolor"], + fillcolor=_CFG["fillcolor"]): + self._pensize = 1 + self._shown = True + self._pencolor = pencolor + self._fillcolor = fillcolor + self._drawing = True + self._speed = 3 + self._stretchfactor = (1, 1) + self._tilt = 0 + self._outlinewidth = 1 + ### self.screen = None # to override by child class + + def resizemode(self, rmode=None): + """Set resizemode to one of the values: "auto", "user", "noresize". + + (Optional) Argument: + rmode -- one of the strings "auto", "user", "noresize" + + Different resizemodes have the following effects: + - "auto" adapts the appearance of the turtle + corresponding to the value of pensize. + - "user" adapts the appearance of the turtle according to the + values of stretchfactor and outlinewidth (outline), + which are set by shapesize() + - "noresize" no adaption of the turtle's appearance takes place. + If no argument is given, return current resizemode. + resizemode("user") is called by a call of shapesize with arguments. + + + Examples (for a Turtle instance named turtle): + >>> turtle.resizemode("noresize") + >>> turtle.resizemode() + 'noresize' + """ + if rmode is None: + return self._resizemode + rmode = rmode.lower() + if rmode in ["auto", "user", "noresize"]: + self.pen(resizemode=rmode) + + def pensize(self, width=None): + """Set or return the line thickness. + + Aliases: pensize | width + + Argument: + width -- positive number + + Set the line thickness to width or return it. If resizemode is set + to "auto" and turtleshape is a polygon, that polygon is drawn with + the same line thickness. If no argument is given, current pensize + is returned. + + Example (for a Turtle instance named turtle): + >>> turtle.pensize() + 1 + >>> turtle.pensize(10) # from here on lines of width 10 are drawn + """ + if width is None: + return self._pensize + self.pen(pensize=width) + + + def penup(self): + """Pull the pen up -- no drawing when moving. + + Aliases: penup | pu | up + + No argument + + Example (for a Turtle instance named turtle): + >>> turtle.penup() + """ + if not self._drawing: + return + self.pen(pendown=False) + + def pendown(self): + """Pull the pen down -- drawing when moving. + + Aliases: pendown | pd | down + + No argument. + + Example (for a Turtle instance named turtle): + >>> turtle.pendown() + """ + if self._drawing: + return + self.pen(pendown=True) + + def isdown(self): + """Return True if pen is down, False if it's up. + + No argument. + + Example (for a Turtle instance named turtle): + >>> turtle.penup() + >>> turtle.isdown() + False + >>> turtle.pendown() + >>> turtle.isdown() + True + """ + return self._drawing + + def speed(self, speed=None): + """ Return or set the turtle's speed. + + Optional argument: + speed -- an integer in the range 0..10 or a speedstring (see below) + + Set the turtle's speed to an integer value in the range 0 .. 10. + If no argument is given: return current speed. + + If input is a number greater than 10 or smaller than 0.5, + speed is set to 0. + Speedstrings are mapped to speedvalues in the following way: + 'fastest' : 0 + 'fast' : 10 + 'normal' : 6 + 'slow' : 3 + 'slowest' : 1 + speeds from 1 to 10 enforce increasingly faster animation of + line drawing and turtle turning. + + Attention: + speed = 0 : *no* animation takes place. forward/back makes turtle jump + and likewise left/right make the turtle turn instantly. + + Example (for a Turtle instance named turtle): + >>> turtle.speed(3) + """ + speeds = {'fastest':0, 'fast':10, 'normal':6, 'slow':3, 'slowest':1 } + if speed is None: + return self._speed + if speed in speeds: + speed = speeds[speed] + elif 0.5 < speed < 10.5: + speed = int(round(speed)) + else: + speed = 0 + self.pen(speed=speed) + + def color(self, *args): + """Return or set the pencolor and fillcolor. + + Arguments: + Several input formats are allowed. + They use 0, 1, 2, or 3 arguments as follows: + + color() + Return the current pencolor and the current fillcolor + as a pair of color specification strings as are returned + by pencolor and fillcolor. + color(colorstring), color((r,g,b)), color(r,g,b) + inputs as in pencolor, set both, fillcolor and pencolor, + to the given value. + color(colorstring1, colorstring2), + color((r1,g1,b1), (r2,g2,b2)) + 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. + For mor info see: pencolor, fillcolor + + Example (for a Turtle instance named turtle): + >>> turtle.color('red', 'green') + >>> turtle.color() + ('red', 'green') + >>> colormode(255) + >>> color((40, 80, 120), (160, 200, 240)) + >>> color() + ('#285078', '#a0c8f0') + """ + if args: + l = len(args) + if l == 1: + pcolor = fcolor = args[0] + elif l == 2: + pcolor, fcolor = args + elif l == 3: + pcolor = fcolor = args + pcolor = self._colorstr(pcolor) + fcolor = self._colorstr(fcolor) + self.pen(pencolor=pcolor, fillcolor=fcolor) + else: + return self._color(self._pencolor), self._color(self._fillcolor) + + def pencolor(self, *args): + """ Return or set the pencolor. + + Arguments: + Four input formats are allowed: + - pencolor() + Return the current pencolor as color specification string, + possibly in hex-number format (see example). + May be used as input to another color/pencolor/fillcolor call. + - pencolor(colorstring) + s is a Tk color specification string, such as "red" or "yellow" + - pencolor((r, g, b)) + *a tuple* of r, g, and b, which represent, an RGB color, + and each of r, g, and b are in the range 0..colormode, + where colormode is either 1.0 or 255 + - pencolor(r, g, b) + r, g, and b represent an RGB color, and each of r, g, and b + are in the range 0..colormode + + If turtleshape is a polygon, the outline of that polygon is drawn + with the newly set pencolor. + + Example (for a Turtle instance named turtle): + >>> turtle.pencolor('brown') + >>> tup = (0.2, 0.8, 0.55) + >>> turtle.pencolor(tup) + >>> turtle.pencolor() + '#33cc8c' + """ + if args: + color = self._colorstr(args) + if color == self._pencolor: + return + self.pen(pencolor=color) + else: + return self._color(self._pencolor) + + def fillcolor(self, *args): + """ Return or set the fillcolor. + + Arguments: + Four input formats are allowed: + - fillcolor() + Return the current fillcolor as color specification string, + possibly in hex-number format (see example). + May be used as input to another color/pencolor/fillcolor call. + - fillcolor(colorstring) + s is a Tk color specification string, such as "red" or "yellow" + - fillcolor((r, g, b)) + *a tuple* of r, g, and b, which represent, an RGB color, + and each of r, g, and b are in the range 0..colormode, + where colormode is either 1.0 or 255 + - fillcolor(r, g, b) + r, g, and b represent an RGB color, and each of r, g, and b + are in the range 0..colormode + + If turtleshape is a polygon, the interior of that polygon is drawn + with the newly set fillcolor. + + Example (for a Turtle instance named turtle): + >>> turtle.fillcolor('violet') + >>> col = turtle.pencolor() + >>> turtle.fillcolor(col) + >>> turtle.fillcolor(0, .5, 0) + """ + if args: + color = self._colorstr(args) + if color == self._fillcolor: + return + self.pen(fillcolor=color) + else: + return self._color(self._fillcolor) + + def showturtle(self): + """Makes the turtle visible. + + Aliases: showturtle | st + + No argument. + + Example (for a Turtle instance named turtle): + >>> turtle.hideturtle() + >>> turtle.showturtle() + """ + self.pen(shown=True) + + def hideturtle(self): + """Makes the turtle invisible. + + Aliases: hideturtle | ht + + No argument. + + It's a good idea to do this while you're in the + middle of a complicated drawing, because hiding + the turtle speeds up the drawing observably. + + Example (for a Turtle instance named turtle): + >>> turtle.hideturtle() + """ + self.pen(shown=False) + + def isvisible(self): + """Return True if the Turtle is shown, False if it's hidden. + + No argument. + + Example (for a Turtle instance named turtle): + >>> turtle.hideturtle() + >>> print turtle.isvisible(): + False + """ + return self._shown + + def pen(self, pen=None, **pendict): + """Return or set the pen's attributes. + + Arguments: + pen -- a dictionary with some or all of the below listed keys. + **pendict -- one or more keyword-arguments with the below + listed keys as keywords. + + Return or set the pen's attributes in a 'pen-dictionary' + with the following key/value pairs: + "shown" : True/False + "pendown" : True/False + "pencolor" : color-string or color-tuple + "fillcolor" : color-string or color-tuple + "pensize" : positive number + "speed" : number in range 0..10 + "resizemode" : "auto" or "user" or "noresize" + "stretchfactor": (positive number, positive number) + "outline" : positive number + "tilt" : number + + This dictionary can be used as argument for a subsequent + pen()-call to restore the former pen-state. Moreover one + or more of these attributes can be provided as keyword-arguments. + This can be used to set several pen attributes in one statement. + + + Examples (for a Turtle instance named turtle): + >>> turtle.pen(fillcolor="black", pencolor="red", pensize=10) + >>> turtle.pen() + {'pensize': 10, 'shown': True, 'resizemode': 'auto', 'outline': 1, + 'pencolor': 'red', 'pendown': True, 'fillcolor': 'black', + 'stretchfactor': (1,1), 'speed': 3} + >>> penstate=turtle.pen() + >>> turtle.color("yellow","") + >>> turtle.penup() + >>> turtle.pen() + {'pensize': 10, 'shown': True, 'resizemode': 'auto', 'outline': 1, + 'pencolor': 'yellow', 'pendown': False, 'fillcolor': '', + 'stretchfactor': (1,1), 'speed': 3} + >>> p.pen(penstate, fillcolor="green") + >>> p.pen() + {'pensize': 10, 'shown': True, 'resizemode': 'auto', 'outline': 1, + 'pencolor': 'red', 'pendown': True, 'fillcolor': 'green', + 'stretchfactor': (1,1), 'speed': 3} + """ + _pd = {"shown" : self._shown, + "pendown" : self._drawing, + "pencolor" : self._pencolor, + "fillcolor" : self._fillcolor, + "pensize" : self._pensize, + "speed" : self._speed, + "resizemode" : self._resizemode, + "stretchfactor" : self._stretchfactor, + "outline" : self._outlinewidth, + "tilt" : self._tilt + } + + if not (pen or pendict): + return _pd + + if isinstance(pen, dict): + p = pen + else: + p = {} + p.update(pendict) + + _p_buf = {} + for key in p: + _p_buf[key] = _pd[key] + + if self.undobuffer: + self.undobuffer.push(("pen", _p_buf)) + + newLine = False + if "pendown" in p: + if self._drawing != p["pendown"]: + newLine = True + if "pencolor" in p: + if isinstance(p["pencolor"], tuple): + p["pencolor"] = self._colorstr((p["pencolor"],)) + if self._pencolor != p["pencolor"]: + newLine = True + if "pensize" in p: + if self._pensize != p["pensize"]: + newLine = True + if newLine: + self._newLine() + if "pendown" in p: + self._drawing = p["pendown"] + if "pencolor" in p: + self._pencolor = p["pencolor"] + if "pensize" in p: + self._pensize = p["pensize"] + if "fillcolor" in p: + if isinstance(p["fillcolor"], tuple): + p["fillcolor"] = self._colorstr((p["fillcolor"],)) + self._fillcolor = p["fillcolor"] + if "speed" in p: + self._speed = p["speed"] + if "resizemode" in p: + self._resizemode = p["resizemode"] + if "stretchfactor" in p: + sf = p["stretchfactor"] + if isinstance(sf, (int, float)): + sf = (sf, sf) + self._stretchfactor = sf + if "outline" in p: + self._outlinewidth = p["outline"] + if "shown" in p: + self._shown = p["shown"] + if "tilt" in p: + self._tilt = p["tilt"] + self._update() + +## three dummy methods to be implemented by child class: + + def _newLine(self, usePos = True): + """dummy method - to be overwritten by child class""" + def _update(self, count=True, forced=False): + """dummy method - to be overwritten by child class""" + def _color(self, args): + """dummy method - to be overwritten by child class""" + def _colorstr(self, args): + """dummy method - to be overwritten by child class""" + + width = pensize + up = penup + pu = penup + pd = pendown + down = pendown + st = showturtle + ht = hideturtle + + +class _TurtleImage(object): + """Helper class: Datatype to store Turtle attributes + """ + + def __init__(self, screen, shapeIndex): + self.screen = screen + self._type = None + self._setshape(shapeIndex) + + def _setshape(self, shapeIndex): + screen = self.screen # RawTurtle.screens[self.screenIndex] + self.shapeIndex = shapeIndex + if self._type == "polygon" == screen._shapes[shapeIndex]._type: + return + if self._type == "image" == screen._shapes[shapeIndex]._type: + return + if self._type in ["image", "polygon"]: + screen._delete(self._item) + elif self._type == "compound": + for item in self._item: + screen._delete(item) + self._type = screen._shapes[shapeIndex]._type + if self._type == "polygon": + self._item = screen._createpoly() + elif self._type == "image": + self._item = screen._createimage(screen._shapes["blank"]._data) + elif self._type == "compound": + self._item = [screen._createpoly() for item in + screen._shapes[shapeIndex]._data] + + +class RawTurtle(TPen, TNavigator): + """Animation part of the RawTurtle. + Puts RawTurtle upon a TurtleScreen and provides tools for + its animation. + """ + screens = [] + + def __init__(self, canvas=None, + shape=_CFG["shape"], + undobuffersize=_CFG["undobuffersize"], + visible=_CFG["visible"]): + if isinstance(canvas, _Screen): + self.screen = canvas + elif isinstance(canvas, TurtleScreen): + if canvas not in RawTurtle.screens: + RawTurtle.screens.append(canvas) + self.screen = canvas + elif isinstance(canvas, (ScrolledCanvas, Canvas)): + for screen in RawTurtle.screens: + if screen.cv == canvas: + self.screen = screen + break + else: + self.screen = TurtleScreen(canvas) + RawTurtle.screens.append(self.screen) + else: + raise TurtleGraphicsError("bad canvas argument %s" % canvas) + + screen = self.screen + TNavigator.__init__(self, screen.mode()) + TPen.__init__(self) + screen._turtles.append(self) + self.drawingLineItem = screen._createline() + self.turtle = _TurtleImage(screen, shape) + self._poly = None + self._creatingPoly = False + self._fillitem = self._fillpath = None + self._shown = visible + self._hidden_from_screen = False + self.currentLineItem = screen._createline() + self.currentLine = [self._position] + self.items = [self.currentLineItem] + self.stampItems = [] + self._undobuffersize = undobuffersize + self.undobuffer = Tbuffer(undobuffersize) + self._update() + + def reset(self): + """Delete the turtle's drawings and restore its default values. + + No argument. +, + Delete the turtle's drawings from the screen, re-center the turtle + and set variables to the default values. + + Example (for a Turtle instance named turtle): + >>> turtle.position() + (0.00,-22.00) + >>> turtle.heading() + 100.0 + >>> turtle.reset() + >>> turtle.position() + (0.00,0.00) + >>> turtle.heading() + 0.0 + """ + TNavigator.reset(self) + TPen._reset(self) + self._clear() + self._drawturtle() + self._update() + + def setundobuffer(self, size): + """Set or disable undobuffer. + + Argument: + size -- an integer or None + + 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 undo() function. + If size is None, no undobuffer is present. + + Example (for a Turtle instance named turtle): + >>> turtle.setundobuffer(42) + """ + if size is None: + self.undobuffer = None + else: + self.undobuffer = Tbuffer(size) + + def undobufferentries(self): + """Return count of entries in the undobuffer. + + No argument. + + Example (for a Turtle instance named turtle): + >>> while undobufferentries(): + ... undo() + """ + if self.undobuffer is None: + return 0 + return self.undobuffer.nr_of_items() + + def _clear(self): + """Delete all of pen's drawings""" + self._fillitem = self._fillpath = None + for item in self.items: + self.screen._delete(item) + self.currentLineItem = self.screen._createline() + self.currentLine = [] + if self._drawing: + self.currentLine.append(self._position) + self.items = [self.currentLineItem] + self.clearstamps() + self.setundobuffer(self._undobuffersize) + + + def clear(self): + """Delete the turtle's drawings from the screen. Do not move turtle. + + No arguments. + + Delete the turtle's drawings from the screen. Do not move turtle. + State and position of the turtle as well as drawings of other + turtles are not affected. + + Examples (for a Turtle instance named turtle): + >>> turtle.clear() + """ + self._clear() + self._update() + + def _update_data(self): + self.screen._incrementudc() + if self.screen._updatecounter != 0: + return + if len(self.currentLine)>1: + self.screen._drawline(self.currentLineItem, self.currentLine, + self._pencolor, self._pensize) + + def _update(self): + """Perform a Turtle-data update. + """ + screen = self.screen + if screen._tracing == 0: + return + elif screen._tracing == 1: + self._update_data() + self._drawturtle() + screen._update() # TurtleScreenBase + screen._delay(screen._delayvalue) # TurtleScreenBase + else: + self._update_data() + if screen._updatecounter == 0: + for t in screen.turtles(): + t._drawturtle() + screen._update() + + def tracer(self, flag=None, delay=None): + """Turns turtle animation on/off and set delay for update drawings. + + Optional arguments: + n -- nonnegative integer + delay -- nonnegative integer + + If n is given, only each n-th regular screen update is really performed. + (Can be used to accelerate the drawing of complex graphics.) + Second arguments sets delay value (see RawTurtle.delay()) + + Example (for a Turtle instance named turtle): + >>> turtle.tracer(8, 25) + >>> dist = 2 + >>> for i in range(200): + ... turtle.fd(dist) + ... turtle.rt(90) + ... dist += 2 + """ + return self.screen.tracer(flag, delay) + + def _color(self, args): + return self.screen._color(args) + + def _colorstr(self, args): + return self.screen._colorstr(args) + + def _cc(self, args): + """Convert colortriples to hexstrings. + """ + if isinstance(args, basestring): + return args + try: + r, g, b = args + except: + raise TurtleGraphicsError("bad color arguments: %s" % str(args)) + if self.screen._colormode == 1.0: + r, g, b = [round(255.0*x) for x in (r, g, b)] + if not ((0 <= r <= 255) and (0 <= g <= 255) and (0 <= b <= 255)): + raise TurtleGraphicsError("bad color sequence: %s" % str(args)) + return "#%02x%02x%02x" % (r, g, b) + + def clone(self): + """Create and return a clone of the turtle. + + No argument. + + Create and return a clone of the turtle with same position, heading + and turtle properties. + + Example (for a Turtle instance named mick): + mick = Turtle() + joe = mick.clone() + """ + screen = self.screen + self._newLine(self._drawing) + + turtle = self.turtle + self.screen = None + self.turtle = None # too make self deepcopy-able + + q = deepcopy(self) + + self.screen = screen + self.turtle = turtle + + q.screen = screen + q.turtle = _TurtleImage(screen, self.turtle.shapeIndex) + + screen._turtles.append(q) + ttype = screen._shapes[self.turtle.shapeIndex]._type + if ttype == "polygon": + q.turtle._item = screen._createpoly() + elif ttype == "image": + q.turtle._item = screen._createimage(screen._shapes["blank"]._data) + elif ttype == "compound": + q.turtle._item = [screen._createpoly() for item in + screen._shapes[self.turtle.shapeIndex]._data] + q.currentLineItem = screen._createline() + q._update() + return q + + def shape(self, name=None): + """Set turtle shape to shape with given name / return current shapename. + + Optional argument: + name -- a string, which is a valid shapename + + Set turtle shape to shape with given name or, if name is not given, + return name of current shape. + Shape with name must exist in the TurtleScreen's shape dictionary. + Initially there are the following polygon shapes: + 'arrow', 'turtle', 'circle', 'square', 'triangle', 'classic'. + To learn about how to deal with shapes see Screen-method register_shape. + + Example (for a Turtle instance named turtle): + >>> turtle.shape() + 'arrow' + >>> turtle.shape("turtle") + >>> turtle.shape() + 'turtle' + """ + if name is None: + return self.turtle.shapeIndex + if not name in self.screen.getshapes(): + raise TurtleGraphicsError("There is no shape named %s" % name) + self.turtle._setshape(name) + self._update() + + def shapesize(self, stretch_wid=None, stretch_len=None, outline=None): + """Set/return turtle's stretchfactors/outline. Set resizemode to "user". + + Optional arguments: + stretch_wid : positive number + stretch_len : positive number + outline : positive number + + Return or set the pen's attributes x/y-stretchfactors and/or outline. + Set resizemode to "user". + If and only if resizemode is set to "user", the turtle will be displayed + stretched according to its stretchfactors: + stretch_wid is stretchfactor perpendicular to orientation + stretch_len is stretchfactor in direction of turtles orientation. + outline determines the width of the shapes's outline. + + Examples (for a Turtle instance named turtle): + >>> turtle.resizemode("user") + >>> turtle.shapesize(5, 5, 12) + >>> turtle.shapesize(outline=8) + """ + if stretch_wid is stretch_len is outline is None: + stretch_wid, stretch_len = self._stretchfactor + return stretch_wid, stretch_len, self._outlinewidth + if stretch_wid is not None: + if stretch_len is None: + stretchfactor = stretch_wid, stretch_wid + else: + stretchfactor = stretch_wid, stretch_len + elif stretch_len is not None: + stretchfactor = self._stretchfactor[0], stretch_len + else: + stretchfactor = self._stretchfactor + if outline is None: + outline = self._outlinewidth + self.pen(resizemode="user", + stretchfactor=stretchfactor, outline=outline) + + def settiltangle(self, angle): + """Rotate the turtleshape to point in the specified direction + + Optional argument: + angle -- number + + Rotate the turtleshape to point in the direction specified by angle, + regardless of its current tilt-angle. DO NOT change the turtle's + heading (direction of movement). + + + Examples (for a Turtle instance named turtle): + >>> turtle.shape("circle") + >>> turtle.shapesize(5,2) + >>> turtle.settiltangle(45) + >>> stamp() + >>> turtle.fd(50) + >>> turtle.settiltangle(-45) + >>> stamp() + >>> turtle.fd(50) + """ + tilt = -angle * self._degreesPerAU * self._angleOrient + tilt = (tilt * math.pi / 180.0) % (2*math.pi) + self.pen(resizemode="user", tilt=tilt) + + def tiltangle(self): + """Return the current tilt-angle. + + No argument. + + Return the current tilt-angle, i. e. the angle between the + orientation of the turtleshape and the heading of the turtle + (its direction of movement). + + Examples (for a Turtle instance named turtle): + >>> turtle.shape("circle") + >>> turtle.shapesize(5,2) + >>> turtle.tilt(45) + >>> turtle.tiltangle() + """ + tilt = -self._tilt * (180.0/math.pi) * self._angleOrient + return (tilt / self._degreesPerAU) % self._fullcircle + + def tilt(self, angle): + """Rotate the turtleshape by angle. + + Argument: + angle - a number + + Rotate the turtleshape by angle from its current tilt-angle, + but do NOT change the turtle's heading (direction of movement). + + Examples (for a Turtle instance named turtle): + >>> turtle.shape("circle") + >>> turtle.shapesize(5,2) + >>> turtle.tilt(30) + >>> turtle.fd(50) + >>> turtle.tilt(30) + >>> turtle.fd(50) + """ + self.settiltangle(angle + self.tiltangle()) + + def _polytrafo(self, poly): + """Computes transformed polygon shapes from a shape + according to current position and heading. + """ + screen = self.screen + p0, p1 = self._position + e0, e1 = self._orient + e = Vec2D(e0, e1 * screen.yscale / screen.xscale) + e0, e1 = (1.0 / abs(e)) * e + return [(p0+(e1*x+e0*y)/screen.xscale, p1+(-e0*x+e1*y)/screen.yscale) + for (x, y) in poly] + + def _drawturtle(self): + """Manages the correct rendering of the turtle with respect to + its shape, resizemode, stretch and tilt etc.""" + screen = self.screen + shape = screen._shapes[self.turtle.shapeIndex] + ttype = shape._type + titem = self.turtle._item + if self._shown and screen._updatecounter == 0 and screen._tracing > 0: + self._hidden_from_screen = False + tshape = shape._data + if ttype == "polygon": + if self._resizemode == "noresize": + w = 1 + shape = tshape + else: + if self._resizemode == "auto": + lx = ly = max(1, self._pensize/5.0) + w = self._pensize + tiltangle = 0 + elif self._resizemode == "user": + lx, ly = self._stretchfactor + w = self._outlinewidth + tiltangle = self._tilt + shape = [(lx*x, ly*y) for (x, y) in tshape] + t0, t1 = math.sin(tiltangle), math.cos(tiltangle) + shape = [(t1*x+t0*y, -t0*x+t1*y) for (x, y) in shape] + shape = self._polytrafo(shape) + fc, oc = self._fillcolor, self._pencolor + screen._drawpoly(titem, shape, fill=fc, outline=oc, + width=w, top=True) + elif ttype == "image": + screen._drawimage(titem, self._position, tshape) + elif ttype == "compound": + lx, ly = self._stretchfactor + w = self._outlinewidth + for item, (poly, fc, oc) in zip(titem, tshape): + poly = [(lx*x, ly*y) for (x, y) in poly] + poly = self._polytrafo(poly) + screen._drawpoly(item, poly, fill=self._cc(fc), + outline=self._cc(oc), width=w, top=True) + else: + if self._hidden_from_screen: + return + if ttype == "polygon": + screen._drawpoly(titem, ((0, 0), (0, 0), (0, 0)), "", "") + elif ttype == "image": + screen._drawimage(titem, self._position, + screen._shapes["blank"]._data) + elif ttype == "compound": + for item in titem: + screen._drawpoly(item, ((0, 0), (0, 0), (0, 0)), "", "") + self._hidden_from_screen = True + +############################## stamp stuff ############################### + + def stamp(self): + """Stamp a copy of the turtleshape onto the canvas and return its id. + + No argument. + + Stamp a copy of the turtle shape onto the canvas at the current + turtle position. Return a stamp_id for that stamp, which can be + used to delete it by calling clearstamp(stamp_id). + + Example (for a Turtle instance named turtle): + >>> turtle.color("blue") + >>> turtle.stamp() + 13 + >>> turtle.fd(50) + """ + screen = self.screen + shape = screen._shapes[self.turtle.shapeIndex] + ttype = shape._type + tshape = shape._data + if ttype == "polygon": + stitem = screen._createpoly() + if self._resizemode == "noresize": + w = 1 + shape = tshape + else: + if self._resizemode == "auto": + lx = ly = max(1, self._pensize/5.0) + w = self._pensize + tiltangle = 0 + elif self._resizemode == "user": + lx, ly = self._stretchfactor + w = self._outlinewidth + tiltangle = self._tilt + shape = [(lx*x, ly*y) for (x, y) in tshape] + t0, t1 = math.sin(tiltangle), math.cos(tiltangle) + shape = [(t1*x+t0*y, -t0*x+t1*y) for (x, y) in shape] + shape = self._polytrafo(shape) + fc, oc = self._fillcolor, self._pencolor + screen._drawpoly(stitem, shape, fill=fc, outline=oc, + width=w, top=True) + elif ttype == "image": + stitem = screen._createimage("") + screen._drawimage(stitem, self._position, tshape) + elif ttype == "compound": + stitem = [] + for element in tshape: + item = screen._createpoly() + stitem.append(item) + stitem = tuple(stitem) + lx, ly = self._stretchfactor + w = self._outlinewidth + for item, (poly, fc, oc) in zip(stitem, tshape): + poly = [(lx*x, ly*y) for (x, y) in poly] + poly = self._polytrafo(poly) + screen._drawpoly(item, poly, fill=self._cc(fc), + outline=self._cc(oc), width=w, top=True) + self.stampItems.append(stitem) + self.undobuffer.push(("stamp", stitem)) + return stitem + + def _clearstamp(self, stampid): + """does the work for clearstamp() and clearstamps() + """ + if stampid in self.stampItems: + if isinstance(stampid, tuple): + for subitem in stampid: + self.screen._delete(subitem) + else: + self.screen._delete(stampid) + self.stampItems.remove(stampid) + # Delete stampitem from undobuffer if necessary + # if clearstamp is called directly. + item = ("stamp", stampid) + buf = self.undobuffer + if item not in buf.buffer: + return + index = buf.buffer.index(item) + buf.buffer.remove(item) + if index <= buf.ptr: + buf.ptr = (buf.ptr - 1) % buf.bufsize + buf.buffer.insert((buf.ptr+1)%buf.bufsize, [None]) + + def clearstamp(self, stampid): + """Delete stamp with given stampid + + Argument: + stampid - an integer, must be return value of previous stamp() call. + + Example (for a Turtle instance named turtle): + >>> turtle.color("blue") + >>> astamp = turtle.stamp() + >>> turtle.fd(50) + >>> turtle.clearstamp(astamp) + """ + self._clearstamp(stampid) + self._update() + + def clearstamps(self, n=None): + """Delete all or first/last n of turtle's stamps. + + Optional argument: + n -- an integer + + If n is None, delete all of pen's stamps, + else if n > 0 delete first n stamps + else if n < 0 delete last n stamps. + + Example (for a Turtle instance named turtle): + >>> for i in range(8): + ... turtle.stamp(); turtle.fd(30) + ... + >>> turtle.clearstamps(2) + >>> turtle.clearstamps(-2) + >>> turtle.clearstamps() + """ + if n is None: + toDelete = self.stampItems[:] + elif n >= 0: + toDelete = self.stampItems[:n] + else: + toDelete = self.stampItems[n:] + for item in toDelete: + self._clearstamp(item) + self._update() + + def _goto(self, end): + """Move the pen to the point end, thereby drawing a line + if pen is down. All other methods for turtle movement depend + on this one. + """ + ## Version mit undo-stuff + go_modes = ( self._drawing, + self._pencolor, + self._pensize, + isinstance(self._fillpath, list)) + screen = self.screen + undo_entry = ("go", self._position, end, go_modes, + (self.currentLineItem, + self.currentLine[:], + screen._pointlist(self.currentLineItem), + self.items[:]) + ) + if self.undobuffer: + self.undobuffer.push(undo_entry) + start = self._position + if self._speed and screen._tracing == 1: + diff = (end-start) + diffsq = (diff[0]*screen.xscale)**2 + (diff[1]*screen.yscale)**2 + nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)*self._speed)) + delta = diff * (1.0/nhops) + for n in range(1, nhops): + if n == 1: + top = True + else: + top = False + self._position = start + delta * n + if self._drawing: + screen._drawline(self.drawingLineItem, + (start, self._position), + self._pencolor, self._pensize, top) + self._update() + if self._drawing: + screen._drawline(self.drawingLineItem, ((0, 0), (0, 0)), + fill="", width=self._pensize) + # Turtle now at end, + if self._drawing: # now update currentLine + self.currentLine.append(end) + if isinstance(self._fillpath, list): + self._fillpath.append(end) + ###### vererbung!!!!!!!!!!!!!!!!!!!!!! + self._position = end + if self._creatingPoly: + self._poly.append(end) + if len(self.currentLine) > 42: # 42! answer to the ultimate question + # of life, the universe and everything + self._newLine() + self._update() #count=True) + + def _undogoto(self, entry): + """Reverse a _goto. Used for undo() + """ + old, new, go_modes, coodata = entry + drawing, pc, ps, filling = go_modes + cLI, cL, pl, items = coodata + screen = self.screen + if abs(self._position - new) > 0.5: + print "undogoto: HALLO-DA-STIMMT-WAS-NICHT!" + # restore former situation + self.currentLineItem = cLI + self.currentLine = cL + + if pl == [(0, 0), (0, 0)]: + usepc = "" + else: + usepc = pc + screen._drawline(cLI, pl, fill=usepc, width=ps) + + todelete = [i for i in self.items if (i not in items) and + (screen._type(i) == "line")] + for i in todelete: + screen._delete(i) + self.items.remove(i) + + start = old + if self._speed and screen._tracing == 1: + diff = old - new + diffsq = (diff[0]*screen.xscale)**2 + (diff[1]*screen.yscale)**2 + nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)*self._speed)) + delta = diff * (1.0/nhops) + for n in range(1, nhops): + if n == 1: + top = True + else: + top = False + self._position = new + delta * n + if drawing: + screen._drawline(self.drawingLineItem, + (start, self._position), + pc, ps, top) + self._update() + if drawing: + screen._drawline(self.drawingLineItem, ((0, 0), (0, 0)), + fill="", width=ps) + # Turtle now at position old, + self._position = old + ## if undo is done during creating a polygon, the last vertex + ## will be deleted. if the polygon is entirely deleted, + ## creatingPoly will be set to False. + ## Polygons created before the last one will not be affected by undo() + if self._creatingPoly: + if len(self._poly) > 0: + self._poly.pop() + if self._poly == []: + self._creatingPoly = False + self._poly = None + if filling: + if self._fillpath == []: + self._fillpath = None + print "Unwahrscheinlich in _undogoto!" + elif self._fillpath is not None: + self._fillpath.pop() + self._update() #count=True) + + def _rotate(self, angle): + """Turns pen clockwise by angle. + """ + if self.undobuffer: + self.undobuffer.push(("rot", angle, self._degreesPerAU)) + angle *= self._degreesPerAU + neworient = self._orient.rotate(angle) + tracing = self.screen._tracing + if tracing == 1 and self._speed > 0: + anglevel = 3.0 * self._speed + steps = 1 + int(abs(angle)/anglevel) + delta = 1.0*angle/steps + for _ in range(steps): + self._orient = self._orient.rotate(delta) + self._update() + self._orient = neworient + self._update() + + def _newLine(self, usePos=True): + """Closes current line item and starts a new one. + Remark: if current line became too long, animation + performance (via _drawline) slowed down considerably. + """ + if len(self.currentLine) > 1: + self.screen._drawline(self.currentLineItem, self.currentLine, + self._pencolor, self._pensize) + self.currentLineItem = self.screen._createline() + self.items.append(self.currentLineItem) + else: + self.screen._drawline(self.currentLineItem, top=True) + self.currentLine = [] + if usePos: + self.currentLine = [self._position] + + def fill(self, flag=None): + """Call fill(True) before drawing a shape to fill, fill(False) when done. + + Optional argument: + flag -- True/False (or 1/0 respectively) + + Call fill(True) before drawing the shape you want to fill, + and fill(False) when done. + When used without argument: return fillstate (True if filling, + False else) + + Example (for a Turtle instance named turtle): + >>> turtle.fill(True) + >>> turtle.forward(100) + >>> turtle.left(90) + >>> turtle.forward(100) + >>> turtle.left(90) + >>> turtle.forward(100) + >>> turtle.left(90) + >>> turtle.forward(100) + >>> turtle.fill(False) + """ + filling = isinstance(self._fillpath, list) + if flag is None: + return filling + screen = self.screen + entry1 = entry2 = () + if filling: + if len(self._fillpath) > 2: + self.screen._drawpoly(self._fillitem, self._fillpath, + fill=self._fillcolor) + entry1 = ("dofill", self._fillitem) + if flag: + self._fillitem = self.screen._createpoly() + self.items.append(self._fillitem) + self._fillpath = [self._position] + entry2 = ("beginfill", self._fillitem) # , self._fillpath) + self._newLine() + else: + self._fillitem = self._fillpath = None + if self.undobuffer: + if entry1 == (): + if entry2 != (): + self.undobuffer.push(entry2) + else: + if entry2 == (): + self.undobuffer.push(entry1) + else: + self.undobuffer.push(["seq", entry1, entry2]) + self._update() + + def begin_fill(self): + """Called just before drawing a shape to be filled. + + No argument. + + Example (for a Turtle instance named turtle): + >>> turtle.begin_fill() + >>> turtle.forward(100) + >>> turtle.left(90) + >>> turtle.forward(100) + >>> turtle.left(90) + >>> turtle.forward(100) + >>> turtle.left(90) + >>> turtle.forward(100) + >>> turtle.end_fill() + """ + self.fill(True) + + def end_fill(self): + """Fill the shape drawn after the call begin_fill(). + + No argument. + + Example (for a Turtle instance named turtle): + >>> turtle.begin_fill() + >>> turtle.forward(100) + >>> turtle.left(90) + >>> turtle.forward(100) + >>> turtle.left(90) + >>> turtle.forward(100) + >>> turtle.left(90) + >>> turtle.forward(100) + >>> turtle.end_fill() + """ + self.fill(False) + + def dot(self, size=None, *color): + """Draw a dot with diameter size, using color. + + Optional arguments: + size -- an integer >= 1 (if given) + color -- a colorstring or a numeric color tuple + + Draw a circular dot with diameter size, using color. + If size is not given, the maximum of pensize+4 and 2*pensize is used. + + Example (for a Turtle instance named turtle): + >>> turtle.dot() + >>> turtle.fd(50); turtle.dot(20, "blue"); turtle.fd(50) + """ + #print "dot-1:", size, color + if not color: + if isinstance(size, (basestring, tuple)): + color = self._colorstr(size) + size = self._pensize + max(self._pensize, 4) + else: + color = self._pencolor + if not size: + size = self._pensize + max(self._pensize, 4) + else: + if size is None: + size = self._pensize + max(self._pensize, 4) + color = self._colorstr(color) + #print "dot-2:", size, color + if hasattr(self.screen, "_dot"): + item = self.screen._dot(self._position, size, color) + #print "dot:", size, color, "item:", item + self.items.append(item) + if self.undobuffer: + self.undobuffer.push(("dot", item)) + else: + pen = self.pen() + if self.undobuffer: + self.undobuffer.push(["seq"]) + self.undobuffer.cumulate = True + try: + if self.resizemode() == 'auto': + self.ht() + self.pendown() + self.pensize(size) + self.pencolor(color) + self.forward(0) + finally: + self.pen(pen) + if self.undobuffer: + self.undobuffer.cumulate = False + + def _write(self, txt, align, font): + """Performs the writing for write() + """ + item, end = self.screen._write(self._position, txt, align, font, + self._pencolor) + self.items.append(item) + if self.undobuffer: + self.undobuffer.push(("wri", item)) + return end + + def write(self, arg, move=False, align="left", font=("Arial", 8, "normal")): + """Write text at the current turtle position. + + Arguments: + arg -- info, which is to be written to the TurtleScreen + move (optional) -- True/False + align (optional) -- one of the strings "left", "center" or right" + font (optional) -- 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 font. + If move is True, the pen is moved to the bottom-right corner + of the text. By default, move is False. + + Example (for a Turtle instance named turtle): + >>> turtle.write('Home = ', True, align="center") + >>> turtle.write((0,0), True) + """ + if self.undobuffer: + self.undobuffer.push(["seq"]) + self.undobuffer.cumulate = True + end = self._write(str(arg), align.lower(), font) + if move: + x, y = self.pos() + self.setpos(end, y) + if self.undobuffer: + self.undobuffer.cumulate = False + + def begin_poly(self): + """Start recording the vertices of a polygon. + + No argument. + + Start recording the vertices of a polygon. Current turtle position + is first point of polygon. + + Example (for a Turtle instance named turtle): + >>> turtle.begin_poly() + """ + self._poly = [self._position] + self._creatingPoly = True + + def end_poly(self): + """Stop recording the vertices of a polygon. + + No argument. + + Stop recording the vertices of a polygon. Current turtle position is + last point of polygon. This will be connected with the first point. + + Example (for a Turtle instance named turtle): + >>> turtle.end_poly() + """ + self._creatingPoly = False + + def get_poly(self): + """Return the lastly recorded polygon. + + No argument. + + Example (for a Turtle instance named turtle): + >>> p = turtle.get_poly() + >>> turtle.register_shape("myFavouriteShape", p) + """ + ## check if there is any poly? -- 1st solution: + if self._poly is not None: + return tuple(self._poly) + + def getscreen(self): + """Return the TurtleScreen object, the turtle is drawing on. + + No argument. + + Return the TurtleScreen object, the turtle is drawing on. + So TurtleScreen-methods can be called for that object. + + Example (for a Turtle instance named turtle): + >>> ts = turtle.getscreen() + >>> ts + + >>> ts.bgcolor("pink") + """ + return self.screen + + def getturtle(self): + """Return the Turtleobject itself. + + No argument. + + Only reasonable use: as a function to return the 'anonymous turtle': + + Example: + >>> pet = getturtle() + >>> pet.fd(50) + >>> pet + + >>> turtles() + [] + """ + return self + + getpen = getturtle + + + ################################################################ + ### screen oriented methods recurring to methods of TurtleScreen + ################################################################ + + def window_width(self): + """ Returns the width of the turtle window. + + No argument. + + Example (for a TurtleScreen instance named screen): + >>> screen.window_width() + 640 + """ + return self.screen._window_size()[0] + + def window_height(self): + """ Return the height of the turtle window. + + No argument. + + Example (for a TurtleScreen instance named screen): + >>> screen.window_height() + 480 + """ + return self.screen._window_size()[1] + + def _delay(self, delay=None): + """Set delay value which determines speed of turtle animation. + """ + return self.screen.delay(delay) + + ##### event binding methods ##### + + def onclick(self, fun, btn=1, add=None): + """Bind fun to mouse-click event on this turtle on canvas. + + Arguments: + fun -- a function with two arguments, to which will be assigned + the coordinates of the clicked point on the canvas. + num -- number of the mouse-button defaults to 1 (left mouse button). + add -- True or False. If True, new binding will be added, otherwise + it will replace a former binding. + + Example for the anonymous turtle, i. e. the procedural way: + + >>> def turn(x, y): + ... left(360) + ... + >>> onclick(turn) # Now clicking into the turtle will turn it. + >>> onclick(None) # event-binding will be removed + """ + self.screen._onclick(self.turtle._item, fun, btn, add) + self._update() + + def onrelease(self, fun, btn=1, add=None): + """Bind fun to mouse-button-release event on this turtle on canvas. + + Arguments: + fun -- a function with two arguments, to which will be assigned + the coordinates of the clicked point on the canvas. + num -- number of the mouse-button defaults to 1 (left mouse button). + + Example (for a MyTurtle instance named joe): + >>> class MyTurtle(Turtle): + ... def glow(self,x,y): + ... self.fillcolor("red") + ... def unglow(self,x,y): + ... self.fillcolor("") + ... + >>> joe = MyTurtle() + >>> joe.onclick(joe.glow) + >>> joe.onrelease(joe.unglow) + + Clicking on joe turns fillcolor red, unclicking turns it to + transparent. + """ + self.screen._onrelease(self.turtle._item, fun, btn, add) + self._update() + + def ondrag(self, fun, btn=1, add=None): + """Bind fun to mouse-move event on this turtle on canvas. + + Arguments: + fun -- a function with two arguments, to which will be assigned + the coordinates of the clicked point on the canvas. + num -- number of the mouse-button defaults to 1 (left mouse button). + + Every sequence of mouse-move-events on a turtle is preceded by a + mouse-click event on that turtle. + + Example (for a Turtle instance named turtle): + >>> turtle.ondrag(turtle.goto) + + Subsequently clicking and dragging a Turtle will move it + across the screen thereby producing handdrawings (if pen is + down). + """ + self.screen._ondrag(self.turtle._item, fun, btn, add) + + + def _undo(self, action, data): + """Does the main part of the work for undo() + """ + if self.undobuffer is None: + return + if action == "rot": + angle, degPAU = data + self._rotate(-angle*degPAU/self._degreesPerAU) + dummy = self.undobuffer.pop() + elif action == "stamp": + stitem = data[0] + self.clearstamp(stitem) + elif action == "go": + self._undogoto(data) + elif action in ["wri", "dot"]: + item = data[0] + self.screen._delete(item) + self.items.remove(item) + elif action == "dofill": + item = data[0] + self.screen._drawpoly(item, ((0, 0),(0, 0),(0, 0)), + fill="", outline="") + elif action == "beginfill": + item = data[0] + self._fillitem = self._fillpath = None + self.screen._delete(item) + self.items.remove(item) + elif action == "pen": + TPen.pen(self, data[0]) + self.undobuffer.pop() + + def undo(self): + """undo (repeatedly) the last turtle action. + + No argument. + + undo (repeatedly) the last turtle action. + Number of available undo actions is determined by the size of + the undobuffer. + + Example (for a Turtle instance named turtle): + >>> for i in range(4): + ... turtle.fd(50); turtle.lt(80) + ... + >>> for i in range(8): + ... turtle.undo() + ... + """ + if self.undobuffer is None: + return + item = self.undobuffer.pop() + action = item[0] + data = item[1:] + if action == "seq": + while data: + item = data.pop() + self._undo(item[0], item[1:]) + else: + self._undo(action, data) + + turtlesize = shapesize + +RawPen = RawTurtle + +### Screen - Singleton ######################## + +def Screen(): + """Return the singleton screen object. + If none exists at the moment, create a new one and return it, + else return the existing one.""" + if Turtle._screen is None: + Turtle._screen = _Screen() + return Turtle._screen + +class _Screen(TurtleScreen): + + _root = None + _canvas = None + _title = _CFG["title"] + + def __init__(self): + # XXX there is no need for this code to be conditional, + # as there will be only a single _Screen instance, anyway + # XXX actually, the turtle demo is injecting root window, + # so perhaps the conditional creation of a root should be + # preserved (perhaps by passing it as an optional parameter) + if _Screen._root is None: + _Screen._root = self._root = _Root() + self._root.title(_Screen._title) + self._root.ondestroy(self._destroy) + if _Screen._canvas is None: + width = _CFG["width"] + height = _CFG["height"] + canvwidth = _CFG["canvwidth"] + canvheight = _CFG["canvheight"] + leftright = _CFG["leftright"] + topbottom = _CFG["topbottom"] + self._root.setupcanvas(width, height, canvwidth, canvheight) + _Screen._canvas = self._root._getcanvas() + TurtleScreen.__init__(self, _Screen._canvas) + self.setup(width, height, leftright, topbottom) + + def setup(self, width=_CFG["width"], height=_CFG["height"], + startx=_CFG["leftright"], starty=_CFG["topbottom"]): + """ Set the size and position of the main window. + + Arguments: + width: as integer a size in pixels, as float a fraction of the screen. + Default is 50% of screen. + height: as integer the height in pixels, as float a fraction of the + screen. Default is 75% of screen. + startx: if positive, starting position in pixels from the left + edge of the screen, if negative from the right edge + Default, startx=None is to center window horizontally. + starty: if positive, starting position in pixels from the top + edge of the screen, if negative from the bottom edge + Default, starty=None is to center window vertically. + + Examples (for a Screen instance named screen): + >>> screen.setup (width=200, height=200, startx=0, starty=0) + + sets window to 200x200 pixels, in upper left of screen + + >>> screen.setup(width=.75, height=0.5, startx=None, starty=None) + + sets window to 75% of screen by 50% of screen and centers + """ + if not hasattr(self._root, "set_geometry"): + return + sw = self._root.win_width() + sh = self._root.win_height() + if isinstance(width, float) and 0 <= width <= 1: + width = sw*width + if startx is None: + startx = (sw - width) / 2 + if isinstance(height, float) and 0 <= height <= 1: + height = sh*height + if starty is None: + starty = (sh - height) / 2 + self._root.set_geometry(width, height, startx, starty) + self.update() + + def title(self, titlestring): + """Set title of turtle-window + + Argument: + titlestring -- a string, to appear in the titlebar of the + turtle graphics window. + + This is a method of Screen-class. Not available for TurtleScreen- + objects. + + Example (for a Screen instance named screen): + >>> screen.title("Welcome to the turtle-zoo!") + """ + if _Screen._root is not None: + _Screen._root.title(titlestring) + _Screen._title = titlestring + + def _destroy(self): + root = self._root + if root is _Screen._root: + Turtle._pen = None + Turtle._screen = None + _Screen._root = None + _Screen._canvas = None + TurtleScreen._RUNNING = True + root.destroy() + + def bye(self): + """Shut the turtlegraphics window. + + Example (for a TurtleScreen instance named screen): + >>> screen.bye() + """ + self._destroy() + + def exitonclick(self): + """Go into mainloop until the mouse is clicked. + + No arguments. + + Bind bye() method to mouseclick on TurtleScreen. + If "using_IDLE" - value in configuration dictionary is False + (default value), enter mainloop. + If IDLE with -n switch (no subprocess) is used, this value should be + set to True in turtle.cfg. In this case IDLE's mainloop + is active also for the client script. + + This is a method of the Screen-class and not available for + TurtleScreen instances. + + Example (for a Screen instance named screen): + >>> screen.exitonclick() + + """ + def exitGracefully(x, y): + """Screen.bye() with two dummy-parameters""" + self.bye() + self.onclick(exitGracefully) + if _CFG["using_IDLE"]: + return + try: + mainloop() + except AttributeError: + exit(0) + + +class Turtle(RawTurtle): + """RawTurtle auto-creating (scrolled) canvas. + + When a Turtle object is created or a function derived from some + Turtle method is called a TurtleScreen object is automatically created. + """ + _pen = None + _screen = None + + def __init__(self, + shape=_CFG["shape"], + undobuffersize=_CFG["undobuffersize"], + visible=_CFG["visible"]): + if Turtle._screen is None: + Turtle._screen = Screen() + RawTurtle.__init__(self, Turtle._screen, + shape=shape, + undobuffersize=undobuffersize, + visible=visible) + +Pen = Turtle + +def _getpen(): + """Create the 'anonymous' turtle if not already present.""" + if Turtle._pen is None: + Turtle._pen = Turtle() + return Turtle._pen + +def _getscreen(): + """Create a TurtleScreen if not already present.""" + if Turtle._screen is None: + Turtle._screen = Screen() + return Turtle._screen + +def write_docstringdict(filename="turtle_docstringdict"): + """Create and write docstring-dictionary to file. + + Optional argument: + filename -- a string, used as filename + default value is turtle_docstringdict + + Has to be called explicitly, (not used by the turtle-graphics classes) + The docstring dictionary will be written to the Python script .py + It is intended to serve as a template for translation of the docstrings + into different languages. + """ + docsdict = {} + + for methodname in _tg_screen_functions: + key = "_Screen."+methodname + docsdict[key] = eval(key).__doc__ + for methodname in _tg_turtle_functions: + key = "Turtle."+methodname + docsdict[key] = eval(key).__doc__ + + f = open("%s.py" % filename,"w") + keys = sorted([x for x in docsdict.keys() + if x.split('.')[1] not in _alias_list]) + f.write('docsdict = {\n\n') + for key in keys[:-1]: + f.write('%s :\n' % repr(key)) + f.write(' """%s\n""",\n\n' % docsdict[key]) + key = keys[-1] + f.write('%s :\n' % repr(key)) + f.write(' """%s\n"""\n\n' % docsdict[key]) + f.write("}\n") + f.close() + +def read_docstrings(lang): + """Read in docstrings from lang-specific docstring dictionary. + + Transfer docstrings, translated to lang, from a dictionary-file + to the methods of classes Screen and Turtle and - in revised form - + to the corresponding functions. + """ + modname = "turtle_docstringdict_%(language)s" % {'language':lang.lower()} + module = __import__(modname) + docsdict = module.docsdict + for key in docsdict: + #print key + try: + eval(key).im_func.__doc__ = docsdict[key] + except: + print "Bad docstring-entry: %s" % key + +_LANGUAGE = _CFG["language"] + +try: + if _LANGUAGE != "english": + read_docstrings(_LANGUAGE) +except ImportError: + print "Cannot find docsdict for", _LANGUAGE +except: + print ("Unknown Error when trying to import %s-docstring-dictionary" % + _LANGUAGE) + + +def getmethparlist(ob): + "Get strings describing the arguments for the given object" + argText1 = argText2 = "" + # bit of a hack for methods - turn it into a function + # but we drop the "self" param. + if type(ob)==types.MethodType: + fob = ob.im_func + argOffset = 1 + else: + fob = ob + argOffset = 0 + # Try and build one for Python defined functions + if type(fob) in [types.FunctionType, types.LambdaType]: + try: + counter = fob.func_code.co_argcount + items2 = list(fob.func_code.co_varnames[argOffset:counter]) + realArgs = fob.func_code.co_varnames[argOffset:counter] + defaults = fob.func_defaults or [] + defaults = list(map(lambda name: "=%s" % repr(name), defaults)) + defaults = [""] * (len(realArgs)-len(defaults)) + defaults + items1 = map(lambda arg, dflt: arg+dflt, realArgs, defaults) + if fob.func_code.co_flags & 0x4: + items1.append("*"+fob.func_code.co_varnames[counter]) + items2.append("*"+fob.func_code.co_varnames[counter]) + counter += 1 + if fob.func_code.co_flags & 0x8: + items1.append("**"+fob.func_code.co_varnames[counter]) + items2.append("**"+fob.func_code.co_varnames[counter]) + argText1 = ", ".join(items1) + argText1 = "(%s)" % argText1 + argText2 = ", ".join(items2) + argText2 = "(%s)" % argText2 + except: + pass + return argText1, argText2 + +def _turtle_docrevise(docstr): + """To reduce docstrings from RawTurtle class for functions + """ + import re + if docstr is None: + return None + turtlename = _CFG["exampleturtle"] + newdocstr = docstr.replace("%s." % turtlename,"") + parexp = re.compile(r' \(.+ %s\):' % turtlename) + newdocstr = parexp.sub(":", newdocstr) + return newdocstr + +def _screen_docrevise(docstr): + """To reduce docstrings from TurtleScreen class for functions + """ + import re + if docstr is None: + return None + screenname = _CFG["examplescreen"] + newdocstr = docstr.replace("%s." % screenname,"") + parexp = re.compile(r' \(.+ %s\):' % screenname) + newdocstr = parexp.sub(":", newdocstr) + return newdocstr + +## The following mechanism makes all methods of RawTurtle and Turtle available +## as functions. So we can enhance, change, add, delete methods to these +## classes and do not need to change anything here. + + +for methodname in _tg_screen_functions: + pl1, pl2 = getmethparlist(eval('_Screen.' + methodname)) + if pl1 == "": + print ">>>>>>", pl1, pl2 + continue + defstr = ("def %(key)s%(pl1)s: return _getscreen().%(key)s%(pl2)s" % + {'key':methodname, 'pl1':pl1, 'pl2':pl2}) + exec defstr + eval(methodname).__doc__ = _screen_docrevise(eval('_Screen.'+methodname).__doc__) + +for methodname in _tg_turtle_functions: + pl1, pl2 = getmethparlist(eval('Turtle.' + methodname)) + if pl1 == "": + print ">>>>>>", pl1, pl2 + continue + defstr = ("def %(key)s%(pl1)s: return _getpen().%(key)s%(pl2)s" % + {'key':methodname, 'pl1':pl1, 'pl2':pl2}) + exec defstr + eval(methodname).__doc__ = _turtle_docrevise(eval('Turtle.'+methodname).__doc__) + + +done = mainloop = TK.mainloop +del pl1, pl2, defstr + +if __name__ == "__main__": + def switchpen(): + if isdown(): + pu() + else: + pd() + + def demo1(): + """Demo of old turtle.py - module""" + reset() + tracer(True) + up() + backward(100) + down() + # draw 3 squares; the last filled + width(3) + for i in range(3): + if i == 2: + fill(1) + for _ in range(4): + forward(20) + left(90) + if i == 2: + color("maroon") + fill(0) + up() + forward(30) + down() + width(1) + color("black") + # move out of the way + tracer(False) + up() + right(90) + forward(100) + right(90) + forward(100) + right(180) + down() + # some text + write("startstart", 1) + write(u"start", 1) + color("red") + # staircase + for i in range(5): + forward(20) + left(90) + forward(20) + right(90) + # filled staircase + tracer(True) + fill(1) + for i in range(5): + forward(20) + left(90) + forward(20) + right(90) + fill(0) + # more text + + def demo2(): + """Demo of some new features.""" + speed(1) + st() + pensize(3) + setheading(towards(0, 0)) + radius = distance(0, 0)/2.0 + rt(90) + for _ in range(18): + switchpen() + circle(radius, 10) + write("wait a moment...") + while undobufferentries(): + undo() + reset() + lt(90) + colormode(255) + laenge = 10 + pencolor("green") + pensize(3) + lt(180) + for i in range(-2, 16): + if i > 0: + begin_fill() + fillcolor(255-15*i, 0, 15*i) + for _ in range(3): + fd(laenge) + lt(120) + laenge += 10 + lt(15) + speed((speed()+1)%12) + end_fill() + + lt(120) + pu() + fd(70) + rt(30) + pd() + color("red","yellow") + speed(0) + fill(1) + for _ in range(4): + circle(50, 90) + rt(90) + fd(30) + rt(90) + fill(0) + lt(90) + pu() + fd(30) + pd() + shape("turtle") + + tri = getturtle() + tri.resizemode("auto") + turtle = Turtle() + turtle.resizemode(u"auto") + turtle.shape("turtle") + turtle.reset() + turtle.left(90) + turtle.speed(0) + turtle.up() + turtle.goto(280, 40) + turtle.lt(30) + turtle.down() + turtle.speed(6) + turtle.color("blue",u"orange") + turtle.pensize(2) + tri.speed(6) + setheading(towards(turtle)) + count = 1 + while tri.distance(turtle) > 4: + turtle.fd(3.5) + turtle.lt(0.6) + tri.setheading(tri.towards(turtle)) + tri.fd(4) + if count % 20 == 0: + turtle.stamp() + tri.stamp() + switchpen() + count += 1 + tri.write("CAUGHT! ", font=("Arial", 16, "bold"), align=u"right") + tri.pencolor("black") + tri.pencolor(u"red") + + def baba(xdummy, ydummy): + clearscreen() + bye() + + time.sleep(2) + + while undobufferentries(): + tri.undo() + turtle.undo() + tri.fd(50) + tri.write(" Click me!", font = ("Courier", 12, "bold") ) + tri.onclick(baba, 1) + + demo1() + demo2() + exitonclick() diff --git a/PythonHome/Lib/lib-tk/turtle.pyc b/PythonHome/Lib/lib-tk/turtle.pyc deleted file mode 100644 index ae500be82ba5ad3d37949e229e98e6bf0d6ab714..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 135965 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 Sr|Y&e4{tZ(N#Z%jMf3%sbt;zt diff --git a/PythonHome/Lib/lib2to3/btm_matcher.py b/PythonHome/Lib/lib2to3/btm_matcher.py new file mode 100644 index 0000000000..736ba2b9d8 --- /dev/null +++ b/PythonHome/Lib/lib2to3/btm_matcher.py @@ -0,0 +1,168 @@ +"""A bottom-up tree matching algorithm implementation meant to speed +up 2to3's matching process. After the tree patterns are reduced to +their rarest linear path, a linear Aho-Corasick automaton is +created. The linear automaton traverses the linear paths from the +leaves to the root of the AST and returns a set of nodes for further +matching. This reduces significantly the number of candidate nodes.""" + +__author__ = "George Boutsioukis " + +import logging +import itertools +from collections import defaultdict + +from . import pytree +from .btm_utils import reduce_tree + +class BMNode(object): + """Class for a node of the Aho-Corasick automaton used in matching""" + count = itertools.count() + def __init__(self): + self.transition_table = {} + self.fixers = [] + self.id = next(BMNode.count) + self.content = '' + +class BottomMatcher(object): + """The main matcher class. After instantiating the patterns should + be added using the add_fixer method""" + + def __init__(self): + self.match = set() + self.root = BMNode() + self.nodes = [self.root] + self.fixers = [] + self.logger = logging.getLogger("RefactoringTool") + + def add_fixer(self, fixer): + """Reduces a fixer's pattern tree to a linear path and adds it + to the matcher(a common Aho-Corasick automaton). The fixer is + appended on the matching states and called when they are + reached""" + self.fixers.append(fixer) + tree = reduce_tree(fixer.pattern_tree) + linear = tree.get_linear_subpattern() + match_nodes = self.add(linear, start=self.root) + for match_node in match_nodes: + match_node.fixers.append(fixer) + + def add(self, pattern, start): + "Recursively adds a linear pattern to the AC automaton" + #print("adding pattern", pattern, "to", start) + if not pattern: + #print("empty pattern") + return [start] + if isinstance(pattern[0], tuple): + #alternatives + #print("alternatives") + match_nodes = [] + for alternative in pattern[0]: + #add all alternatives, and add the rest of the pattern + #to each end node + end_nodes = self.add(alternative, start=start) + for end in end_nodes: + match_nodes.extend(self.add(pattern[1:], end)) + return match_nodes + else: + #single token + #not last + if pattern[0] not in start.transition_table: + #transition did not exist, create new + next_node = BMNode() + start.transition_table[pattern[0]] = next_node + else: + #transition exists already, follow + next_node = start.transition_table[pattern[0]] + + if pattern[1:]: + end_nodes = self.add(pattern[1:], start=next_node) + else: + end_nodes = [next_node] + return end_nodes + + def run(self, leaves): + """The main interface with the bottom matcher. The tree is + traversed from the bottom using the constructed + automaton. Nodes are only checked once as the tree is + retraversed. When the automaton fails, we give it one more + shot(in case the above tree matches as a whole with the + rejected leaf), then we break for the next leaf. There is the + special case of multiple arguments(see code comments) where we + recheck the nodes + + Args: + The leaves of the AST tree to be matched + + Returns: + A dictionary of node matches with fixers as the keys + """ + current_ac_node = self.root + results = defaultdict(list) + for leaf in leaves: + current_ast_node = leaf + while current_ast_node: + current_ast_node.was_checked = True + for child in current_ast_node.children: + # multiple statements, recheck + if isinstance(child, pytree.Leaf) and child.value == u";": + current_ast_node.was_checked = False + break + if current_ast_node.type == 1: + #name + node_token = current_ast_node.value + else: + node_token = current_ast_node.type + + if node_token in current_ac_node.transition_table: + #token matches + current_ac_node = current_ac_node.transition_table[node_token] + for fixer in current_ac_node.fixers: + if not fixer in results: + results[fixer] = [] + results[fixer].append(current_ast_node) + + else: + #matching failed, reset automaton + current_ac_node = self.root + if (current_ast_node.parent is not None + and current_ast_node.parent.was_checked): + #the rest of the tree upwards has been checked, next leaf + break + + #recheck the rejected node once from the root + if node_token in current_ac_node.transition_table: + #token matches + current_ac_node = current_ac_node.transition_table[node_token] + for fixer in current_ac_node.fixers: + if not fixer in results.keys(): + results[fixer] = [] + results[fixer].append(current_ast_node) + + current_ast_node = current_ast_node.parent + return results + + def print_ac(self): + "Prints a graphviz diagram of the BM automaton(for debugging)" + print("digraph g{") + def print_node(node): + for subnode_key in node.transition_table.keys(): + subnode = node.transition_table[subnode_key] + print("%d -> %d [label=%s] //%s" % + (node.id, subnode.id, type_repr(subnode_key), str(subnode.fixers))) + if subnode_key == 1: + print(subnode.content) + print_node(subnode) + print_node(self.root) + print("}") + +# taken from pytree.py for debugging; only used by print_ac +_type_reprs = {} +def type_repr(type_num): + global _type_reprs + if not _type_reprs: + from .pygram import python_symbols + # printing tokens is possible but not as useful + # from .pgen2 import token // token.__dict__.items(): + for name, val in python_symbols.__dict__.items(): + if type(val) == int: _type_reprs[val] = name + return _type_reprs.setdefault(type_num, type_num) diff --git a/PythonHome/Lib/lib2to3/btm_matcher.pyc b/PythonHome/Lib/lib2to3/btm_matcher.pyc deleted file mode 100644 index 9e2b89b487a137fdbbba1c9d5583ec51dc745fe4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5665 zcmb7IU2_~q744b*kXDvr*>Q{wt}rAxS>r?@5TJ@Uj%A71fkc%WnGy(_VRoi>ccj^w z^>mLdf%O39BNRMP1ywvz#c$w=UqBVF{0AO*=8Y-}&bd9>m5Wpv%RBAvp8mMq_uO;u zoz_2Bmj1l+gY85$e=Yof1CRMFid3mxl%Cr4RO+j=rE*{GqT=c;wcC<8Ra~ z^3sk%pM3ww%0PPXk+N9ZX`IjI&}C#QCVKGCQ6G*<_mQi7sqx zv$6;#IxcKr%fL*vPM0w8OSb&-t7blRT9t`5W-VABT3rQptliqv*rHvSAg**!>9kIC ziiMUiAgh83y~YN4R_M42Fn0V}5Fa$CtB6nc4ye!HT zGlpdq4C@MOR7=PAMmaLmoX!L$8x`3wOK@fRp{!ZdlL0OTJD@YoQV1W&a%<))v~o+A z)kp_7%i5Z(toO0jwb5YSx-pu>S-zH(lk3@k@VC{67L`3kpy^>;=Qhm}o3Ycq>7q70 zq;BUU-Q7p*w0wW_!z~T4A~>?~Aa@5JW(PorZR35R4{X@tzz&L}tP6{6uzPB`Mp70Q zCgARnlxSMAK8pPd!okVglU9CX@ix?0^S&`W&I)}Pphw^&( zch>7u3(b%sp6DpDOX!KBNtxC;o0K7n(lSB4hk6D}vSpc@kn4oYC`6EX@l=uIv}Z8U zaQCj)^_D$LX1FPo@FA6=s{|eLH$%nSXr4qxg9KqQLIT)mHP}eoQh{1JQduBcxSN44 z6)hHMZuAeMNC=-}+QB&@ z$7TAzsCo~Z10Db}fhBlq>Mi!{wbaPrseO#Oj)I}=Ef8mq-K)iuP&5+EswPQ08OZxulYt-0>O|5|17#D zKwiXSh${t6FMFo}y@U|w+LUMmj~S!j9pHz9%5gmy0&2Jxoc#!OzoCI6cU>Lz2+Egh z+3RAAchpt~FRDjvwR!KnI>PJDlk468rrLq~+wRNt{0%#X;tk*#0?{12NuzA%Il#>` zS3u7otPDMyAhQAkLZKn>#^(BQ0Fs=*Nqn;JxZ*s90}A{ISKwbfo$7*s!c2lrmLs%) zMhnuXKS<&{$B2hxEn^Pp&}Iw3AHi-?Q7z_Fc1uXeDVSI7b_jX%mTGBE>gf0dbU^Eo zb5)V42hD4N5{?{lgxHW^K(>)X2#d`q-OU%jASZ|fWx^`+_A>xT;5f6a%aFlPcGX!0 zj+VU(-int{n~QjO$PGN^Unl?^vqH$gq_$ynXag!2Es*7_>L)ZX!06!H$1gVTy{~{D zLJ&v;mk8bns*XCiN+@mKds!WIi8&y$8HYt%>a&l4KA#}Mq;`3RbC2C5@BCR(&_Ys6EX8?`}MmKJ_ znQC?Y1@HM**E`dC0hqb$wcF48J?~uWjKAbvLQNQn+{pt7iv9r4;}{9t1Kfa($U^|l zk3Fbn^WGr|2T&nG_BJfe|MIioN+zTXKRM!d|Qfe3Xp5wZL;=ib!;#c#-bGy?-`hHJUmw8e&5s{((5$8KF zJ0U*y2<*8KI49Z^;;VBZ_Ri1_D9Y4>Avys*S(I;iJKRFH#6{n~3In_346HBlPz^$x zdGrj?QU!mggNMi=gh*YY;rJ9G5#r<~EjU5G$KiT9i_V+;Z}#*%vm4EU`-iB+)ssE5iFGO+Xs4(~$by5Q8BiZu463PzNK}2V4$( z0~|wng7guQ*ghheBsMq|P8JVJ43(XnLxN0nZx6?1KEIUN0V=(xd7=Qx$neT*T%zEH z19+2tNi?`9?N3I??IDRmc7XobD#*x^EY6)2$S@{I2QrWY{L`pr250&PIbMP*66eUC zD|BO6>fwBuO3SUuImB%&&30I?M&|3Y7To0>h}9%eCz2*PH~cZ8Gk5xQzC`GfsV7!h z4=E<*aXkju&V51N+L0{XUHBPxu{K34 zfYgCQwg3~UP+W-z9Sw7syEDtc5x#*_qBs$5l~5n4Fm&fK6GB2#nAt$%SXd+y*~PE( z(jr^#;~byGvd_TL5?fStv5jfwItsPggHvBYO2GVN)&CsIMenq~?DzcB{))FMZ!ffa zbpC$3<@(NI#s&Y3m+%JpFvOw%Fke6cg1vS77fQZb`0D3M{Zgrq!6*`IlI_52w{FiJ z=QYgv2+_2q*^H`qI)0G-5IBiZpByKaH$R-)X`lIcst2{i&sQYUO*5GpjD93SQ5ZVG z=kb^aC=SX-00g^_70B`X>c|DMkPKl8=(`DQUDzv$Ctg5aXqJpBOg(I?^S5p@PH}#w^ zN+AWn7gc&%xdg*j5?zK24rFaX9q}M=M-VC401O3OP21(NoHOM$&mH^IGskaW62EPk z=TIo`JQUyZUIi#ld2rB(tlVb_7pt=4M7|fnqNB|0liN#WnYZ<~o-)=THzU%&u4cRXpc= J=YQ7q{tM>`2$BE* diff --git a/PythonHome/Lib/lib2to3/btm_utils.py b/PythonHome/Lib/lib2to3/btm_utils.py new file mode 100644 index 0000000000..2276dc9e96 --- /dev/null +++ b/PythonHome/Lib/lib2to3/btm_utils.py @@ -0,0 +1,283 @@ +"Utility functions used by the btm_matcher module" + +from . import pytree +from .pgen2 import grammar, token +from .pygram import pattern_symbols, python_symbols + +syms = pattern_symbols +pysyms = python_symbols +tokens = grammar.opmap +token_labels = token + +TYPE_ANY = -1 +TYPE_ALTERNATIVES = -2 +TYPE_GROUP = -3 + +class MinNode(object): + """This class serves as an intermediate representation of the + pattern tree during the conversion to sets of leaf-to-root + subpatterns""" + + def __init__(self, type=None, name=None): + self.type = type + self.name = name + self.children = [] + self.leaf = False + self.parent = None + self.alternatives = [] + self.group = [] + + def __repr__(self): + return str(self.type) + ' ' + str(self.name) + + def leaf_to_root(self): + """Internal method. Returns a characteristic path of the + pattern tree. This method must be run for all leaves until the + linear subpatterns are merged into a single""" + node = self + subp = [] + while node: + if node.type == TYPE_ALTERNATIVES: + node.alternatives.append(subp) + if len(node.alternatives) == len(node.children): + #last alternative + subp = [tuple(node.alternatives)] + node.alternatives = [] + node = node.parent + continue + else: + node = node.parent + subp = None + break + + if node.type == TYPE_GROUP: + node.group.append(subp) + #probably should check the number of leaves + if len(node.group) == len(node.children): + subp = get_characteristic_subpattern(node.group) + node.group = [] + node = node.parent + continue + else: + node = node.parent + subp = None + break + + if node.type == token_labels.NAME and node.name: + #in case of type=name, use the name instead + subp.append(node.name) + else: + subp.append(node.type) + + node = node.parent + return subp + + def get_linear_subpattern(self): + """Drives the leaf_to_root method. The reason that + leaf_to_root must be run multiple times is because we need to + reject 'group' matches; for example the alternative form + (a | b c) creates a group [b c] that needs to be matched. Since + matching multiple linear patterns overcomes the automaton's + capabilities, leaf_to_root merges each group into a single + choice based on 'characteristic'ity, + + i.e. (a|b c) -> (a|b) if b more characteristic than c + + Returns: The most 'characteristic'(as defined by + get_characteristic_subpattern) path for the compiled pattern + tree. + """ + + for l in self.leaves(): + subp = l.leaf_to_root() + if subp: + return subp + + def leaves(self): + "Generator that returns the leaves of the tree" + for child in self.children: + for x in child.leaves(): + yield x + if not self.children: + yield self + +def reduce_tree(node, parent=None): + """ + Internal function. Reduces a compiled pattern tree to an + intermediate representation suitable for feeding the + automaton. This also trims off any optional pattern elements(like + [a], a*). + """ + + new_node = None + #switch on the node type + if node.type == syms.Matcher: + #skip + node = node.children[0] + + if node.type == syms.Alternatives : + #2 cases + if len(node.children) <= 2: + #just a single 'Alternative', skip this node + new_node = reduce_tree(node.children[0], parent) + else: + #real alternatives + new_node = MinNode(type=TYPE_ALTERNATIVES) + #skip odd children('|' tokens) + for child in node.children: + if node.children.index(child)%2: + continue + reduced = reduce_tree(child, new_node) + if reduced is not None: + new_node.children.append(reduced) + elif node.type == syms.Alternative: + if len(node.children) > 1: + + new_node = MinNode(type=TYPE_GROUP) + for child in node.children: + reduced = reduce_tree(child, new_node) + if reduced: + new_node.children.append(reduced) + if not new_node.children: + # delete the group if all of the children were reduced to None + new_node = None + + else: + new_node = reduce_tree(node.children[0], parent) + + elif node.type == syms.Unit: + if (isinstance(node.children[0], pytree.Leaf) and + node.children[0].value == '('): + #skip parentheses + return reduce_tree(node.children[1], parent) + if ((isinstance(node.children[0], pytree.Leaf) and + node.children[0].value == '[') + or + (len(node.children)>1 and + hasattr(node.children[1], "value") and + node.children[1].value == '[')): + #skip whole unit if its optional + return None + + leaf = True + details_node = None + alternatives_node = None + has_repeater = False + repeater_node = None + has_variable_name = False + + for child in node.children: + if child.type == syms.Details: + leaf = False + details_node = child + elif child.type == syms.Repeater: + has_repeater = True + repeater_node = child + elif child.type == syms.Alternatives: + alternatives_node = child + if hasattr(child, 'value') and child.value == '=': # variable name + has_variable_name = True + + #skip variable name + if has_variable_name: + #skip variable name, '=' + name_leaf = node.children[2] + if hasattr(name_leaf, 'value') and name_leaf.value == '(': + # skip parenthesis + name_leaf = node.children[3] + else: + name_leaf = node.children[0] + + #set node type + if name_leaf.type == token_labels.NAME: + #(python) non-name or wildcard + if name_leaf.value == 'any': + new_node = MinNode(type=TYPE_ANY) + else: + if hasattr(token_labels, name_leaf.value): + new_node = MinNode(type=getattr(token_labels, name_leaf.value)) + else: + new_node = MinNode(type=getattr(pysyms, name_leaf.value)) + + elif name_leaf.type == token_labels.STRING: + #(python) name or character; remove the apostrophes from + #the string value + name = name_leaf.value.strip("'") + if name in tokens: + new_node = MinNode(type=tokens[name]) + else: + new_node = MinNode(type=token_labels.NAME, name=name) + elif name_leaf.type == syms.Alternatives: + new_node = reduce_tree(alternatives_node, parent) + + #handle repeaters + if has_repeater: + if repeater_node.children[0].value == '*': + #reduce to None + new_node = None + elif repeater_node.children[0].value == '+': + #reduce to a single occurence i.e. do nothing + pass + else: + #TODO: handle {min, max} repeaters + raise NotImplementedError + pass + + #add children + if details_node and new_node is not None: + for child in details_node.children[1:-1]: + #skip '<', '>' markers + reduced = reduce_tree(child, new_node) + if reduced is not None: + new_node.children.append(reduced) + if new_node: + new_node.parent = parent + return new_node + + +def get_characteristic_subpattern(subpatterns): + """Picks the most characteristic from a list of linear patterns + Current order used is: + names > common_names > common_chars + """ + if not isinstance(subpatterns, list): + return subpatterns + if len(subpatterns)==1: + return subpatterns[0] + + # first pick out the ones containing variable names + subpatterns_with_names = [] + subpatterns_with_common_names = [] + common_names = ['in', 'for', 'if' , 'not', 'None'] + subpatterns_with_common_chars = [] + common_chars = "[]().,:" + for subpattern in subpatterns: + if any(rec_test(subpattern, lambda x: type(x) is str)): + if any(rec_test(subpattern, + lambda x: isinstance(x, str) and x in common_chars)): + subpatterns_with_common_chars.append(subpattern) + elif any(rec_test(subpattern, + lambda x: isinstance(x, str) and x in common_names)): + subpatterns_with_common_names.append(subpattern) + + else: + subpatterns_with_names.append(subpattern) + + if subpatterns_with_names: + subpatterns = subpatterns_with_names + elif subpatterns_with_common_names: + subpatterns = subpatterns_with_common_names + elif subpatterns_with_common_chars: + subpatterns = subpatterns_with_common_chars + # of the remaining subpatterns pick out the longest one + return max(subpatterns, key=len) + +def rec_test(sequence, test_func): + """Tests test_func on all items of sequence and items of included + sub-iterables""" + for x in sequence: + if isinstance(x, (list, tuple)): + for y in rec_test(x, test_func): + yield y + else: + yield test_func(x) diff --git a/PythonHome/Lib/lib2to3/btm_utils.pyc b/PythonHome/Lib/lib2to3/btm_utils.pyc deleted file mode 100644 index 91347a105170a67e52918c9119300f486ffce226..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7368 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 diff --git a/PythonHome/Lib/lib2to3/fixer_base.py b/PythonHome/Lib/lib2to3/fixer_base.py new file mode 100644 index 0000000000..f6421ba3f7 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixer_base.py @@ -0,0 +1,189 @@ +# Copyright 2006 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Base class for fixers (optional, but recommended).""" + +# Python imports +import logging +import itertools + +# Local imports +from .patcomp import PatternCompiler +from . import pygram +from .fixer_util import does_tree_import + +class BaseFix(object): + + """Optional base class for fixers. + + The subclass name must be FixFooBar where FooBar is the result of + removing underscores and capitalizing the words of the fix name. + For example, the class name for a fixer named 'has_key' should be + FixHasKey. + """ + + PATTERN = None # Most subclasses should override with a string literal + pattern = None # Compiled pattern, set by compile_pattern() + pattern_tree = None # Tree representation of the pattern + options = None # Options object passed to initializer + filename = None # The filename (set by set_filename) + logger = None # A logger (set by set_filename) + numbers = itertools.count(1) # For new_name() + used_names = set() # A set of all used NAMEs + order = "post" # Does the fixer prefer pre- or post-order traversal + explicit = False # Is this ignored by refactor.py -f all? + run_order = 5 # Fixers will be sorted by run order before execution + # Lower numbers will be run first. + _accept_type = None # [Advanced and not public] This tells RefactoringTool + # which node type to accept when there's not a pattern. + + keep_line_order = False # For the bottom matcher: match with the + # original line order + BM_compatible = False # Compatibility with the bottom matching + # module; every fixer should set this + # manually + + # Shortcut for access to Python grammar symbols + syms = pygram.python_symbols + + def __init__(self, options, log): + """Initializer. Subclass may override. + + Args: + options: an dict containing the options passed to RefactoringTool + that could be used to customize the fixer through the command line. + log: a list to append warnings and other messages to. + """ + self.options = options + self.log = log + self.compile_pattern() + + def compile_pattern(self): + """Compiles self.PATTERN into self.pattern. + + Subclass may override if it doesn't want to use + self.{pattern,PATTERN} in .match(). + """ + if self.PATTERN is not None: + PC = PatternCompiler() + self.pattern, self.pattern_tree = PC.compile_pattern(self.PATTERN, + with_tree=True) + + def set_filename(self, filename): + """Set the filename, and a logger derived from it. + + The main refactoring tool should call this. + """ + self.filename = filename + self.logger = logging.getLogger(filename) + + def match(self, node): + """Returns match for a given parse tree node. + + Should return a true or false object (not necessarily a bool). + It may return a non-empty dict of matching sub-nodes as + returned by a matching pattern. + + Subclass may override. + """ + results = {"node": node} + return self.pattern.match(node, results) and results + + def transform(self, node, results): + """Returns the transformation for a given parse tree node. + + Args: + node: the root of the parse tree that matched the fixer. + results: a dict mapping symbolic names to part of the match. + + Returns: + None, or a node that is a modified copy of the + argument node. The node argument may also be modified in-place to + effect the same change. + + Subclass *must* override. + """ + raise NotImplementedError() + + def new_name(self, template=u"xxx_todo_changeme"): + """Return a string suitable for use as an identifier + + The new name is guaranteed not to conflict with other identifiers. + """ + name = template + while name in self.used_names: + name = template + unicode(self.numbers.next()) + self.used_names.add(name) + return name + + def log_message(self, message): + if self.first_log: + self.first_log = False + self.log.append("### In file %s ###" % self.filename) + self.log.append(message) + + def cannot_convert(self, node, reason=None): + """Warn the user that a given chunk of code is not valid Python 3, + but that it cannot be converted automatically. + + First argument is the top-level node for the code in question. + Optional second argument is why it can't be converted. + """ + lineno = node.get_lineno() + for_output = node.clone() + for_output.prefix = u"" + msg = "Line %d: could not convert: %s" + self.log_message(msg % (lineno, for_output)) + if reason: + self.log_message(reason) + + def warning(self, node, reason): + """Used for warning the user about possible uncertainty in the + translation. + + First argument is the top-level node for the code in question. + Optional second argument is why it can't be converted. + """ + lineno = node.get_lineno() + self.log_message("Line %d: %s" % (lineno, reason)) + + def start_tree(self, tree, filename): + """Some fixers need to maintain tree-wide state. + This method is called once, at the start of tree fix-up. + + tree - the root node of the tree to be processed. + filename - the name of the file the tree came from. + """ + self.used_names = tree.used_names + self.set_filename(filename) + self.numbers = itertools.count(1) + self.first_log = True + + def finish_tree(self, tree, filename): + """Some fixers need to maintain tree-wide state. + This method is called once, at the conclusion of tree fix-up. + + tree - the root node of the tree to be processed. + filename - the name of the file the tree came from. + """ + pass + + +class ConditionalFix(BaseFix): + """ Base class for fixers which not execute if an import is found. """ + + # This is the name of the import which, if found, will cause the test to be skipped + skip_on = None + + def start_tree(self, *args): + super(ConditionalFix, self).start_tree(*args) + self._should_skip = None + + def should_skip(self, node): + if self._should_skip is not None: + return self._should_skip + pkg = self.skip_on.split(".") + name = pkg[-1] + pkg = ".".join(pkg[:-1]) + self._should_skip = does_tree_import(pkg, name, node) + return self._should_skip diff --git a/PythonHome/Lib/lib2to3/fixer_base.pyc b/PythonHome/Lib/lib2to3/fixer_base.pyc deleted file mode 100644 index e427cfca66ae5f311203fd76bee3c1515e3acd78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7017 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 diff --git a/PythonHome/Lib/lib2to3/fixer_util.py b/PythonHome/Lib/lib2to3/fixer_util.py new file mode 100644 index 0000000000..78fdf26dce --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixer_util.py @@ -0,0 +1,432 @@ +"""Utility functions, node construction macros, etc.""" +# Author: Collin Winter + +from itertools import islice + +# Local imports +from .pgen2 import token +from .pytree import Leaf, Node +from .pygram import python_symbols as syms +from . import patcomp + + +########################################################### +### Common node-construction "macros" +########################################################### + +def KeywordArg(keyword, value): + return Node(syms.argument, + [keyword, Leaf(token.EQUAL, u"="), value]) + +def LParen(): + return Leaf(token.LPAR, u"(") + +def RParen(): + return Leaf(token.RPAR, u")") + +def Assign(target, source): + """Build an assignment statement""" + if not isinstance(target, list): + target = [target] + if not isinstance(source, list): + source.prefix = u" " + source = [source] + + return Node(syms.atom, + target + [Leaf(token.EQUAL, u"=", prefix=u" ")] + source) + +def Name(name, prefix=None): + """Return a NAME leaf""" + return Leaf(token.NAME, name, prefix=prefix) + +def Attr(obj, attr): + """A node tuple for obj.attr""" + return [obj, Node(syms.trailer, [Dot(), attr])] + +def Comma(): + """A comma leaf""" + return Leaf(token.COMMA, u",") + +def Dot(): + """A period (.) leaf""" + return Leaf(token.DOT, u".") + +def ArgList(args, lparen=LParen(), rparen=RParen()): + """A parenthesised argument list, used by Call()""" + node = Node(syms.trailer, [lparen.clone(), rparen.clone()]) + if args: + node.insert_child(1, Node(syms.arglist, args)) + return node + +def Call(func_name, args=None, prefix=None): + """A function call""" + node = Node(syms.power, [func_name, ArgList(args)]) + if prefix is not None: + node.prefix = prefix + return node + +def Newline(): + """A newline literal""" + return Leaf(token.NEWLINE, u"\n") + +def BlankLine(): + """A blank line""" + return Leaf(token.NEWLINE, u"") + +def Number(n, prefix=None): + return Leaf(token.NUMBER, n, prefix=prefix) + +def Subscript(index_node): + """A numeric or string subscript""" + return Node(syms.trailer, [Leaf(token.LBRACE, u"["), + index_node, + Leaf(token.RBRACE, u"]")]) + +def String(string, prefix=None): + """A string leaf""" + return Leaf(token.STRING, string, prefix=prefix) + +def ListComp(xp, fp, it, test=None): + """A list comprehension of the form [xp for fp in it if test]. + + If test is None, the "if test" part is omitted. + """ + xp.prefix = u"" + fp.prefix = u" " + it.prefix = u" " + for_leaf = Leaf(token.NAME, u"for") + for_leaf.prefix = u" " + in_leaf = Leaf(token.NAME, u"in") + in_leaf.prefix = u" " + inner_args = [for_leaf, fp, in_leaf, it] + if test: + test.prefix = u" " + if_leaf = Leaf(token.NAME, u"if") + if_leaf.prefix = u" " + inner_args.append(Node(syms.comp_if, [if_leaf, test])) + inner = Node(syms.listmaker, [xp, Node(syms.comp_for, inner_args)]) + return Node(syms.atom, + [Leaf(token.LBRACE, u"["), + inner, + Leaf(token.RBRACE, u"]")]) + +def FromImport(package_name, name_leafs): + """ Return an import statement in the form: + from package import name_leafs""" + # XXX: May not handle dotted imports properly (eg, package_name='foo.bar') + #assert package_name == '.' or '.' not in package_name, "FromImport has "\ + # "not been tested with dotted package names -- use at your own "\ + # "peril!" + + for leaf in name_leafs: + # Pull the leaves out of their old tree + leaf.remove() + + children = [Leaf(token.NAME, u"from"), + Leaf(token.NAME, package_name, prefix=u" "), + Leaf(token.NAME, u"import", prefix=u" "), + Node(syms.import_as_names, name_leafs)] + imp = Node(syms.import_from, children) + return imp + + +########################################################### +### Determine whether a node represents a given literal +########################################################### + +def is_tuple(node): + """Does the node represent a tuple literal?""" + if isinstance(node, Node) and node.children == [LParen(), RParen()]: + return True + return (isinstance(node, Node) + and len(node.children) == 3 + and isinstance(node.children[0], Leaf) + and isinstance(node.children[1], Node) + and isinstance(node.children[2], Leaf) + and node.children[0].value == u"(" + and node.children[2].value == u")") + +def is_list(node): + """Does the node represent a list literal?""" + return (isinstance(node, Node) + and len(node.children) > 1 + and isinstance(node.children[0], Leaf) + and isinstance(node.children[-1], Leaf) + and node.children[0].value == u"[" + and node.children[-1].value == u"]") + + +########################################################### +### Misc +########################################################### + +def parenthesize(node): + return Node(syms.atom, [LParen(), node, RParen()]) + + +consuming_calls = set(["sorted", "list", "set", "any", "all", "tuple", "sum", + "min", "max", "enumerate"]) + +def attr_chain(obj, attr): + """Follow an attribute chain. + + If you have a chain of objects where a.foo -> b, b.foo-> c, etc, + use this to iterate over all objects in the chain. Iteration is + terminated by getattr(x, attr) is None. + + Args: + obj: the starting object + attr: the name of the chaining attribute + + Yields: + Each successive object in the chain. + """ + next = getattr(obj, attr) + while next: + yield next + next = getattr(next, attr) + +p0 = """for_stmt< 'for' any 'in' node=any ':' any* > + | comp_for< 'for' any 'in' node=any any* > + """ +p1 = """ +power< + ( 'iter' | 'list' | 'tuple' | 'sorted' | 'set' | 'sum' | + 'any' | 'all' | 'enumerate' | (any* trailer< '.' 'join' >) ) + trailer< '(' node=any ')' > + any* +> +""" +p2 = """ +power< + ( 'sorted' | 'enumerate' ) + trailer< '(' arglist ')' > + any* +> +""" +pats_built = False +def in_special_context(node): + """ Returns true if node is in an environment where all that is required + of it is being iterable (ie, it doesn't matter if it returns a list + or an iterator). + See test_map_nochange in test_fixers.py for some examples and tests. + """ + global p0, p1, p2, pats_built + if not pats_built: + p0 = patcomp.compile_pattern(p0) + p1 = patcomp.compile_pattern(p1) + p2 = patcomp.compile_pattern(p2) + pats_built = True + patterns = [p0, p1, p2] + for pattern, parent in zip(patterns, attr_chain(node, "parent")): + results = {} + if pattern.match(parent, results) and results["node"] is node: + return True + return False + +def is_probably_builtin(node): + """ + Check that something isn't an attribute or function name etc. + """ + prev = node.prev_sibling + if prev is not None and prev.type == token.DOT: + # Attribute lookup. + return False + parent = node.parent + if parent.type in (syms.funcdef, syms.classdef): + return False + if parent.type == syms.expr_stmt and parent.children[0] is node: + # Assignment. + return False + if parent.type == syms.parameters or \ + (parent.type == syms.typedargslist and ( + (prev is not None and prev.type == token.COMMA) or + parent.children[0] is node + )): + # The name of an argument. + return False + return True + +def find_indentation(node): + """Find the indentation of *node*.""" + while node is not None: + if node.type == syms.suite and len(node.children) > 2: + indent = node.children[1] + if indent.type == token.INDENT: + return indent.value + node = node.parent + return u"" + +########################################################### +### The following functions are to find bindings in a suite +########################################################### + +def make_suite(node): + if node.type == syms.suite: + return node + node = node.clone() + parent, node.parent = node.parent, None + suite = Node(syms.suite, [node]) + suite.parent = parent + return suite + +def find_root(node): + """Find the top level namespace.""" + # Scamper up to the top level namespace + while node.type != syms.file_input: + node = node.parent + if not node: + raise ValueError("root found before file_input node was found.") + return node + +def does_tree_import(package, name, node): + """ Returns true if name is imported from package at the + top level of the tree which node belongs to. + To cover the case of an import like 'import foo', use + None for the package and 'foo' for the name. """ + binding = find_binding(name, find_root(node), package) + return bool(binding) + +def is_import(node): + """Returns true if the node is an import statement.""" + return node.type in (syms.import_name, syms.import_from) + +def touch_import(package, name, node): + """ Works like `does_tree_import` but adds an import statement + if it was not imported. """ + def is_import_stmt(node): + return (node.type == syms.simple_stmt and node.children and + is_import(node.children[0])) + + root = find_root(node) + + if does_tree_import(package, name, root): + return + + # figure out where to insert the new import. First try to find + # the first import and then skip to the last one. + insert_pos = offset = 0 + for idx, node in enumerate(root.children): + if not is_import_stmt(node): + continue + for offset, node2 in enumerate(root.children[idx:]): + if not is_import_stmt(node2): + break + insert_pos = idx + offset + break + + # if there are no imports where we can insert, find the docstring. + # if that also fails, we stick to the beginning of the file + if insert_pos == 0: + for idx, node in enumerate(root.children): + if (node.type == syms.simple_stmt and node.children and + node.children[0].type == token.STRING): + insert_pos = idx + 1 + break + + if package is None: + import_ = Node(syms.import_name, [ + Leaf(token.NAME, u"import"), + Leaf(token.NAME, name, prefix=u" ") + ]) + else: + import_ = FromImport(package, [Leaf(token.NAME, name, prefix=u" ")]) + + children = [import_, Newline()] + root.insert_child(insert_pos, Node(syms.simple_stmt, children)) + + +_def_syms = set([syms.classdef, syms.funcdef]) +def find_binding(name, node, package=None): + """ Returns the node which binds variable name, otherwise None. + If optional argument package is supplied, only imports will + be returned. + See test cases for examples.""" + for child in node.children: + ret = None + if child.type == syms.for_stmt: + if _find(name, child.children[1]): + return child + n = find_binding(name, make_suite(child.children[-1]), package) + if n: ret = n + elif child.type in (syms.if_stmt, syms.while_stmt): + n = find_binding(name, make_suite(child.children[-1]), package) + if n: ret = n + elif child.type == syms.try_stmt: + n = find_binding(name, make_suite(child.children[2]), package) + if n: + ret = n + else: + for i, kid in enumerate(child.children[3:]): + if kid.type == token.COLON and kid.value == ":": + # i+3 is the colon, i+4 is the suite + n = find_binding(name, make_suite(child.children[i+4]), package) + if n: ret = n + elif child.type in _def_syms and child.children[1].value == name: + ret = child + elif _is_import_binding(child, name, package): + ret = child + elif child.type == syms.simple_stmt: + ret = find_binding(name, child, package) + elif child.type == syms.expr_stmt: + if _find(name, child.children[0]): + ret = child + + if ret: + if not package: + return ret + if is_import(ret): + return ret + return None + +_block_syms = set([syms.funcdef, syms.classdef, syms.trailer]) +def _find(name, node): + nodes = [node] + while nodes: + node = nodes.pop() + if node.type > 256 and node.type not in _block_syms: + nodes.extend(node.children) + elif node.type == token.NAME and node.value == name: + return node + return None + +def _is_import_binding(node, name, package=None): + """ Will reuturn node if node will import name, or node + will import * from package. None is returned otherwise. + See test cases for examples. """ + + if node.type == syms.import_name and not package: + imp = node.children[1] + if imp.type == syms.dotted_as_names: + for child in imp.children: + if child.type == syms.dotted_as_name: + if child.children[2].value == name: + return node + elif child.type == token.NAME and child.value == name: + return node + elif imp.type == syms.dotted_as_name: + last = imp.children[-1] + if last.type == token.NAME and last.value == name: + return node + elif imp.type == token.NAME and imp.value == name: + return node + elif node.type == syms.import_from: + # unicode(...) is used to make life easier here, because + # from a.b import parses to ['import', ['a', '.', 'b'], ...] + if package and unicode(node.children[1]).strip() != package: + return None + n = node.children[3] + if package and _find(u"as", n): + # See test_from_import_as for explanation + return None + elif n.type == syms.import_as_names and _find(name, n): + return node + elif n.type == syms.import_as_name: + child = n.children[2] + if child.type == token.NAME and child.value == name: + return node + elif n.type == token.NAME and n.value == name: + return node + elif package and n.type == token.STAR: + return node + return None diff --git a/PythonHome/Lib/lib2to3/fixer_util.pyc b/PythonHome/Lib/lib2to3/fixer_util.pyc deleted file mode 100644 index 78ff67d157b9f7e3730fde9ac3a7da589ae9a5d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14173 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 fcBDE{#XSc!@Zs7~l=5c+t + ')' + > + > + """ + + def transform(self, node, results): + syms = self.syms + assert results + func = results["func"] + args = results["args"] + kwds = results.get("kwds") + prefix = node.prefix + func = func.clone() + if (func.type not in (token.NAME, syms.atom) and + (func.type != syms.power or + func.children[-2].type == token.DOUBLESTAR)): + # Need to parenthesize + func = parenthesize(func) + func.prefix = "" + args = args.clone() + args.prefix = "" + if kwds is not None: + kwds = kwds.clone() + kwds.prefix = "" + l_newargs = [pytree.Leaf(token.STAR, u"*"), args] + if kwds is not None: + l_newargs.extend([Comma(), + pytree.Leaf(token.DOUBLESTAR, u"**"), + kwds]) + l_newargs[-2].prefix = u" " # that's the ** token + # XXX Sometimes we could be cleverer, e.g. apply(f, (x, y) + t) + # can be translated into f(x, y, *t) instead of f(*(x, y) + t) + #new = pytree.Node(syms.power, (func, ArgList(l_newargs))) + return Call(func, l_newargs, prefix=prefix) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_apply.pyc b/PythonHome/Lib/lib2to3/fixes/fix_apply.pyc deleted file mode 100644 index 4d762d5dd2005efa779fa27426ff1bbd2552313b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1838 zcmbVM*={3M5UpO^UNTDv@DL44zqxHi78+hN5l+ZRNST1z0ffn@r(<6`ZTDjJy`IF# zc_I7(f52DpLHq&lggVvMM0sMd<#N@j<<_m`I)6TH{r>%%!H6~=hyTCepDvh;iH1xq z8rzgwl-V@2$%5=q>QLs=(5+-w^femRD!E3fM_HYQb;=qvY*5yuVUu+psT$2%G~pn1 z`i1D0=!fAJjThPvH(rKE|pGxQl`NGr`t!K@2ZFc5BaA*W}>)?7AY>CBNcT~QNB6X zDjWnzQ1{rO<@0AzT&Z&3Z_BmY0s%H^=d15#aj&UjH zW#Y44ia0}FgX*N3fHeUgDV3D*~^0gM=(!l_Egf^CSIpo8=c*I>w43?=Qdp_VDC*aMlk)#H*Y+X2?P% zov3&sFpMNyb!}8W4zd0rGLnZ$OteZX+q@VnQ)gYN^fEO%#KRB*2=O9>7|rSy;L<2p zS14J)0twMRbG`GE^K(2u8Z?si@9}E|XI}nX^IMpG%7Xrk30Y0+k=5ew zQ{kRjJJzmU@zCJ=Oy~~VY`X#8J}FHU<#DE>NJwfOMcToJ39_f!%tXye}#X4j}Qr<-5QK%c~3n1G(gFuhEX&wMo|=^UsYews>M|0 z&!yub=1EdUiOOhcl2jT~wMhDk(jW56{W7_h)BaDIQlkB;C{ BW~u-H diff --git a/PythonHome/Lib/lib2to3/fixes/fix_basestring.py b/PythonHome/Lib/lib2to3/fixes/fix_basestring.py new file mode 100644 index 0000000000..a3c9a43649 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_basestring.py @@ -0,0 +1,14 @@ +"""Fixer for basestring -> str.""" +# Author: Christian Heimes + +# Local imports +from .. import fixer_base +from ..fixer_util import Name + +class FixBasestring(fixer_base.BaseFix): + BM_compatible = True + + PATTERN = "'basestring'" + + def transform(self, node, results): + return Name(u"str", prefix=node.prefix) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_basestring.pyc b/PythonHome/Lib/lib2to3/fixes/fix_basestring.pyc deleted file mode 100644 index d76cb745b55a48b61469eaa2aa4aef111e466d69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 762 zcmbV~!AiqG5Qb-yG-|O>@T$;@n2SB=Rf@LgNrR*XF%;Ie*-A>%lhw1SHr)JeA44BO6u1RL#jfqa;~u~jHz*nge3ssaoNPf( zX52UrK5KxX4D%-Ux&`HFGVw%)&KtQ{A%0X@E%n#ya7w(|uxvYDCy diff --git a/PythonHome/Lib/lib2to3/fixes/fix_buffer.py b/PythonHome/Lib/lib2to3/fixes/fix_buffer.py new file mode 100644 index 0000000000..c6b0928024 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_buffer.py @@ -0,0 +1,22 @@ +# Copyright 2007 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Fixer that changes buffer(...) into memoryview(...).""" + +# Local imports +from .. import fixer_base +from ..fixer_util import Name + + +class FixBuffer(fixer_base.BaseFix): + BM_compatible = True + + explicit = True # The user must ask for this fixer + + PATTERN = """ + power< name='buffer' trailer< '(' [any] ')' > any* > + """ + + def transform(self, node, results): + name = results["name"] + name.replace(Name(u"memoryview", prefix=name.prefix)) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_buffer.pyc b/PythonHome/Lib/lib2to3/fixes/fix_buffer.pyc deleted file mode 100644 index 7f99caf2255c4eb62f35698bb96cd2e45a2db493..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 919 zcmbVKO>fjN5FIDk0E;U1z=fL;hon8^036GTZUrY;q3lYCu*l@Yp{|?{#SZOC<+S`L z{uh6M8KtW}M8-n>Y4<9L&GJ`?N0M=JE0U0?nKuQ~((wgUSQVpz$E{fKlv& z_Mr(N3os5qdT=p=8b8e78^9jmeHKC$!aBY~#hxL&Qde@|_B^+|JkQ(D((q!eYdOS8 zk{of>+KxA}>4x1GB`@7!qC8BD8G@Z7)Ko$gxslUZfM=_`k@g-sSbyp2{hEdHmT2ZN zg2Y)E5zTyuftzkd(;;JIo33N(W>SPX|KsVqOF5kI7F#`!CejhNL#{L(M{&eI*fX|gC@`RoZdOZ3 zG)9u+RxKN1*bfo~im8z$)d$(@yp$=)kW!+n;Yt{(>#0^($(x_esI5sUJ4TzpJVGzo zzE;IntKy06o^ELehEPmGB>m3Gk8-r8?uO<8rWk4mY|h;J?OhCnAl^c_MGDb$)u<_? zKR3fD?EyN=H=^vCKDVmS(xu6(UaL}BNAm6IX7e&#rL^u_lFs`#rYUXsKAIs)Aq%}Q z2))(Bk~9;d>PlpVF3?5z{oajMX(y)Rvcy}6SI$-ZFD`DplSzjKsbFY{p?}B@{hxq2 By6gY| diff --git a/PythonHome/Lib/lib2to3/fixes/fix_callable.py b/PythonHome/Lib/lib2to3/fixes/fix_callable.py new file mode 100644 index 0000000000..df33d614ba --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_callable.py @@ -0,0 +1,37 @@ +# Copyright 2007 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Fixer for callable(). + +This converts callable(obj) into isinstance(obj, collections.Callable), adding a +collections import if needed.""" + +# Local imports +from lib2to3 import fixer_base +from lib2to3.fixer_util import Call, Name, String, Attr, touch_import + +class FixCallable(fixer_base.BaseFix): + BM_compatible = True + + order = "pre" + + # Ignore callable(*args) or use of keywords. + # Either could be a hint that the builtin callable() is not being used. + PATTERN = """ + power< 'callable' + trailer< lpar='(' + ( not(arglist | argument) any ','> ) + rpar=')' > + after=any* + > + """ + + def transform(self, node, results): + func = results['func'] + + touch_import(None, u'collections', node=node) + + args = [func.clone(), String(u', ')] + args.extend(Attr(Name(u'collections'), Name(u'Callable'))) + return Call(Name(u'isinstance'), args, prefix=node.prefix) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_callable.pyc b/PythonHome/Lib/lib2to3/fixes/fix_callable.pyc deleted file mode 100644 index 9b4f696fec903b006369c0bc302df7337dcfd7b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1462 zcmbVMO>fgc5FOizQvyhQT;PIMaEODd9N?N(v=y8nLQW-wsbm~`Q#SHPw7Z5@N>7FV z#Q)+4z?)6e76}eu$&>NS?wi>+Zxj5u-T(gX<20v>C&2FuyygQ;L6pFHRQObSRQZ(n zIO_KgKPe;frv5Cog|kUDv&B%T+BQNNRU4btxr`9p#@e!! zxm8VVMh6$mhub163RNGAtbZ*pRJClh6>2VODGOPQ)K5H-hjwfqX3jmOv&_h-%drj& zV>)M&RnmrtOsxjAi|tvf?JZu~wE3rWjc;!vfa7htxg?qE?Bg|0U?fQPn5iUigm;*5 zFbd8=8Ay$%5l_XkS!!tlZ0`#^%jS#JV=>r}GjLJP;ITSWC8x_}rgsL>Z^`u%*htik zjWT^)Dr3b;z-ud6+i_N(iowo6;CFW@=53wtz`b7J5<_6$dchiI90BuhNDg;es~P5_MC^)<h1@SIRZAoW~4@QxHKxZD~!+ZMfbra}(i%oN<~Q9lchwqf*VD+2;8X-v+}r z-6(CeJhcu`XSKoAtsY^!;i}~I{rmm{@3H4@xaBHoTI0&3sk>TfS~W#m@+UWas9R}o z!`Xk6=1sNCtinHlJ87c}+w%ZLKQTJUhmD7V81HX)(Y){yAQ$6Ib*<8+Oc%*Iex~ Nrr{HW!5uI1e*rSSK>z>% diff --git a/PythonHome/Lib/lib2to3/fixes/fix_dict.py b/PythonHome/Lib/lib2to3/fixes/fix_dict.py new file mode 100644 index 0000000000..f681e4d713 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_dict.py @@ -0,0 +1,107 @@ +# Copyright 2007 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Fixer for dict methods. + +d.keys() -> list(d.keys()) +d.items() -> list(d.items()) +d.values() -> list(d.values()) + +d.iterkeys() -> iter(d.keys()) +d.iteritems() -> iter(d.items()) +d.itervalues() -> iter(d.values()) + +d.viewkeys() -> d.keys() +d.viewitems() -> d.items() +d.viewvalues() -> d.values() + +Except in certain very specific contexts: the iter() can be dropped +when the context is list(), sorted(), iter() or for...in; the list() +can be dropped when the context is list() or sorted() (but not iter() +or for...in!). Special contexts that apply to both: list(), sorted(), tuple() +set(), any(), all(), sum(). + +Note: iter(d.keys()) could be written as iter(d) but since the +original d.iterkeys() was also redundant we don't fix this. And there +are (rare) contexts where it makes a difference (e.g. when passing it +as an argument to a function that introspects the argument). +""" + +# Local imports +from .. import pytree +from .. import patcomp +from ..pgen2 import token +from .. import fixer_base +from ..fixer_util import Name, Call, LParen, RParen, ArgList, Dot +from .. import fixer_util + + +iter_exempt = fixer_util.consuming_calls | set(["iter"]) + + +class FixDict(fixer_base.BaseFix): + BM_compatible = True + + PATTERN = """ + power< head=any+ + trailer< '.' method=('keys'|'items'|'values'| + 'iterkeys'|'iteritems'|'itervalues'| + 'viewkeys'|'viewitems'|'viewvalues') > + parens=trailer< '(' ')' > + tail=any* + > + """ + + def transform(self, node, results): + head = results["head"] + method = results["method"][0] # Extract node for method name + tail = results["tail"] + syms = self.syms + method_name = method.value + isiter = method_name.startswith(u"iter") + isview = method_name.startswith(u"view") + if isiter or isview: + method_name = method_name[4:] + assert method_name in (u"keys", u"items", u"values"), repr(method) + head = [n.clone() for n in head] + tail = [n.clone() for n in tail] + special = not tail and self.in_special_context(node, isiter) + args = head + [pytree.Node(syms.trailer, + [Dot(), + Name(method_name, + prefix=method.prefix)]), + results["parens"].clone()] + new = pytree.Node(syms.power, args) + if not (special or isview): + new.prefix = u"" + new = Call(Name(u"iter" if isiter else u"list"), [new]) + if tail: + new = pytree.Node(syms.power, [new] + tail) + new.prefix = node.prefix + return new + + P1 = "power< func=NAME trailer< '(' node=any ')' > any* >" + p1 = patcomp.compile_pattern(P1) + + P2 = """for_stmt< 'for' any 'in' node=any ':' any* > + | comp_for< 'for' any 'in' node=any any* > + """ + p2 = patcomp.compile_pattern(P2) + + def in_special_context(self, node, isiter): + if node.parent is None: + return False + results = {} + if (node.parent.parent is not None and + self.p1.match(node.parent.parent, results) and + results["node"] is node): + if isiter: + # iter(d.iterkeys()) -> iter(d.keys()), etc. + return results["func"].value in iter_exempt + else: + # list(d.keys()) -> list(d.keys()), etc. + return results["func"].value in fixer_util.consuming_calls + if not isiter: + return False + # for ... in d.iterkeys() -> for ... in d.keys(), etc. + return self.p2.match(node.parent, results) and results["node"] is node diff --git a/PythonHome/Lib/lib2to3/fixes/fix_dict.pyc b/PythonHome/Lib/lib2to3/fixes/fix_dict.pyc deleted file mode 100644 index ed946b194217684647d4962ead233b159470e1be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3709 zcmbVPTW=f36+X+G#1(akb8&^H@${u!It`0B0SdUWTi^2J2*%1lQP#g z=F`USuke_EU`U827(Gf_lzEi5Xwo8&*KJw1Y0`G<4rLw6yEN&#byxU3n)KYdN7)AD zn>5*^yib!pbR^`l1{D4wLK{lGxq&te5Nl= zFj61gS6OOoup*4WO0CYX^BM{>U&h&7U+1n!Bi4(p^;$Qt-qc-R(ckbJN^^LBm_wr zkH=~83lWkWjQs05)pzS;4J)lGIGS5klyHEfJ@T(;|M6(74%v-3d+h}djID~RD!Wv+ zR7a&fx%(}q+If{}XfxWf<#BN-KUu~3at_o}TJ3TJ#n@Z<4%|s1X zhh+hv!ehX}6jS-I=@0RkXBadv&m#?}YYYB$82^ATKsKNt@QeXzlhFrI1Rw(x0>~Po zFT^cMIwCTl@GxL+&AW(u)BbpKBBz8?8vHvS(g?>r$oyhEjo1S z(Q<RN(LT z9?h_!O^?64K}(+&KAl26(N`_{`cDMwnBDzW_FsvO?9!n8m)HtJJvQQ1iva2yz&@RR7sq8zth{0Q$}KCXWqsdNCdbdq~)UG#3}N zG^V>_Q!rc?bJFMB#axmyk!oU!thm7E+#^!rbMAguUJgfU4QOyvDX=;CPEf84uAcv{ zCfLOmG0|M+#_~y`A2CO<*|@d_SLO-A1SByA5COP*QrEb$*v48{wFphKve5PhNNEwt z%@}7z7K~~7Anbz^vZ9b`2H4piqchoTGw4l7p5S4sbK&5L*W0LX2t5l>>n9Mxe6L=K*$*4CWSQ;}=iUqZe6v zbjOyTykJN+JVyNPGzOxxFYv1{xV!V8V_`nUK%VdI;OXPLi|@eO_CD}#;k%DjPpI#B z?}FaHNW!|9Q+xdl>UI%Jj_ zro~l}yF!J)8lM1>3*3%*6+!5`Mcp}TF~KL!A6MEVJm&8h(91xdgy;-?^)}fS9irkH zu7uI>05;!9^S9{~u(D#I`O#6#LN5a4z+g34gPIE!h=+DZGJ#8nysaS!W-yIAwngTT zax`OMe|?10U;gd7{=tX+&eH_ZGjdL)sa8XAPfd57K;pEcev7KfZ|$%;cC z=7x+DA*%>EI1Zb}m + """ + + def transform(self, node, results): + syms = self.syms + + tail = [n.clone() for n in results["tail"]] + + try_cleanup = [ch.clone() for ch in results["cleanup"]] + for except_clause, e_suite in find_excepts(try_cleanup): + if len(except_clause.children) == 4: + (E, comma, N) = except_clause.children[1:4] + comma.replace(Name(u"as", prefix=u" ")) + + if N.type != token.NAME: + # Generate a new N for the except clause + new_N = Name(self.new_name(), prefix=u" ") + target = N.clone() + target.prefix = u"" + N.replace(new_N) + new_N = new_N.clone() + + # Insert "old_N = new_N" as the first statement in + # the except body. This loop skips leading whitespace + # and indents + #TODO(cwinter) suite-cleanup + suite_stmts = e_suite.children + for i, stmt in enumerate(suite_stmts): + if isinstance(stmt, pytree.Node): + break + + # The assignment is different if old_N is a tuple or list + # In that case, the assignment is old_N = new_N.args + if is_tuple(N) or is_list(N): + assign = Assign(target, Attr(new_N, Name(u'args'))) + else: + assign = Assign(target, new_N) + + #TODO(cwinter) stopgap until children becomes a smart list + for child in reversed(suite_stmts[:i]): + e_suite.insert_child(0, child) + e_suite.insert_child(i, assign) + elif N.prefix == u"": + # No space after a comma is legal; no space after "as", + # not so much. + N.prefix = u" " + + #TODO(cwinter) fix this when children becomes a smart list + children = [c.clone() for c in node.children[:3]] + try_cleanup + tail + return pytree.Node(node.type, children) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_except.pyc b/PythonHome/Lib/lib2to3/fixes/fix_except.pyc deleted file mode 100644 index 72a727d0d2b402a911e95a3672b6f22e1f905f0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2949 zcmbVOTW{P%6h7mT-FU`L zBH2&n34Q?*zkpxBU*MPY2k^uj=bUkRK_#Mf?1|_2T)uOit^GCA`D5qD?EtE)hX239 zNB@jV2r$G|KA!fC(di716-vbM_%uq7WZ-K>ym2fKlnln{ zGnE+?-tBZgmTQ&Lt=n>NcTJuit4zs(jI{JwF)~TKF1Vzxk?(TBbZjc&+tTEdSV_bl zN7_`n{;dz`M7p>J^1d|I>fji0;2n-rh0p^(*Gd}n&G^}oGID$<{q(|xH5tUrkmTBs zqdu#p=wL)H_w)^zh}EdfkKY0A2IA43$ibZTFlAtxxJ=GXrj*?`h&X<#QoE((9#USt z1I$g2xLIUV>*y#ob=+?nlkrO*9WX7VMA~DVX3B0Tq|Bku6CIFQs%5ei;G++4IokyT zP+(;Vc(nf*_8ce$lnxXQj06~5Yw*;8Y=$XyD*e?_gUX+%L!zQ|!40sodg#D+;$#RX zGj#7@w`}(aYd^vTa&p5Kij4%j)h1$^Cm2zq7_K>=D3=^EGcN@^n>+S1IF8~l!}=yy zp80XEdgK^y({ZS@Azve2(;mJ8FZu?)ZR~v;9qh%?!5uUHe2+q`Y4t3u4NS>2aver# zSdsJxxYvXR#Hv^jSA`+O*mPUmZ4^qr$mTRjMKo~?ok=& z&rpC1&}8SHHi@|>*YR~-uHRjkJsl<37)+Oi)Hzn%tv9;Bc0&*=Kg}oidlr8crT!Y_QF@6-^@9nNz9hU&ue~Ylifx@v??Lu<7}ey^0cIhHG$RuLflY$}W`CP;>!11=}{ne!-RW36vDY zG>oPIOL^3Wr!~m_6v#wAbO`B7))IRTIT?OAOD8}v3tpFr4Jc*^g}{Fm2XeOwTR8`3 zp8}R~F=riER(7q5DG6aP#pS%z!dw};2Wmu4#VHYH45Unk}mchRTCT^u@z)HDXc}fDPX_>5S z_o%=7cFthk^Q^48D56mnQ6J~jp}yvkJINFdh@8kW#|3g?qj}ClEuxC-QAyg7#p5-` z^T@q|G^`kaSfwsmWm}n=#D1V$;&W-tyQG=%^fw=G@qkO!sYl0>yG-9{+!*4Fbd=)R zo}x7FDjA%2F3nMwI>IG$F5zQ6nZkoytB_|J%HpZ+@$h84Y*VZFkY8wURseM#8_nLh z^Q3Q)^if2DW7DN~99UJzT;7vuoK-ZWc<65NC=SL+;`6?5M>BfW=aAadnRT%ck2&qm zk!}J{(~uc`d)#qMY3Q@IfP?wYbDhJO`KiWVO35c=*2M7cA zV2g!fI5|@39j-T*(#e?V2+X|PMDeTQvBmkSs>o4W&Xnng_=^OOKSuCg*ts_E*-$;8 R64%rn&HB8czYV9|{0H7fZqxt( diff --git a/PythonHome/Lib/lib2to3/fixes/fix_exec.py b/PythonHome/Lib/lib2to3/fixes/fix_exec.py new file mode 100644 index 0000000000..50e1854454 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_exec.py @@ -0,0 +1,40 @@ +# Copyright 2006 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Fixer for exec. + +This converts usages of the exec statement into calls to a built-in +exec() function. + +exec code in ns1, ns2 -> exec(code, ns1, ns2) +""" + +# Local imports +from .. import pytree +from .. import fixer_base +from ..fixer_util import Comma, Name, Call + + +class FixExec(fixer_base.BaseFix): + BM_compatible = True + + PATTERN = """ + exec_stmt< 'exec' a=any 'in' b=any [',' c=any] > + | + exec_stmt< 'exec' (not atom<'(' [any] ')'>) a=any > + """ + + def transform(self, node, results): + assert results + syms = self.syms + a = results["a"] + b = results.get("b") + c = results.get("c") + args = [a.clone()] + args[0].prefix = "" + if b is not None: + args.extend([Comma(), b.clone()]) + if c is not None: + args.extend([Comma(), c.clone()]) + + return Call(Name(u"exec"), args, prefix=node.prefix) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_exec.pyc b/PythonHome/Lib/lib2to3/fixes/fix_exec.pyc deleted file mode 100644 index 60dd9f7fa72ac33bf6c61c5d54fb5cdba71c8a5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1387 zcmbVLUuzRV5TCtEE=_2)2!chW`*s&-3)a^fY)gI8AlHDHR?f?1lU}?(<#r<}q%XE# z!O!8V-@%XL7w|WGEk#5SFYGTfvoo_Zznyh|u64e@`*@tt&FA9(C6wy@VE<(LsVv3u%O2yoS#6nA16M*(oX>j zObb#V*tM)Tn02rPKEvaH3(*TeN8;lyB5iWBCw-QE8NY~&3+bnYFGp59@wa@Lu=qjt zY|!#Ap+Qj^8JjZS^8;U=*a*Mt_qsPp>*$0#3L>!xXR8vnjz0u$oFF%<7%n{C}crzLfScfosLekbhK;A=chcn znla*rb}-p(j;-QC;|=DIq3A~d604#uI^w?ltwG!54w0)rk!hTDpwyd2Ln zR=JNsHCJX0!oiy;Df9E#q@%3v;O+ika1{2#huFQV^qobZ6ouSWh()1&#CMN&Zqlsgo2j;>TVfCJnDI<)`u`})GO|~5(BsoIQ{=hpVqH9O Fe*wEc8rc8< diff --git a/PythonHome/Lib/lib2to3/fixes/fix_execfile.py b/PythonHome/Lib/lib2to3/fixes/fix_execfile.py new file mode 100644 index 0000000000..2f29d3b281 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_execfile.py @@ -0,0 +1,52 @@ +# Copyright 2006 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Fixer for execfile. + +This converts usages of the execfile function into calls to the built-in +exec() function. +""" + +from .. import fixer_base +from ..fixer_util import (Comma, Name, Call, LParen, RParen, Dot, Node, + ArgList, String, syms) + + +class FixExecfile(fixer_base.BaseFix): + BM_compatible = True + + PATTERN = """ + power< 'execfile' trailer< '(' arglist< filename=any [',' globals=any [',' locals=any ] ] > ')' > > + | + power< 'execfile' trailer< '(' filename=any ')' > > + """ + + def transform(self, node, results): + assert results + filename = results["filename"] + globals = results.get("globals") + locals = results.get("locals") + + # Copy over the prefix from the right parentheses end of the execfile + # call. + execfile_paren = node.children[-1].children[-1].clone() + # Construct open().read(). + open_args = ArgList([filename.clone()], rparen=execfile_paren) + open_call = Node(syms.power, [Name(u"open"), open_args]) + read = [Node(syms.trailer, [Dot(), Name(u'read')]), + Node(syms.trailer, [LParen(), RParen()])] + open_expr = [open_call] + read + # Wrap the open call in a compile call. This is so the filename will be + # preserved in the execed code. + filename_arg = filename.clone() + filename_arg.prefix = u" " + exec_str = String(u"'exec'", u" ") + compile_args = open_expr + [Comma(), filename_arg, Comma(), exec_str] + compile_call = Call(Name(u"compile"), compile_args, u"") + # Finally, replace the execfile call with an exec call. + args = [compile_call] + if globals is not None: + args.extend([Comma(), globals.clone()]) + if locals is not None: + args.extend([Comma(), locals.clone()]) + return Call(Name(u"exec"), args, prefix=node.prefix) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_execfile.pyc b/PythonHome/Lib/lib2to3/fixes/fix_execfile.pyc deleted file mode 100644 index 9475b53c252bcca3d3cf1b97ab3d8df31612c645..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2028 zcmbVNTW{k;6h7lPHz#Q-cwm>S5z@wspbzj`Dz;1asZ=Ys62f$4oOqHt_!4=>&`Qn= z<%u7{3x9zB#Seh*jN`T|UI0fvIWyl3og_?UQ=RD;5TGkTcpOMiGCK$Bgx0x4s&aR z$y-5NyIppOmtCp_t)Xhu%+dg*|-B^PeFaTkx?$gSm zTZ^`XRyt%*z!dBBS*KChorQE{q+_Oy2y{E7dO&bj59zI~b05KWMDc*?5rq@ddlV0O z$^OPvJEW&<1=1Zerj?EJP~A8F5eQ69D2C4tZTG0&V<+1w)c^z04?`+LQBP_8Mr*=u zQ%72YL=N-aR`u7{RlEOC-MK|>aEl?Gm^x1ousHYj(62L8g$Jeqk%9RRKL+LvbdtaD zn02|~NvU{@ip`EGWfWJ8bGPDQGKig3JTQwQ+rV-KmdqIjv$3-&C5F^{69N2x%4??pB?yj<88*p=MgeF>}JL1fP9YD=hHqT z)gLn9czt%W8}VG4xa75#dF-)XGutv<8YXWqfl{g})yf~Ufe90i-z3qFYG{h2*$)>f z#H_0O6<=w_B-ibJTV8KU%|_c^@G(;WHXAD4NOvV|Y_fX0ac7pjc@U5x>LYLmm#4}6 zGEL^6>EiQCz8w|QunqWNb7KNQ)pCVPJ9~sf>SHz{#=;R(F}2^e-VyKP_o0|{#$t%Q zcf})X2>A!*^|;g~-Z13*C=AV29EMpDS1B*K4Hso4HCOHU>yRUlbTUty+x6wMi;ENg z%zpyuef<9^37>D_DPG0F^hB@Mv(B1kGFrkgE*1y`Ecr|xd@L%Rqzxz-Lk1ZSaARO( m05@Q%L6CtS?;YbigR9>-|DS=Ix*ax^I${@10@l8GVgC(XM6Ch< diff --git a/PythonHome/Lib/lib2to3/fixes/fix_exitfunc.py b/PythonHome/Lib/lib2to3/fixes/fix_exitfunc.py new file mode 100644 index 0000000000..89fb3db533 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_exitfunc.py @@ -0,0 +1,72 @@ +""" +Convert use of sys.exitfunc to use the atexit module. +""" + +# Author: Benjamin Peterson + +from lib2to3 import pytree, fixer_base +from lib2to3.fixer_util import Name, Attr, Call, Comma, Newline, syms + + +class FixExitfunc(fixer_base.BaseFix): + keep_line_order = True + BM_compatible = True + + PATTERN = """ + ( + sys_import=import_name<'import' + ('sys' + | + dotted_as_names< (any ',')* 'sys' (',' any)* > + ) + > + | + expr_stmt< + power< 'sys' trailer< '.' 'exitfunc' > > + '=' func=any > + ) + """ + + def __init__(self, *args): + super(FixExitfunc, self).__init__(*args) + + def start_tree(self, tree, filename): + super(FixExitfunc, self).start_tree(tree, filename) + self.sys_import = None + + def transform(self, node, results): + # First, find a the sys import. We'll just hope it's global scope. + if "sys_import" in results: + if self.sys_import is None: + self.sys_import = results["sys_import"] + return + + func = results["func"].clone() + func.prefix = u"" + register = pytree.Node(syms.power, + Attr(Name(u"atexit"), Name(u"register")) + ) + call = Call(register, [func], node.prefix) + node.replace(call) + + if self.sys_import is None: + # That's interesting. + self.warning(node, "Can't find sys import; Please add an atexit " + "import at the top of your file.") + return + + # Now add an atexit import after the sys import. + names = self.sys_import.children[1] + if names.type == syms.dotted_as_names: + names.append_child(Comma()) + names.append_child(Name(u"atexit", u" ")) + else: + containing_stmt = self.sys_import.parent + position = containing_stmt.children.index(self.sys_import) + stmt_container = containing_stmt.parent + new_import = pytree.Node(syms.import_name, + [Name(u"import"), Name(u"atexit", u" ")] + ) + new = pytree.Node(syms.simple_stmt, [new_import]) + containing_stmt.insert_child(position + 1, Newline()) + containing_stmt.insert_child(position + 2, new) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_exitfunc.pyc b/PythonHome/Lib/lib2to3/fixes/fix_exitfunc.pyc deleted file mode 100644 index 8c4fbe1939d7ec0d1f3578068c4bef21911c314a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2682 zcmbVO-)|d55T3j9?<6D?+B7^=hY^HOD%-Z{FtM|wEKOT;0_3`-sSNt_o z775Xar9+8JnM1itBbRcIMjkoPdXzONZ_=nqd5cCZ%G)$*Q{JIbhw?6sx|H{5)MM)g zDUW6wG~sPc`kCmQ=!elJB`rD(+BonF7QKVA_(^H&&yDiSiEkEWpiWaenHOWvOOM7(o?0Qqu8hbE4IO680Sg`53JQPIEb^% zHhJlw%=6d+&QP6XX;IsmMQ-c{D<7w)k5*_d66Ub}A%D&1EEFfqA;o#}L^dRaO{9=R z<^*vfF=!)q7<4E+3;@df%8q*eE1%%f9E+ThD9x)<+k5rDsNit+`}L%M#SZKW`n>OT zi_6z+N=j>062(T2F#CQG7Yo0Cr+@onU;MG#JAI#(thoOgC%3QAU$(spfI6*oWNdEt zuW*2ns`5nX{S^?a<1~}$pzrtBjOqLLuf)~A*Z0Awdx+;Un9G32xL{BVmGL!h>OB^g z{~TH}ja{0#v~=hfVwMw=8TP{f)+>j($cA_UEE@z($(Ib)o>{vJU85sQE0UAn*y$Q(r^ zL|tP?C4^lFfsF%)m|g+u6E+T&Y0Cpz;`iA#?n z54dMdbdXsacV)YjH0a!sK@$Vc7yq3#h(ljCuxrXkJ2dm?+@rImj5la0#?C8H{uE@J zu;7ljO8jAMGTWl0O?zi8TJqU%34(1pc1brKXm-fH4Xlh{Jr`(6M-Z{L_-z&V>>8c5 zY1t(7NjwnFHc+T8G(t$?`fadk7ZcbAass1}!^)y=!*` z8&m0px<|Xqjf*G)kYX5avlMEe^yWOFIj*s8<#SL)t7&Si(&ihU9K=Q6`jfOs(DVGd zzkTUH$rLwpKTZ;EJnMI$UgVjN$HA5r-i}2%*Sw$KhZH3_hw$ad+B`+Q1UFd-wD2t+ zNyUycup8Jat+?7k9@WT)Wuij74q_)ADD-$5!c_>C%G;q;mBnKv#{{1vubEp%xs|3bmPM)`Zt^+{@P?aL4N>618ju__!==%-yV*)~8`lRhrbMynt+? zeMc)R#(;iNsFT(6Wsx|Z{{Ozfg~EU-AU|z*GJ<94dK6&u;>7#HcZ8?NVc!$M{C}s4Yn>)ave2jEGr{%P^TW;6uHiiLw z%f&@eQjQrch`D+ygt8$RZ*iR~?Envmj^;MaYQ_q85u), list(<>), tuple(<>), sorted(<>), ...join(<>), or +for V in <>:. + +NOTE: This is still not correct if the original code was depending on +filter(F, X) to return a string if X is a string and a tuple if X is a +tuple. That would require type inference, which we don't do. Let +Python 2.6 figure it out. +""" + +# Local imports +from ..pgen2 import token +from .. import fixer_base +from ..fixer_util import Name, Call, ListComp, in_special_context + +class FixFilter(fixer_base.ConditionalFix): + BM_compatible = True + + PATTERN = """ + filter_lambda=power< + 'filter' + trailer< + '(' + arglist< + lambdef< 'lambda' + (fp=NAME | vfpdef< '(' fp=NAME ')'> ) ':' xp=any + > + ',' + it=any + > + ')' + > + > + | + power< + 'filter' + trailer< '(' arglist< none='None' ',' seq=any > ')' > + > + | + power< + 'filter' + args=trailer< '(' [any] ')' > + > + """ + + skip_on = "future_builtins.filter" + + def transform(self, node, results): + if self.should_skip(node): + return + + if "filter_lambda" in results: + new = ListComp(results.get("fp").clone(), + results.get("fp").clone(), + results.get("it").clone(), + results.get("xp").clone()) + + elif "none" in results: + new = ListComp(Name(u"_f"), + Name(u"_f"), + results["seq"].clone(), + Name(u"_f")) + + else: + if in_special_context(node): + return None + new = node.clone() + new.prefix = u"" + new = Call(Name(u"list"), [new]) + new.prefix = node.prefix + return new diff --git a/PythonHome/Lib/lib2to3/fixes/fix_filter.pyc b/PythonHome/Lib/lib2to3/fixes/fix_filter.pyc deleted file mode 100644 index 58e3986b084632bab0342ec3ae28d58d420be0dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2225 zcmbVNUr*yk5FaNYfgH3as;gSv%eIwjM?!g^Y9A0my+iQCrKf;;*ObaN_BvT`);{n0 z0Ev5|->5J5-Y-Ur)weI^@zaGXkf0}rIk7Xo4LNo^S zC}~jU(X2t^26>D(DQnWKMdMbDw_;}u9Ok!;avmr|&< z={KTlqMyc(DCy8)u*~k>dqn%{LYBf#BP-%*q$kpdRAp9{!TyGL-4jaNTx81F;4Zn> z?{;5F5xvb-0%a*|8EKQ|gM_Rbb!8vby!wMrJW+3 zoBi)ll}QCnWkp`uepfY6!2ks$yTl+rle$K`KvS-2coG>Iw3y3a7|o>H?4lT!8{hzC z-OXo(T?e9cXbKstC=0nb^1|8`kkKFet{-9`?qQ$LvCLNh=-9DG5>484o!jEh9WQb7 zqT|q+qr;%d!hb@oEAZ6G4YO!=l0<_dKbPgUV=&XNx&DHHzEas;2`3fY3NRj(6YkJk zGfd>iIg#nM@N0MX)oPhJ4ANpSeD-2bT#2`7kvOHm7dKSD=kJJ~@V9(%Q4At|xrp$_ z%FY9dzwywYvJaH+E5gyjP|c~~m81UGbO|4^-=qaMK+AzY1oQ=h5=Oq^D8!C{H}TRikWU~^Ch;A0L+v}P-xCnF=DQh zpGfQGN1VaXhz*V0IAH;97|Zo3N{N9oV*9t_#K@7;pe?sD+`%pbJCGxeUWuo>Up5e4?YWk}kW?Utq}13Vf_ivO4&e&yJ4v zMniWHPEnZa5x4K{DL&vRBhK0rEVB&I_S#R|jdo)gtO9c$!Z68W1jV^7CQ@&Xup!G} z#Pih!&p9f?3Lmk$Fr0r^xw=Fj0o~2<(c&*|l@v4q=W2%y*MT=5dyl;@ G8-D{Brt^^i diff --git a/PythonHome/Lib/lib2to3/fixes/fix_funcattrs.py b/PythonHome/Lib/lib2to3/fixes/fix_funcattrs.py new file mode 100644 index 0000000000..9e45c02857 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_funcattrs.py @@ -0,0 +1,21 @@ +"""Fix function attribute names (f.func_x -> f.__x__).""" +# Author: Collin Winter + +# Local imports +from .. import fixer_base +from ..fixer_util import Name + + +class FixFuncattrs(fixer_base.BaseFix): + BM_compatible = True + + PATTERN = """ + power< any+ trailer< '.' attr=('func_closure' | 'func_doc' | 'func_globals' + | 'func_name' | 'func_defaults' | 'func_code' + | 'func_dict') > any* > + """ + + def transform(self, node, results): + attr = results["attr"][0] + attr.replace(Name((u"__%s__" % attr.value[5:]), + prefix=attr.prefix)) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_funcattrs.pyc b/PythonHome/Lib/lib2to3/fixes/fix_funcattrs.pyc deleted file mode 100644 index c6d704bb5e98f6f5d1035fba6df7ccbbe65797bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1083 zcmbVL&5G1O5Ux%#Q3qER55fv!ACzPj=ir`%b|k|EvESr|{_ zL-{s7gfC!KXLY;?YC~75x~nQ*)mQC*KNx>~`+iZt#2ZR>KHt>buGUstnPlBS;o8{mOhpG3L0|?I+ot@~pXd$ZeM?O;$9C9Pp=c z1f{I9UR$$2DcVy0OTJPSHag~0 zs^bBlIwS=#Or0CyCX&q)6kCs)afCb{efDAN!#Vcc@k}~i25|Qll1r8kJH~bli3j92 z#OS%DgpO1ELQiKx+&4lf`imud-AUvxCPzy%(aE*W3Yj=|$?IdLdzsMv;6$2{x^lT2 zto$;}P)`!7BE~%ka}Tx2>Xph@TIG*zd$OWoF(d_X<;G&NzOdKO5eaQf)pqqwGz@_Q zc7xq!t`>V0O(BR1A>7yrQMYBU$s|n6u9x-zmDy`iwDmf(D%S(JH_w;Lm&rV#Vcmms z+Fv6~Xb=gd0~WF{486H~MXr7!aL5n|IzU3=x0lgdrH6h}gJ<|o@KLyY{|m-7<8&y0 NN=yx)f""" + + # This should be run last -- some things check for the import + run_order = 10 + + def transform(self, node, results): + new = BlankLine() + new.prefix = node.prefix + return new diff --git a/PythonHome/Lib/lib2to3/fixes/fix_future.pyc b/PythonHome/Lib/lib2to3/fixes/fix_future.pyc deleted file mode 100644 index f8ca6dc2aaba0ba731a4790d9089fcc60e297209..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 888 zcmbVK!EV$r5FIDkKm(O3apGpmVRPC894Qsuik`{}Wmh1gl}vWy2p1=gY=?HGa)OWI zzxV-WoE1gl1d-<1j>qHo-Z=hwnEiPFak+*47vuN}!<{4403{-WIs(n0ji8Kx(K-el zLz_UE;5q>r!PNvB+?c?3fNuaF$`tApmiav@_70(tt@$Fk5Y6BRD}~^y?Tz&=%NlFi zzc+Ye3|Ed@+3RX6YksZ#Cth`2w!PnRtvWf&RD`8-hTt=VM%_p&HkFg(zXSX?*H!oV z60<$6F4WCMAn;o<9iC&jrw9@yGtyJWL4HE=%LzGv!cbJP%wtM^fiMaXME`_OX_)fX z)Pt6yt6KT;_)hFGpN`p6RIuZxir8+cQi4Gu&N19$1Ro6i8pADvD+aeQh=9u=X^~TM z5frC5>#ao5IaTolPUeZ4hE_g9ubsc98xMljd*4*0g=) z)kcrx-kz;iuZu;v#15S>wwAV_f_FUsfowtMJiu^NB4ufm#%Z(|X_6U2)Mkq;aS8>& lAJ1m+N{_};<{TdpK9*4NzqkZjPDUe6Lu<&lG&y2N(Jzjh!V>@h diff --git a/PythonHome/Lib/lib2to3/fixes/fix_getcwdu.py b/PythonHome/Lib/lib2to3/fixes/fix_getcwdu.py new file mode 100644 index 0000000000..82233c8993 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_getcwdu.py @@ -0,0 +1,19 @@ +""" +Fixer that changes os.getcwdu() to os.getcwd(). +""" +# Author: Victor Stinner + +# Local imports +from .. import fixer_base +from ..fixer_util import Name + +class FixGetcwdu(fixer_base.BaseFix): + BM_compatible = True + + PATTERN = """ + power< 'os' trailer< dot='.' name='getcwdu' > any* > + """ + + def transform(self, node, results): + name = results["name"] + name.replace(Name(u"getcwd", prefix=name.prefix)) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_getcwdu.pyc b/PythonHome/Lib/lib2to3/fixes/fix_getcwdu.pyc deleted file mode 100644 index a5d6d6a82ae7506c0f9f60f57b6e66aaca2f1cf4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 895 zcmbVK!EV$r5FI<&0Ff${BL^glOVS=90oQf~iwYN5RoRsg(Ml$pc-vIYI*J{&mC9-P zDE^BdV8&UszzJc=FEg=c=FRg2KM&#`pT90D*slP;Z*bdp2sJ=~$e`w+8MGV<4vhQ& zbO3D#MTmX~io?|eHh3_B?*Kc1FGU1(1dH?$C3}ewzi)0-FWhD6M0HtiFO(I=W*5p; z*Y%Jd31=Ss^eBrPj!`K?a52J$!sWWOYWx@Czj@gze~7t1jEU|$p}-k#`y4@GCyZzo zf$u7$u8?UlfqaotA)6z_;*ZstYt^5K#Mnf*zHBskwQ;9OmWVCZK27%Y6EPL#_V!pz z|4LDjphR_on>4k@2zQ+7Kl>KIT>w|upqCg`C6~jFu^mHU0rm53IzlQqL}-jP9hqIP zP?wa7I8wS-oh~btQ}a0m`FJ00mEMebOs)2p?Vz2_DLTbHf_;Hjw))ttSGrlha_04l zq_>1}-)`33x+i!IMcLYo>D#C1SgHpsW+^dqj}fFK(o*_2lCm}Rpvk41%YIPq0FBuv zS(&ygU9;9BvGcdf@Z~Y^?oSu}X#uAr^MPbC}einV_Qr4zI9(V@y?!Qmi h;2Q1q^EYQWZ#Y~&-~UnZLY$1PPf6;LQh3M?`7iGjwZs4b diff --git a/PythonHome/Lib/lib2to3/fixes/fix_has_key.py b/PythonHome/Lib/lib2to3/fixes/fix_has_key.py new file mode 100644 index 0000000000..bead4cb51c --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_has_key.py @@ -0,0 +1,110 @@ +# Copyright 2006 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Fixer for has_key(). + +Calls to .has_key() methods are expressed in terms of the 'in' +operator: + + d.has_key(k) -> k in d + +CAVEATS: +1) While the primary target of this fixer is dict.has_key(), the + fixer will change any has_key() method call, regardless of its + class. + +2) Cases like this will not be converted: + + m = d.has_key + if m(k): + ... + + Only *calls* to has_key() are converted. While it is possible to + convert the above to something like + + m = d.__contains__ + if m(k): + ... + + this is currently not done. +""" + +# Local imports +from .. import pytree +from ..pgen2 import token +from .. import fixer_base +from ..fixer_util import Name, parenthesize + + +class FixHasKey(fixer_base.BaseFix): + BM_compatible = True + + PATTERN = """ + anchor=power< + before=any+ + trailer< '.' 'has_key' > + trailer< + '(' + ( not(arglist | argument) arg=any ','> + ) + ')' + > + after=any* + > + | + negation=not_test< + 'not' + anchor=power< + before=any+ + trailer< '.' 'has_key' > + trailer< + '(' + ( not(arglist | argument) arg=any ','> + ) + ')' + > + > + > + """ + + def transform(self, node, results): + assert results + syms = self.syms + if (node.parent.type == syms.not_test and + self.pattern.match(node.parent)): + # Don't transform a node matching the first alternative of the + # pattern when its parent matches the second alternative + return None + negation = results.get("negation") + anchor = results["anchor"] + prefix = node.prefix + before = [n.clone() for n in results["before"]] + arg = results["arg"].clone() + after = results.get("after") + if after: + after = [n.clone() for n in after] + if arg.type in (syms.comparison, syms.not_test, syms.and_test, + syms.or_test, syms.test, syms.lambdef, syms.argument): + arg = parenthesize(arg) + if len(before) == 1: + before = before[0] + else: + before = pytree.Node(syms.power, before) + before.prefix = u" " + n_op = Name(u"in", prefix=u" ") + if negation: + n_not = Name(u"not", prefix=u" ") + n_op = pytree.Node(syms.comp_op, (n_not, n_op)) + new = pytree.Node(syms.comparison, (arg, n_op, before)) + if after: + new = parenthesize(new) + new = pytree.Node(syms.power, (new,) + tuple(after)) + if node.parent.type in (syms.comparison, syms.expr, syms.xor_expr, + syms.and_expr, syms.shift_expr, + syms.arith_expr, syms.term, + syms.factor, syms.power): + new = parenthesize(new) + new.prefix = prefix + return new diff --git a/PythonHome/Lib/lib2to3/fixes/fix_has_key.pyc b/PythonHome/Lib/lib2to3/fixes/fix_has_key.pyc deleted file mode 100644 index e8f7f94b29c03434a79852611e0d0b351d687a5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3153 zcmbtW?`|7K5TCOh|GC6%2&8Q&4NDQ6U5XJ!;zN~0q@h(MAfQX2A}Snb-#R|~{+Qi$ z8zcJ*;T8DCWAK5u;8_qaz|5>;Cr}kZ6Ww@sc6a7Cznh)8;-7W*w@2R{bYS*Z#NUtb z(J_h$;0UDyQ2`PM(gGY6z@d2&k|LxfI4aqBiPx9lXvxl(ASpvyfujnfRXD1mwhVF! z`Zeg{@e2F|a0>ACkqc234jMIb`E~)|L3|>W=;liFLLCg`xY2C6?p~NAT9{n4=30?T z)5{|*LM4Sf87ir@j6|FXBUP$J-W8@Ng%@X@n-8T5O|I^`uE4)&Ze`FE@9u~Jor=)Q z?pODB4-f9T?>EJxUYtm_FjR3GsY$IJ~jZ_^p_V%ML>Ng_JE zFguna%*KnLX7EJ^BfBk>JPuWqU_0Q;qV+*rRFIU^c z{Hau1tReQ>64P65V>-Mu*BKRJzNszYwLIa?-h(H0{;^@MAWL4uyD)DMMGef;B-Tbu z@M;{7QjBhkQqSA=CAIqb^KbP`|Ss7oKI~SD3nxp_|$n?ByAF3SouE zb(WV{US_!p-3koKpsqURB|1wH)X0umgGrU9*tsbD4;`Fh=h{H1**ch)q5le-Sm%8O z3ITf=ZVGB(u0T|Sh`ZaV<4h4s3DhqR>6g#xk@vZst1v;7%g`;rDOy`*5c5^EfRv!D zLbu2pFc_rd55`?*-1T$T5LKOet+__qFpR5Yw9X8jf47#T4UXhhme*On#_|TsO_r~- zT!(Ir342%|!pd1?Hi>v4(OI%Z;JJ%_SnHdP|=l zFrtwdQPGYwTj`a=YCfVfRO$r&8cOJ0Z2pQW$bF@9#T8zUQ*F<1g=d`^52eL4t23s8 zhlioT%9JsJG&G%_?GV^$7#wzef0-N+!cIbJx<8#f#oiHXY-bc@m_=N<*kZ2im^uxW zGgc;H+Kyz`?w(aDj4;s8Xh?8+PzBsX>fd4rS8iK}LXxEBwqFB}V&o9Q)LJebQQf z=xt>_k>OJ#^~te4eTF#;@U1banS9#7WniIi;;8lb)42UOiQ9Kf{=sAF*_vc9Ylbas z@?;h3d8V;}rVnwVAD{qd#i=>#&U&%rTy|U>zv-;vsO;Qyt~qbuXw9h?)=|HPx;1AL z|I2vhE$2GQ6+C$v*BTTIvls*!ejEe=zvUoE^JtXNl$bhHBWWo1d!ONl3?_h~Pa$UJ zi`~P+`~JTF9 isinstance(x, T) + type(x) is T -> isinstance(x, T) + type(x) != T -> not isinstance(x, T) + type(x) is not T -> not isinstance(x, T) + +* Change "while 1:" into "while True:". + +* Change both + + v = list(EXPR) + v.sort() + foo(v) + +and the more general + + v = EXPR + v.sort() + foo(v) + +into + + v = sorted(EXPR) + foo(v) +""" +# Author: Jacques Frechet, Collin Winter + +# Local imports +from .. import fixer_base +from ..fixer_util import Call, Comma, Name, Node, BlankLine, syms + +CMP = "(n='!=' | '==' | 'is' | n=comp_op< 'is' 'not' >)" +TYPE = "power< 'type' trailer< '(' x=any ')' > >" + +class FixIdioms(fixer_base.BaseFix): + explicit = True # The user must ask for this fixer + + PATTERN = r""" + isinstance=comparison< %s %s T=any > + | + isinstance=comparison< T=any %s %s > + | + while_stmt< 'while' while='1' ':' any+ > + | + sorted=any< + any* + simple_stmt< + expr_stmt< id1=any '=' + power< list='list' trailer< '(' (not arglist) any ')' > > + > + '\n' + > + sort= + simple_stmt< + power< id2=any + trailer< '.' 'sort' > trailer< '(' ')' > + > + '\n' + > + next=any* + > + | + sorted=any< + any* + simple_stmt< expr_stmt< id1=any '=' expr=any > '\n' > + sort= + simple_stmt< + power< id2=any + trailer< '.' 'sort' > trailer< '(' ')' > + > + '\n' + > + next=any* + > + """ % (TYPE, CMP, CMP, TYPE) + + def match(self, node): + r = super(FixIdioms, self).match(node) + # If we've matched one of the sort/sorted subpatterns above, we + # want to reject matches where the initial assignment and the + # subsequent .sort() call involve different identifiers. + if r and "sorted" in r: + if r["id1"] == r["id2"]: + return r + return None + return r + + def transform(self, node, results): + if "isinstance" in results: + return self.transform_isinstance(node, results) + elif "while" in results: + return self.transform_while(node, results) + elif "sorted" in results: + return self.transform_sort(node, results) + else: + raise RuntimeError("Invalid match") + + def transform_isinstance(self, node, results): + x = results["x"].clone() # The thing inside of type() + T = results["T"].clone() # The type being compared against + x.prefix = u"" + T.prefix = u" " + test = Call(Name(u"isinstance"), [x, Comma(), T]) + if "n" in results: + test.prefix = u" " + test = Node(syms.not_test, [Name(u"not"), test]) + test.prefix = node.prefix + return test + + def transform_while(self, node, results): + one = results["while"] + one.replace(Name(u"True", prefix=one.prefix)) + + def transform_sort(self, node, results): + sort_stmt = results["sort"] + next_stmt = results["next"] + list_call = results.get("list") + simple_expr = results.get("expr") + + if list_call: + list_call.replace(Name(u"sorted", prefix=list_call.prefix)) + elif simple_expr: + new = simple_expr.clone() + new.prefix = u"" + simple_expr.replace(Call(Name(u"sorted"), [new], + prefix=simple_expr.prefix)) + else: + raise RuntimeError("should not have reached here") + sort_stmt.remove() + + btwn = sort_stmt.prefix + # Keep any prefix lines between the sort_stmt and the list_call and + # shove them right after the sorted() call. + if u"\n" in btwn: + if next_stmt: + # The new prefix should be everything from the sort_stmt's + # prefix up to the last newline, then the old prefix after a new + # line. + prefix_lines = (btwn.rpartition(u"\n")[0], next_stmt[0].prefix) + next_stmt[0].prefix = u"\n".join(prefix_lines) + else: + assert list_call.parent + assert list_call.next_sibling is None + # Put a blank line after list_call and set its prefix. + end_line = BlankLine() + list_call.parent.append_child(end_line) + assert list_call.next_sibling is end_line + # The new prefix should be everything up to the first new line + # of sort_stmt's prefix. + end_line.prefix = btwn.rpartition(u"\n")[0] diff --git a/PythonHome/Lib/lib2to3/fixes/fix_idioms.pyc b/PythonHome/Lib/lib2to3/fixes/fix_idioms.pyc deleted file mode 100644 index dcfe1b6f7d2e510d6ee4cef31dbe2ecad5d872fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4432 zcmds4-EJGl6+X*faV1wm61!28qGJOADJKKAl=lx=_B-_?@{zw`WAhGe&1P2Bn795b6H9|J3r@~IX~YyGh6-7J^!EI{OM>Q zvtJeO-{5fxnnY*-ijnG z>9s%&B3~j9txD7oTanS4oI*rX{wnfTr?sdm_)G(bN^jWr;P}I5LNq z#V||FQxivVmN-*nrWo2dH%S)RJT-%Cnie*n^z*`P`~G9IKkTPxwiHlYPAn)Ati~=& zl{WY3ku$?V4=#R&4$2a(qwsWy%x?OW@e!gcG=q|o6$6HH8vHKoG4`-6ntoTl8 zq|t5PNjx{}(VJmBw&uysBNM0a#cX_>Pwmd5Mf*>(V(6>R=ca4Mu`4<+{&*OaW}I)k zEH66c;55rR=UcwtPb0b(j?Jw(v#HJdVOI_x)6mFx1{bpOl6-2p%AWPw+ zIgKxD9-j1_?KC)7L$i;76m@p8BV`KY=56+6FHA+`Nmm1OXM=z14ySVB+!8go~5O*p{0tEf`}jCi!gl zIC@fsquahiM4_|aESN-lx6SrWL_5r`etyQKU249!MSX5!d`Ixys#1LWRl2O zC4M@s!Q4~j7T`nM|Ihq5VA12r%4Z*s`z@LR|DIgo5X6~Skt_Y6i%q_&viTb8&pCG#i5&6WsX^R9!3tUiso+LPm)ZNN5@=0z(}~T4CbwtZLVXztKRv~ds7+kW+ReDZ1>pFAzHU%p};cWlG*jNYDH25X@D zJs!u7cpuk3@ILZt_#1GWn`fUCFl52tPwAAA&?B%8-Z_Hx=+PO!(lsp1*Qz&b$GWDT zobkba)Ks|jFSu~PSsmJZpeN6~8mc3-q6I5d<{p}_()0c}j*R-J^xj99M&hOJG|Q84 zfqi{xK?M~*TAE`}3VI>HMI}z`i#*SAb#_3)KqW9HxpmWVp@-7@xLOaUTitMF6Gyq? zt$7h|mY>^}nM7M*(S@@b+7gYjq`|HXGLnxT~s!a9>TXYU~shpu<_cSFXAMpQEPoHkG$7XBu6wq#EoI1S&DwqYh(npwPR}_IQd3 znG%a;>Z4r<0VmUGm2Flirv`N}&Tv7X&6C^$oB`BcMRZ zpu>Sxn8IFFu5nju$<>NhqTB=M^QMR4Naw*5`KZ!J8oWS$igduGt|cQdwJ3A8295p< zcIfYmd*BtTx*3LR1jy?Zai7m7QAn`;wXeqdGFq1_pMsQmjRR7@yb*C%6`#fE#uUZIBlb8B+j9}I0|hBmjF znSKl^>1?1;6rI^3Fc{1M7f?=_h!04`y>gpm=T^(Ie#ON_oTaMHD8pw3N$~k*(?aX& zGv{nh3N52rS7}G+;*)Wlo&~Jm0aHkq`jd%Gqi}$4rbu0I7wr1k35Vz9M|#hX<3D=SS1O;Ac$R=7Jy@10HeX#%(8hYhpI_tw4j zO2hk^*U*~riMLT%^ZZJyy5==%#@no{d-p3X)Rp_y4v!n%KMYfRJ%ypVHw^L3JjGQz zRIOPdN+mBQ<9HC47&v};_(F}_|J`B1s&V-2`1nO|peK6pF($N@1x)vVTFy;-pK3wL zpW)H7s^K--4=SzImfu=y)ebs5zjW^~jIsgL#aIG13*U{?A|97e(sHhaov_yEYhe$5 p&EXE&xZQJnXyOA-?>|3CX?50a>BGHGAkpz8YScEoZ3L!K`7ac$mqq{p diff --git a/PythonHome/Lib/lib2to3/fixes/fix_import.py b/PythonHome/Lib/lib2to3/fixes/fix_import.py new file mode 100644 index 0000000000..88e9d10334 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_import.py @@ -0,0 +1,99 @@ +"""Fixer for import statements. +If spam is being imported from the local directory, this import: + from spam import eggs +Becomes: + from .spam import eggs + +And this import: + import spam +Becomes: + from . import spam +""" + +# Local imports +from .. import fixer_base +from os.path import dirname, join, exists, sep +from ..fixer_util import FromImport, syms, token + + +def traverse_imports(names): + """ + Walks over all the names imported in a dotted_as_names node. + """ + pending = [names] + while pending: + node = pending.pop() + if node.type == token.NAME: + yield node.value + elif node.type == syms.dotted_name: + yield "".join([ch.value for ch in node.children]) + elif node.type == syms.dotted_as_name: + pending.append(node.children[0]) + elif node.type == syms.dotted_as_names: + pending.extend(node.children[::-2]) + else: + raise AssertionError("unknown node type") + + +class FixImport(fixer_base.BaseFix): + BM_compatible = True + + PATTERN = """ + import_from< 'from' imp=any 'import' ['('] any [')'] > + | + import_name< 'import' imp=any > + """ + + def start_tree(self, tree, name): + super(FixImport, self).start_tree(tree, name) + self.skip = "absolute_import" in tree.future_features + + def transform(self, node, results): + if self.skip: + return + imp = results['imp'] + + if node.type == syms.import_from: + # Some imps are top-level (eg: 'import ham') + # some are first level (eg: 'import ham.eggs') + # some are third level (eg: 'import ham.eggs as spam') + # Hence, the loop + while not hasattr(imp, 'value'): + imp = imp.children[0] + if self.probably_a_local_import(imp.value): + imp.value = u"." + imp.value + imp.changed() + else: + have_local = False + have_absolute = False + for mod_name in traverse_imports(imp): + if self.probably_a_local_import(mod_name): + have_local = True + else: + have_absolute = True + if have_absolute: + if have_local: + # We won't handle both sibling and absolute imports in the + # same statement at the moment. + self.warning(node, "absolute and local imports together") + return + + new = FromImport(u".", [imp]) + new.prefix = node.prefix + return new + + def probably_a_local_import(self, imp_name): + if imp_name.startswith(u"."): + # Relative imports are certainly not local imports. + return False + imp_name = imp_name.split(u".", 1)[0] + base_path = dirname(self.filename) + base_path = join(base_path, imp_name) + # If there is no __init__.py next to the file its not in a package + # so can't be a relative import. + if not exists(join(dirname(base_path), "__init__.py")): + return False + for ext in [".py", sep, ".pyc", ".so", ".sl", ".pyd"]: + if exists(base_path + ext): + return True + return False diff --git a/PythonHome/Lib/lib2to3/fixes/fix_import.pyc b/PythonHome/Lib/lib2to3/fixes/fix_import.pyc deleted file mode 100644 index 6bde2782f45d68dcd4499c7f8a7963c6f2d748e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3163 zcmbVOTW=dh6h33GuSuIUks1OOUCPAz<18tO-p&8SlYAWnKNh3r~|1eEK#f|DN(0HDlAjzP+X?Op^igIg*p{Vs?@1cQlm}{8rV^xxK2rf zIt@yi)M-*OL!B9{Rp|lD&Qe$-U80>+)Q5JRCy$9f>zt;rK^yHR`|uEAEjrM-+s|@0 zN`_f(U1I~Q6P;SK(!AMs%`iyZ$hch{rGtr%4&8p9C9d7pZk+Xk*bSpx_iUCQUc@A{ z3tR6rUHn9~FjJhM2Lsc*rh8eU&0{JnPw6yQ)9`6~Q$OL@zgc+{2d_sZgxFRPmLu+S zuzoi%I{FL0w!;fG2>71{iMBkklSQemVxSKqV~ypK89i+CTdb@h_L~xl=$pgD*a|OZ zyE^UhVQhwHdU(w55M!c&q9a8IztC7w{wvEJDalcZ#;B7b3t6V!66Np8j6Rd%#x^$AT74@)R9F zQIxuY8)nw(&<~7XtfpD0SHysYC5l+AM}MMT<_w0TbT`fRQ&zCb1#TT+G8K>48-JIKGb8F*g8aSJBq^`=x3u(dM20%hC`i(cJ8TF zGl7idW!}7MjLvP8r8n|C%L}M6CL~A!9a}vxLVj*#_3o`~{F1 zsPbdQ3u*jIK)I$08>NIAJg_-7z&$X!f`(r_Tpd#{nFxxap43 zA?PoROFU-g;1VYcdf0k>>lHeZ#IwPwSo@Ki5!!p-$)Li6 z&2feD-)QVm{!l^z5y_RuB}~zm2#Wbf+yJj)`UqYixYIPQkuP$CwSG-4sVBnyRiB}b{=e^x{akAQtrgKvoB zGR`m;Aqb@7sAg%QvY^g@aOTx~sj8}KQO&7Fsfkgwyr`Vg0;s9S?Z zsZm{EZjt+WgQo<`1y}{6fHQCnh&rr@%M_^u;GxQ>z~3s*unqtY5J61_rY|NB-sWoz zxx;r8zL@Z#gwLZv6;OSiFIDVjV`W-mFYfalv9WibHrX5bhFUL>6fvFzS%$9`-;dJB z`aam%l<}Y693bAkV!~vTcRXDP+sw!(MV*nSAGEnKaWD! zl^|2j_T^;Xm#};vU>n8S_r*;CX-T533r3+vL*(lEXsW<5Am=Y#MRZIqc6&XJ^Bz70+?ERpanockji s#nO~Q2=c*EbT4<}H6$9>tGMvLoR|DvDKd7IK~)4%o>v#txpHIiZ$rDKjsO4v diff --git a/PythonHome/Lib/lib2to3/fixes/fix_imports.py b/PythonHome/Lib/lib2to3/fixes/fix_imports.py new file mode 100644 index 0000000000..93c9e6787b --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_imports.py @@ -0,0 +1,145 @@ +"""Fix incompatible imports and module references.""" +# Authors: Collin Winter, Nick Edds + +# Local imports +from .. import fixer_base +from ..fixer_util import Name, attr_chain + +MAPPING = {'StringIO': 'io', + 'cStringIO': 'io', + 'cPickle': 'pickle', + '__builtin__' : 'builtins', + 'copy_reg': 'copyreg', + 'Queue': 'queue', + 'SocketServer': 'socketserver', + 'ConfigParser': 'configparser', + 'repr': 'reprlib', + 'FileDialog': 'tkinter.filedialog', + 'tkFileDialog': 'tkinter.filedialog', + 'SimpleDialog': 'tkinter.simpledialog', + 'tkSimpleDialog': 'tkinter.simpledialog', + 'tkColorChooser': 'tkinter.colorchooser', + 'tkCommonDialog': 'tkinter.commondialog', + 'Dialog': 'tkinter.dialog', + 'Tkdnd': 'tkinter.dnd', + 'tkFont': 'tkinter.font', + 'tkMessageBox': 'tkinter.messagebox', + 'ScrolledText': 'tkinter.scrolledtext', + 'Tkconstants': 'tkinter.constants', + 'Tix': 'tkinter.tix', + 'ttk': 'tkinter.ttk', + 'Tkinter': 'tkinter', + 'markupbase': '_markupbase', + '_winreg': 'winreg', + 'thread': '_thread', + 'dummy_thread': '_dummy_thread', + # anydbm and whichdb are handled by fix_imports2 + 'dbhash': 'dbm.bsd', + 'dumbdbm': 'dbm.dumb', + 'dbm': 'dbm.ndbm', + 'gdbm': 'dbm.gnu', + 'xmlrpclib': 'xmlrpc.client', + 'DocXMLRPCServer': 'xmlrpc.server', + 'SimpleXMLRPCServer': 'xmlrpc.server', + 'httplib': 'http.client', + 'htmlentitydefs' : 'html.entities', + 'HTMLParser' : 'html.parser', + 'Cookie': 'http.cookies', + 'cookielib': 'http.cookiejar', + 'BaseHTTPServer': 'http.server', + 'SimpleHTTPServer': 'http.server', + 'CGIHTTPServer': 'http.server', + #'test.test_support': 'test.support', + 'commands': 'subprocess', + 'UserString' : 'collections', + 'UserList' : 'collections', + 'urlparse' : 'urllib.parse', + 'robotparser' : 'urllib.robotparser', +} + + +def alternates(members): + return "(" + "|".join(map(repr, members)) + ")" + + +def build_pattern(mapping=MAPPING): + mod_list = ' | '.join(["module_name='%s'" % key for key in mapping]) + bare_names = alternates(mapping.keys()) + + yield """name_import=import_name< 'import' ((%s) | + multiple_imports=dotted_as_names< any* (%s) any* >) > + """ % (mod_list, mod_list) + yield """import_from< 'from' (%s) 'import' ['('] + ( any | import_as_name< any 'as' any > | + import_as_names< any* >) [')'] > + """ % mod_list + yield """import_name< 'import' (dotted_as_name< (%s) 'as' any > | + multiple_imports=dotted_as_names< + any* dotted_as_name< (%s) 'as' any > any* >) > + """ % (mod_list, mod_list) + + # Find usages of module members in code e.g. thread.foo(bar) + yield "power< bare_with_attr=(%s) trailer<'.' any > any* >" % bare_names + + +class FixImports(fixer_base.BaseFix): + + BM_compatible = True + keep_line_order = True + # This is overridden in fix_imports2. + mapping = MAPPING + + # We want to run this fixer late, so fix_import doesn't try to make stdlib + # renames into relative imports. + run_order = 6 + + def build_pattern(self): + return "|".join(build_pattern(self.mapping)) + + def compile_pattern(self): + # We override this, so MAPPING can be pragmatically altered and the + # changes will be reflected in PATTERN. + self.PATTERN = self.build_pattern() + super(FixImports, self).compile_pattern() + + # Don't match the node if it's within another match. + def match(self, node): + match = super(FixImports, self).match + results = match(node) + if results: + # Module usage could be in the trailer of an attribute lookup, so we + # might have nested matches when "bare_with_attr" is present. + if "bare_with_attr" not in results and \ + any(match(obj) for obj in attr_chain(node, "parent")): + return False + return results + return False + + def start_tree(self, tree, filename): + super(FixImports, self).start_tree(tree, filename) + self.replace = {} + + def transform(self, node, results): + import_mod = results.get("module_name") + if import_mod: + mod_name = import_mod.value + new_name = unicode(self.mapping[mod_name]) + import_mod.replace(Name(new_name, prefix=import_mod.prefix)) + if "name_import" in results: + # If it's not a "from x import x, y" or "import x as y" import, + # marked its usage to be replaced. + self.replace[mod_name] = new_name + if "multiple_imports" in results: + # This is a nasty hack to fix multiple imports on a line (e.g., + # "import StringIO, urlparse"). The problem is that I can't + # figure out an easy way to make a pattern recognize the keys of + # MAPPING randomly sprinkled in an import statement. + results = self.match(node) + if results: + self.transform(node, results) + else: + # Replace usage of the module. + bare_name = results["bare_with_attr"][0] + new_name = self.replace.get(bare_name.value) + if new_name: + bare_name.replace(Name(new_name, prefix=bare_name.prefix)) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_imports.pyc b/PythonHome/Lib/lib2to3/fixes/fix_imports.pyc deleted file mode 100644 index 1f50f80f354c50d828d7e789c108519ed89dccdf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5230 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 GQSc43#e^9E diff --git a/PythonHome/Lib/lib2to3/fixes/fix_input.py b/PythonHome/Lib/lib2to3/fixes/fix_input.py new file mode 100644 index 0000000000..fbf4c72f5c --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_input.py @@ -0,0 +1,26 @@ +"""Fixer that changes input(...) into eval(input(...)).""" +# Author: Andre Roberge + +# Local imports +from .. import fixer_base +from ..fixer_util import Call, Name +from .. import patcomp + + +context = patcomp.compile_pattern("power< 'eval' trailer< '(' any ')' > >") + + +class FixInput(fixer_base.BaseFix): + BM_compatible = True + PATTERN = """ + power< 'input' args=trailer< '(' [any] ')' > > + """ + + def transform(self, node, results): + # If we're already wrapped in a eval() call, we're done. + if context.match(node.parent.parent): + return + + new = node.clone() + new.prefix = u"" + return Call(Name(u"eval"), [new], prefix=node.prefix) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_input.pyc b/PythonHome/Lib/lib2to3/fixes/fix_input.pyc deleted file mode 100644 index affdba7317bdb0b44dbacdfe037cf7e2317f60de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1103 zcmbVL!EVz)5S_Ihw+WP1LLhNK@`<>Y9Drk6K`M}t+6Xz75T`minZAacUZ6!FB zkK(`h0p4sVrJN9!_IY-8Jp1O&*#EIL`2OzGG^byWkM|2Kvj7xCDNs=1krq^WlzJq1 z@00ea3MdVz>QUNTdjl60QW}y_AuTtk=+Tv+bd!pZlt;@x&GGdHeIvRedY=xc*raLP z=Nq2`UY8fDjqD<`QNGCPGi9Q(UUfDejYhjLZ4;@_nT~IqyQ9*>hp__7Xq<)LWcaO2mV}OEaf{RUkCt$z=qF#uUOdTb2gs?$$>$$$(6^1L@GqZn-#0RkW zcunK4k8|!C*V)55#4^VKOSBa9MbHw$d)$Zi5i^>y%V+(+f*~S&k^$Ks*^nEJIC#!n zlQ}Y=D^E;gPCw}Y)UnAjAs)K53W~=pr)9{S+NukSbVL>OU96+BR@G}~uA5pVe4Mau ziR&JxbPX~}&z(^>g>ng7Wjbw*S%Sn|kZ zww&oTzqc<>PF^LG sys.intern(s)""" + +# Local imports +from .. import pytree +from .. import fixer_base +from ..fixer_util import Name, Attr, touch_import + + +class FixIntern(fixer_base.BaseFix): + BM_compatible = True + order = "pre" + + PATTERN = """ + power< 'intern' + trailer< lpar='(' + ( not(arglist | argument) any ','> ) + rpar=')' > + after=any* + > + """ + + def transform(self, node, results): + syms = self.syms + obj = results["obj"].clone() + if obj.type == syms.arglist: + newarglist = obj.clone() + else: + newarglist = pytree.Node(syms.arglist, [obj.clone()]) + after = results["after"] + if after: + after = [n.clone() for n in after] + new = pytree.Node(syms.power, + Attr(Name(u"sys"), Name(u"intern")) + + [pytree.Node(syms.trailer, + [results["lpar"].clone(), + newarglist, + results["rpar"].clone()])] + after) + new.prefix = node.prefix + touch_import(None, u'sys', node) + return new diff --git a/PythonHome/Lib/lib2to3/fixes/fix_intern.pyc b/PythonHome/Lib/lib2to3/fixes/fix_intern.pyc deleted file mode 100644 index f3d5dff5e9736c549b9b60264fb19b44fe212dff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1574 zcmbVM-;diw5FXo!lk;6^)t9PORk`pG2hl@n->SQa9;FfzM3wIlB04ZmvN@dkN7&t{ zjpRHXPyLJdzxoH1Z)S7XBEbV#@_2S;cfQ$gW*oe`5&ik&uctHGJpsO7;WZh=oM-~+ z(cGufqspg=PadxWSqC%;+`2<$hpH}3x>SWU390JQqz7M@R6xr);gJFd zfe_PSVsKw@gKOc+>8XQb%#~K=J-$(lXVtt``Y0Z_{0CxVJ07d^qGV^e%JuOe`J2;i zflT7Mu}Q8k%EH*VjiIe8RokPy-o%6BL5%Nc7&p`9F|?24Ux$csO#Cj$QG$s77Du9f zF&M?ee+;E1)!`r>eeBK`C>+CoE>`E8F&E4&zhC1u`{1-CS`uvoYJKML?$YC~*mkJx z(9)+C4HM8SpY&6)IB%Eg2VBZ!cejBzi|Yc?r!DLV=hNM7NNq^^EnNUAq~|~1rfrYf z-fsIZKK{F?jQ^^J5dw}~iRgyaUC zvND^>$l+Pp)UMC%W~Fc?#B&u-q3%YZnJd{WeVH;+$^#|4cMa+0N-K;~%Hty_W5iCl zk`7aq3sGv0$4Kb;b!kny4?Sgr#G!a-YpMREjNZI!Gc7XhtLkszbmHaWifqh znE!TVb?Ck8DbeuBahrIto z@+p`16TF7=36W int / unicode -> str conversion. + +eg. isinstance(x, (int, long)) -> isinstance(x, (int, int)) + -> isinstance(x, int) +""" + +from .. import fixer_base +from ..fixer_util import token + + +class FixIsinstance(fixer_base.BaseFix): + BM_compatible = True + PATTERN = """ + power< + 'isinstance' + trailer< '(' arglist< any ',' atom< '(' + args=testlist_gexp< any+ > + ')' > > ')' > + > + """ + + run_order = 6 + + def transform(self, node, results): + names_inserted = set() + testlist = results["args"] + args = testlist.children + new_args = [] + iterator = enumerate(args) + for idx, arg in iterator: + if arg.type == token.NAME and arg.value in names_inserted: + if idx < len(args) - 1 and args[idx + 1].type == token.COMMA: + iterator.next() + continue + else: + new_args.append(arg) + if arg.type == token.NAME: + names_inserted.add(arg.value) + if new_args and new_args[-1].type == token.COMMA: + del new_args[-1] + if len(new_args) == 1: + atom = testlist.parent + new_args[0].prefix = atom.prefix + atom.replace(new_args[0]) + else: + args[:] = new_args + node.changed() diff --git a/PythonHome/Lib/lib2to3/fixes/fix_isinstance.pyc b/PythonHome/Lib/lib2to3/fixes/fix_isinstance.pyc deleted file mode 100644 index b79a0d5298d9c39eb94c930f4432f48dcbd3336d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1807 zcmbVMUvC>l5TCuX&(5_ep&*q=AT2`34upU}eM_Szp-4z1ASbB83OX)#YiFJF-F0`b zbtL<#d2}rWODSHFD52kOQ5P zMOBXFCwo!@&8M;{bynqy1=bmvRV7rduF9P_R%2X$i?%=8mVH=ldly?<-pNfYx2I6q z+KT1!)0W&U*EXMAn+d>A7I%JKoklo zxJtv&7q!Jj9k#iyC>KgKIO&J1{0oSOR#!;!?lnr;y9L?15jvCV0$Q@y?{NhSZQZU+ z%PZO2hQL)*e{`eI5kt*Ba>_bZPR43hdy9|d-i=yst0(vH^Z#DDJkt@tWeoEURtxJ8 z%YKhYo$t9tNb`Ur+g!A0-lB=1MVrP%i-=r6^ESPNq(igcY2KkPfBcos0$Oxwu}1SX znuO$F)27RS%x_*2(LAKf$g^E?os|n@?VU>^^NRU-m$Ud_b7kK3<~ZrlWQ_+wJbOsb zUJ>X#qDjntfkOQILL7%QxwE>KHQ4SUJ%yDK0u(d%`X$%WMTiHJ z-!#g(E|}~>7dd9kt$|S`=Gml9d3$$NtATH4_IA8~^u)3A=V{R>@1uYjOAfz1I@QoTqx5uVX_n9$+IRbQO(KwGBC?Og5DS3Yx?s?v@sGkp(c_9J#9);r8d`ZGFC5eAOl4M%tO~EYZ|I{Gs{Bj%|C0RACQ>XDp z`lNife|q|4aO{DYrc5f6D>GmuxAFYPpa%SwakJPiNF<_e6hy)C5-Qg%N%ATKG;C?W p (map|filter|zip) and + itertools.ifilterfalse --> itertools.filterfalse (bugs 2360-2363) + + imports from itertools are fixed in fix_itertools_import.py + + If itertools is imported as something else (ie: import itertools as it; + it.izip(spam, eggs)) method calls will not get fixed. + """ + +# Local imports +from .. import fixer_base +from ..fixer_util import Name + +class FixItertools(fixer_base.BaseFix): + BM_compatible = True + it_funcs = "('imap'|'ifilter'|'izip'|'izip_longest'|'ifilterfalse')" + PATTERN = """ + power< it='itertools' + trailer< + dot='.' func=%(it_funcs)s > trailer< '(' [any] ')' > > + | + power< func=%(it_funcs)s trailer< '(' [any] ')' > > + """ %(locals()) + + # Needs to be run after fix_(map|zip|filter) + run_order = 6 + + def transform(self, node, results): + prefix = None + func = results['func'][0] + if ('it' in results and + func.value not in (u'ifilterfalse', u'izip_longest')): + dot, it = (results['dot'], results['it']) + # Remove the 'itertools' + prefix = it.prefix + it.remove() + # Replace the node which contains ('.', 'function') with the + # function (to be consistent with the second part of the pattern) + dot.remove() + func.parent.replace(func) + + prefix = prefix or func.prefix + func.replace(Name(func.value[1:], prefix=prefix)) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_itertools.pyc b/PythonHome/Lib/lib2to3/fixes/fix_itertools.pyc deleted file mode 100644 index e82a6c9d24017be4c6fc9c7acee00a38463954b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1760 zcmbVM{c7As5TBLqboLR)fzW^D5KmomQ81R$8H5 zB~6ea;Jiy;ArIC6`U0I<$#=#rq*Q1}v-9!OeC_&w?TkPD^xN?g`p3ubceuo+=}p&qmcbcA99> ztPFp6@aVxll7q>(gDEOqTf_5O7aL5T)`I64X2xYnOtQvIr1O|o?>c}N`4u;5c&A3k z)NrE-(tg|LG^NZVQ>DdMT&z}RGT{WFGrmlfGW@MnikI5* zm9Sla)6Ubw>PA>xuwx_?dYvp%BRbgtWwR8KZXko@e{os&b-T&`2$y+)L}0ra^>XgJ z)(@!lVo2@0L+wPxh+2;wo^L^X91*_x8c7sVAHz26n?f9B)PEAC%at&8qj#+dC+1J| zb%{`GyQk7`Mg16S^CVmsKfGo`mbOl%Ld$QnyGhF5mBpJZD53NTv-@{Vx zon!f(;B^4Cg?0dEc)qsb^~i0}Fn~R>_hHXFAHsP6Z2)JUgF(ipzOi<=<`4kiAt7Bb zU?o87L-oNScV13y5vTjt2<~NDWOTt8d0>dg5zX1mQs=1-62D++ill95%C4TuPJnZ8 zIRKV2$JR(Uu~dty7C5vK0es%w-6ihVGhGTx<$IH=M#O}KVFT2n&~JoeD?H1kwN&R? zR4QGHnEtxKFhb=Htkjw4?M$Prad0t(8q+Ug$~D5(5py58>FE!0ajN9vq16YcbnFb# z&2@qIgxy9%oQ%@ol~>%wjk$vaSio+w8*G<-;cc_AKW4YRT^2dxEmS8-i6=Hm+<{J# zLT8PlEk$usH^S~9bM!J<>Y_@mTqt45?Q+6h?n>jeVO&l>K0P`4KAyQ?>ZVL|oryZ$ zMUPENj{DDf#nh~uxD1U#fawII9Y649U1_P{Ns{R$#*8e)M6TRUjg`uE!i9H)cNJbt Z4)gy8`VQ3Tr{}#LD{S5-yo!I~Y diff --git a/PythonHome/Lib/lib2to3/fixes/fix_itertools_imports.py b/PythonHome/Lib/lib2to3/fixes/fix_itertools_imports.py new file mode 100644 index 0000000000..28610cfcb9 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_itertools_imports.py @@ -0,0 +1,57 @@ +""" Fixer for imports of itertools.(imap|ifilter|izip|ifilterfalse) """ + +# Local imports +from lib2to3 import fixer_base +from lib2to3.fixer_util import BlankLine, syms, token + + +class FixItertoolsImports(fixer_base.BaseFix): + BM_compatible = True + PATTERN = """ + import_from< 'from' 'itertools' 'import' imports=any > + """ %(locals()) + + def transform(self, node, results): + imports = results['imports'] + if imports.type == syms.import_as_name or not imports.children: + children = [imports] + else: + children = imports.children + for child in children[::2]: + if child.type == token.NAME: + member = child.value + name_node = child + elif child.type == token.STAR: + # Just leave the import as is. + return + else: + assert child.type == syms.import_as_name + name_node = child.children[0] + member_name = name_node.value + if member_name in (u'imap', u'izip', u'ifilter'): + child.value = None + child.remove() + elif member_name in (u'ifilterfalse', u'izip_longest'): + node.changed() + name_node.value = (u'filterfalse' if member_name[1] == u'f' + else u'zip_longest') + + # Make sure the import statement is still sane + children = imports.children[:] or [imports] + remove_comma = True + for child in children: + if remove_comma and child.type == token.COMMA: + child.remove() + else: + remove_comma ^= True + + while children and children[-1].type == token.COMMA: + children.pop().remove() + + # If there are no imports left, just get rid of the entire statement + if (not (imports.children or getattr(imports, 'value', None)) or + imports.parent is None): + p = node.prefix + node = BlankLine() + node.prefix = p + return node diff --git a/PythonHome/Lib/lib2to3/fixes/fix_itertools_imports.pyc b/PythonHome/Lib/lib2to3/fixes/fix_itertools_imports.pyc deleted file mode 100644 index f64c67ae65a22831f810e0fa6e55f1ded0d09332..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1985 zcmbtV&2Jk;6o0ep@7RfxqKcr1`hdtHP=ty&rLAz9RI1cCXl*INO0}%Lv+3IV)tPaL zk$s_X=D&b{fg4xO+!22RLY(2fw~iY)fK(jM^P8FX_501diT!)4@x%G&{V}XQHvWEs zL!Y4t0EQ?91Qx^s5(|bF2%6gv+mMuCSc0Ss!!jfl7*=qv1k!>@6+$#B!`A>W0X`en zAgDm!sZ!uBiq50xN~%tnsZNySnKHVQg`LPqWwI>R2Tqju`63FV7?&2&m(h9>`mvVp zb)rA<;|L688Yn^v=Z$!04UexgJ}#dI)8rnpOED@;N2pX9{goxYiJLI7UC>ou=eF}VDsIufAdscA3?^1Y6Ax$c!)#)f!G%oRj|9XVPV4rp$V8+FttFx%PTfC)m_pq z1uRRD)>o^jU;P4$5`m$w1>e}Pd;Ih#Se9W?=1?V=lqr;&^GXGl6;hT}NDpt=RN3ZR z3e#VCu8a5{ObxygY>mWW3iMu7VS>SGu)sU91=9+sU&$MtJWgLn{9niIhzRwTE`PGNyuf7vRUki4LcI2w?;u(LYmllQzw#HBi3^g1HUL2ACZRvPAM4gx%XF*(a8rZ9M*-p;lV8PDEEP!U3}q zuljkRVB5^tuIQs#lXeT8+o)JTD=*H{OQ}sn4K*VX&giz?w59n?Q))nNs26@bE86bg z({qRXcMT4;Cbz7a=h7u?W)sD#k9_T=ej@Q^0gRtTaiC=C+Se|7C*%428oaG8tj9v_n8WcBFX4 zMuDDAvMAgeXG!8?=VN^i3Sgl>K<(h-Ni@2MqtRWHeRM%jq$cUDA0KaZfe!LH=QGMr zHNMFS@vV<3nrMhU(X{H~EwLl&__t$~tT#mqwI+@h%7(Zt+V(9`!5QvYo7NrihP@}Y z*uF0K)#vl_xOmUwC)@LqESSa8^V~KjGA$HGrvxYWO*D#&(}}Y&KKM-gr`^He#O=9v z(C`(~*MsZQ6{z9RbOkD+Vz;cG!>2(F<9R_g#yUw~@#msSUAbO3AVQTlGf~WE&NsEV hiR5;K|BD{sb)ZE5w^}CeUP0FbI_aWnyDj$YzW^b%vjzYF diff --git a/PythonHome/Lib/lib2to3/fixes/fix_long.py b/PythonHome/Lib/lib2to3/fixes/fix_long.py new file mode 100644 index 0000000000..5dddde0d08 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_long.py @@ -0,0 +1,19 @@ +# Copyright 2006 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Fixer that turns 'long' into 'int' everywhere. +""" + +# Local imports +from lib2to3 import fixer_base +from lib2to3.fixer_util import is_probably_builtin + + +class FixLong(fixer_base.BaseFix): + BM_compatible = True + PATTERN = "'long'" + + def transform(self, node, results): + if is_probably_builtin(node): + node.value = u"int" + node.changed() diff --git a/PythonHome/Lib/lib2to3/fixes/fix_long.pyc b/PythonHome/Lib/lib2to3/fixes/fix_long.pyc deleted file mode 100644 index 70e572f80f0f07a833e9c1a5b211a3f73d8e7ec6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 810 zcmbVKU2oGc6unN;!m3TG*fS#91I<&B;1wb01W%(vX(dEd$>hUbGdW3RJA+ERjUUDT z;sx)<)IA3fr0uFYaOf$v6>mqS1jzq!|-BW;+ZQdv;y~$EG zUDazIGLy9d#}g!r&$8^AeeUW)50t)qSg${(%altz^7?0TDf@Yh@SMg1U$FE~#d{)U z)s-N@mw7KRMN013), list(<>), +tuple(<>), sorted(<>), ...join(<>), or for V in <>:. + +NOTE: This is still not correct if the original code was depending on +map(F, X, Y, ...) to go on until the longest argument is exhausted, +substituting None for missing values -- like zip(), it now stops as +soon as the shortest argument is exhausted. +""" + +# Local imports +from ..pgen2 import token +from .. import fixer_base +from ..fixer_util import Name, Call, ListComp, in_special_context +from ..pygram import python_symbols as syms + +class FixMap(fixer_base.ConditionalFix): + BM_compatible = True + + PATTERN = """ + map_none=power< + 'map' + trailer< '(' arglist< 'None' ',' arg=any [','] > ')' > + > + | + map_lambda=power< + 'map' + trailer< + '(' + arglist< + lambdef< 'lambda' + (fp=NAME | vfpdef< '(' fp=NAME ')'> ) ':' xp=any + > + ',' + it=any + > + ')' + > + > + | + power< + 'map' trailer< '(' [arglist=any] ')' > + > + """ + + skip_on = 'future_builtins.map' + + def transform(self, node, results): + if self.should_skip(node): + return + + if node.parent.type == syms.simple_stmt: + self.warning(node, "You should use a for loop here") + new = node.clone() + new.prefix = u"" + new = Call(Name(u"list"), [new]) + elif "map_lambda" in results: + new = ListComp(results["xp"].clone(), + results["fp"].clone(), + results["it"].clone()) + else: + if "map_none" in results: + new = results["arg"].clone() + else: + if "arglist" in results: + args = results["arglist"] + if args.type == syms.arglist and \ + args.children[0].type == token.NAME and \ + args.children[0].value == "None": + self.warning(node, "cannot convert map(None, ...) " + "with multiple arguments because map() " + "now truncates to the shortest sequence") + return + if in_special_context(node): + return None + new = node.clone() + new.prefix = u"" + new = Call(Name(u"list"), [new]) + new.prefix = node.prefix + return new diff --git a/PythonHome/Lib/lib2to3/fixes/fix_map.pyc b/PythonHome/Lib/lib2to3/fixes/fix_map.pyc deleted file mode 100644 index 63e0f39e7928de3ddf3b3e84e905b344e8df7b17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3009 zcmb7G&2k$>5bl*^+1}WRD*=iCMNPp$t13qapg4rYMF`1>7)o|Qq9nDfc1P0KyEDtq ztSwW{feI&Hgje7RIPfN%c>%tjl^h#GRZwYr=clKCzV7MX_FtRfZ{K~tm(t?b#`|+T zwg$NN8X zXaT>>nlXZUV3ckqFrCf+mSx=8xeefVzutdvTP!d{v=r28gVZn;D_$C9Dm7J_V`DNY zjuRLrOQ|!Zr^0BD8xrX8ws^8gBfvE^*h1n!rgtnioNNw(nAS~3SRv;#gbK!PhqfL= zy{nNzQ^7&-rWVRtUO*ITWGZ5nt3xS%Q~+rkIKbFrm~Bb~*oM|XBaHK4&lrXO(l-cI z3pXMPK->xwb0~E)4KbbYEs4j-kEp}DOm>m5esCYbacfxl3isf?DN1)86Q$!t2FDyM zId_e?tJo_~+{|GAq!^prx-OP*4<99Eijn`ZAz$FJAA(4fh=3$2L)({&4wsA33RetV zYm|fGUesphKXEJ+_#taz4bbkE=2%vD{2H(Ku+cl4xhhdPwnZ=MaUA%bW5Q_nL~q-# z-A(j~c#6q$u_Jo@p4jon8+v-CEKiDYmb{+2GyUG8=#@P@Uz%}&i8s6kIe~qRu8YT* z2R^K&1M{RwGtN^}4k(93|T8=OXa zm>l5WBG;ya4js0rnt8qz=0l3TL?dFRF1L;s$h{VwwkcjEWV>7E1_fbQnR-?*==C7$ z&}oYfyHx#3F642xLN^-`Jn5dFtS%=n+bm!I!OdxL{C9tLeaXSwzfk5Svh+^^mKM^@ z7f^^k*LZQodx1TyY*2Our?Ig~2Ujm|T%&Abxe9O^r#HRRjE=@N-&z9pWv~S7wXtB} zRu^~yqrHeP{;qu=^ogm3otZk%1UII{m$uxPQgA=zj{>SYAbcNzArW8aChHxSsd?#N zljfzIFFwmFk6;oZaolS2W+4j0MbX0Dwnzj@6WtVceI%Riyl8d4?H?;Q6Ge>%jxKUm zqU~8Pg)(#{F1D_!b&95rDr+tlT8nlmbt)sShVBYT<8y2eRq1P9i6*R_uc7XwY>Fvr zqHUP*-H^-Jy25!^j+08G^!w_ZqIt+hL?uz1hwSr^p&2r6Lx$RelFn3~LCFvc3jk0T zybRw$hI~hc*FYj3c~h*+Cw`#O+`Q^aT0mhvviL6Wn?Tq`I6|KIunwMmrN+;4HU7w% zkDqbNuuNlsH9*DZPcB^V=8NDnOzfw8KDZWiT5kqh!A7tiybHP&YzA+&Hi8>?!r*#v zGk7c5YOi9a<9Xf&jX1d8!#L&-r#SX`632zfYM>T-8~3YPBKgrt9-#*nB|byOdE?SI z_xAT640pYI9FN%Op#bMAmtNPeA)E3Z9=it84Z81iTiw=f#Grcdah#bH7BRr(RO*kK zU|>c=-)~ (metaclass=X) methods. + + The various forms of classef (inherits nothing, inherits once, inherints + many) don't parse the same in the CST so we look at ALL classes for + a __metaclass__ and if we find one normalize the inherits to all be + an arglist. + + For one-liner classes ('class X: pass') there is no indent/dedent so + we normalize those into having a suite. + + Moving the __metaclass__ into the classdef can also cause the class + body to be empty so there is some special casing for that as well. + + This fixer also tries very hard to keep original indenting and spacing + in all those corner cases. + +""" +# Author: Jack Diederich + +# Local imports +from .. import fixer_base +from ..pygram import token +from ..fixer_util import Name, syms, Node, Leaf + + +def has_metaclass(parent): + """ we have to check the cls_node without changing it. + There are two possiblities: + 1) clsdef => suite => simple_stmt => expr_stmt => Leaf('__meta') + 2) clsdef => simple_stmt => expr_stmt => Leaf('__meta') + """ + for node in parent.children: + if node.type == syms.suite: + return has_metaclass(node) + elif node.type == syms.simple_stmt and node.children: + expr_node = node.children[0] + if expr_node.type == syms.expr_stmt and expr_node.children: + left_side = expr_node.children[0] + if isinstance(left_side, Leaf) and \ + left_side.value == '__metaclass__': + return True + return False + + +def fixup_parse_tree(cls_node): + """ one-line classes don't get a suite in the parse tree so we add + one to normalize the tree + """ + for node in cls_node.children: + if node.type == syms.suite: + # already in the preferred format, do nothing + return + + # !%@#! oneliners have no suite node, we have to fake one up + for i, node in enumerate(cls_node.children): + if node.type == token.COLON: + break + else: + raise ValueError("No class suite and no ':'!") + + # move everything into a suite node + suite = Node(syms.suite, []) + while cls_node.children[i+1:]: + move_node = cls_node.children[i+1] + suite.append_child(move_node.clone()) + move_node.remove() + cls_node.append_child(suite) + node = suite + + +def fixup_simple_stmt(parent, i, stmt_node): + """ if there is a semi-colon all the parts count as part of the same + simple_stmt. We just want the __metaclass__ part so we move + everything after the semi-colon into its own simple_stmt node + """ + for semi_ind, node in enumerate(stmt_node.children): + if node.type == token.SEMI: # *sigh* + break + else: + return + + node.remove() # kill the semicolon + new_expr = Node(syms.expr_stmt, []) + new_stmt = Node(syms.simple_stmt, [new_expr]) + while stmt_node.children[semi_ind:]: + move_node = stmt_node.children[semi_ind] + new_expr.append_child(move_node.clone()) + move_node.remove() + parent.insert_child(i, new_stmt) + new_leaf1 = new_stmt.children[0].children[0] + old_leaf1 = stmt_node.children[0].children[0] + new_leaf1.prefix = old_leaf1.prefix + + +def remove_trailing_newline(node): + if node.children and node.children[-1].type == token.NEWLINE: + node.children[-1].remove() + + +def find_metas(cls_node): + # find the suite node (Mmm, sweet nodes) + for node in cls_node.children: + if node.type == syms.suite: + break + else: + raise ValueError("No class suite!") + + # look for simple_stmt[ expr_stmt[ Leaf('__metaclass__') ] ] + for i, simple_node in list(enumerate(node.children)): + if simple_node.type == syms.simple_stmt and simple_node.children: + expr_node = simple_node.children[0] + if expr_node.type == syms.expr_stmt and expr_node.children: + # Check if the expr_node is a simple assignment. + left_node = expr_node.children[0] + if isinstance(left_node, Leaf) and \ + left_node.value == u'__metaclass__': + # We found a assignment to __metaclass__. + fixup_simple_stmt(node, i, simple_node) + remove_trailing_newline(simple_node) + yield (node, i, simple_node) + + +def fixup_indent(suite): + """ If an INDENT is followed by a thing with a prefix then nuke the prefix + Otherwise we get in trouble when removing __metaclass__ at suite start + """ + kids = suite.children[::-1] + # find the first indent + while kids: + node = kids.pop() + if node.type == token.INDENT: + break + + # find the first Leaf + while kids: + node = kids.pop() + if isinstance(node, Leaf) and node.type != token.DEDENT: + if node.prefix: + node.prefix = u'' + return + else: + kids.extend(node.children[::-1]) + + +class FixMetaclass(fixer_base.BaseFix): + BM_compatible = True + + PATTERN = """ + classdef + """ + + def transform(self, node, results): + if not has_metaclass(node): + return + + fixup_parse_tree(node) + + # find metaclasses, keep the last one + last_metaclass = None + for suite, i, stmt in find_metas(node): + last_metaclass = stmt + stmt.remove() + + text_type = node.children[0].type # always Leaf(nnn, 'class') + + # figure out what kind of classdef we have + if len(node.children) == 7: + # Node(classdef, ['class', 'name', '(', arglist, ')', ':', suite]) + # 0 1 2 3 4 5 6 + if node.children[3].type == syms.arglist: + arglist = node.children[3] + # Node(classdef, ['class', 'name', '(', 'Parent', ')', ':', suite]) + else: + parent = node.children[3].clone() + arglist = Node(syms.arglist, [parent]) + node.set_child(3, arglist) + elif len(node.children) == 6: + # Node(classdef, ['class', 'name', '(', ')', ':', suite]) + # 0 1 2 3 4 5 + arglist = Node(syms.arglist, []) + node.insert_child(3, arglist) + elif len(node.children) == 4: + # Node(classdef, ['class', 'name', ':', suite]) + # 0 1 2 3 + arglist = Node(syms.arglist, []) + node.insert_child(2, Leaf(token.RPAR, u')')) + node.insert_child(2, arglist) + node.insert_child(2, Leaf(token.LPAR, u'(')) + else: + raise ValueError("Unexpected class definition") + + # now stick the metaclass in the arglist + meta_txt = last_metaclass.children[0].children[0] + meta_txt.value = 'metaclass' + orig_meta_prefix = meta_txt.prefix + + if arglist.children: + arglist.append_child(Leaf(token.COMMA, u',')) + meta_txt.prefix = u' ' + else: + meta_txt.prefix = u'' + + # compact the expression "metaclass = Meta" -> "metaclass=Meta" + expr_stmt = last_metaclass.children[0] + assert expr_stmt.type == syms.expr_stmt + expr_stmt.children[1].prefix = u'' + expr_stmt.children[2].prefix = u'' + + arglist.append_child(last_metaclass) + + fixup_indent(suite) + + # check for empty suite + if not suite.children: + # one-liner that was just __metaclass_ + suite.remove() + pass_leaf = Leaf(text_type, u'pass') + pass_leaf.prefix = orig_meta_prefix + node.append_child(pass_leaf) + node.append_child(Leaf(token.NEWLINE, u'\n')) + + elif len(suite.children) > 1 and \ + (suite.children[-2].type == token.INDENT and + suite.children[-1].type == token.DEDENT): + # there was only one line in the class body and it was __metaclass__ + pass_leaf = Leaf(text_type, u'pass') + suite.insert_child(-1, pass_leaf) + suite.insert_child(-1, Leaf(token.NEWLINE, u'\n')) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_metaclass.pyc b/PythonHome/Lib/lib2to3/fixes/fix_metaclass.pyc deleted file mode 100644 index 7463ff4a0af5758d53ad8eacfbc59d310eb62df4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6469 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 method.__?__). +""" +# Author: Christian Heimes + +# Local imports +from .. import fixer_base +from ..fixer_util import Name + +MAP = { + "im_func" : "__func__", + "im_self" : "__self__", + "im_class" : "__self__.__class__" + } + +class FixMethodattrs(fixer_base.BaseFix): + BM_compatible = True + PATTERN = """ + power< any+ trailer< '.' attr=('im_func' | 'im_self' | 'im_class') > any* > + """ + + def transform(self, node, results): + attr = results["attr"][0] + new = unicode(MAP[attr.value]) + attr.replace(Name(new, prefix=attr.prefix)) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_methodattrs.pyc b/PythonHome/Lib/lib2to3/fixes/fix_methodattrs.pyc deleted file mode 100644 index 30fe38e207254066bfba4ca034a53b50369bd239..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1107 zcmbVLO>fgc5S_IXr%h?8Kpc8N@`<=0awt+Sl#~|1iA0rCgor8@$GZ`({1JKAw3XUZ z`BD5Y{s3>*fpP^~`*vo>JNx#{*#EiN|MBt5G^N$!V}6ZcJ_8id3@Au>lnW|6nt3GH z_bK{;W%?PuipNfEL)ZLEnjPi9XGGr0&r)+T?Ry z0^Vhp;k;@}6&BiltyGv;TW9meY7<87(l9IJVfcKs`eG>Mp_IGBe&%6+BmlM#SY(&F zmh;5ucCCZ8NrDt>Fr-{GWh$lZ!9hOuRso~)#a)0s^T6$B12`_t6JziRC&FIm+ATOB zKX$B{wD}_>Q#!^lj{zD&3YKC9tzbhg!D>LFcpC8)%m+X}#Ivj}bbSye<<+y$)=8GL zHy93_D6gWyiufSB4%udczimfqup5qe_tS9X@}*qT?rOZ@qmBUA9#hysVRvqPvXD>E zwNK~pZw1|SoPz)ikoBG0rCT8o6}ZAQa?&DB3lUoyW4P3rbUqrCUfq4RJc=kS< zpXJ$n&sHzaxE&0mY`e&nXt=zxd=kVh&7!J{M{o@DC9x$Qik3Q`A!Ui)LD9Ljq%11c zi@=Od8_CK2RP9&ehGA{OZxwuT=yTeI*eS~@*fa%w#ByRiyq#-{|f=a B?aKfF diff --git a/PythonHome/Lib/lib2to3/fixes/fix_ne.py b/PythonHome/Lib/lib2to3/fixes/fix_ne.py new file mode 100644 index 0000000000..7025980b48 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_ne.py @@ -0,0 +1,23 @@ +# Copyright 2006 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Fixer that turns <> into !=.""" + +# Local imports +from .. import pytree +from ..pgen2 import token +from .. import fixer_base + + +class FixNe(fixer_base.BaseFix): + # This is so simple that we don't need the pattern compiler. + + _accept_type = token.NOTEQUAL + + def match(self, node): + # Override + return node.value == u"<>" + + def transform(self, node, results): + new = pytree.Leaf(token.NOTEQUAL, u"!=", prefix=node.prefix) + return new diff --git a/PythonHome/Lib/lib2to3/fixes/fix_ne.pyc b/PythonHome/Lib/lib2to3/fixes/fix_ne.pyc deleted file mode 100644 index 5844647f913d6236990990457a94ce9751dc72a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 941 zcmb7CO>fgc5S{fp4ymXF2X25;xcHPqxuy{RWP143Al7RR2@r2dG!YoJm&l^@0b z;tw!yUFZ=t(LT@Y?9RM5v-mpR@1w0vL6vP*%2C>2yx1XL=j0!jl?@HLg1 zs*uvK_d_2aP&yEQKs=ybL>oC6(NCglqEG3NiXkoIdr1CR;LY|sw_|snxv}fo+K#8Q z@wRr&_~>M^4dg(q1Y9JrzjQ5g?+>uqTyWjH2jXs!$*eQW4pB+G;D3UUpf37^op2UOFd|BpF-qrvzv~rl9|~M4+WB@|1R@0CMF*VDZmE6E%8q@^g}BG% z#v650a4Z|-!9EddvYKz#t8%+OcFl_wL|CAyc_M`={!k2yG8E)m5NQ$gw4RCK zh<1vc7uC-SL_@j`)DKNpTDam~&-Lh}?`X?XDn_0}7I}_y&Nhi}I)=1(`~LO252y14 zPK>IFKaPR8p+L*FE1h*nUh}s*sT(0lo7HyHwACYVEDDf%s$!&esA)`{RcwsIjE$+9 zqASJq3={0R`v_!t&U next(it), per PEP 3114.""" +# Author: Collin Winter + +# Things that currently aren't covered: +# - listcomp "next" names aren't warned +# - "with" statement targets aren't checked + +# Local imports +from ..pgen2 import token +from ..pygram import python_symbols as syms +from .. import fixer_base +from ..fixer_util import Name, Call, find_binding + +bind_warning = "Calls to builtin next() possibly shadowed by global binding" + + +class FixNext(fixer_base.BaseFix): + BM_compatible = True + PATTERN = """ + power< base=any+ trailer< '.' attr='next' > trailer< '(' ')' > > + | + power< head=any+ trailer< '.' attr='next' > not trailer< '(' ')' > > + | + classdef< 'class' any+ ':' + suite< any* + funcdef< 'def' + name='next' + parameters< '(' NAME ')' > any+ > + any* > > + | + global=global_stmt< 'global' any* 'next' any* > + """ + + order = "pre" # Pre-order tree traversal + + def start_tree(self, tree, filename): + super(FixNext, self).start_tree(tree, filename) + + n = find_binding(u'next', tree) + if n: + self.warning(n, bind_warning) + self.shadowed_next = True + else: + self.shadowed_next = False + + def transform(self, node, results): + assert results + + base = results.get("base") + attr = results.get("attr") + name = results.get("name") + + if base: + if self.shadowed_next: + attr.replace(Name(u"__next__", prefix=attr.prefix)) + else: + base = [n.clone() for n in base] + base[0].prefix = u"" + node.replace(Call(Name(u"next", prefix=node.prefix), base)) + elif name: + n = Name(u"__next__", prefix=name.prefix) + name.replace(n) + elif attr: + # We don't do this transformation if we're assigning to "x.next". + # Unfortunately, it doesn't seem possible to do this in PATTERN, + # so it's being done here. + if is_assign_target(node): + head = results["head"] + if "".join([str(n) for n in head]).strip() == u'__builtin__': + self.warning(node, bind_warning) + return + attr.replace(Name(u"__next__")) + elif "global" in results: + self.warning(node, bind_warning) + self.shadowed_next = True + + +### The following functions help test if node is part of an assignment +### target. + +def is_assign_target(node): + assign = find_assign(node) + if assign is None: + return False + + for child in assign.children: + if child.type == token.EQUAL: + return False + elif is_subtree(child, node): + return True + return False + +def find_assign(node): + if node.type == syms.expr_stmt: + return node + if node.type == syms.simple_stmt or node.parent is None: + return None + return find_assign(node.parent) + +def is_subtree(root, node): + if root == node: + return True + return any(is_subtree(c, node) for c in root.children) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_next.pyc b/PythonHome/Lib/lib2to3/fixes/fix_next.pyc deleted file mode 100644 index d0be9925a116c858f73049ff915fe2f01004516a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3435 zcmb7G?QYyu5S{DYc(X~`gaU<16*U!Vwgm#Tm5}-o^(z&ic2&HEidBp8uAS6duf6rX zt0q$V2M{3f173o6KtkdfcnV&C7vP-nri}^`VH1z<=iHeyXXd)`*P(@9?|s!9%Iw#` z`wAZWGejcNhcuFSk{cO&()Yx$-;lf^V8vlU&bxzx9a|!PivLp-ISdnB=8!t(+B)!fdTDAsp zGuuw9V6&`(%&isaw(Fb@-dzv0mATXJ1QSf(*|-y&`{0A~Yng{F9RuO!D9T4^QFjlc zJK1p$%ObKn<3X9*dVB%nn>-^L#5U~^71xC5#^Y2Q*W)~QOS-B^qCr+9S+Qj=Vt_L? zaAh!EFv`f8Xo%& zL<)3_qzFVqqtj$`5CjB>!1;^}8!ZWY9U5$Z$Nq%?zX{H)E(P@Ga$M}Z9k?paat^Jo ztp>4k)#X*b+{0Bl{**I^>%%<@-7wdk@0l z-^eaf$di#LyJ&lC8*BqN&`0NKLv|ZdeZqC4Cfi5^UF35pYDv)+H$Q79f>dM5bf-K{ zld8?5m^^lh)CzrenIzW5m5W@JrlF=58T=%!3S@((2bmr14N%+NYMMID<5?O+)UT>< z#yN70i!{Y-nr~`@+F=|sGEW&bI1IBo5Te4KKx^&(t!!{V&jx2*dG0=w*HWtbwaHFM z58lFKnYCh$dCSH(D`v@4T&bQ;DXu?3KTyOBVIzpualt!Th(pnSQ1)6oYp|f)e z^lu8ZC)JkhHf033k*N5`EV_W+807V-sUbHW9FeC8g)bwYweU+%9v3_c^%B#l zm&YRPHL9wm+U8XoMpPRXA)M4%{2{w@QvJE_$hp}fo`5#EfJ3;dU%H= z9j86=rTXz78{J_gqbD;BTKc<62Uaj`ux4q4oR~6#kw!a;97BneLHws^Nk;LE%({og z3(>{!B19C;s`YGdosykpOu-V7tJbEK%gSP-s>(_;aw~Nqd8|ddN+)?dOv45S!lN8z zHVpH!NJAy`3c8t%Q0TI)B0|z&yV@}-vqJS*IHL*Xs%#Q6w?bMLlCB*(7pgVXR+LFP zJJwEfXTz5{{R+ja6h|mtgV5|yagY>on&eenSX`{*HSE{BR*)mh27jJ!+UA6J!W=Rk z2L{7R-6`vT2&5W(gx|s%9&Kfw%xr`VvLsGMVP+szX`kTL02x?C zkzmevXI)I!*>uSgl|B_r+6%>1Oni%>8+R}2=lU;H;N!pjaSPw(-ZKyid`MXSCj#6|S}1o!J%1D459u)lJFcJOU$9@!7F4S*=VQ~T>9KR)~~%iUZ&Z=K4{gf zlNdk9scJtWFP3a2! __bool__ methods.""" +# Author: Collin Winter + +# Local imports +from .. import fixer_base +from ..fixer_util import Name, syms + +class FixNonzero(fixer_base.BaseFix): + BM_compatible = True + PATTERN = """ + classdef< 'class' any+ ':' + suite< any* + funcdef< 'def' name='__nonzero__' + parameters< '(' NAME ')' > any+ > + any* > > + """ + + def transform(self, node, results): + name = results["name"] + new = Name(u"__bool__", prefix=name.prefix) + name.replace(new) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_nonzero.pyc b/PythonHome/Lib/lib2to3/fixes/fix_nonzero.pyc deleted file mode 100644 index 93ce354ad1e1d0021e58aa3a956e2a048feb0724..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1055 zcmbVL-HOvd6h4!rtyUI9Q1C(s-XyMAMDLbb+{y}q8zfy2Lm{Tg1heF)WF}~(d$m54 z@8P5P0)A)G>auvF19Rq_IVazI=O^~hgYozG9~UX@mW}fzwt54R5k-)KGK)$IZ zwoM$nPi8PzO;bXzr2f=oYEoDT_XUI=L*)Enyh@bx*`XbXAVDxIYEvl_1^A#x{hbjb z%sJ)(ghWPyiAJ``&f)C96&ZvJ1FU`^Z0usCWujCj^Qr3@)pL`2^Vs!{Jmcn&eyOg| za?0MrYo1*|-qmRj1nIdoXut5TIcL$` zfVuCS9>Q3+5}oq-v5+et@{^j|-^z8Fq|!GR45MV3_ef19cOj}PwF=p*8KRb-eH>(j zdI)W@d|RxRWwCmuo99a&3dM3iOOy3R-$a;hlUiZQsyi?g6C*JecZJWY?pbpJacssW zj;ki?N;diJv$m7^0LuI{PMd0-=wem&6yF`6ot=b1cnjV?)c%EE$cZrnLu)98qoEb} zd|_%3$61qt2W$#iT$%n(7iC{n^9yiQ=lCHo^ak|*_?T);`}}9zvYwZ7TimmL0c^|H A7ytkO diff --git a/PythonHome/Lib/lib2to3/fixes/fix_numliterals.py b/PythonHome/Lib/lib2to3/fixes/fix_numliterals.py new file mode 100644 index 0000000000..b0c23f8041 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_numliterals.py @@ -0,0 +1,28 @@ +"""Fixer that turns 1L into 1, 0755 into 0o755. +""" +# Copyright 2007 Georg Brandl. +# Licensed to PSF under a Contributor Agreement. + +# Local imports +from ..pgen2 import token +from .. import fixer_base +from ..fixer_util import Number + + +class FixNumliterals(fixer_base.BaseFix): + # This is so simple that we don't need the pattern compiler. + + _accept_type = token.NUMBER + + def match(self, node): + # Override + return (node.value.startswith(u"0") or node.value[-1] in u"Ll") + + def transform(self, node, results): + val = node.value + if val[-1] in u'Ll': + val = val[:-1] + elif val.startswith(u'0') and val.isdigit() and len(set(val)) > 1: + val = u"0o" + val[1:] + + return Number(val, prefix=node.prefix) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_numliterals.pyc b/PythonHome/Lib/lib2to3/fixes/fix_numliterals.pyc deleted file mode 100644 index b39e8a0a67c7c298d570ec3477a5839bee6fe687..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1205 zcmbVLO>fgc5S_Ihx2Y(!2ZVaU0;$RYsj=gD}uI

1}e3u z@}u})`~Y~fPAOL!WuIr(GqdyFc>Q0S8$UmNnPjy3`FOs@vJ*f~GzBWkJu-?)kER|e z@qIErl>tqI&JW1+s0?Wu!tap|Xt73f1cvm3=$h#Bbe-}wnhe&Z_;bMf;=67lK1(^` zwyA8iKZ=Tq>uCR3G<iYEiD85vjAk@}jNRTo3Rh2X+_M-pQz#otR>F!1dvYs9^<@>X!B1^1>ZbrktH^Bge||5lj=cvU)mK|;Qyr>p&-Kf4 z4U(ivOPwTc=1Ef4d28UtlHdrAKYloV7qe7I(k#Ev`T~qKVcDL~M+O=F5C#)0k7?%+D&6U4 hasattr(obj, '__call__') +operator.sequenceIncludes(obj) -> operator.contains(obj) +operator.isSequenceType(obj) -> isinstance(obj, collections.Sequence) +operator.isMappingType(obj) -> isinstance(obj, collections.Mapping) +operator.isNumberType(obj) -> isinstance(obj, numbers.Number) +operator.repeat(obj, n) -> operator.mul(obj, n) +operator.irepeat(obj, n) -> operator.imul(obj, n) +""" + +# Local imports +from lib2to3 import fixer_base +from lib2to3.fixer_util import Call, Name, String, touch_import + + +def invocation(s): + def dec(f): + f.invocation = s + return f + return dec + + +class FixOperator(fixer_base.BaseFix): + BM_compatible = True + order = "pre" + + methods = """ + method=('isCallable'|'sequenceIncludes' + |'isSequenceType'|'isMappingType'|'isNumberType' + |'repeat'|'irepeat') + """ + obj = "'(' obj=any ')'" + PATTERN = """ + power< module='operator' + trailer< '.' %(methods)s > trailer< %(obj)s > > + | + power< %(methods)s trailer< %(obj)s > > + """ % dict(methods=methods, obj=obj) + + def transform(self, node, results): + method = self._check_method(node, results) + if method is not None: + return method(node, results) + + @invocation("operator.contains(%s)") + def _sequenceIncludes(self, node, results): + return self._handle_rename(node, results, u"contains") + + @invocation("hasattr(%s, '__call__')") + def _isCallable(self, node, results): + obj = results["obj"] + args = [obj.clone(), String(u", "), String(u"'__call__'")] + return Call(Name(u"hasattr"), args, prefix=node.prefix) + + @invocation("operator.mul(%s)") + def _repeat(self, node, results): + return self._handle_rename(node, results, u"mul") + + @invocation("operator.imul(%s)") + def _irepeat(self, node, results): + return self._handle_rename(node, results, u"imul") + + @invocation("isinstance(%s, collections.Sequence)") + def _isSequenceType(self, node, results): + return self._handle_type2abc(node, results, u"collections", u"Sequence") + + @invocation("isinstance(%s, collections.Mapping)") + def _isMappingType(self, node, results): + return self._handle_type2abc(node, results, u"collections", u"Mapping") + + @invocation("isinstance(%s, numbers.Number)") + def _isNumberType(self, node, results): + return self._handle_type2abc(node, results, u"numbers", u"Number") + + def _handle_rename(self, node, results, name): + method = results["method"][0] + method.value = name + method.changed() + + def _handle_type2abc(self, node, results, module, abc): + touch_import(None, module, node) + obj = results["obj"] + args = [obj.clone(), String(u", " + u".".join([module, abc]))] + return Call(Name(u"isinstance"), args, prefix=node.prefix) + + def _check_method(self, node, results): + method = getattr(self, "_" + results["method"][0].value.encode("ascii")) + if callable(method): + if "module" in results: + return method + else: + sub = (unicode(results["obj"]),) + invocation_str = unicode(method.invocation) % sub + self.warning(node, u"You should use '%s' here." % invocation_str) + return None diff --git a/PythonHome/Lib/lib2to3/fixes/fix_operator.pyc b/PythonHome/Lib/lib2to3/fixes/fix_operator.pyc deleted file mode 100644 index c0f492fa02339343c106601a6a7dda40054597b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4925 zcmb_g>u%e~6&~v5NO2M;PVBn3WxH!g#%@(0{nH;wuuXaecGWHwV6j3_mL|tG9g0*r zzEFYw=v(wf3iJWm?>j?^vXX6GuVrvNJeqT6&gDDjjN1RYHTc`7zng}t z`n2)?Lpmxi1)FgT+MvnReSSOA=k3xn@~8Kx{q^7K=DN zUKQj14>=Xf1u>IyeyH;cQr;#em1SmZm#;|3^+E@QJ#$*ykP?=bn3qZY^@<(d%D2iE zukywJ#%BcIs$ziQh#vM21EWVB(m2qUGMNN(UGzYi7C8)5Y;r|bh9`bJUu1a^QcSCQ z7@%ew!=E7)QRS#VDfQY>XAUBYizc$XX5mV63&UTOI#bG*aViI!G{=k6&$BRKyjdE# zkD93&;a!<`F^pe)6d%4w;=_kU_M;b6%W(9U##_89c*IDD_sBy|v?aJi7@}{G2KxuKtBG=}x zco|d~qxy%aJISKQqhXU*hG)a|Ofg*Js+iBfRl}TM1m^{a%X@>>uash8#nsj9U~NBh z2PYqnhAxuZ;~;(I4iARr?{8|e$iC3|BX^!fWuhMs>wtW7<022@giD9xp}Rk_Rxk&~ zec~>^+L!!D(v!90oUOfA+pfyFgp`6HsCE_?LAj8)Azt|Z86NXP3;^vZMgY8}&Rgnr zTb)VxzU-^~ea@F(O(SHG3fW8q1!3=pCpvuT+pTQ2$j0CWVoN zWZ5iEA?)%gpwIpDAT=mz^8<1cipsg?Y&zxvX0?09%d)d?4#Wbr6~qEeU#k`XV$a)k zqAQt1mi){k#cd4!NsvZ~_H&&gv5qLuV+?s)9GEz+pb**ob!d!1G&HqpnO%%^8QwP+ zs<5cVq{TNFa?J&K}2|BCdtK=;_YCNC2OXWjU-@# z{Mgn7vF2ryx1?&nNjML&kByDi!1gXNDmkAx$&`oEOEnim-{AKJ>|kAX*>dj@&!6Iv!mgYl`oB%5)7o~non2?d zPEgM6`|Q+u!`; z`SYK76OTQl*udj<9 + [any] + > + > + | + testlist_gexp< any + comp_for< + 'for' NAME 'in' + target=testlist_safe< any (',' any)+ [','] + > + [any] + > + >) + (']' | ')') > + """ + + def transform(self, node, results): + target = results["target"] + + lparen = LParen() + lparen.prefix = target.prefix + target.prefix = u"" # Make it hug the parentheses + target.insert_child(0, lparen) + target.append_child(RParen()) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_paren.pyc b/PythonHome/Lib/lib2to3/fixes/fix_paren.pyc deleted file mode 100644 index e962769304250b2e2ad00a0c32fb0315c53d327d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1512 zcmds1T}vB56urBf#2OTQ5=tq|OW6$-q4qVEnqr}#LDoQNqD(f~iCMc}-I=rz;*9&bSQQybtrSG z?~=o|N2y0yjrujp>eR2pTO;MtWrHRN*XcXa4bi9m8pRDd4c0j24B~w4;DutlB67Y&jeVHYdikr>eG|^&QFkCs&T8ZakL{mwW;+p6ljXuFET~e7J)zT#X|Uj-@1$Ngdk0{$)eAyYKthp zT8VLdTx6xhuGk#@-(lz@h=t1+ z>FKpc#zuYFl55W{RhO>zyQ$?-HvW9x{@Qswc|5n3|wT2umJl}@aZ7qK$T^GfMiYIMj^ zTR62G4`7lNT0q-9J4!}pX)@X~#p^Ssq-H7Y+}-lZtYea?qFm!77`9=aN|{HQlG4&!%B+ZIDVq$TSIv~!gwi>d%%R96qjZV%>x, ...' into 'print(..., file=x)' + +No changes are applied if print_function is imported from __future__ + +""" + +# Local imports +from .. import patcomp +from .. import pytree +from ..pgen2 import token +from .. import fixer_base +from ..fixer_util import Name, Call, Comma, String, is_tuple + + +parend_expr = patcomp.compile_pattern( + """atom< '(' [atom|STRING|NAME] ')' >""" + ) + + +class FixPrint(fixer_base.BaseFix): + + BM_compatible = True + + PATTERN = """ + simple_stmt< any* bare='print' any* > | print_stmt + """ + + def transform(self, node, results): + assert results + + bare_print = results.get("bare") + + if bare_print: + # Special-case print all by itself + bare_print.replace(Call(Name(u"print"), [], + prefix=bare_print.prefix)) + return + assert node.children[0] == Name(u"print") + args = node.children[1:] + if len(args) == 1 and parend_expr.match(args[0]): + # We don't want to keep sticking parens around an + # already-parenthesised expression. + return + + sep = end = file = None + if args and args[-1] == Comma(): + args = args[:-1] + end = " " + if args and args[0] == pytree.Leaf(token.RIGHTSHIFT, u">>"): + assert len(args) >= 2 + file = args[1].clone() + args = args[3:] # Strip a possible comma after the file expression + # Now synthesize a print(args, sep=..., end=..., file=...) node. + l_args = [arg.clone() for arg in args] + if l_args: + l_args[0].prefix = u"" + if sep is not None or end is not None or file is not None: + if sep is not None: + self.add_kwarg(l_args, u"sep", String(repr(sep))) + if end is not None: + self.add_kwarg(l_args, u"end", String(repr(end))) + if file is not None: + self.add_kwarg(l_args, u"file", file) + n_stmt = Call(Name(u"print"), l_args) + n_stmt.prefix = node.prefix + return n_stmt + + def add_kwarg(self, l_nodes, s_kwd, n_expr): + # XXX All this prefix-setting may lose comments (though rarely) + n_expr.prefix = u"" + n_argument = pytree.Node(self.syms.argument, + (Name(s_kwd), + pytree.Leaf(token.EQUAL, u"="), + n_expr)) + if l_nodes: + l_nodes.append(Comma()) + n_argument.prefix = u" " + l_nodes.append(n_argument) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_print.pyc b/PythonHome/Lib/lib2to3/fixes/fix_print.pyc deleted file mode 100644 index 2b3287d43c237ddf3561693c67d12bff4a5b0fff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2683 zcmbVO-EJF26h5E50uK0ri544=A6bVxD^QR5Ym9 zprT2=CKU_RTcBc*dW)pAN5dsb=jcpPZ<*40(g6)uXn^|~^b^q;(Ko$SN}JSeEwGIX zis(UhqD?p$nQ&~f(rq=HyGKcRsP8sIJe#t($z=6FWHeiC-Q2t+6K-v7&Ezi2VD&Ar z@RkU^A$BX&WxBl)Zv0!m-9EWh>3&OokmY*&1mexkDC~>XHcX5TlkqsubQ)%Z%BgrT zDf=!Pm0@PXtQe1s!|uS0iZI5Wn;0F(&1U8yC@sW<+#IHH;`*avTrC8=@X8sjE56QB zqhnoGY!mE&BN-ngR<~r=$66;Tv}0m7$#cicyQ88=9INX(1pLs=gUoE~CgWV&4KRrt z75Bo;)@JxElhf{g^tkhI+Sz%!_afZ9xf!w8QBvye#&H zf<9|zkg=z`81^=zJN3vek|X+2F+Bt_6~pzkM$;OZFL)k$T@=yKI=;B1R?V)A%MdMFR}t`V2PDt_@{M@ zfKKI%`9p*P+_J#s!>7-eLTE;@LAHcrKAAgerqC^NA-ZKQK2+hEC+F^{*LF1MxK8#1 zHH!ok)oFdW%2!kuqej_sXomk#`}vDCI-RE}>=vo-JbHOoox+C(nIn}hFu~5mbukB7 zhP4f{KdULibV1L}XtU%^&t=T-YDzS`A}WxbHFEC}b`cl;M~7ku&$XC8FG<78N;-H$ z`tm&&x|eB+<^+8&mprJvoMl*#Fr7Au^IE5Ali&#EZfgbD=|~AN0w-KT(vzfw#zv#+ zGOSU?@X!9nxoVV5gYBenM98tKHBd-di-EtPWE#ga1CrEX&N8@keI`Wdz2`HSwjAfg;k6Y^Op7X!{q`;ZMZjuzX|sSw5q-JS>r zB`JcD*JR#@D=Dy%>Uah()EOogbc*s5T_e(inv)y@-%KfYz=P~W?0Of61QqwH7`C}3*;PzIZ52W1zg8_!4gVh* C6A%^v diff --git a/PythonHome/Lib/lib2to3/fixes/fix_raise.py b/PythonHome/Lib/lib2to3/fixes/fix_raise.py new file mode 100644 index 0000000000..b958ba0129 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_raise.py @@ -0,0 +1,90 @@ +"""Fixer for 'raise E, V, T' + +raise -> raise +raise E -> raise E +raise E, V -> raise E(V) +raise E, V, T -> raise E(V).with_traceback(T) +raise E, None, T -> raise E.with_traceback(T) + +raise (((E, E'), E''), E'''), V -> raise E(V) +raise "foo", V, T -> warns about string exceptions + + +CAVEATS: +1) "raise E, V" will be incorrectly translated if V is an exception + instance. The correct Python 3 idiom is + + raise E from V + + but since we can't detect instance-hood by syntax alone and since + any client code would have to be changed as well, we don't automate + this. +""" +# Author: Collin Winter + +# Local imports +from .. import pytree +from ..pgen2 import token +from .. import fixer_base +from ..fixer_util import Name, Call, Attr, ArgList, is_tuple + +class FixRaise(fixer_base.BaseFix): + + BM_compatible = True + PATTERN = """ + raise_stmt< 'raise' exc=any [',' val=any [',' tb=any]] > + """ + + def transform(self, node, results): + syms = self.syms + + exc = results["exc"].clone() + if exc.type == token.STRING: + msg = "Python 3 does not support string exceptions" + self.cannot_convert(node, msg) + return + + # Python 2 supports + # raise ((((E1, E2), E3), E4), E5), V + # as a synonym for + # raise E1, V + # Since Python 3 will not support this, we recurse down any tuple + # literals, always taking the first element. + if is_tuple(exc): + while is_tuple(exc): + # exc.children[1:-1] is the unparenthesized tuple + # exc.children[1].children[0] is the first element of the tuple + exc = exc.children[1].children[0].clone() + exc.prefix = u" " + + if "val" not in results: + # One-argument raise + new = pytree.Node(syms.raise_stmt, [Name(u"raise"), exc]) + new.prefix = node.prefix + return new + + val = results["val"].clone() + if is_tuple(val): + args = [c.clone() for c in val.children[1:-1]] + else: + val.prefix = u"" + args = [val] + + if "tb" in results: + tb = results["tb"].clone() + tb.prefix = u"" + + e = exc + # If there's a traceback and None is passed as the value, then don't + # add a call, since the user probably just wants to add a + # traceback. See issue #9661. + if val.type != token.NAME or val.value != u"None": + e = Call(exc, args) + with_tb = Attr(e, Name(u'with_traceback')) + [ArgList([tb])] + new = pytree.Node(syms.simple_stmt, [Name(u"raise")] + with_tb) + new.prefix = node.prefix + return new + else: + return pytree.Node(syms.raise_stmt, + [Name(u"raise"), Call(exc, args)], + prefix=node.prefix) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_raise.pyc b/PythonHome/Lib/lib2to3/fixes/fix_raise.pyc deleted file mode 100644 index 25f690ae9dd487a13f15705703ebdf25c49d60e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2467 zcmbVNUys{F5TA9Ne~zzr91>N9fW4C-E?iHdeM6<{wFHFJMwJs?McQH9ONDLSmz-V8CxCV&{BeUF_`o0dMdbzJd+<>GBqb4LR7_}g2!>A331tSZR z4vad;*8ow6xeXIk*o0pJ&H;WHZ9&+Afzu`fN-y#s!Hz=vJS zD)+ql?mXc7pgQiobIf~hFHoND-tzOFbA0>K9qPV%cX%49nWu6;5Mw_$afX+;`&lZk z3S7foDR&$PZSQq&6R9Xo$5-Jh?)^!Y?U$}rp1hsV@KZleCHKc!p}16eluo%g3&cW2 zSt>2ddVF-;I~oqYvc9~{_cvkN=ciE|^ReJj8f1Ac0u?VgdX~!AS0d!m1g(isbGp%I zA#RjP<)?u--Rb`=kW zLK7~u-+Huf|;LA z(Gy=HOdKB&SeOx*U#KiWFG-D>Me@*!FulNGNK^yKVySW=%6**Ku>mlFA+=E#6YIOIo2 z1lAk_fu&Z{^=DH3VQpY#xdVp`mc*+At%K}Im8knwadhd~zNR3(=pJ5b&)zqpDn+urgt8fU3dVgcAeu9yNt^T?-&( zu&Tp3bq9a}Mibf38RWmg+2<78YP;5In$$mT&2cg>0lXf<^AI(e;I$ydwu4dzoHQZ- z15_L47OW7w1Ingufy$9{Y7picIT_4buxgMj(g9iDxKQ5ICTO92n@!QnCJ;PExCMLP zyxN5|inXA0_D2I={|)Olq`MHdiIu~=mJHBBg@ ztd4L%K`XBHU_KU9J34WrfAA}aLs43*aY2Pd4YeTTt4+5o&|F{WgIN@Zxkz0bPh1?O>OM9XMODA4 zF_$8tLHb8edm5Mg5iXhHk{K?QlIkFlQG(^JOVgnmE6o-0L@!cOP8Q@s7O|2pvAFcd z(@{#~RL`k6b;$%p{sdam&!^HQ0DV>}DFZcj@DwzW99M@gpG4!AaWuZGvU@M7cS)k2 z_U8~=ora^%kH6OBGn9}IkpOEOJ8YLV*bXyWHruX!%xuFp_L$8~ys_DV(MBE{@7qSh z+(X_^*}lHD*@w*0A)ub;c_}tW&(l%#yd(Qvmc u`$9#re)xA@xlAB3_!0gPsHGF`|1nr+;r%i^4?aL8lF%FG4n}x~ImW+U@)+;{ diff --git a/PythonHome/Lib/lib2to3/fixes/fix_raw_input.py b/PythonHome/Lib/lib2to3/fixes/fix_raw_input.py new file mode 100644 index 0000000000..3a73b81864 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_raw_input.py @@ -0,0 +1,17 @@ +"""Fixer that changes raw_input(...) into input(...).""" +# Author: Andre Roberge + +# Local imports +from .. import fixer_base +from ..fixer_util import Name + +class FixRawInput(fixer_base.BaseFix): + + BM_compatible = True + PATTERN = """ + power< name='raw_input' trailer< '(' [any] ')' > any* > + """ + + def transform(self, node, results): + name = results["name"] + name.replace(Name(u"input", prefix=name.prefix)) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_raw_input.pyc b/PythonHome/Lib/lib2to3/fixes/fix_raw_input.pyc deleted file mode 100644 index b7c5443e2ecc1597c0b9f06971c0d1f1007dfb62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 905 zcma)4O>fjN5FI<&0E;Sm<$&Y^QqmrBDA%%rMIa%;3S}1|!Xo2Myfl^bq1aKWR8Gr} z;(zf6m~qM$IMtG0X5#sH^X%Z)!Sv^cFUtb1SAgGVxa|vs5+FxpP;xK~Y7RLEMt%S$ zfI5UcL_Y-0;d}yHJea@_fE~ccJc2TUWpam#oglobzUf}LGv!2arkbzXie6pFs_6!o zq-lC2s>ZblfBdxKn3gaEH$~V|0l86DkN-maw@|fq_tC)WnYwsQ$@^I-bB^0SLeMx1 zBcgfW=L%^qAkR*yd@xryC2`tIE(xoW$ajYA!#E_$U@L zf#$K8{a2+RRf+BdHwkNx5w18^cG0*dHIb%exZpfX-3 z7opYl8l_37ha$EW*jtIc*S)0X-=*bc_ojItBlBiP4irRz7x#|b) z4$zptl|@^3%2gXPQhWD&wR)K?GHP){&0DwTm(j%%2TN=s9t9C!_&4dNm$GaNWP)dq q5&ZSg23Hxcp^u#7v!gfWpCm=zFuFAvFUILO{)}#CBo!XAL;f31u(_oG diff --git a/PythonHome/Lib/lib2to3/fixes/fix_reduce.py b/PythonHome/Lib/lib2to3/fixes/fix_reduce.py new file mode 100644 index 0000000000..6bd785c1cd --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_reduce.py @@ -0,0 +1,35 @@ +# Copyright 2008 Armin Ronacher. +# Licensed to PSF under a Contributor Agreement. + +"""Fixer for reduce(). + +Makes sure reduce() is imported from the functools module if reduce is +used in that module. +""" + +from lib2to3 import fixer_base +from lib2to3.fixer_util import touch_import + + + +class FixReduce(fixer_base.BaseFix): + + BM_compatible = True + order = "pre" + + PATTERN = """ + power< 'reduce' + trailer< '(' + arglist< ( + (not(argument) any ',' + not(argument + > + """ + + def transform(self, node, results): + touch_import(u'functools', u'reduce', node) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_reduce.pyc b/PythonHome/Lib/lib2to3/fixes/fix_reduce.pyc deleted file mode 100644 index de60d08574b34bf91fa532fc202f7a9f4b8db806..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1231 zcmcgr&2G~`5FXo!0gFO~cz^{Cb|jPoTtie+(G!i3Qwd>3GLF5b3${1xk7%Xd%0uy9 zJOIqBO`=|q=z*1Hc6N4tzMYv3ejY?W-hW(`FsuOgBP4x{tOCf8drnw)wU~*l#OPstZc)Xs0Rlg=pMOvRBeYp*}T2n;A=Xwxp(&bkZbv zZ(H7(S z$H>f|3BK~+I>2!SoJz7~in)too_9sd^W4pC zp7#@vM@oODEH?)zEKc)Mw%fvpO~cI?HBwbvIcV=*pPju)mnp&A sys.maxsize +""" +# Author: Christian Heimes +# based on Collin Winter's fix_import + +# Local imports +from .. import fixer_base +from ..fixer_util import Name, attr_chain + +MAPPING = {"sys": {"maxint" : "maxsize"}, + } +LOOKUP = {} + +def alternates(members): + return "(" + "|".join(map(repr, members)) + ")" + + +def build_pattern(): + #bare = set() + for module, replace in MAPPING.items(): + for old_attr, new_attr in replace.items(): + LOOKUP[(module, old_attr)] = new_attr + #bare.add(module) + #bare.add(old_attr) + #yield """ + # import_name< 'import' (module=%r + # | dotted_as_names< any* module=%r any* >) > + # """ % (module, module) + yield """ + import_from< 'from' module_name=%r 'import' + ( attr_name=%r | import_as_name< attr_name=%r 'as' any >) > + """ % (module, old_attr, old_attr) + yield """ + power< module_name=%r trailer< '.' attr_name=%r > any* > + """ % (module, old_attr) + #yield """bare_name=%s""" % alternates(bare) + + +class FixRenames(fixer_base.BaseFix): + BM_compatible = True + PATTERN = "|".join(build_pattern()) + + order = "pre" # Pre-order tree traversal + + # Don't match the node if it's within another match + def match(self, node): + match = super(FixRenames, self).match + results = match(node) + if results: + if any(match(obj) for obj in attr_chain(node, "parent")): + return False + return results + return False + + #def start_tree(self, tree, filename): + # super(FixRenames, self).start_tree(tree, filename) + # self.replace = {} + + def transform(self, node, results): + mod_name = results.get("module_name") + attr_name = results.get("attr_name") + #bare_name = results.get("bare_name") + #import_mod = results.get("module") + + if mod_name and attr_name: + new_attr = unicode(LOOKUP[(mod_name.value, attr_name.value)]) + attr_name.replace(Name(new_attr, prefix=attr_name.prefix)) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_renames.pyc b/PythonHome/Lib/lib2to3/fixes/fix_renames.pyc deleted file mode 100644 index d02c097ca62c2ed7a6eed062013070ced1f2849d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2366 zcmbVN>uwuG6h5=QBz78_Ms2D9g5^@|L?QwzDui4^(^7=mxM7_VVWlkV-Ep(luGife z(*!xcinu%nFTs290(|GJoj{czDNgq6oVlFaeBas9-^=yC_J8b#H2anD{t}OwKtx16 zNJWuDiK5h@oBM=NBkipkFXpq-aqF zHHvDa9U9hYfD?6|d_nYmZ;7HM>NYR2`!68w$472F3bS+^*tnl)H`k*e)uvv@iZ-9u zU3b$p$7U-Hj^dGZKWxu66aTF1u>%`T1!3zD1DwhIeqeNy7c6JmfjLA8 z$u=d9VFnkhrNLMxay`zA&?Ow5_H}NW*gzu8yBKX9JdFDXN!E|bhgv8El83^2iPpYTfKD-kWvI_Sp#5jdv>y>}nltX0KOu3IFaP3noaNRZ zS!758{O98(Xl-=$ePoW+$8Hx+nm_H@Z>I|7})3)%w#0Vk5RUb$9x8%!G6Vz@0GZv49lb|3^5P{O#+bNCgIGRL}}I} zyn;6#mqWNQ&UMIk88uuNew)V-z$^$=kZ$PEA4IV7V<}YWq93xjkCcL+K&SmiqgzynQr4@MZ@$^-Q0xTHN1&b@OqQQ*JAj{J> z9~4%q%j$CZl6q4$Sru=-`0{<>sqfDc_T{Gc@`<)g^6ee}>?7-OAv~tKB)fZOZ|^Iw zBY9?d1WYlUybXx6xL*avg2_!Bmzb+S#i~;+)s{Q*-4~y}A7vq8#wPMuNc8-H%l(Os zlcLIuWRKA$7vXUtXJK#SGtX^_3Gn~ol=8KTg0&f`g5+vtMXfnkovKqS*RK5o%1zVw diff --git a/PythonHome/Lib/lib2to3/fixes/fix_repr.py b/PythonHome/Lib/lib2to3/fixes/fix_repr.py new file mode 100644 index 0000000000..f34365647f --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_repr.py @@ -0,0 +1,23 @@ +# Copyright 2006 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Fixer that transforms `xyzzy` into repr(xyzzy).""" + +# Local imports +from .. import fixer_base +from ..fixer_util import Call, Name, parenthesize + + +class FixRepr(fixer_base.BaseFix): + + BM_compatible = True + PATTERN = """ + atom < '`' expr=any '`' > + """ + + def transform(self, node, results): + expr = results["expr"].clone() + + if expr.type == self.syms.testlist1: + expr = parenthesize(expr) + return Call(Name(u"repr"), [expr], prefix=node.prefix) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_repr.pyc b/PythonHome/Lib/lib2to3/fixes/fix_repr.pyc deleted file mode 100644 index 32262db56619e0dd5593827999fb6f00ca639fe1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 985 zcmbVKOOMkq5FXoYb}1~ZkT@WL$Zf-=h=;^wSwUBDf`ZaYh^UgAHZGguJY+jkQN1JnQuOi_;xh-`hGrH!jDhj|2dj{i;w{%hzv3gnnA%K;lOAu zKno~(ko2JFL(+#LfF!`Z9w-j$16bjqK70Y#1AIshAq!v<9Z=#22(R*uGNHRjUFb|& z+Erx=8_qZFcH7RwymVD)RBa+3xIfG}-ia838z8Lcwp^rEMMT&25YAJry)#Y=<*s3* zPK_$vg|hipIjW3BV@&$1RmwL)vv&~`w#tZmB7ECDY8&ZeYw;wa`t~WpApGM?T~&mq z;mQ0YRGZp7OUu?T&i*>LB%VaGk9Lk`CkQ)EMQ*RXNS_7l1gshC0M;m>fKMFE6Y37* zdj@!*#Af^80(uXOVEm(hiyb4$_nb{4Dl+y$5TS;aq$J)!MT|n}qC<2s4Zu=YrSfN8 zTX&9a3+t}X0cD-et$P>~^_aAZNrjja`6~XRReI%}vdTJ@jk1k)Hl_j*S_k$Xdc)c4 zd@ + | + single=any) ']' > + | + atom< '(' items=testlist_gexp< any ((',' any)* [',']) > ')' > + ) + ')' > > + """ + + def transform(self, node, results): + single = results.get("single") + if single: + # Make a fake listmaker + fake = pytree.Node(syms.listmaker, [single.clone()]) + single.replace(fake) + items = fake + else: + items = results["items"] + + # Build the contents of the literal + literal = [pytree.Leaf(token.LBRACE, u"{")] + literal.extend(n.clone() for n in items.children) + literal.append(pytree.Leaf(token.RBRACE, u"}")) + # Set the prefix of the right brace to that of the ')' or ']' + literal[-1].prefix = items.next_sibling.prefix + maker = pytree.Node(syms.dictsetmaker, literal) + maker.prefix = node.prefix + + # If the original was a one tuple, we need to remove the extra comma. + if len(maker.children) == 4: + n = maker.children[2] + n.remove() + maker.children[-1].prefix = n.prefix + + # Finally, replace the set call with our shiny new literal. + return maker diff --git a/PythonHome/Lib/lib2to3/fixes/fix_set_literal.pyc b/PythonHome/Lib/lib2to3/fixes/fix_set_literal.pyc deleted file mode 100644 index b2b2347bc43bd3cf3b96e6a270b3462cc1aaf8ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1944 zcmbVNZExH}5T3Q~e94gz+Nyz41QtlxK`27-4J8pxX(gnPA}0cIO=KKR=ap3%rj#wA7C4r(&;ucc5_(%jW71#!wo^iJUz*v z6kt2ObgkCiai4XXGhMqLID1)Hw+iNYd2yiKUgz*SY=x6uR{IDGlumi4L8+w3=tj-$JL-r;BgI*!5)v(wfw?(|e& zOz*}WMjLnDv~fFRvG^CdoO^Q_i|hFm%RWZ_XJ|L+(JMuBpJqO_-;h%@@yPi!>9J(e z=Qcc5bmh^!lLR#D5lj?*=6$M%>W00+f@&OB=0 zR-L3+0>&kp0o{F$N--yPP+$13fp36$<7Dm2V04vtJQGs9b8h(GbEZ5?yezNBATy%l zdo)*qNCxzEJU%o2Fij8@t&245=fkV-ONzKW6dKUU_n4%9GDs^TiR5 ztYw;FWYWcCZ%!{Qqun~yHM*(YiLkNkGa$h_m%%T&^d*bq2Ouag%Bo$$x5}9BH-%1E z>e$=$R3-fKI3}&0nk?6%yr;8q!pYReOY>5{W)s}Y{#v!cu$!j#b#v}WO|)m8JWmI`(6lQv^vYDBO=YR`?c ziM(SR_ZaU(!gtH@B5_g%ai4I+ua$Yp)%E+!Enq(cA+@Fg?|rqZmc60>j(S(U=RHsl z)r$WRvY}e{g2I!)zKPSdI>&JAxF_hEak<>}r1HqD!AnmOc3iy2C7%Di+E z(RWV{51%Fb$p^4`703T=qlB;I)LSlJ-~}oe2Ht*`Y3_hDEt(wAm|yf{0+zZay8lYL s$(`D!=dLu;C0$>!*)INXo|hML)$1db3~Y6&+TotHT->0yuGV}102w8VaR2}S diff --git a/PythonHome/Lib/lib2to3/fixes/fix_standarderror.py b/PythonHome/Lib/lib2to3/fixes/fix_standarderror.py new file mode 100644 index 0000000000..6cad51116d --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_standarderror.py @@ -0,0 +1,18 @@ +# Copyright 2007 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Fixer for StandardError -> Exception.""" + +# Local imports +from .. import fixer_base +from ..fixer_util import Name + + +class FixStandarderror(fixer_base.BaseFix): + BM_compatible = True + PATTERN = """ + 'StandardError' + """ + + def transform(self, node, results): + return Name(u"Exception", prefix=node.prefix) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_standarderror.pyc b/PythonHome/Lib/lib2to3/fixes/fix_standarderror.pyc deleted file mode 100644 index b432fa2facc23acefd6ba675cd641550dd4d7e4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 822 zcmbtSO>5gg5S^7|wRH%%^jz?zM3?x`UPDM7+*4|bWC#_8tt_oUK_6y!1u68F{;2-1 z{DHn1$7!2e$-+F%?9R@L@7TUOG;3h}*wxl2Grlmiu20X2%+fbxJ8$00Q# zwGrhJ;)qN@HzV5OU_?KO?ufqTF;y{T$qO#_4)CeIHFmn~?KJa6R~5EeSc~ZNe7d+T z&Cb_-H>(3=CJNxkfGywAo5Gp>UWC16(HcL2gMx=jhATbxz}M$6_ZDE#gJObtDE&m- z4>;x{O0$HYbEkmu^q+Nds4N^$o}8Af5*zcmgt<2We~{{jq8mkbN@WQrEr(aY#~yu* zXlD(2ljl>Wn{uLLd#>qBvlXZ7E8|&0YuwOym%t?facAqRdb4io&3oT}ShHG=QM(6) zMVHy`yJrU87M+9s?P~;%J13Pe8UGTXbq8U!7TvXO`)X)7WI8K57=H|B{#loOyDNOX zY4*Ind|a&-=`v-Gf5`nm!<6|P!5lM+RUF2_Qiey`*ShLUu)!In41bNs;Oj<2l*~DX Z1(PB5o sys.exc_info()[0] +sys.exc_value -> sys.exc_info()[1] +sys.exc_traceback -> sys.exc_info()[2] +""" + +# By Jeff Balogh and Benjamin Peterson + +# Local imports +from .. import fixer_base +from ..fixer_util import Attr, Call, Name, Number, Subscript, Node, syms + +class FixSysExc(fixer_base.BaseFix): + # This order matches the ordering of sys.exc_info(). + exc_info = [u"exc_type", u"exc_value", u"exc_traceback"] + BM_compatible = True + PATTERN = """ + power< 'sys' trailer< dot='.' attribute=(%s) > > + """ % '|'.join("'%s'" % e for e in exc_info) + + def transform(self, node, results): + sys_attr = results["attribute"][0] + index = Number(self.exc_info.index(sys_attr.value)) + + call = Call(Name(u"exc_info"), prefix=sys_attr.prefix) + attr = Attr(Name(u"sys"), call) + attr[1].children[0].prefix = results["dot"].prefix + attr.append(Subscript(index)) + return Node(syms.power, attr, prefix=node.prefix) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_sys_exc.pyc b/PythonHome/Lib/lib2to3/fixes/fix_sys_exc.pyc deleted file mode 100644 index 6c25f28ebf722a99636370fbd01dc541ed5451e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1661 zcmbVM-HzK-5T0Wv&TiW6Rst$TD$bZ&7=4)z2IRH&PI`4>9L3qgiaUgl;=n zduDATgXeLc%U}{0+IrZUw8cy}_7KBqJ2Od>)pn~Z)@Fj0zWu71(YnLh*xLuMt*d74)C>F{*u$G{?+wN^hJJv5K}u|Iyp+%lBw zge4=(MaK!70mPc<>Xf%OsopO0p80^6 zFTc!Ymw7gOVyjOsnK;8TLf{c{KCM@V(?7e`rC!#}_+2(+e;y?q7MErhAER&nfLJ>m z%m5uR*tldR-i4xtLu;27E+dY2(;*OR!G^4W8Q%48(3A{*}E$_AV`sL>b-@0lYhEI$~-kQcQaqGAz-ab8Zl+%ev8k zqUAIJhvh#Q%$SwYJ&1s@w!2ahGln87Q@uoLL{cyTqZP1mz@-yNm#|UtLzbtFF6FGa zu63CPY!z@%1PrV=ky5(tBct=V^hC+c!CH+rZElSO!nAQ(!F@L8_>x__@$!ErUvNVG zmIjwj@c{k|XHM##I&n_ad+J2JqXbepK8i{-bri`h5Jg3mwmGK3F-#B32Qu6uw*~P_+U=o}_?KWT;{mYUK7+#Lk@W6A9mFK?iOh$aL91%rn zl^{&aDPZy1wbj}z7m{8hj)8oW8;1TIR~)V+Iq(04DzKexff_UMhK1L?uReAD2J#zM AR{#J2 diff --git a/PythonHome/Lib/lib2to3/fixes/fix_throw.py b/PythonHome/Lib/lib2to3/fixes/fix_throw.py new file mode 100644 index 0000000000..1468d89a45 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_throw.py @@ -0,0 +1,56 @@ +"""Fixer for generator.throw(E, V, T). + +g.throw(E) -> g.throw(E) +g.throw(E, V) -> g.throw(E(V)) +g.throw(E, V, T) -> g.throw(E(V).with_traceback(T)) + +g.throw("foo"[, V[, T]]) will warn about string exceptions.""" +# Author: Collin Winter + +# Local imports +from .. import pytree +from ..pgen2 import token +from .. import fixer_base +from ..fixer_util import Name, Call, ArgList, Attr, is_tuple + +class FixThrow(fixer_base.BaseFix): + BM_compatible = True + PATTERN = """ + power< any trailer< '.' 'throw' > + trailer< '(' args=arglist< exc=any ',' val=any [',' tb=any] > ')' > + > + | + power< any trailer< '.' 'throw' > trailer< '(' exc=any ')' > > + """ + + def transform(self, node, results): + syms = self.syms + + exc = results["exc"].clone() + if exc.type is token.STRING: + self.cannot_convert(node, "Python 3 does not support string exceptions") + return + + # Leave "g.throw(E)" alone + val = results.get(u"val") + if val is None: + return + + val = val.clone() + if is_tuple(val): + args = [c.clone() for c in val.children[1:-1]] + else: + val.prefix = u"" + args = [val] + + throw_args = results["args"] + + if "tb" in results: + tb = results["tb"].clone() + tb.prefix = u"" + + e = Call(exc, args) + with_tb = Attr(e, Name(u'with_traceback')) + [ArgList([tb])] + throw_args.replace(pytree.Node(syms.power, with_tb)) + else: + throw_args.replace(Call(exc, args)) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_throw.pyc b/PythonHome/Lib/lib2to3/fixes/fix_throw.pyc deleted file mode 100644 index fca3c72266b20aeacf47bb4046c078a73eb5fae9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1965 zcmbVN-EJF26h6CN|0ZorkU&L343&`A5PZ=}T%~~&T7*=rXl)hMO}ebtV`rWHF*D;P z5%yJ(cn_X}SKtMB5gq`(Gn+puE-Ea|**P=kocZQE=Zq_V-D&;)!;gcQE`Jq#zrxTz zLrjQ9kPb~;N*&5v8oA`KUZJ!?nMWh9)IGajrBSuitCZF#tJA1XS%XFm%9=E4Qr4nT zi?R(GZNRQZvP$z!nj&DGej&ObdNH~~lLig^CWH7B;%Rawm6#Sv%w#TAWD3 zpX`X|J7U=FwOX^QrLHJ{pYMsAwVQ2tSc}`+{_}44UltrwykXHhP0VpT@P#hD3gXKUq@+b>X_`S*|S6&ySQ(RG7T&yIyB2g zDy;%8hfLjdx*5P@4E-U5M7kZ4$a2M|-s99GEl6rG@ENfF1ER$YFN#yCc14t*3y_ke ztaN%E(XpxNh&^j{nT#6?zat_w(~lrhK;30Z9&wP)PDi|sQagXiiW&3#NbHGD_bOZ& zboF)sZsEeI*XMAsOLQ?8`zD5Ek*{|EK2}6?qIHERio(!O02CNcN0u^@ZH=5yKY&B^D)~odK zH%HsFuF*Klaie2Yw*=I_u79Bk8SgH2)Ki@ZRCEEkJH{YRrL*$;)0aHS@Hjgz87@mRUf#v$jTU|P%1)nW+Hl{*X_1#bW6l>cxbD8eF!-+jEiMg{C z8H;)*%a-cHIp99CtrQ<8=|suAY+ohOqJf9afZI7>)PZePc2IJW;^7D|Es^(&iL{7p z8~I#=_C{K!Q#;Aopmf#C)aZas0)7)MBoJa4eH<{k#tQE1kSPf^c#XHq5G5^R9}8rK z7MS%8pC#kNG#NiI#lu5>U^L6n_HPgGkv&XBxyI9*eE<*rDFiu9x9w~@ZO5x@Ih&5> zZbI(3O{}*tZ{xe=eBylM`b>nSDhzYHRbgmxhGAArmMN=D*HA4bDi5#F_aHr6L?#*I zvEr*A><@=ef_@+{zXAXDHwYSVY-4CfQgdqcn%nm|$u@i#PKp>Ppi`L{&esBeG7oHJ z1h%r6S|&$@OOvE!UTvD$xXiUJ2^Np>K0ien@VWm7uqA7^q-T! + +def func(x, d): + ((a, b), c) = x + ... + +It will also support lambdas: + + lambda (x, y): x + y -> lambda t: t[0] + t[1] + + # The parens are a syntax error in Python 3 + lambda (x): x + y -> lambda x: x + y +""" +# Author: Collin Winter + +# Local imports +from .. import pytree +from ..pgen2 import token +from .. import fixer_base +from ..fixer_util import Assign, Name, Newline, Number, Subscript, syms + +def is_docstring(stmt): + return isinstance(stmt, pytree.Node) and \ + stmt.children[0].type == token.STRING + +class FixTupleParams(fixer_base.BaseFix): + run_order = 4 #use a lower order since lambda is part of other + #patterns + BM_compatible = True + + PATTERN = """ + funcdef< 'def' any parameters< '(' args=any ')' > + ['->' any] ':' suite=any+ > + | + lambda= + lambdef< 'lambda' args=vfpdef< '(' inner=any ')' > + ':' body=any + > + """ + + def transform(self, node, results): + if "lambda" in results: + return self.transform_lambda(node, results) + + new_lines = [] + suite = results["suite"] + args = results["args"] + # This crap is so "def foo(...): x = 5; y = 7" is handled correctly. + # TODO(cwinter): suite-cleanup + if suite[0].children[1].type == token.INDENT: + start = 2 + indent = suite[0].children[1].value + end = Newline() + else: + start = 0 + indent = u"; " + end = pytree.Leaf(token.INDENT, u"") + + # We need access to self for new_name(), and making this a method + # doesn't feel right. Closing over self and new_lines makes the + # code below cleaner. + def handle_tuple(tuple_arg, add_prefix=False): + n = Name(self.new_name()) + arg = tuple_arg.clone() + arg.prefix = u"" + stmt = Assign(arg, n.clone()) + if add_prefix: + n.prefix = u" " + tuple_arg.replace(n) + new_lines.append(pytree.Node(syms.simple_stmt, + [stmt, end.clone()])) + + if args.type == syms.tfpdef: + handle_tuple(args) + elif args.type == syms.typedargslist: + for i, arg in enumerate(args.children): + if arg.type == syms.tfpdef: + # Without add_prefix, the emitted code is correct, + # just ugly. + handle_tuple(arg, add_prefix=(i > 0)) + + if not new_lines: + return + + # This isn't strictly necessary, but it plays nicely with other fixers. + # TODO(cwinter) get rid of this when children becomes a smart list + for line in new_lines: + line.parent = suite[0] + + # TODO(cwinter) suite-cleanup + after = start + if start == 0: + new_lines[0].prefix = u" " + elif is_docstring(suite[0].children[start]): + new_lines[0].prefix = indent + after = start + 1 + + for line in new_lines: + line.parent = suite[0] + suite[0].children[after:after] = new_lines + for i in range(after+1, after+len(new_lines)+1): + suite[0].children[i].prefix = indent + suite[0].changed() + + def transform_lambda(self, node, results): + args = results["args"] + body = results["body"] + inner = simplify_args(results["inner"]) + + # Replace lambda ((((x)))): x with lambda x: x + if inner.type == token.NAME: + inner = inner.clone() + inner.prefix = u" " + args.replace(inner) + return + + params = find_params(args) + to_index = map_to_index(params) + tup_name = self.new_name(tuple_name(params)) + + new_param = Name(tup_name, prefix=u" ") + args.replace(new_param.clone()) + for n in body.post_order(): + if n.type == token.NAME and n.value in to_index: + subscripts = [c.clone() for c in to_index[n.value]] + new = pytree.Node(syms.power, + [new_param.clone()] + subscripts) + new.prefix = n.prefix + n.replace(new) + + +### Helper functions for transform_lambda() + +def simplify_args(node): + if node.type in (syms.vfplist, token.NAME): + return node + elif node.type == syms.vfpdef: + # These look like vfpdef< '(' x ')' > where x is NAME + # or another vfpdef instance (leading to recursion). + while node.type == syms.vfpdef: + node = node.children[1] + return node + raise RuntimeError("Received unexpected node %s" % node) + +def find_params(node): + if node.type == syms.vfpdef: + return find_params(node.children[1]) + elif node.type == token.NAME: + return node.value + return [find_params(c) for c in node.children if c.type != token.COMMA] + +def map_to_index(param_list, prefix=[], d=None): + if d is None: + d = {} + for i, obj in enumerate(param_list): + trailer = [Subscript(Number(unicode(i)))] + if isinstance(obj, list): + map_to_index(obj, trailer, d=d) + else: + d[obj] = prefix + trailer + return d + +def tuple_name(param_list): + l = [] + for obj in param_list: + if isinstance(obj, list): + l.append(tuple_name(obj)) + else: + l.append(obj) + return u"_".join(l) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_tuple_params.pyc b/PythonHome/Lib/lib2to3/fixes/fix_tuple_params.pyc deleted file mode 100644 index 88f89f2cf3357e0945774afcfbf78ae7561e6b79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5308 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 diff --git a/PythonHome/Lib/lib2to3/fixes/fix_types.py b/PythonHome/Lib/lib2to3/fixes/fix_types.py new file mode 100644 index 0000000000..fc9d495927 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_types.py @@ -0,0 +1,62 @@ +# Copyright 2007 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Fixer for removing uses of the types module. + +These work for only the known names in the types module. The forms above +can include types. or not. ie, It is assumed the module is imported either as: + + import types + from types import ... # either * or specific types + +The import statements are not modified. + +There should be another fixer that handles at least the following constants: + + type([]) -> list + type(()) -> tuple + type('') -> str + +""" + +# Local imports +from ..pgen2 import token +from .. import fixer_base +from ..fixer_util import Name + +_TYPE_MAPPING = { + 'BooleanType' : 'bool', + 'BufferType' : 'memoryview', + 'ClassType' : 'type', + 'ComplexType' : 'complex', + 'DictType': 'dict', + 'DictionaryType' : 'dict', + 'EllipsisType' : 'type(Ellipsis)', + #'FileType' : 'io.IOBase', + 'FloatType': 'float', + 'IntType': 'int', + 'ListType': 'list', + 'LongType': 'int', + 'ObjectType' : 'object', + 'NoneType': 'type(None)', + 'NotImplementedType' : 'type(NotImplemented)', + 'SliceType' : 'slice', + 'StringType': 'bytes', # XXX ? + 'StringTypes' : 'str', # XXX ? + 'TupleType': 'tuple', + 'TypeType' : 'type', + 'UnicodeType': 'str', + 'XRangeType' : 'range', + } + +_pats = ["power< 'types' trailer< '.' name='%s' > >" % t for t in _TYPE_MAPPING] + +class FixTypes(fixer_base.BaseFix): + BM_compatible = True + PATTERN = '|'.join(_pats) + + def transform(self, node, results): + new_value = unicode(_TYPE_MAPPING.get(results["name"].value)) + if new_value: + return Name(new_value, prefix=node.prefix) + return None diff --git a/PythonHome/Lib/lib2to3/fixes/fix_types.pyc b/PythonHome/Lib/lib2to3/fixes/fix_types.pyc deleted file mode 100644 index 918adbb229a76dc71003788fce7b082b970bd5f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2154 zcmbVM>uwuG6h3PwPU1Fg=?w}k43yS(FGgxbC8`q9q%Dfnn#eYSnv`Yj87JfJ?wFl% zE>if_J`_*DBk&@;0N**ACPDl`#MwFbneSX?s(&rlfB)f^-iQwW=0Lx}=a(WPO*Ft7 zk*-i0QC6Wrg(8-#lvXL5qrqG$&rv#0S&arYitHuQ^Q3F^KrfJ91X&_o2RTLhG{`dP zGbK3-a*p(SAm>S60J%u|63AuJ@0ZdCAXi9#2=Wo>t031%e+=>oX$A5r>CZr}ll~m! z2I-q1IImGEn;*FR~1h&yEFXi}#!(z{D< ziQW*s8~}5hdd)AmB!8eJ&+MKl)YuiOFqzx2`Iee_pF+r-o~5Q;ulKi& zH)_`vuO-Cg>AtwV&fRXV@+5<^&Ho*#6e2k!^C}s-9aA4AIXp+{OdlT7R=|+E&{oQt zJ8C^B3t#VNnbERg34*mYo4O)EZ7eVr@OoIUEBuv)60|7Bh06|eIJC9fZFT)!;4MDW zPtC}V?dUL!b9}dv4@oeY$perShS6~;;B0hR3@H7!o26O}jY?o=IAbYk*iM4lPI8^1 zCSX&O_#lalU7EUGuJp*|I0D<3__^54pI)`p-4&HuA2Hm6LS4k;{N_Pc~dD`J)hRM+m#9?bKV}3a6oZCrKEmI8I#>1i&-qL|=v8<{>bU^}N(ER<5NS{2YvUGK%Le-x8q) z!3`${=s551gk_6oF))~p%S}tRU`}iok8NR{ljb=wx)sjD&~Ybqated?sU4M7>oIqv zAMOW(cEh6=3JiuAI2$xqN_njIWrKMVB>O&d;?FrTBLX+{``nJ4K0c*L@~yJ9KX#dA zN8f_u)a{z$k!l21G*l=On~I{{kURZ#;|A0#YDFr57egYCo>-o}Reb&?7K0}?B7>K; z%Fpd&j?6s0iTEMKJNp*a1?u*i920n64@R6PcZt6>eEuseLClj19aK2(%B0Gh;QzNO z9aO3Kk}$kr@Q@!wG~pwn9?t7EdAp8GHa|y!n>#HGu0WH=LS|!D7A7o15%*tiJdIyG z-q=|0d>c3zHIf?dBE4I-80~+D+~v+c zz~{N#HQ+p3=`{J?%Jy-r-3Y+=(CL=R?{&d&i&0v6vv~5k5Jfx-HZ5y@n_a}(m4V>y ut>OuLX7}W{|ASM?_NXk>3SVH)plj805q_0wv~coQ`G<7U64k5MDt`k-O$zb= diff --git a/PythonHome/Lib/lib2to3/fixes/fix_unicode.py b/PythonHome/Lib/lib2to3/fixes/fix_unicode.py new file mode 100644 index 0000000000..2d776f6105 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_unicode.py @@ -0,0 +1,42 @@ +r"""Fixer for unicode. + +* Changes unicode to str and unichr to chr. + +* If "...\u..." is not unicode literal change it into "...\\u...". + +* Change u"..." into "...". + +""" + +from ..pgen2 import token +from .. import fixer_base + +_mapping = {u"unichr" : u"chr", u"unicode" : u"str"} + +class FixUnicode(fixer_base.BaseFix): + BM_compatible = True + PATTERN = "STRING | 'unicode' | 'unichr'" + + def start_tree(self, tree, filename): + super(FixUnicode, self).start_tree(tree, filename) + self.unicode_literals = 'unicode_literals' in tree.future_features + + def transform(self, node, results): + if node.type == token.NAME: + new = node.clone() + new.value = _mapping[node.value] + return new + elif node.type == token.STRING: + val = node.value + if not self.unicode_literals and val[0] in u'\'"' and u'\\' in val: + val = ur'\\'.join([ + v.replace(u'\\u', ur'\\u').replace(u'\\U', ur'\\U') + for v in val.split(ur'\\') + ]) + if val[0] in u'uU': + val = val[1:] + if val == node.value: + return node + new = node.clone() + new.value = val + return new diff --git a/PythonHome/Lib/lib2to3/fixes/fix_unicode.pyc b/PythonHome/Lib/lib2to3/fixes/fix_unicode.pyc deleted file mode 100644 index d3a8edb4d8d942efe92daf6184fe98f9f07ecbfb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1672 zcmbVM-EP}f4Caw+CH4|D7<#c>3>A!_5qjYQDbTB~Xp{b+z-kO~f})07RgsPpIkKeb z9HlGZT%|XAjXlNoB728j?*;aeQkq?EGb|pGA`i)rq};!@hrhk~FioiYxj3KTF>gRp zq8X^7)S+C_%AuJv6}m$p|k|98sV^ zY@bPau8US2LR@hE(MfD{!@wb@#>2_QfMpdDZ#Fs=>a*;Hs*l@p6G-yo00(%?T@Ve} z6=|UDN(%t4Vh9;mM;MR7X&~2s3;XF&_-gXfU;BFeRaMNM(j7)KFf6xuXF&OgqRVy@%)GEWS(ay`?h>AXZ#J* zs7q^HeF{03+jtCLOlnsN1l$*X1Og9ubD4qy>OXg=-tP*(BD!=5$*@76cGoUNeFB}{ zczELBsMh2XwnWPf+Nyu2wRCG2jRJy@u_{n?JXT_pP7xc-fVbvK(X)5o(Io=(X*uLA z!V+;)z++oBnSbxlPrtA!0u|znF70Bi_|`up;*joqdD$k#CH=`YNZKy%AId`Dn|h?P zyo-|zgc@$$-l*YOoQp8;jz&fqQmZ}g#A6Yg|OYNv0&VjnCJmsqIogKBUZb7#N zT_BlBr4f&C6v;wF(W*?FoJ9uas7Bq}U=ChKNx7) > + """ % (old_module, old_module) + yield """import_from< 'from' mod_member=%r 'import' + ( member=%s | import_as_name< member=%s 'as' any > | + import_as_names< members=any* >) > + """ % (old_module, members, members) + yield """import_from< 'from' module_star=%r 'import' star='*' > + """ % old_module + yield """import_name< 'import' + dotted_as_name< module_as=%r 'as' any > > + """ % old_module + # bare_with_attr has a special significance for FixImports.match(). + yield """power< bare_with_attr=%r trailer< '.' member=%s > any* > + """ % (old_module, members) + + +class FixUrllib(FixImports): + + def build_pattern(self): + return "|".join(build_pattern()) + + def transform_import(self, node, results): + """Transform for the basic import case. Replaces the old + import name with a comma separated list of its + replacements. + """ + import_mod = results.get("module") + pref = import_mod.prefix + + names = [] + + # create a Node list of the replacement modules + for name in MAPPING[import_mod.value][:-1]: + names.extend([Name(name[0], prefix=pref), Comma()]) + names.append(Name(MAPPING[import_mod.value][-1][0], prefix=pref)) + import_mod.replace(names) + + def transform_member(self, node, results): + """Transform for imports of specific module elements. Replaces + the module to be imported from with the appropriate new + module. + """ + mod_member = results.get("mod_member") + pref = mod_member.prefix + member = results.get("member") + + # Simple case with only a single member being imported + if member: + # this may be a list of length one, or just a node + if isinstance(member, list): + member = member[0] + new_name = None + for change in MAPPING[mod_member.value]: + if member.value in change[1]: + new_name = change[0] + break + if new_name: + mod_member.replace(Name(new_name, prefix=pref)) + else: + self.cannot_convert(node, "This is an invalid module element") + + # Multiple members being imported + else: + # a dictionary for replacements, order matters + modules = [] + mod_dict = {} + members = results["members"] + for member in members: + # we only care about the actual members + if member.type == syms.import_as_name: + as_name = member.children[2].value + member_name = member.children[0].value + else: + member_name = member.value + as_name = None + if member_name != u",": + for change in MAPPING[mod_member.value]: + if member_name in change[1]: + if change[0] not in mod_dict: + modules.append(change[0]) + mod_dict.setdefault(change[0], []).append(member) + + new_nodes = [] + indentation = find_indentation(node) + first = True + def handle_name(name, prefix): + if name.type == syms.import_as_name: + kids = [Name(name.children[0].value, prefix=prefix), + name.children[1].clone(), + name.children[2].clone()] + return [Node(syms.import_as_name, kids)] + return [Name(name.value, prefix=prefix)] + for module in modules: + elts = mod_dict[module] + names = [] + for elt in elts[:-1]: + names.extend(handle_name(elt, pref)) + names.append(Comma()) + names.extend(handle_name(elts[-1], pref)) + new = FromImport(module, names) + if not first or node.parent.prefix.endswith(indentation): + new.prefix = indentation + new_nodes.append(new) + first = False + if new_nodes: + nodes = [] + for new_node in new_nodes[:-1]: + nodes.extend([new_node, Newline()]) + nodes.append(new_nodes[-1]) + node.replace(nodes) + else: + self.cannot_convert(node, "All module elements are invalid") + + def transform_dot(self, node, results): + """Transform for calls to module members in code.""" + module_dot = results.get("bare_with_attr") + member = results.get("member") + new_name = None + if isinstance(member, list): + member = member[0] + for change in MAPPING[module_dot.value]: + if member.value in change[1]: + new_name = change[0] + break + if new_name: + module_dot.replace(Name(new_name, + prefix=module_dot.prefix)) + else: + self.cannot_convert(node, "This is an invalid module element") + + def transform(self, node, results): + if results.get("module"): + self.transform_import(node, results) + elif results.get("mod_member"): + self.transform_member(node, results) + elif results.get("bare_with_attr"): + self.transform_dot(node, results) + # Renaming and star imports are not supported for these modules. + elif results.get("module_star"): + self.cannot_convert(node, "Cannot handle star imports.") + elif results.get("module_as"): + self.cannot_convert(node, "This module is now multiple modules") diff --git a/PythonHome/Lib/lib2to3/fixes/fix_urllib.pyc b/PythonHome/Lib/lib2to3/fixes/fix_urllib.pyc deleted file mode 100644 index 582b6e64b41900e4188026c81aa13a08667dbfc1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7025 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 + """ + + COMMA = pytree.Leaf(token.COMMA, u",") + COLON = pytree.Leaf(token.COLON, u":") + SEPS = (COMMA, COLON) + + def transform(self, node, results): + new = node.clone() + comma = False + for child in new.children: + if child in self.SEPS: + prefix = child.prefix + if prefix.isspace() and u"\n" not in prefix: + child.prefix = u"" + comma = True + else: + if comma: + prefix = child.prefix + if not prefix: + child.prefix = u" " + comma = False + return new diff --git a/PythonHome/Lib/lib2to3/fixes/fix_ws_comma.pyc b/PythonHome/Lib/lib2to3/fixes/fix_ws_comma.pyc deleted file mode 100644 index 6144ad2dc41aed7672a0e92d6782df2d58d0262a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1351 zcmbVM!A{#i5S?`#hqzRw2P6(0R_Y<9jX1P7gis*`wGss6L_$rWu48YAgX0a}wE&Sw zmFSHx=qL0K`d|Hl&a6Rz#G$I?9nZ|Zot=3*>&ly9)VQe|87F3fDMV2ro2` zCC165=2{lfkV`!jxmzf7$^nmLDl@gp`KPCW{0?|NOteswFcO$RVqvx(L!liMlS`co zQQB2<%2Sb*rihZg<;n`#1@vyj>9vd~+v=#Mb`a z-lnOiwZFUH_K73^C5ro^jP|dU`9v0_sz^ANV>{L&TV(TA+x$RGPC*dM2n#?2l!;L) qlM|7>HJSNzZw+z_ZzEnr6ZJncGL)>BEN#$lKoN + rest=any* > + """ + + def start_tree(self, tree, filename): + super(FixXrange, self).start_tree(tree, filename) + self.transformed_xranges = set() + + def finish_tree(self, tree, filename): + self.transformed_xranges = None + + def transform(self, node, results): + name = results["name"] + if name.value == u"xrange": + return self.transform_xrange(node, results) + elif name.value == u"range": + return self.transform_range(node, results) + else: + raise ValueError(repr(name)) + + def transform_xrange(self, node, results): + name = results["name"] + name.replace(Name(u"range", prefix=name.prefix)) + # This prevents the new range call from being wrapped in a list later. + self.transformed_xranges.add(id(node)) + + def transform_range(self, node, results): + if (id(node) not in self.transformed_xranges and + not self.in_special_context(node)): + range_call = Call(Name(u"range"), [results["args"].clone()]) + # Encase the range call in list(). + list_call = Call(Name(u"list"), [range_call], + prefix=node.prefix) + # Put things that were after the range() call after the list call. + for n in results["rest"]: + list_call.append_child(n) + return list_call + + P1 = "power< func=NAME trailer< '(' node=any ')' > any* >" + p1 = patcomp.compile_pattern(P1) + + P2 = """for_stmt< 'for' any 'in' node=any ':' any* > + | comp_for< 'for' any 'in' node=any any* > + | comparison< any 'in' node=any any*> + """ + p2 = patcomp.compile_pattern(P2) + + def in_special_context(self, node): + if node.parent is None: + return False + results = {} + if (node.parent.parent is not None and + self.p1.match(node.parent.parent, results) and + results["node"] is node): + # list(d.keys()) -> list(d.keys()), etc. + return results["func"].value in consuming_calls + # for ... in d.iterkeys() -> for ... in d.keys(), etc. + return self.p2.match(node.parent, results) and results["node"] is node diff --git a/PythonHome/Lib/lib2to3/fixes/fix_xrange.pyc b/PythonHome/Lib/lib2to3/fixes/fix_xrange.pyc deleted file mode 100644 index 55aca33a51fc64d408ad1bb6e557ee4ec81539d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2967 zcmbVO+io015UrlQc^xOV69QO?U_eN_&Vx~sH!XP4<- za3uSM@W2D`zz^^n{1-pKIn|q8Cj<${a`*PFx~oo|s+!v0XP5ta@?C!@v%eaCZ==~5 zT`Dp_ZzK(*Ffs~c5QyQtCPhs~bs5xU)Q~|#Mok$s{a#(qwq(%4ydha2`%AI|p{D#S z@?7NWL0i(6^t(%Z=woyb^24kO-Cp9t;a*biW;Q&m_}ksu+S&~B(v8E#d@Bzi(>3Va zGP)f~$J>d`x>VoQ(e;v1rh|J)QMgsC49BINj`DIh9%9LQ@fJ2Fi5reb6W7KVihQLH z%>m(4chRgvmjMt%iv~3Xr%rHS6aWB395jgy2Q5kKI#?2bz!ew`kd`GoBl|0oEz5Hw zgR?|paPGz8IbB?pbV)_lB@{K z0msJG=yYtvfJ@+ZIV}DZOc3Qn}bwSq4E&Gv_YwDD1I2<7$+pvA4!9 zylt~$N4>3Lq}2|rr0HFZMLYWeMq5w6$hV&s`Svw8zW$WNvFv9zZcUy=WW-x&wvJBB zhM8MSCaAS%F@Pbo2&`UM!~>pu<1&lrHq|hqRnZxCD_lc6jYf`=J9(MgJw@eROf8=h zuNw6vP^#Lu7yx##a^turM>W}ps(~B?Qf*SisdL3w@N%efvXFOf$EJjk*73SZho!7FAB8`Adr2uc~pSk5t*D z>hev6(Z4%RGeu*vF0hF%^2pol-UN_n9g-iRSt>vrE_(zxog?rECWv%zk|)$bORC=&?18B(n0xks zh?or z`m$hObA3;PPniH&}G=WC3JDjgdWFA+&CVM(`mseL+EjZG*0F3K16hk z@X3^K7d{C;y7Tz){ivsfGdhPO(L3yTt@2eZd2}`6HM0+~(FD~w#w9MR%BaH)BJt>2 z#1Dyx`Yw#r(f=&oOjC?a%P4J{W}_Lj>+M>*-EOv5nr5|u7WBHy*wqXh$LV+o6ET;F y-HGqXsmlwWdNmEuDc%NFp1b(i#J8e;wY-t4iuetW@hw7Q>4Ii$&0IEXwSNH7_dlrs diff --git a/PythonHome/Lib/lib2to3/fixes/fix_xreadlines.py b/PythonHome/Lib/lib2to3/fixes/fix_xreadlines.py new file mode 100644 index 0000000000..f50b9a2755 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_xreadlines.py @@ -0,0 +1,25 @@ +"""Fix "for x in f.xreadlines()" -> "for x in f". + +This fixer will also convert g(f.xreadlines) into g(f.__iter__).""" +# Author: Collin Winter + +# Local imports +from .. import fixer_base +from ..fixer_util import Name + + +class FixXreadlines(fixer_base.BaseFix): + BM_compatible = True + PATTERN = """ + power< call=any+ trailer< '.' 'xreadlines' > trailer< '(' ')' > > + | + power< any+ trailer< '.' no_call='xreadlines' > > + """ + + def transform(self, node, results): + no_call = results.get("no_call") + + if no_call: + no_call.replace(Name(u"__iter__", prefix=no_call.prefix)) + else: + node.replace([x.clone() for x in results["call"]]) diff --git a/PythonHome/Lib/lib2to3/fixes/fix_xreadlines.pyc b/PythonHome/Lib/lib2to3/fixes/fix_xreadlines.pyc deleted file mode 100644 index b66d6938395151e88f61c19e6b600608f0c259e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1121 zcmbVL&5qMB5FRIKfT9&EIB`H&l~7X6Ta{Kez>@yvW<|K~yT$Jl#rXqnt3+u!YIobby{o*DORfGTz%st$7PhY9YsaBIm zwmdqefiQ$($47T@Zm*#w@>Lj|)%+F;hAIGd!wcD6FQN);T~mSMBZQkSA@VX?Y7!~A zQMIfGtN&W0WxhzPn&>*qH_t|+lXwu**zNNB$0TE#x9hkJr4zES5qbmn)LbWo$jTH` pK^?>ddoN&Vm3EzVmVJB=IQ%Z&e`n*`aa=c`N8PWp3J%$!{|mP=^&tQN diff --git a/PythonHome/Lib/lib2to3/fixes/fix_zip.py b/PythonHome/Lib/lib2to3/fixes/fix_zip.py new file mode 100644 index 0000000000..c5d7b66d67 --- /dev/null +++ b/PythonHome/Lib/lib2to3/fixes/fix_zip.py @@ -0,0 +1,35 @@ +""" +Fixer that changes zip(seq0, seq1, ...) into list(zip(seq0, seq1, ...) +unless there exists a 'from future_builtins import zip' statement in the +top-level namespace. + +We avoid the transformation if the zip() call is directly contained in +iter(<>), list(<>), tuple(<>), sorted(<>), ...join(<>), or for V in <>:. +""" + +# Local imports +from .. import fixer_base +from ..fixer_util import Name, Call, in_special_context + +class FixZip(fixer_base.ConditionalFix): + + BM_compatible = True + PATTERN = """ + power< 'zip' args=trailer< '(' [any] ')' > + > + """ + + skip_on = "future_builtins.zip" + + def transform(self, node, results): + if self.should_skip(node): + return + + if in_special_context(node): + return None + + new = node.clone() + new.prefix = u"" + new = Call(Name(u"list"), [new]) + new.prefix = node.prefix + return new diff --git a/PythonHome/Lib/lib2to3/fixes/fix_zip.pyc b/PythonHome/Lib/lib2to3/fixes/fix_zip.pyc deleted file mode 100644 index 846ab3cdde339d9d603016e560b51d43f0695c30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1315 zcmb7DU2oM!5FPtE7ckHw@{)(DT8W42NapKO z%6~KGx>tN!v8qoiccO#(%XCH1e}2ECU~liJ`Fy^ujAO5?30!>YIvtzz&Gtgo-f?A|ZcrdMtovejZ+mC# zBzin_R*#1Puyix}X!^_>H*S2dP)|J)kh^<#=DA5hU;+M!bC|V|Sgxv|3z3a8m;=C% z&ORXVO`I54hECU}vZbKX=gd`WT>SZ zX-3}rSm7DW-$ZAy3B5|F-xOSjoV?xNihEq1O=RN!0dCw)sLY5r2n_=|zQf505~LC! z!P%P_oR1wH45&nd6pvFU6U$d&!l@r@Q-o8ajEcu*%S>Q#{gm2-^kAF9-V{2AFu>bK`v<_lR5H#;D_zFVa zjpPm*CB#dRgwO0FgGr{l}GDodH|vW&A+maT6FD_cQ$)DN1k!?|}KQ_^;r z@s%A>KK$kA=-0(TL@e!>-Yq2ZJ>1X5ypT#?VFiIRO{W=FdQikxgpjgqd<{f!X(8r= tF(262$mqyz)If6Wd)FBGBP)xMjwQYvS>$JTWMogk1<`UkxsiO6z6Kw{EL8vi diff --git a/PythonHome/Lib/lib2to3/main.py b/PythonHome/Lib/lib2to3/main.py new file mode 100644 index 0000000000..ad0625e527 --- /dev/null +++ b/PythonHome/Lib/lib2to3/main.py @@ -0,0 +1,269 @@ +""" +Main program for 2to3. +""" + +from __future__ import with_statement + +import sys +import os +import difflib +import logging +import shutil +import optparse + +from . import refactor + + +def diff_texts(a, b, filename): + """Return a unified diff of two strings.""" + a = a.splitlines() + b = b.splitlines() + return difflib.unified_diff(a, b, filename, filename, + "(original)", "(refactored)", + lineterm="") + + +class StdoutRefactoringTool(refactor.MultiprocessRefactoringTool): + """ + A refactoring tool that can avoid overwriting its input files. + Prints output to stdout. + + Output files can optionally be written to a different directory and or + have an extra file suffix appended to their name for use in situations + where you do not want to replace the input files. + """ + + def __init__(self, fixers, options, explicit, nobackups, show_diffs, + input_base_dir='', output_dir='', append_suffix=''): + """ + Args: + fixers: A list of fixers to import. + options: A dict with RefactoringTool configuration. + explicit: A list of fixers to run even if they are explicit. + nobackups: If true no backup '.bak' files will be created for those + files that are being refactored. + show_diffs: Should diffs of the refactoring be printed to stdout? + input_base_dir: The base directory for all input files. This class + will strip this path prefix off of filenames before substituting + it with output_dir. Only meaningful if output_dir is supplied. + All files processed by refactor() must start with this path. + output_dir: If supplied, all converted files will be written into + this directory tree instead of input_base_dir. + append_suffix: If supplied, all files output by this tool will have + this appended to their filename. Useful for changing .py to + .py3 for example by passing append_suffix='3'. + """ + self.nobackups = nobackups + self.show_diffs = show_diffs + if input_base_dir and not input_base_dir.endswith(os.sep): + input_base_dir += os.sep + self._input_base_dir = input_base_dir + self._output_dir = output_dir + self._append_suffix = append_suffix + super(StdoutRefactoringTool, self).__init__(fixers, options, explicit) + + def log_error(self, msg, *args, **kwargs): + self.errors.append((msg, args, kwargs)) + self.logger.error(msg, *args, **kwargs) + + def write_file(self, new_text, filename, old_text, encoding): + orig_filename = filename + if self._output_dir: + if filename.startswith(self._input_base_dir): + filename = os.path.join(self._output_dir, + filename[len(self._input_base_dir):]) + else: + raise ValueError('filename %s does not start with the ' + 'input_base_dir %s' % ( + filename, self._input_base_dir)) + if self._append_suffix: + filename += self._append_suffix + if orig_filename != filename: + output_dir = os.path.dirname(filename) + if not os.path.isdir(output_dir): + os.makedirs(output_dir) + self.log_message('Writing converted %s to %s.', orig_filename, + filename) + if not self.nobackups: + # Make backup + backup = filename + ".bak" + if os.path.lexists(backup): + try: + os.remove(backup) + except os.error, err: + self.log_message("Can't remove backup %s", backup) + try: + os.rename(filename, backup) + except os.error, err: + self.log_message("Can't rename %s to %s", filename, backup) + # Actually write the new file + write = super(StdoutRefactoringTool, self).write_file + write(new_text, filename, old_text, encoding) + if not self.nobackups: + shutil.copymode(backup, filename) + if orig_filename != filename: + # Preserve the file mode in the new output directory. + shutil.copymode(orig_filename, filename) + + def print_output(self, old, new, filename, equal): + if equal: + self.log_message("No changes to %s", filename) + else: + self.log_message("Refactored %s", filename) + if self.show_diffs: + diff_lines = diff_texts(old, new, filename) + try: + if self.output_lock is not None: + with self.output_lock: + for line in diff_lines: + print line + sys.stdout.flush() + else: + for line in diff_lines: + print line + except UnicodeEncodeError: + warn("couldn't encode %s's diff for your terminal" % + (filename,)) + return + + +def warn(msg): + print >> sys.stderr, "WARNING: %s" % (msg,) + + +def main(fixer_pkg, args=None): + """Main program. + + Args: + fixer_pkg: the name of a package where the fixers are located. + args: optional; a list of command line arguments. If omitted, + sys.argv[1:] is used. + + Returns a suggested exit status (0, 1, 2). + """ + # Set up option parser + parser = optparse.OptionParser(usage="2to3 [options] file|dir ...") + parser.add_option("-d", "--doctests_only", action="store_true", + help="Fix up doctests only") + parser.add_option("-f", "--fix", action="append", default=[], + help="Each FIX specifies a transformation; default: all") + parser.add_option("-j", "--processes", action="store", default=1, + type="int", help="Run 2to3 concurrently") + parser.add_option("-x", "--nofix", action="append", default=[], + help="Prevent a transformation from being run") + parser.add_option("-l", "--list-fixes", action="store_true", + help="List available transformations") + parser.add_option("-p", "--print-function", action="store_true", + help="Modify the grammar so that print() is a function") + parser.add_option("-v", "--verbose", action="store_true", + help="More verbose logging") + parser.add_option("--no-diffs", action="store_true", + help="Don't show diffs of the refactoring") + parser.add_option("-w", "--write", action="store_true", + help="Write back modified files") + parser.add_option("-n", "--nobackups", action="store_true", default=False, + help="Don't write backups for modified files") + parser.add_option("-o", "--output-dir", action="store", type="str", + default="", help="Put output files in this directory " + "instead of overwriting the input files. Requires -n.") + parser.add_option("-W", "--write-unchanged-files", action="store_true", + help="Also write files even if no changes were required" + " (useful with --output-dir); implies -w.") + parser.add_option("--add-suffix", action="store", type="str", default="", + help="Append this string to all output filenames." + " Requires -n if non-empty. " + "ex: --add-suffix='3' will generate .py3 files.") + + # Parse command line arguments + refactor_stdin = False + flags = {} + options, args = parser.parse_args(args) + if options.write_unchanged_files: + flags["write_unchanged_files"] = True + if not options.write: + warn("--write-unchanged-files/-W implies -w.") + options.write = True + # If we allowed these, the original files would be renamed to backup names + # but not replaced. + if options.output_dir and not options.nobackups: + parser.error("Can't use --output-dir/-o without -n.") + if options.add_suffix and not options.nobackups: + parser.error("Can't use --add-suffix without -n.") + + if not options.write and options.no_diffs: + warn("not writing files and not printing diffs; that's not very useful") + if not options.write and options.nobackups: + parser.error("Can't use -n without -w") + if options.list_fixes: + print "Available transformations for the -f/--fix option:" + for fixname in refactor.get_all_fix_names(fixer_pkg): + print fixname + if not args: + return 0 + if not args: + print >> sys.stderr, "At least one file or directory argument required." + print >> sys.stderr, "Use --help to show usage." + return 2 + if "-" in args: + refactor_stdin = True + if options.write: + print >> sys.stderr, "Can't write to stdin." + return 2 + if options.print_function: + flags["print_function"] = True + + # Set up logging handler + level = logging.DEBUG if options.verbose else logging.INFO + logging.basicConfig(format='%(name)s: %(message)s', level=level) + logger = logging.getLogger('lib2to3.main') + + # Initialize the refactoring tool + avail_fixes = set(refactor.get_fixers_from_package(fixer_pkg)) + unwanted_fixes = set(fixer_pkg + ".fix_" + fix for fix in options.nofix) + explicit = set() + if options.fix: + all_present = False + for fix in options.fix: + if fix == "all": + all_present = True + else: + explicit.add(fixer_pkg + ".fix_" + fix) + requested = avail_fixes.union(explicit) if all_present else explicit + else: + requested = avail_fixes.union(explicit) + fixer_names = requested.difference(unwanted_fixes) + input_base_dir = os.path.commonprefix(args) + if (input_base_dir and not input_base_dir.endswith(os.sep) + and not os.path.isdir(input_base_dir)): + # One or more similar names were passed, their directory is the base. + # os.path.commonprefix() is ignorant of path elements, this corrects + # for that weird API. + input_base_dir = os.path.dirname(input_base_dir) + if options.output_dir: + input_base_dir = input_base_dir.rstrip(os.sep) + logger.info('Output in %r will mirror the input directory %r layout.', + options.output_dir, input_base_dir) + rt = StdoutRefactoringTool( + sorted(fixer_names), flags, sorted(explicit), + options.nobackups, not options.no_diffs, + input_base_dir=input_base_dir, + output_dir=options.output_dir, + append_suffix=options.add_suffix) + + # Refactor all files and directories passed as arguments + if not rt.errors: + if refactor_stdin: + rt.refactor_stdin() + else: + try: + rt.refactor(args, options.write, options.doctests_only, + options.processes) + except refactor.MultiprocessingUnsupported: + assert options.processes > 1 + print >> sys.stderr, "Sorry, -j isn't " \ + "supported on this platform." + return 1 + rt.summarize() + + # Return error status (0 if rt.errors is zero) + return int(bool(rt.errors)) diff --git a/PythonHome/Lib/lib2to3/main.pyc b/PythonHome/Lib/lib2to3/main.pyc deleted file mode 100644 index 70ebd87996ea15a6c47fd30c51ff92e862f3f7ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9681 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 3 and nodes[1].type == token.EQUAL: + name = nodes[0].value + nodes = nodes[2:] + repeat = None + if len(nodes) >= 2 and nodes[-1].type == self.syms.Repeater: + repeat = nodes[-1] + nodes = nodes[:-1] + + # Now we've reduced it to: STRING | NAME [Details] | (...) | [...] + pattern = self.compile_basic(nodes, repeat) + + if repeat is not None: + assert repeat.type == self.syms.Repeater + children = repeat.children + child = children[0] + if child.type == token.STAR: + min = 0 + max = pytree.HUGE + elif child.type == token.PLUS: + min = 1 + max = pytree.HUGE + elif child.type == token.LBRACE: + assert children[-1].type == token.RBRACE + assert len(children) in (3, 5) + min = max = self.get_int(children[1]) + if len(children) == 5: + max = self.get_int(children[3]) + else: + assert False + if min != 1 or max != 1: + pattern = pattern.optimize() + pattern = pytree.WildcardPattern([[pattern]], min=min, max=max) + + if name is not None: + pattern.name = name + return pattern.optimize() + + def compile_basic(self, nodes, repeat=None): + # Compile STRING | NAME [Details] | (...) | [...] + assert len(nodes) >= 1 + node = nodes[0] + if node.type == token.STRING: + value = unicode(literals.evalString(node.value)) + return pytree.LeafPattern(_type_of_literal(value), value) + elif node.type == token.NAME: + value = node.value + if value.isupper(): + if value not in TOKEN_MAP: + raise PatternSyntaxError("Invalid token: %r" % value) + if nodes[1:]: + raise PatternSyntaxError("Can't have details for token") + return pytree.LeafPattern(TOKEN_MAP[value]) + else: + if value == "any": + type = None + elif not value.startswith("_"): + type = getattr(self.pysyms, value, None) + if type is None: + raise PatternSyntaxError("Invalid symbol: %r" % value) + if nodes[1:]: # Details present + content = [self.compile_node(nodes[1].children[1])] + else: + content = None + return pytree.NodePattern(type, content) + elif node.value == "(": + return self.compile_node(nodes[1]) + elif node.value == "[": + assert repeat is None + subpattern = self.compile_node(nodes[1]) + return pytree.WildcardPattern([[subpattern]], min=0, max=1) + assert False, node + + def get_int(self, node): + assert node.type == token.NUMBER + return int(node.value) + + +# Map named tokens to the type value for a LeafPattern +TOKEN_MAP = {"NAME": token.NAME, + "STRING": token.STRING, + "NUMBER": token.NUMBER, + "TOKEN": None} + + +def _type_of_literal(value): + if value[0].isalpha(): + return token.NAME + elif value in grammar.opmap: + return grammar.opmap[value] + else: + return None + + +def pattern_convert(grammar, raw_node_info): + """Converts raw node information to a Node or Leaf instance.""" + type, value, context, children = raw_node_info + if children or type in grammar.number2symbol: + return pytree.Node(type, children, context=context) + else: + return pytree.Leaf(type, value, context=context) + + +def compile_pattern(pattern): + return PatternCompiler().compile_pattern(pattern) diff --git a/PythonHome/Lib/lib2to3/patcomp.pyc b/PythonHome/Lib/lib2to3/patcomp.pyc deleted file mode 100644 index 58a7ceaaa8af096ee39d96270f751227444606cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6486 zcma)A&vP6{6@I-V?P^!QY}t~f*u+C6#!Es(#R2o9l9Ux&F(UHDnU!%^>ROLh!w-hH*oS-=I7f{846DNwIIKlV5o|WXJ;?hdf)6@O> z_3QUufA4iW|C+3QeE)~dwiG`H?;Cis86y&kv``vp83{`gI?^pk3l&>;q~%CBBH^fX zN2E6@tx@TfrB#+*MOqc#oZv! zqcm~b{oWw%M(JX$wzd_yn`zMNMX4KSZXRq$iMx^Zdu~B|o1HH9t3F?yKRDz>`t12o^QsHS6rEmr$r+zMllW z$oKOaT719P4|lrwv{XvUBAZ9C_+T|&f6$HBujTz$9zd^D_u^pBBl|Cqid@U4&3UV= z;-N6vV-z|5jdV&{I$Dm%hC_EeFao`F$^xBqDzXnp1SNbFT_xH5hU}N**2AyLfg}5l zJQ$UO5jj9vmV=5MjLH6p>>JsxNP2?=-!qSH2>$P5t2K3{*>wo8Mq|JPbc!rb<7Cs# zb_Rnq$}+9Tn@PM8w}T{iA8)~m*&u*pH0oSQ?r<4V?y25rxyJJS)s@Dw8f~RU~S7SnmT20R%q;0y+`_MF3w$J_Hht z5(J4kWx^kzfiz=8LpE0Fw(3k&KObu6CZ6m)6!5H$p$EWU;5$BC%#jX!0_~+?4 zm7t<^_zj4wI=og8L!5jZLkzpHuS;+su0!WpN#Z;Xx^N-FlUw}OfJ<gGT+Y#Rl-V&^X&@liZz_Y(q1qfSkGcqC`7+Yds&7~#=J zJi4HcXzuma`+ys2B-`s{`4lP^uZAPk2?l$`_>%+}po6K~!JZCh^_GP*`fnkwUkGM# zL+6UR8!B7D*5^u3>tF;7-;beB-+u}9jNl`qGwM_mrp*bsLM~O!e1HnfY;BC)zjsLu zrg(zg53>OxU^bw_{iH4<)&aI_l6qo*69)K#owQ%3JK+DvMiL|M0xZ(5asuj%vIFG? zj84}XHZ_mE;5Eu){rqHTDbPeCOcG^z6n-Yq^w&F4J6}}z52N*+%|@L{@Gi2zW9_Vg zp@0gHN>Eh3%W$E{u1IUKC{I=UMa1)yei+rMGVdx21_tj1G9Umvj`J;_fzLb7CNfU@ z{Ty(Njd@y|(Hn-d6<+a8G-U(}DNPv1Trx9e&Xmo$Qk#2}1L#d^z&~Rb!FnB(x?8a^ zw@Z><(MF^TMivkSl1~whDA6afY1=_J%$9!Q$il6Mvy2a9IBM-L@0H}yJB$-Fw#F7f z2q*d}KRHX2F=k9TItVJ$j3w}(O`~Ifsqmv&6$T!f5*!LH(Wx>uYCf@mn(}?k9Le@M z;{1(q>d5yBab^u%@q{?|f&_%VQ_VfDbALdT>P!q(I3kzfz=()k;iT+W=+B=o{}g#- zzb1xbH$brrq_B`92f#$A4{JtyMYcyJ{inevWLtm%^Rv>KQ2}f#l-fC`qe0@xWekTM z$*^{UkE49PULv0{_#$|upx)&5RL2AlBtCRkw1QQ%gs>0^vU`mpYPtaUYnm?7W>?de`b%JJIY2I-- zhg}u9FR(THPaz0($(X_%d%G;zv{MKO<2|F&L9gf@!7PyBn7pdYA39WlC9EhRh#oz3 zk_pK#O7?KbZIbrcb|l+z_NR(EH3Vl+?=2hyMy}A;th?=F6vUfSSFgyUj~s461YWD) zKRBp^-oK<#Mngi-SKKse@1z+*Uw7|hklaEBkNAcf%B^IfLucak$RBMUs;@!nQ~B(iG=D$lF007O9RVZVdN5X7tp>2_E|0 zh&GY*h4&EQ@=5d$fpa~`;2wzT$NQnzP9#*SGx6y`@#} z0%|IX7Y!mzmnvm*ZOPNhckbO@*2>-0drf$i$m$#3(oLJPdbY}lu^HtE#kq#2H*s>Y znI)5!Iw4#Git?eEa$2OlrQgVNGL0dDmILLmgC%FG@FGZfZ()RXaeStNq$;q-tXzB4 z9^NaQ?Q1Ab8Isgkw?Ln5p^(a~Ia8V~T|*QaGcTK3Y1UlP`mB{Od>;A;W>^Ju?{H7_&QoP9PUUkd{nIKxD^HC@u_) z9cJSf0RIqC{ja2kfAK8z5q%ecjFvgDValUn6cS!eKhaL*Z##-fr$|mTYT}J}L`na_ zq#c1Id6S);vxE##WG@*UKnYIg*bbUQ;H}0>)VIeZ1py?$`i>-c^pZIt#C;85=T%9J zBDiqC3#kan*-5@)(GG)Ir zg<&A~(aab@c*HapPQata8Qg_HC}aZ7d|tADb2Rjh0SubR2{co;_W_Do*;%;8N`muP z9J+dl`nG!|%`Tz!W{_OX-K_w}0&Jup?q>E>pqB*nsvy||d!)vC-XAitNjkY`XI;x5 zoY*Z37~(M(^KP(E*yA?Ut=3%gRvNc;Lt<;Tu?0O&p^0S#DeYlYvBcsX;cPVuHipQ= z{LUvh`~3~SxZTk0-&ne{tbAi0qk%q5HP_yLYq{ayS-PvKs<$+pN>8Ok{Vg2=%)vP* z^`1w+ZexoDoVx)Li@CjTvHQCyY_hDWZIf+lELK?%1a-;E7sr$wu&%4icGe3BIxU_s zz5h9$>{S#}npZ@aM@~Bfbl~1Uhn8t`7C2DFnmgW6@I`7cet=O&)) z3JRM(!hAOQB}O=OBWROddj4qY)lWlDyPvXT5s*Q>^|M$pkLp1xGxSNxt-)UcQ{rUIuKw+AK$6i%WJa~~CW#RDXt$a(>+dgTQS z%&zjRg9TurNGH?RiiNTf=Z7L*m?r%U;Ez^4_yB_sOXkE`mMXhxuNyKq4IaCig~bUj zDtfrPU~0x2Q*K8WcNc^N_vpIxc(d)|vVtC@X-=}!TaVIf7O^axu#Y?xGRVZbwkngE z5oXrID^ie+zV&$B(mnJkC>(pz(>41g4EQ4+z3h|{?-J%ppY;^N8G`j8^aoYxP2+IS z(GAoW)vK*-c{V?-1l$XM!K2rpV(KpHswm$N`|YDE)?f#h$tgZLUqACyBI;v+%ff4% zP!yuA>pA?S67}8(lA}gPu{S{M0La;VtkVZ1(09Wa*H67jb3pF diff --git a/PythonHome/Lib/lib2to3/pgen2/__init__.py b/PythonHome/Lib/lib2to3/pgen2/__init__.py new file mode 100644 index 0000000000..af39048452 --- /dev/null +++ b/PythonHome/Lib/lib2to3/pgen2/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""The pgen2 package.""" diff --git a/PythonHome/Lib/lib2to3/pgen2/__init__.pyc b/PythonHome/Lib/lib2to3/pgen2/__init__.pyc deleted file mode 100644 index e2df8002a552c58b5ff8fa07e2c14013fc5a605d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 159 zcmZSn%*(YSJRvxl0SXv_v;zVK0YNsIX+$k$Yeke#qvO|UW`v>QcO-}l2J*%aSYgmnE3e2yv&mL ac)fzk5)Pmmo80`A(wtN~79hJAh#3G3mLNp{ diff --git a/PythonHome/Lib/lib2to3/pgen2/conv.py b/PythonHome/Lib/lib2to3/pgen2/conv.py new file mode 100644 index 0000000000..28fbb0b95f --- /dev/null +++ b/PythonHome/Lib/lib2to3/pgen2/conv.py @@ -0,0 +1,257 @@ +# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Convert graminit.[ch] spit out by pgen to Python code. + +Pgen is the Python parser generator. It is useful to quickly create a +parser from a grammar file in Python's grammar notation. But I don't +want my parsers to be written in C (yet), so I'm translating the +parsing tables to Python data structures and writing a Python parse +engine. + +Note that the token numbers are constants determined by the standard +Python tokenizer. The standard token module defines these numbers and +their names (the names are not used much). The token numbers are +hardcoded into the Python tokenizer and into pgen. A Python +implementation of the Python tokenizer is also available, in the +standard tokenize module. + +On the other hand, symbol numbers (representing the grammar's +non-terminals) are assigned by pgen based on the actual grammar +input. + +Note: this module is pretty much obsolete; the pgen module generates +equivalent grammar tables directly from the Grammar.txt input file +without having to invoke the Python pgen C program. + +""" + +# Python imports +import re + +# Local imports +from pgen2 import grammar, token + + +class Converter(grammar.Grammar): + """Grammar subclass that reads classic pgen output files. + + The run() method reads the tables as produced by the pgen parser + generator, typically contained in two C files, graminit.h and + graminit.c. The other methods are for internal use only. + + See the base class for more documentation. + + """ + + def run(self, graminit_h, graminit_c): + """Load the grammar tables from the text files written by pgen.""" + self.parse_graminit_h(graminit_h) + self.parse_graminit_c(graminit_c) + self.finish_off() + + def parse_graminit_h(self, filename): + """Parse the .h file written by pgen. (Internal) + + This file is a sequence of #define statements defining the + nonterminals of the grammar as numbers. We build two tables + mapping the numbers to names and back. + + """ + try: + f = open(filename) + except IOError, err: + print "Can't open %s: %s" % (filename, err) + return False + self.symbol2number = {} + self.number2symbol = {} + lineno = 0 + for line in f: + lineno += 1 + mo = re.match(r"^#define\s+(\w+)\s+(\d+)$", line) + if not mo and line.strip(): + print "%s(%s): can't parse %s" % (filename, lineno, + line.strip()) + else: + symbol, number = mo.groups() + number = int(number) + assert symbol not in self.symbol2number + assert number not in self.number2symbol + self.symbol2number[symbol] = number + self.number2symbol[number] = symbol + return True + + def parse_graminit_c(self, filename): + """Parse the .c file written by pgen. (Internal) + + The file looks as follows. The first two lines are always this: + + #include "pgenheaders.h" + #include "grammar.h" + + After that come four blocks: + + 1) one or more state definitions + 2) a table defining dfas + 3) a table defining labels + 4) a struct defining the grammar + + A state definition has the following form: + - one or more arc arrays, each of the form: + static arc arcs__[] = { + {, }, + ... + }; + - followed by a state array, of the form: + static state states_[] = { + {, arcs__}, + ... + }; + + """ + try: + f = open(filename) + except IOError, err: + print "Can't open %s: %s" % (filename, err) + return False + # The code below essentially uses f's iterator-ness! + lineno = 0 + + # Expect the two #include lines + lineno, line = lineno+1, f.next() + assert line == '#include "pgenheaders.h"\n', (lineno, line) + lineno, line = lineno+1, f.next() + assert line == '#include "grammar.h"\n', (lineno, line) + + # Parse the state definitions + lineno, line = lineno+1, f.next() + allarcs = {} + states = [] + while line.startswith("static arc "): + while line.startswith("static arc "): + mo = re.match(r"static arc arcs_(\d+)_(\d+)\[(\d+)\] = {$", + line) + assert mo, (lineno, line) + n, m, k = map(int, mo.groups()) + arcs = [] + for _ in range(k): + lineno, line = lineno+1, f.next() + mo = re.match(r"\s+{(\d+), (\d+)},$", line) + assert mo, (lineno, line) + i, j = map(int, mo.groups()) + arcs.append((i, j)) + lineno, line = lineno+1, f.next() + assert line == "};\n", (lineno, line) + allarcs[(n, m)] = arcs + lineno, line = lineno+1, f.next() + mo = re.match(r"static state states_(\d+)\[(\d+)\] = {$", line) + assert mo, (lineno, line) + s, t = map(int, mo.groups()) + assert s == len(states), (lineno, line) + state = [] + for _ in range(t): + lineno, line = lineno+1, f.next() + mo = re.match(r"\s+{(\d+), arcs_(\d+)_(\d+)},$", line) + assert mo, (lineno, line) + k, n, m = map(int, mo.groups()) + arcs = allarcs[n, m] + assert k == len(arcs), (lineno, line) + state.append(arcs) + states.append(state) + lineno, line = lineno+1, f.next() + assert line == "};\n", (lineno, line) + lineno, line = lineno+1, f.next() + self.states = states + + # Parse the dfas + dfas = {} + mo = re.match(r"static dfa dfas\[(\d+)\] = {$", line) + assert mo, (lineno, line) + ndfas = int(mo.group(1)) + for i in range(ndfas): + lineno, line = lineno+1, f.next() + mo = re.match(r'\s+{(\d+), "(\w+)", (\d+), (\d+), states_(\d+),$', + line) + assert mo, (lineno, line) + symbol = mo.group(2) + number, x, y, z = map(int, mo.group(1, 3, 4, 5)) + assert self.symbol2number[symbol] == number, (lineno, line) + assert self.number2symbol[number] == symbol, (lineno, line) + assert x == 0, (lineno, line) + state = states[z] + assert y == len(state), (lineno, line) + lineno, line = lineno+1, f.next() + mo = re.match(r'\s+("(?:\\\d\d\d)*")},$', line) + assert mo, (lineno, line) + first = {} + rawbitset = eval(mo.group(1)) + for i, c in enumerate(rawbitset): + byte = ord(c) + for j in range(8): + if byte & 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 Q5@i&At5C>K= os.path.getmtime(b) + + +def main(*args): + """Main program, when run as a script: produce grammar pickle files. + + Calls load_grammar for each argument, a path to a grammar text file. + """ + if not args: + args = sys.argv[1:] + logging.basicConfig(level=logging.INFO, stream=sys.stdout, + format='%(message)s') + for gt in args: + load_grammar(gt, save=True, force=True) + return True + +if __name__ == "__main__": + sys.exit(int(not main())) diff --git a/PythonHome/Lib/lib2to3/pgen2/driver.pyc b/PythonHome/Lib/lib2to3/pgen2/driver.pyc deleted file mode 100644 index 034dd1be2a111ee7d7e9216e274619b803a6b72e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5223 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 delta 2435 zcmb7F&u<%55T3WT*Rf+KX;PvJL!oD$hu!CedPhU!rx^-i_Zz zX{tth2vX0;XAa!BqDmG24u1pU3d}d_#0f>T#M#-|d2i><_sx&}bM>dStnhoi`fKaE zW{)O+MZSN+mmRYRh}tX_1r9}u+N=~PC{pCmpg`>c4T{t*k_t*>O0>_*E`3jQPV}(t zQc$LLnL_q4LytDdl&N3A+UDLpYFEirX|&$Ltv?I%u0!n_wd-W&$P~!b>D(bRL#9US zM=j$27KhRFW)R&|MfA(*QF<3dEA zVeK0h%)}ES|58zOkXxLKB_a1f$+qH!v2>xh7fKo7z|{=mZF+#b!`>(8KhM5=@b$wG z0SG0sq6@t2afFoCS=iG-H;x*^<3ZPq#FDFxd?6J;X(u%{E%NqYzhlJ~b-E_9LhYeB zJ&8v_ZWo?yS`*iq_?E4b4x4sHsRus9nKjYA#}6dJ-ezrWcRTFvMq#&+#&>s<12b&w z9^~0tOHSoD-w%gj>igTg-7eyFRhj&1lY0+zGtMsvF$?c^SxK2?&a6T`ojH^$>N}vX z&m?lL9XcA`_rWidXguVyJ6pL9dqc7$#L5+__`U@8fFhmpydIvymG zc!RLV@d^XID7MB!3N+Z44f|nahMj@oc!>U!kn9CUGze(%WpO+?^J-ZMdc=)m1pGQH z{|=rpD>@VW%mPq@k0SL;^n{-kvw&8EC;L9}8QXCu82_+vbG$ycl+!Wl?nv3|1>U4@ z;3ym(@kV_UrX`pV-f<^xl@oHCxA{eJR3dpO(d$@p zQB%Ii$w<1x2abQ6yOU|~pwW~X(P%WCu0qVR$Y;e1J!oOM)`J#q(0Bs$qT3|ldAHfT z+osLt;kY!zdA{F^_)RW9*sS4JPDi32Omukf#mT7#jT(8<@OPz1LFdq%r0^%T3?DB~ zR(7RxHJUr%%c4rCSW^W~)*V&nUoB4>dJ2~$?J+Bp&kfOli1UVi+`5l!G3(sJuoR~j zsbqYBF86Fs3fP^RxUunCd1@);mKoa0leu+2sBpm}OZGz+-1cvbe_nVi|Gwn23mhfM zC>*9KsIiTq+=mUD(Xm{Jp096|8J#x-POU1hPT&FTyaVzCY-QM7(s<*QJ;8R^)UD3FGyRzNQCI2m*jf7CgV`72L?)+SMyM&WSsVS|=`qhOag vA15-%z>t2E-Ft+O_Z0Oj02Y$hb6P)^R>!<{3$?;>Vfjbban+J?)uQ?vvgW<) diff --git a/PythonHome/Lib/lib2to3/pgen2/literals.py b/PythonHome/Lib/lib2to3/pgen2/literals.py new file mode 100644 index 0000000000..0b3948a54e --- /dev/null +++ b/PythonHome/Lib/lib2to3/pgen2/literals.py @@ -0,0 +1,60 @@ +# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Safely evaluate Python string literals without using eval().""" + +import re + +simple_escapes = {"a": "\a", + "b": "\b", + "f": "\f", + "n": "\n", + "r": "\r", + "t": "\t", + "v": "\v", + "'": "'", + '"': '"', + "\\": "\\"} + +def escape(m): + all, tail = m.group(0, 1) + assert all.startswith("\\") + esc = simple_escapes.get(tail) + if esc is not None: + return esc + if tail.startswith("x"): + hexes = tail[1:] + if len(hexes) < 2: + raise ValueError("invalid hex string escape ('\\%s')" % tail) + try: + i = int(hexes, 16) + except ValueError: + raise ValueError("invalid hex string escape ('\\%s')" % tail) + else: + try: + i = int(tail, 8) + except ValueError: + raise ValueError("invalid octal string escape ('\\%s')" % tail) + return chr(i) + +def evalString(s): + assert s.startswith("'") or s.startswith('"'), repr(s[:1]) + q = s[0] + if s[:3] == q*3: + q = q*3 + assert s.endswith(q), repr(s[-len(q):]) + assert len(s) >= 2*len(q) + s = s[len(q):-len(q)] + return re.sub(r"\\(\'|\"|\\|[abfnrtv]|x.{0,2}|[0-7]{1,3})", escape, s) + +def test(): + for i in range(256): + c = chr(i) + s = repr(c) + e = evalString(s) + if e != c: + print i, c, s, e + + +if __name__ == "__main__": + test() diff --git a/PythonHome/Lib/lib2to3/pgen2/literals.pyc b/PythonHome/Lib/lib2to3/pgen2/literals.pyc deleted file mode 100644 index 369aa5f458d5ed3038410c0f778d3e4188d08ad5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1958 zcmb7E&2Jk;6o0d}N?Y&(e2T0OjUHDU-eATeRDF2a6g)WIyhK+c%)xO7@dk(P` zADHyQH)nA=h@J7jyl_Xo%(pI2vO_;joXO+V`rjll51c=+Z06|p@@n!oew$XIOx3ZB zMX!mzFM3n-1JN6zXQH=6&qc3`?nIv!{Y>PN$VIV-9j-rxw}STtUR!}>NOU}I?WISd zMzC?u)wYipe5QrGUsD- zjqSvJhjwW>xy4a6j(`7Je6Qo;^uIG?VaI?R=Dk7R@jk4Jb7z?@?gplxSZi{Z z^s>+LyqAl~CMW&WM8)D3pdj5iSH`&6%ZwOOlS#F&z)Dl3a$J%*ad(dLHgiF~@kC5< zno0>5C#e`vU$%ztHC6(XHd080orks>zD)MRG}&Ksy(eM+&}3_v6@*{yUjTNZVwW?} z><18}?x{I-Q#Dl?vY~FP8CAmDQg^*#oK+phfZIM{>hG9Lm z^$~#wwBmW0?t{{-RmcaeG0gIbj+o;-ffw}S@}RV2+8_R{hn^J1>G?@nwh=D@4p02E z-3r;CIk8xH;+QDY3nO&ALdUpOs(b{v2+mELDYF?=Ap=&0g9RG}GhyH|9AVfFmxkfu zFbs#U;{AgxcV~OU^VQdnSJpcSkn=1rMd~R4p9Rz_YEeB<9k%h# z_#!{^}7i6Zi(_1w{-)P4LCP&FKv8& z+9EvL8kepBSXUP@KxQ$Eb#s g=O;ZqNX: + if p.addtoken(...): # parse a token; may raise ParseError + break + root = p.rootnode # root of abstract syntax tree + + A Parser instance may be reused by calling setup() repeatedly. + + A Parser instance contains state pertaining to the current token + sequence, and should not be used concurrently by different threads + to parse separate token sequences. + + See driver.py for how to get input tokens by tokenizing a file or + string. + + Parsing is complete when addtoken() returns True; the root of the + abstract syntax tree can then be retrieved from the rootnode + instance variable. When a syntax error occurs, addtoken() raises + the ParseError exception. There is no error recovery; the parser + cannot be used after a syntax error was reported (but it can be + reinitialized by calling setup()). + + """ + + def __init__(self, grammar, convert=None): + """Constructor. + + The grammar argument is a grammar.Grammar instance; see the + grammar module for more information. + + The parser is not ready yet for parsing; you must call the + setup() method to get it started. + + The optional convert argument is a function mapping concrete + syntax tree nodes to abstract syntax tree nodes. If not + given, no conversion is done and the syntax tree produced is + the concrete syntax tree. If given, it must be a function of + two arguments, the first being the grammar (a grammar.Grammar + instance), and the second being the concrete syntax tree node + to be converted. The syntax tree is converted from the bottom + up. + + A concrete syntax tree node is a (type, value, context, nodes) + tuple, where type is the node type (a token or symbol number), + value is None for symbols and a string for tokens, context is + None or an opaque value used for error reporting (typically a + (lineno, offset) pair), and nodes is a list of children for + symbols, and None for tokens. + + An abstract syntax tree node may be anything; this is entirely + up to the converter function. + + """ + self.grammar = grammar + self.convert = convert or (lambda grammar, node: node) + + def setup(self, start=None): + """Prepare for parsing. + + This *must* be called before starting to parse. + + The optional argument is an alternative start symbol; it + defaults to the grammar's start symbol. + + You can use a Parser instance to parse any number of programs; + each time you call setup() the parser is reset to an initial + state determined by the (implicit or explicit) start symbol. + + """ + if start is None: + start = self.grammar.start + # Each stack entry is a tuple: (dfa, state, node). + # A node is a tuple: (type, value, context, children), + # where children is a list of nodes or None, and context may be None. + newnode = (start, None, None, []) + stackentry = (self.grammar.dfas[start], 0, newnode) + self.stack = [stackentry] + self.rootnode = None + self.used_names = set() # Aliased to self.rootnode.used_names in pop() + + def addtoken(self, type, value, context): + """Add a token; return True iff this is the end of the program.""" + # Map from token to label + ilabel = self.classify(type, value, context) + # Loop until the token is shifted; may raise exceptions + while True: + dfa, state, node = self.stack[-1] + states, first = dfa + arcs = states[state] + # Look for a state with this label + for i, newstate in arcs: + t, v = self.grammar.labels[i] + if ilabel == i: + # Look it up in the list of labels + assert t < 256 + # Shift a token; we're done with it + self.shift(type, value, newstate, context) + # Pop while we are in an accept-only state + state = newstate + while states[state] == [(0, state)]: + self.pop() + if not self.stack: + # Done parsing! + return True + dfa, state, node = self.stack[-1] + states, first = dfa + # Done with this token + return False + elif t >= 256: + # See if it's a symbol and if we're in its first set + itsdfa = self.grammar.dfas[t] + itsstates, itsfirst = itsdfa + if ilabel in itsfirst: + # Push a symbol + self.push(t, self.grammar.dfas[t], newstate, context) + break # To continue the outer while loop + else: + if (0, state) in arcs: + # An accepting state, pop it and try something else + self.pop() + if not self.stack: + # Done parsing, but another token is input + raise ParseError("too much input", + type, value, context) + else: + # No success finding a transition + raise ParseError("bad input", type, value, context) + + def classify(self, type, value, context): + """Turn a token into a label. (Internal)""" + if type == token.NAME: + # Keep a listing of all used names + self.used_names.add(value) + # Check for reserved words + ilabel = self.grammar.keywords.get(value) + if ilabel is not None: + return ilabel + ilabel = self.grammar.tokens.get(type) + if ilabel is None: + raise ParseError("bad token", type, value, context) + return ilabel + + def shift(self, type, value, newstate, context): + """Shift a token. (Internal)""" + dfa, state, node = self.stack[-1] + newnode = (type, value, context, None) + newnode = self.convert(self.grammar, newnode) + if newnode is not None: + node[-1].append(newnode) + self.stack[-1] = (dfa, newstate, node) + + def push(self, type, newdfa, newstate, context): + """Push a nonterminal. (Internal)""" + dfa, state, node = self.stack[-1] + newnode = (type, None, context, []) + self.stack[-1] = (dfa, newstate, node) + self.stack.append((newdfa, 0, newnode)) + + def pop(self): + """Pop a nonterminal. (Internal)""" + popdfa, popstate, popnode = self.stack.pop() + newnode = self.convert(self.grammar, popnode) + if newnode is not None: + if self.stack: + dfa, state, node = self.stack[-1] + node[-1].append(newnode) + else: + self.rootnode = newnode + self.rootnode.used_names = self.used_names diff --git a/PythonHome/Lib/lib2to3/pgen2/parse.pyc b/PythonHome/Lib/lib2to3/pgen2/parse.pyc deleted file mode 100644 index 3f9212c7344080dc1a2e1318e27e0b4b4d9cfd47..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7056 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 JUGZ-&{}<8IsAd2F diff --git a/PythonHome/Lib/lib2to3/pgen2/pgen.py b/PythonHome/Lib/lib2to3/pgen2/pgen.py new file mode 100644 index 0000000000..63084a4cd5 --- /dev/null +++ b/PythonHome/Lib/lib2to3/pgen2/pgen.py @@ -0,0 +1,386 @@ +# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +# Pgen imports +from . import grammar, token, tokenize + +class PgenGrammar(grammar.Grammar): + pass + +class ParserGenerator(object): + + def __init__(self, filename, stream=None): + close_stream = None + if stream is None: + stream = open(filename) + close_stream = stream.close + self.filename = filename + self.stream = stream + self.generator = tokenize.generate_tokens(stream.readline) + self.gettoken() # Initialize lookahead + self.dfas, self.startsymbol = self.parse() + if close_stream is not None: + close_stream() + self.first = {} # map from symbol name to set of tokens + self.addfirstsets() + + def make_grammar(self): + c = PgenGrammar() + names = self.dfas.keys() + names.sort() + names.remove(self.startsymbol) + names.insert(0, self.startsymbol) + for name in names: + i = 256 + len(c.symbol2number) + c.symbol2number[name] = i + c.number2symbol[i] = name + for name in names: + dfa = self.dfas[name] + states = [] + for state in dfa: + arcs = [] + for label, next in state.arcs.iteritems(): + arcs.append((self.make_label(c, label), dfa.index(next))) + if state.isfinal: + arcs.append((0, dfa.index(state))) + states.append(arcs) + c.states.append(states) + c.dfas[c.symbol2number[name]] = (states, self.make_first(c, name)) + c.start = c.symbol2number[self.startsymbol] + return c + + def make_first(self, c, name): + rawfirst = self.first[name] + first = {} + for label in rawfirst: + ilabel = self.make_label(c, label) + ##assert ilabel not in first # XXX failed on <> ... != + first[ilabel] = 1 + return first + + def make_label(self, c, label): + # XXX Maybe this should be a method on a subclass of converter? + ilabel = len(c.labels) + if label[0].isalpha(): + # Either a symbol name or a named token + if label in c.symbol2number: + # A symbol name (a non-terminal) + if label in c.symbol2label: + return c.symbol2label[label] + else: + c.labels.append((c.symbol2number[label], None)) + c.symbol2label[label] = ilabel + return ilabel + else: + # A named token (NAME, NUMBER, STRING) + itoken = getattr(token, label, None) + assert isinstance(itoken, int), label + assert itoken in token.tok_name, label + if itoken in c.tokens: + return c.tokens[itoken] + else: + c.labels.append((itoken, None)) + c.tokens[itoken] = ilabel + return ilabel + else: + # Either a keyword or an operator + assert label[0] in ('"', "'"), label + value = eval(label) + if value[0].isalpha(): + # A keyword + if value in c.keywords: + return c.keywords[value] + else: + c.labels.append((token.NAME, value)) + c.keywords[value] = ilabel + return ilabel + else: + # An operator (any non-numeric token) + itoken = grammar.opmap[value] # Fails if unknown token + if itoken in c.tokens: + return c.tokens[itoken] + else: + c.labels.append((itoken, None)) + c.tokens[itoken] = ilabel + return ilabel + + def addfirstsets(self): + names = self.dfas.keys() + names.sort() + for name in names: + if name not in self.first: + self.calcfirst(name) + #print name, self.first[name].keys() + + def calcfirst(self, name): + dfa = self.dfas[name] + self.first[name] = None # dummy to detect left recursion + state = dfa[0] + totalset = {} + overlapcheck = {} + for label, next in state.arcs.iteritems(): + if label in self.dfas: + if label in self.first: + fset = self.first[label] + if fset is None: + raise ValueError("recursion for rule %r" % name) + else: + self.calcfirst(label) + fset = self.first[label] + totalset.update(fset) + overlapcheck[label] = fset + else: + totalset[label] = 1 + overlapcheck[label] = {label: 1} + inverse = {} + for label, itsfirst in overlapcheck.iteritems(): + for symbol in itsfirst: + if symbol in inverse: + raise ValueError("rule %s is ambiguous; %s is in the" + " first sets of %s as well as %s" % + (name, symbol, label, inverse[symbol])) + inverse[symbol] = label + self.first[name] = totalset + + def parse(self): + dfas = {} + startsymbol = None + # MSTART: (NEWLINE | RULE)* ENDMARKER + while self.type != token.ENDMARKER: + while self.type == token.NEWLINE: + self.gettoken() + # RULE: NAME ':' RHS NEWLINE + name = self.expect(token.NAME) + self.expect(token.OP, ":") + a, z = self.parse_rhs() + self.expect(token.NEWLINE) + #self.dump_nfa(name, a, z) + dfa = self.make_dfa(a, z) + #self.dump_dfa(name, dfa) + oldlen = len(dfa) + self.simplify_dfa(dfa) + newlen = len(dfa) + dfas[name] = dfa + #print name, oldlen, newlen + if startsymbol is None: + startsymbol = name + return dfas, startsymbol + + def make_dfa(self, start, finish): + # To turn an NFA into a DFA, we define the states of the DFA + # to correspond to *sets* of states of the NFA. Then do some + # state reduction. Let's represent sets as dicts with 1 for + # values. + assert isinstance(start, NFAState) + assert isinstance(finish, NFAState) + def closure(state): + base = {} + addclosure(state, base) + return base + def addclosure(state, base): + assert isinstance(state, NFAState) + if state in base: + return + base[state] = 1 + for label, next in state.arcs: + if label is None: + addclosure(next, base) + states = [DFAState(closure(start), finish)] + for state in states: # NB states grows while we're iterating + arcs = {} + for nfastate in state.nfaset: + for label, next in nfastate.arcs: + if label is not None: + addclosure(next, arcs.setdefault(label, {})) + for label, nfaset in arcs.iteritems(): + for st in states: + if st.nfaset == nfaset: + break + else: + st = DFAState(nfaset, finish) + states.append(st) + state.addarc(st, label) + return states # List of DFAState instances; first one is start + + def dump_nfa(self, name, start, finish): + print "Dump of NFA for", name + todo = [start] + for i, state in enumerate(todo): + print " State", i, state is finish and "(final)" or "" + for label, next in state.arcs: + if next in todo: + j = todo.index(next) + else: + j = len(todo) + todo.append(next) + if label is None: + print " -> %d" % j + else: + print " %s -> %d" % (label, j) + + def dump_dfa(self, name, dfa): + print "Dump of DFA for", name + for i, state in enumerate(dfa): + print " State", i, state.isfinal and "(final)" or "" + for label, next in state.arcs.iteritems(): + print " %s -> %d" % (label, dfa.index(next)) + + def simplify_dfa(self, dfa): + # This is not theoretically optimal, but works well enough. + # Algorithm: repeatedly look for two states that have the same + # set of arcs (same labels pointing to the same nodes) and + # unify them, until things stop changing. + + # dfa is a list of DFAState instances + changes = True + while changes: + changes = False + for i, state_i in enumerate(dfa): + for j in range(i+1, len(dfa)): + state_j = dfa[j] + if state_i == state_j: + #print " unify", i, j + del dfa[j] + for state in dfa: + state.unifystate(state_j, state_i) + changes = True + break + + def parse_rhs(self): + # RHS: ALT ('|' ALT)* + a, z = self.parse_alt() + if self.value != "|": + return a, z + else: + aa = NFAState() + zz = NFAState() + aa.addarc(a) + z.addarc(zz) + while self.value == "|": + self.gettoken() + a, z = self.parse_alt() + aa.addarc(a) + z.addarc(zz) + return aa, zz + + def parse_alt(self): + # ALT: ITEM+ + a, b = self.parse_item() + while (self.value in ("(", "[") or + self.type in (token.NAME, token.STRING)): + c, d = self.parse_item() + b.addarc(c) + b = d + return a, b + + def parse_item(self): + # ITEM: '[' RHS ']' | ATOM ['+' | '*'] + if self.value == "[": + self.gettoken() + a, z = self.parse_rhs() + self.expect(token.OP, "]") + a.addarc(z) + return a, z + else: + a, z = self.parse_atom() + value = self.value + if value not in ("+", "*"): + return a, z + self.gettoken() + z.addarc(a) + if value == "+": + return a, z + else: + return a, a + + def parse_atom(self): + # ATOM: '(' RHS ')' | NAME | STRING + if self.value == "(": + self.gettoken() + a, z = self.parse_rhs() + self.expect(token.OP, ")") + return a, z + elif self.type in (token.NAME, token.STRING): + a = NFAState() + z = NFAState() + a.addarc(z, self.value) + self.gettoken() + return a, z + else: + self.raise_error("expected (...) or NAME or STRING, got %s/%s", + self.type, self.value) + + def expect(self, type, value=None): + if self.type != type or (value is not None and self.value != value): + self.raise_error("expected %s/%s, got %s/%s", + type, value, self.type, self.value) + value = self.value + self.gettoken() + return value + + def gettoken(self): + tup = self.generator.next() + while tup[0] in (tokenize.COMMENT, tokenize.NL): + tup = self.generator.next() + self.type, self.value, self.begin, self.end, self.line = tup + #print token.tok_name[self.type], repr(self.value) + + def raise_error(self, msg, *args): + if args: + try: + msg = msg % args + except: + msg = " ".join([msg] + map(str, args)) + raise SyntaxError(msg, (self.filename, self.end[0], + self.end[1], self.line)) + +class NFAState(object): + + def __init__(self): + self.arcs = [] # list of (label, NFAState) pairs + + def addarc(self, next, label=None): + assert label is None or isinstance(label, str) + assert isinstance(next, NFAState) + self.arcs.append((label, next)) + +class DFAState(object): + + def __init__(self, nfaset, final): + assert isinstance(nfaset, dict) + assert isinstance(iter(nfaset).next(), NFAState) + assert isinstance(final, NFAState) + self.nfaset = nfaset + self.isfinal = final in nfaset + self.arcs = {} # map from label to DFAState + + def addarc(self, next, label): + assert isinstance(label, str) + assert label not in self.arcs + assert isinstance(next, DFAState) + self.arcs[label] = next + + def unifystate(self, old, new): + for label, next in self.arcs.iteritems(): + if next is old: + self.arcs[label] = new + + def __eq__(self, other): + # Equality test -- ignore the nfaset instance variable + assert isinstance(other, DFAState) + if self.isfinal != other.isfinal: + return False + # Can't just return self.arcs == other.arcs, because that + # would invoke this method recursively, with cycles... + if len(self.arcs) != len(other.arcs): + return False + for label, next in self.arcs.iteritems(): + if next is not other.arcs.get(label): + return False + return True + + __hash__ = None # For Py3 compatibility. + +def generate_grammar(filename="Grammar.txt"): + p = ParserGenerator(filename) + return p.make_grammar() diff --git a/PythonHome/Lib/lib2to3/pgen2/pgen.pyc b/PythonHome/Lib/lib2to3/pgen2/pgen.pyc deleted file mode 100644 index c008e69806b282f1a2797aa782f185ffb2c58f6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11693 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 NT_OFFSET + +def ISEOF(x): + return x == ENDMARKER diff --git a/PythonHome/Lib/lib2to3/pgen2/token.pyc b/PythonHome/Lib/lib2to3/pgen2/token.pyc deleted file mode 100644 index a83745716927c97b374e720e234b5bd7bf9d4f85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2243 zcmc(f>2ecC5Xb+rv3y~CaTwcx?}Ni&8;k*iSxIYK<<+jeyN**`PASH%5XFZGT2fGz z;tM=fo+Gc47s&i)1%fZRzC_ag)YCKD-P7GOt$*}%{kH#obcDv|ocVulp8D?@Kmjq# zKr+x4NDH(T(h5BXIR|Znv_Z3wEVLcc4()(+KszCw&@M<9v>Vb5Jr6k#?Sb?_FF-Cp zdm+8hK1d(5AJPvUfDAwfA%oD1kc-eukW0|Zkjv03kSow3$Pn}@r zqtI)RYtZYE>(CpJ8_+Sx7<3#m4xNBZKqn!S&?(3ibQ&@Zoq^0iXCbrDImjGz9x@NT z3AqWq1-S*i4Y>`y1GxiTfGj}oLheHELGD2pA&bx@$P#oJvJAZsxet8+c>rC3tUw<^ z9zs_ktI$V~N6^QR$IvH`C#ae{uiV+RC<`+y*K-F{ssx3q-!S<-O5m}<0=pZ_YE~1+_PxKHMh+d+P z=qCn%Tf}YR z4zWPoCGHW6#1gSg+$SCoE5t)$m3TzJWao$(;=?56%~NLUAY5OXWkS|#OA^raw_pE6#@&o@<1c6cflL%VAiomAA^$R5@+;+qN77E+27`ed) zx6=s0pL5M1VPBTZT01J2L$+)}_)f`9*tY&&Dd&b(jN-89Z`$>~yYChKbVboGxPEL` z6kIFPfVbm>)>8OM@S@#Zs-eJu@_`rl4XIRe>}2GYidNY1_98oHYG)+cjACPxFGijd zZCTYfxrWLq?U*pFXE%y$kei|Fn9SQZ+}%CLOL!~`L2PHu@;u{apXHqV_U>K~ryKHe zp_5O=Fcq01cQ>`sVPxMdwFddJXZ)oj9^{78RKZx|qE~QjC+3S`ey_CQx!+o+p1To8 zTg8poPKL$JtuKa!U@vD3bHnt(WHjBIj5OVIO*&$?+svdxM$_12bKa(@`7+a&j(F=d z159Ugm=bhcK!&%PL^i+C2Dv>K*RHlb7nJGMaipj2XksPaAA zU!fC*!M@FxYoss^wp~B56)9UevZvK*%q37hJ3OseTQ5&)FAh)YwiT*Lhd|R`b(acb$ JzqQkR{{(TSfE54$ diff --git a/PythonHome/Lib/lib2to3/pgen2/tokenize.py b/PythonHome/Lib/lib2to3/pgen2/tokenize.py new file mode 100644 index 0000000000..4cb2a41262 --- /dev/null +++ b/PythonHome/Lib/lib2to3/pgen2/tokenize.py @@ -0,0 +1,499 @@ +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation. +# All rights reserved. + +"""Tokenization help for Python programs. + +generate_tokens(readline) is a generator that breaks a stream of +text into Python tokens. It accepts a readline-like method which is called +repeatedly to get the next line of input (or "" for EOF). It generates +5-tuples with these members: + + the token type (see token.py) + the token (a string) + the starting (row, column) indices of the token (a 2-tuple of ints) + the ending (row, column) indices of the token (a 2-tuple of ints) + the original line (string) + +It is designed to match the working of the Python tokenizer exactly, except +that it produces COMMENT tokens for comments and gives type OP for all +operators + +Older entry points + tokenize_loop(readline, tokeneater) + tokenize(readline, tokeneater=printtoken) +are the same, except instead of generating tokens, tokeneater is a callback +function to which the 5 fields described above are passed as 5 arguments, +each time a new token is found.""" + +__author__ = 'Ka-Ping Yee ' +__credits__ = \ + 'GvR, ESR, Tim Peters, Thomas Wouters, Fred Drake, Skip Montanaro' + +import string, re +from codecs import BOM_UTF8, lookup +from lib2to3.pgen2.token import * + +from . import token +__all__ = [x for x in dir(token) if x[0] != '_'] + ["tokenize", + "generate_tokens", "untokenize"] +del token + +try: + bytes +except NameError: + # Support bytes type in Python <= 2.5, so 2to3 turns itself into + # valid Python 3 code. + bytes = str + +def group(*choices): return '(' + '|'.join(choices) + ')' +def any(*choices): return group(*choices) + '*' +def maybe(*choices): return group(*choices) + '?' + +Whitespace = r'[ \f\t]*' +Comment = r'#[^\r\n]*' +Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment) +Name = r'[a-zA-Z_]\w*' + +Binnumber = r'0[bB][01]*' +Hexnumber = r'0[xX][\da-fA-F]*[lL]?' +Octnumber = r'0[oO]?[0-7]*[lL]?' +Decnumber = r'[1-9]\d*[lL]?' +Intnumber = group(Binnumber, Hexnumber, Octnumber, Decnumber) +Exponent = r'[eE][-+]?\d+' +Pointfloat = group(r'\d+\.\d*', r'\.\d+') + maybe(Exponent) +Expfloat = r'\d+' + Exponent +Floatnumber = group(Pointfloat, Expfloat) +Imagnumber = group(r'\d+[jJ]', Floatnumber + r'[jJ]') +Number = group(Imagnumber, Floatnumber, Intnumber) + +# Tail end of ' string. +Single = r"[^'\\]*(?:\\.[^'\\]*)*'" +# Tail end of " string. +Double = r'[^"\\]*(?:\\.[^"\\]*)*"' +# Tail end of ''' string. +Single3 = r"[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*'''" +# Tail end of """ string. +Double3 = r'[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""' +Triple = group("[ubUB]?[rR]?'''", '[ubUB]?[rR]?"""') +# Single-line ' or " string. +String = group(r"[uU]?[rR]?'[^\n'\\]*(?:\\.[^\n'\\]*)*'", + r'[uU]?[rR]?"[^\n"\\]*(?:\\.[^\n"\\]*)*"') + +# Because of leftmost-then-longest match semantics, be sure to put the +# longest operators first (e.g., if = came before ==, == would get +# recognized as two instances of =). +Operator = group(r"\*\*=?", r">>=?", r"<<=?", r"<>", r"!=", + r"//=?", r"->", + r"[+\-*/%&@|^=<>]=?", + r"~") + +Bracket = '[][(){}]' +Special = group(r'\r?\n', r'[:;.,`@]') +Funny = group(Operator, Bracket, Special) + +PlainToken = group(Number, Funny, String, Name) +Token = Ignore + PlainToken + +# First (or only) line of ' or " string. +ContStr = group(r"[uUbB]?[rR]?'[^\n'\\]*(?:\\.[^\n'\\]*)*" + + group("'", r'\\\r?\n'), + r'[uUbB]?[rR]?"[^\n"\\]*(?:\\.[^\n"\\]*)*' + + group('"', r'\\\r?\n')) +PseudoExtras = group(r'\\\r?\n', Comment, Triple) +PseudoToken = Whitespace + group(PseudoExtras, Number, Funny, ContStr, Name) + +tokenprog, pseudoprog, single3prog, double3prog = map( + re.compile, (Token, PseudoToken, Single3, Double3)) +endprogs = {"'": re.compile(Single), '"': re.compile(Double), + "'''": single3prog, '"""': double3prog, + "r'''": single3prog, 'r"""': double3prog, + "u'''": single3prog, 'u"""': double3prog, + "b'''": single3prog, 'b"""': double3prog, + "ur'''": single3prog, 'ur"""': double3prog, + "br'''": single3prog, 'br"""': double3prog, + "R'''": single3prog, 'R"""': double3prog, + "U'''": single3prog, 'U"""': double3prog, + "B'''": single3prog, 'B"""': double3prog, + "uR'''": single3prog, 'uR"""': double3prog, + "Ur'''": single3prog, 'Ur"""': double3prog, + "UR'''": single3prog, 'UR"""': double3prog, + "bR'''": single3prog, 'bR"""': double3prog, + "Br'''": single3prog, 'Br"""': double3prog, + "BR'''": single3prog, 'BR"""': double3prog, + 'r': None, 'R': None, + 'u': None, 'U': None, + 'b': None, 'B': None} + +triple_quoted = {} +for t in ("'''", '"""', + "r'''", 'r"""', "R'''", 'R"""', + "u'''", 'u"""', "U'''", 'U"""', + "b'''", 'b"""', "B'''", 'B"""', + "ur'''", 'ur"""', "Ur'''", 'Ur"""', + "uR'''", 'uR"""', "UR'''", 'UR"""', + "br'''", 'br"""', "Br'''", 'Br"""', + "bR'''", 'bR"""', "BR'''", 'BR"""',): + triple_quoted[t] = t +single_quoted = {} +for t in ("'", '"', + "r'", 'r"', "R'", 'R"', + "u'", 'u"', "U'", 'U"', + "b'", 'b"', "B'", 'B"', + "ur'", 'ur"', "Ur'", 'Ur"', + "uR'", 'uR"', "UR'", 'UR"', + "br'", 'br"', "Br'", 'Br"', + "bR'", 'bR"', "BR'", 'BR"', ): + single_quoted[t] = t + +tabsize = 8 + +class TokenError(Exception): pass + +class StopTokenizing(Exception): pass + +def printtoken(type, token, start, end, line): # for testing + (srow, scol) = start + (erow, ecol) = end + print "%d,%d-%d,%d:\t%s\t%s" % \ + (srow, scol, erow, ecol, tok_name[type], repr(token)) + +def tokenize(readline, tokeneater=printtoken): + """ + The tokenize() function accepts two parameters: one representing the + input stream, and one providing an output mechanism for tokenize(). + + The first parameter, readline, must be a callable object which provides + the same interface as the readline() method of built-in file objects. + Each call to the function should return one line of input as a string. + + The second parameter, tokeneater, must also be a callable object. It is + called once for each token, with five arguments, corresponding to the + tuples generated by generate_tokens(). + """ + try: + tokenize_loop(readline, tokeneater) + except StopTokenizing: + pass + +# backwards compatible interface +def tokenize_loop(readline, tokeneater): + for token_info in generate_tokens(readline): + tokeneater(*token_info) + +class Untokenizer: + + def __init__(self): + self.tokens = [] + self.prev_row = 1 + self.prev_col = 0 + + def add_whitespace(self, start): + row, col = start + assert row <= self.prev_row + col_offset = col - self.prev_col + if col_offset: + self.tokens.append(" " * col_offset) + + def untokenize(self, iterable): + for t in iterable: + if len(t) == 2: + self.compat(t, iterable) + break + tok_type, token, start, end, line = t + self.add_whitespace(start) + self.tokens.append(token) + self.prev_row, self.prev_col = end + if tok_type in (NEWLINE, NL): + self.prev_row += 1 + self.prev_col = 0 + return "".join(self.tokens) + + def compat(self, token, iterable): + startline = False + indents = [] + toks_append = self.tokens.append + toknum, tokval = token + if toknum in (NAME, NUMBER): + tokval += ' ' + if toknum in (NEWLINE, NL): + startline = True + for tok in iterable: + toknum, tokval = tok[:2] + + if toknum in (NAME, NUMBER): + tokval += ' ' + + if toknum == INDENT: + indents.append(tokval) + continue + elif toknum == DEDENT: + indents.pop() + continue + elif toknum in (NEWLINE, NL): + startline = True + elif startline and indents: + toks_append(indents[-1]) + startline = False + toks_append(tokval) + +cookie_re = re.compile(r'^[ \t\f]*#.*coding[:=][ \t]*([-\w.]+)') + +def _get_normal_name(orig_enc): + """Imitates get_normal_name in tokenizer.c.""" + # Only care about the first 12 characters. + enc = orig_enc[:12].lower().replace("_", "-") + if enc == "utf-8" or enc.startswith("utf-8-"): + return "utf-8" + if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \ + enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")): + return "iso-8859-1" + return orig_enc + +def detect_encoding(readline): + """ + The detect_encoding() function is used to detect the encoding that should + be used to decode a Python source file. It requires one argument, readline, + in the same way as the tokenize() generator. + + It will call readline a maximum of twice, and return the encoding used + (as a string) and a list of any lines (left as bytes) it has read + in. + + It detects the encoding from the presence of a utf-8 bom or an encoding + cookie as specified in pep-0263. If both a bom and a cookie are present, but + disagree, a SyntaxError will be raised. If the encoding cookie is an invalid + charset, raise a SyntaxError. Note that if a utf-8 bom is found, + 'utf-8-sig' is returned. + + If no encoding is specified, then the default of 'utf-8' will be returned. + """ + bom_found = False + encoding = None + default = 'utf-8' + def read_or_stop(): + try: + return readline() + except StopIteration: + return bytes() + + def find_cookie(line): + try: + line_string = line.decode('ascii') + except UnicodeDecodeError: + return None + match = cookie_re.match(line_string) + if not match: + return None + encoding = _get_normal_name(match.group(1)) + try: + codec = lookup(encoding) + except LookupError: + # This behaviour mimics the Python interpreter + raise SyntaxError("unknown encoding: " + encoding) + + if bom_found: + if codec.name != 'utf-8': + # This behaviour mimics the Python interpreter + raise SyntaxError('encoding problem: utf-8') + encoding += '-sig' + return encoding + + first = read_or_stop() + if first.startswith(BOM_UTF8): + bom_found = True + first = first[3:] + default = 'utf-8-sig' + if not first: + return default, [] + + encoding = find_cookie(first) + if encoding: + return encoding, [first] + + second = read_or_stop() + if not second: + return default, [first] + + encoding = find_cookie(second) + if encoding: + return encoding, [first, second] + + return default, [first, second] + +def untokenize(iterable): + """Transform tokens back into Python source code. + + Each element returned by the iterable must be a token sequence + with at least two elements, a token number and token value. If + only two tokens are passed, the resulting output is poor. + + Round-trip invariant for full input: + Untokenized source will match input source exactly + + Round-trip invariant for limited intput: + # Output text will tokenize the back to the input + t1 = [tok[:2] for tok in generate_tokens(f.readline)] + newcode = untokenize(t1) + readline = iter(newcode.splitlines(1)).next + t2 = [tok[:2] for tokin generate_tokens(readline)] + assert t1 == t2 + """ + ut = Untokenizer() + return ut.untokenize(iterable) + +def generate_tokens(readline): + """ + The generate_tokens() generator requires one argument, readline, which + must be a callable object which provides the same interface as the + readline() method of built-in file objects. Each call to the function + should return one line of input as a string. Alternately, readline + can be a callable function terminating with StopIteration: + readline = open(myfile).next # Example of alternate readline + + The generator produces 5-tuples with these members: the token type; the + token string; a 2-tuple (srow, scol) of ints specifying the row and + column where the token begins in the source; a 2-tuple (erow, ecol) of + ints specifying the row and column where the token ends in the source; + and the line on which the token was found. The line passed is the + logical line; continuation lines are included. + """ + lnum = parenlev = continued = 0 + namechars, numchars = string.ascii_letters + '_', '0123456789' + contstr, needcont = '', 0 + contline = None + indents = [0] + + while 1: # loop over lines in stream + try: + line = readline() + except StopIteration: + line = '' + lnum = lnum + 1 + pos, max = 0, len(line) + + if contstr: # continued string + if not line: + raise TokenError, ("EOF in multi-line string", strstart) + endmatch = endprog.match(line) + if endmatch: + pos = end = endmatch.end(0) + yield (STRING, contstr + line[:end], + strstart, (lnum, end), contline + line) + contstr, needcont = '', 0 + contline = None + elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n': + yield (ERRORTOKEN, contstr + line, + strstart, (lnum, len(line)), contline) + contstr = '' + contline = None + continue + else: + contstr = contstr + line + contline = contline + line + continue + + elif parenlev == 0 and not continued: # new statement + if not line: break + column = 0 + while pos < max: # measure leading whitespace + if line[pos] == ' ': column = column + 1 + elif line[pos] == '\t': column = (column//tabsize + 1)*tabsize + elif line[pos] == '\f': column = 0 + else: break + pos = pos + 1 + if pos == max: break + + if line[pos] in '#\r\n': # skip comments or blank lines + if line[pos] == '#': + comment_token = line[pos:].rstrip('\r\n') + nl_pos = pos + len(comment_token) + yield (COMMENT, comment_token, + (lnum, pos), (lnum, pos + len(comment_token)), line) + yield (NL, line[nl_pos:], + (lnum, nl_pos), (lnum, len(line)), line) + else: + yield ((NL, COMMENT)[line[pos] == '#'], line[pos:], + (lnum, pos), (lnum, len(line)), line) + continue + + if column > indents[-1]: # count indents or dedents + indents.append(column) + yield (INDENT, line[:pos], (lnum, 0), (lnum, pos), line) + while column < indents[-1]: + if column not in indents: + raise IndentationError( + "unindent does not match any outer indentation level", + ("", lnum, pos, line)) + indents = indents[:-1] + yield (DEDENT, '', (lnum, pos), (lnum, pos), line) + + else: # continued statement + if not line: + raise TokenError, ("EOF in multi-line statement", (lnum, 0)) + continued = 0 + + while pos < max: + pseudomatch = pseudoprog.match(line, pos) + if pseudomatch: # scan for tokens + start, end = pseudomatch.span(1) + spos, epos, pos = (lnum, start), (lnum, end), end + token, initial = line[start:end], line[start] + + if initial in numchars or \ + (initial == '.' and token != '.'): # ordinary number + yield (NUMBER, token, spos, epos, line) + elif initial in '\r\n': + newline = NEWLINE + if parenlev > 0: + newline = NL + yield (newline, token, spos, epos, line) + elif initial == '#': + assert not token.endswith("\n") + yield (COMMENT, token, spos, epos, line) + elif token in triple_quoted: + endprog = endprogs[token] + endmatch = endprog.match(line, pos) + if endmatch: # all on one line + pos = endmatch.end(0) + token = line[start:pos] + yield (STRING, token, spos, (lnum, pos), line) + else: + strstart = (lnum, start) # multiple lines + contstr = line[start:] + contline = line + break + elif initial in single_quoted or \ + token[:2] in single_quoted or \ + token[:3] in single_quoted: + if token[-1] == '\n': # continued string + strstart = (lnum, start) + endprog = (endprogs[initial] or endprogs[token[1]] or + endprogs[token[2]]) + contstr, needcont = line[start:], 1 + contline = line + break + else: # ordinary string + yield (STRING, token, spos, epos, line) + elif initial in namechars: # ordinary name + yield (NAME, token, spos, epos, line) + elif initial == '\\': # continued stmt + # This yield is new; needed for better idempotency: + yield (NL, token, spos, (lnum, pos), line) + continued = 1 + else: + if initial in '([{': parenlev = parenlev + 1 + elif initial in ')]}': parenlev = parenlev - 1 + yield (OP, token, spos, epos, line) + else: + yield (ERRORTOKEN, line[pos], + (lnum, pos), (lnum, pos+1), line) + pos = pos + 1 + + for indent in indents[1:]: # pop remaining indent levels + yield (DEDENT, '', (lnum, 0), (lnum, 0), '') + yield (ENDMARKER, '', (lnum, 0), (lnum, 0), '') + +if __name__ == '__main__': # testing + import sys + if len(sys.argv) > 1: tokenize(open(sys.argv[1]).readline) + else: tokenize(sys.stdin.readline) diff --git a/PythonHome/Lib/lib2to3/pgen2/tokenize.pyc b/PythonHome/Lib/lib2to3/pgen2/tokenize.pyc deleted file mode 100644 index ef5a3f1e9e5fe7e1114e328e8226ff50778dcf73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16570 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 diff --git a/PythonHome/Lib/lib2to3/pygram.py b/PythonHome/Lib/lib2to3/pygram.py new file mode 100644 index 0000000000..621ff24c95 --- /dev/null +++ b/PythonHome/Lib/lib2to3/pygram.py @@ -0,0 +1,40 @@ +# Copyright 2006 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Export the Python grammar and symbols.""" + +# Python imports +import os + +# Local imports +from .pgen2 import token +from .pgen2 import driver +from . import pytree + +# The grammar file +_GRAMMAR_FILE = os.path.join(os.path.dirname(__file__), "Grammar.txt") +_PATTERN_GRAMMAR_FILE = os.path.join(os.path.dirname(__file__), + "PatternGrammar.txt") + + +class Symbols(object): + + def __init__(self, grammar): + """Initializer. + + Creates an attribute for each grammar symbol (nonterminal), + whose value is the symbol's type (an int >= 256). + """ + for name, symbol in grammar.symbol2number.iteritems(): + setattr(self, name, symbol) + + +python_grammar = driver.load_grammar(_GRAMMAR_FILE) + +python_symbols = Symbols(python_grammar) + +python_grammar_no_print_statement = python_grammar.copy() +del python_grammar_no_print_statement.keywords["print"] + +pattern_grammar = driver.load_grammar(_PATTERN_GRAMMAR_FILE) +pattern_symbols = Symbols(pattern_grammar) diff --git a/PythonHome/Lib/lib2to3/pygram.pyc b/PythonHome/Lib/lib2to3/pygram.pyc deleted file mode 100644 index 6ae0adbf11b4e61c8c46a416895dd2fcfdc325a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1369 zcmb7DOHbQC5FXnhKoUrJwg(R8(i*AFA$^<*Dy0-50YVNEs+G!h;tg42dsFWQNJUTS zPw0>7Z|b!_pq*KVKt-jhc6KuF$2V*1=UnOg>BnXV#*c;nukpwqNJ0P)sR5x0u>l@3 z7K8ac{O0DscC+Jm}rswyd_{u5G_MkhRtz6MLVtN zfECTJ(r`_uLNh-?vU}ARnX*-n*~dfG6RCZc1xXTQc94d)942iM%R2vs&k;8;z#*ch zh=_BR=3)`WFyj|2yOsMxl`$sEXxhtD*434gizpulO0g`xqgKh!dM?Ob#^%Smg69ADx$h`fq1}zi5;LieO!ZpA(QVT}7 z(oZ!w#g#W5$|S!b*-yFRLCin1tX?YF<7X#hfnpM2v9bG%w+D*ZU6I)===3I_<$&2v zDpH&<;b{Is@iB2`94R0e18>rN%^6;X5{VVW=ie*s-%4r5e{M$UAhOiRsLDZ zrFoa}NZL!$)Hkl5Avg{-sORzhP;{^oc?g+%oUydwq71ISro@OF}iRj9O zJkvj?x_~`mkaVg#HcK z^Qb`N@XPv}Do0=HraA)s*6+FdsqppSzQo0{gr!RF;hYUGMHWg`rI7rKnv}S!8`t;` n@OA!I`Rcax6= 256) + parent = None # Parent node pointer, or None + children = () # Tuple of subnodes + was_changed = False + was_checked = False + + def __new__(cls, *args, **kwds): + """Constructor that prevents Base from being instantiated.""" + assert cls is not Base, "Cannot instantiate Base" + return object.__new__(cls) + + def __eq__(self, other): + """ + Compare two nodes for equality. + + This calls the method _eq(). + """ + if self.__class__ is not other.__class__: + return NotImplemented + return self._eq(other) + + __hash__ = None # For Py3 compatibility. + + def __ne__(self, other): + """ + Compare two nodes for inequality. + + This calls the method _eq(). + """ + if self.__class__ is not other.__class__: + return NotImplemented + return not self._eq(other) + + def _eq(self, other): + """ + Compare two nodes for equality. + + This is called by __eq__ and __ne__. It is only called if the two nodes + have the same type. This must be implemented by the concrete subclass. + Nodes should be considered equal if they have the same structure, + ignoring the prefix string and other context information. + """ + raise NotImplementedError + + def clone(self): + """ + Return a cloned (deep) copy of self. + + This must be implemented by the concrete subclass. + """ + raise NotImplementedError + + def post_order(self): + """ + Return a post-order iterator for the tree. + + This must be implemented by the concrete subclass. + """ + raise NotImplementedError + + def pre_order(self): + """ + Return a pre-order iterator for the tree. + + This must be implemented by the concrete subclass. + """ + raise NotImplementedError + + def set_prefix(self, prefix): + """ + Set the prefix for the node (see Leaf class). + + DEPRECATED; use the prefix property directly. + """ + warnings.warn("set_prefix() is deprecated; use the prefix property", + DeprecationWarning, stacklevel=2) + self.prefix = prefix + + def get_prefix(self): + """ + Return the prefix for the node (see Leaf class). + + DEPRECATED; use the prefix property directly. + """ + warnings.warn("get_prefix() is deprecated; use the prefix property", + DeprecationWarning, stacklevel=2) + return self.prefix + + def replace(self, new): + """Replace this node with a new one in the parent.""" + assert self.parent is not None, str(self) + assert new is not None + if not isinstance(new, list): + new = [new] + l_children = [] + found = False + for ch in self.parent.children: + if ch is self: + assert not found, (self.parent.children, self, new) + if new is not None: + l_children.extend(new) + found = True + else: + l_children.append(ch) + assert found, (self.children, self, new) + self.parent.changed() + self.parent.children = l_children + for x in new: + x.parent = self.parent + self.parent = None + + def get_lineno(self): + """Return the line number which generated the invocant node.""" + node = self + while not isinstance(node, Leaf): + if not node.children: + return + node = node.children[0] + return node.lineno + + def changed(self): + if self.parent: + self.parent.changed() + self.was_changed = True + + def remove(self): + """ + Remove the node from the tree. Returns the position of the node in its + parent's children before it was removed. + """ + if self.parent: + for i, node in enumerate(self.parent.children): + if node is self: + self.parent.changed() + del self.parent.children[i] + self.parent = None + return i + + @property + def next_sibling(self): + """ + The node immediately following the invocant in their parent's children + list. If the invocant does not have a next sibling, it is None + """ + if self.parent is None: + return None + + # Can't use index(); we need to test by identity + for i, child in enumerate(self.parent.children): + if child is self: + try: + return self.parent.children[i+1] + except IndexError: + return None + + @property + def prev_sibling(self): + """ + The node immediately preceding the invocant in their parent's children + list. If the invocant does not have a previous sibling, it is None. + """ + if self.parent is None: + return None + + # Can't use index(); we need to test by identity + for i, child in enumerate(self.parent.children): + if child is self: + if i == 0: + return None + return self.parent.children[i-1] + + def leaves(self): + for child in self.children: + for x in child.leaves(): + yield x + + def depth(self): + if self.parent is None: + return 0 + return 1 + self.parent.depth() + + def get_suffix(self): + """ + Return the string immediately following the invocant node. This is + effectively equivalent to node.next_sibling.prefix + """ + next_sib = self.next_sibling + if next_sib is None: + return u"" + return next_sib.prefix + + if sys.version_info < (3, 0): + def __str__(self): + return unicode(self).encode("ascii") + +class Node(Base): + + """Concrete implementation for interior nodes.""" + + def __init__(self,type, children, + context=None, + prefix=None, + fixers_applied=None): + """ + Initializer. + + Takes a type constant (a symbol number >= 256), a sequence of + child nodes, and an optional context keyword argument. + + As a side effect, the parent pointers of the children are updated. + """ + assert type >= 256, type + self.type = type + self.children = list(children) + for ch in self.children: + assert ch.parent is None, repr(ch) + ch.parent = self + if prefix is not None: + self.prefix = prefix + if fixers_applied: + self.fixers_applied = fixers_applied[:] + else: + self.fixers_applied = None + + def __repr__(self): + """Return a canonical string representation.""" + return "%s(%s, %r)" % (self.__class__.__name__, + type_repr(self.type), + self.children) + + def __unicode__(self): + """ + Return a pretty string representation. + + This reproduces the input source exactly. + """ + return u"".join(map(unicode, self.children)) + + if sys.version_info > (3, 0): + __str__ = __unicode__ + + def _eq(self, other): + """Compare two nodes for equality.""" + return (self.type, self.children) == (other.type, other.children) + + def clone(self): + """Return a cloned (deep) copy of self.""" + return Node(self.type, [ch.clone() for ch in self.children], + fixers_applied=self.fixers_applied) + + def post_order(self): + """Return a post-order iterator for the tree.""" + for child in self.children: + for node in child.post_order(): + yield node + yield self + + def pre_order(self): + """Return a pre-order iterator for the tree.""" + yield self + for child in self.children: + for node in child.pre_order(): + yield node + + def _prefix_getter(self): + """ + The whitespace and comments preceding this node in the input. + """ + if not self.children: + return "" + return self.children[0].prefix + + def _prefix_setter(self, prefix): + if self.children: + self.children[0].prefix = prefix + + prefix = property(_prefix_getter, _prefix_setter) + + def set_child(self, i, child): + """ + Equivalent to 'node.children[i] = child'. This method also sets the + child's parent attribute appropriately. + """ + child.parent = self + self.children[i].parent = None + self.children[i] = child + self.changed() + + def insert_child(self, i, child): + """ + Equivalent to 'node.children.insert(i, child)'. This method also sets + the child's parent attribute appropriately. + """ + child.parent = self + self.children.insert(i, child) + self.changed() + + def append_child(self, child): + """ + Equivalent to 'node.children.append(child)'. This method also sets the + child's parent attribute appropriately. + """ + child.parent = self + self.children.append(child) + self.changed() + + +class Leaf(Base): + + """Concrete implementation for leaf nodes.""" + + # Default values for instance variables + _prefix = "" # Whitespace and comments preceding this token in the input + lineno = 0 # Line where this token starts in the input + column = 0 # Column where this token tarts in the input + + def __init__(self, type, value, + context=None, + prefix=None, + fixers_applied=[]): + """ + Initializer. + + Takes a type constant (a token number < 256), a string value, and an + optional context keyword argument. + """ + assert 0 <= type < 256, type + if context is not None: + self._prefix, (self.lineno, self.column) = context + self.type = type + self.value = value + if prefix is not None: + self._prefix = prefix + self.fixers_applied = fixers_applied[:] + + def __repr__(self): + """Return a canonical string representation.""" + return "%s(%r, %r)" % (self.__class__.__name__, + self.type, + self.value) + + def __unicode__(self): + """ + Return a pretty string representation. + + This reproduces the input source exactly. + """ + return self.prefix + unicode(self.value) + + if sys.version_info > (3, 0): + __str__ = __unicode__ + + def _eq(self, other): + """Compare two nodes for equality.""" + return (self.type, self.value) == (other.type, other.value) + + def clone(self): + """Return a cloned (deep) copy of self.""" + return Leaf(self.type, self.value, + (self.prefix, (self.lineno, self.column)), + fixers_applied=self.fixers_applied) + + def leaves(self): + yield self + + def post_order(self): + """Return a post-order iterator for the tree.""" + yield self + + def pre_order(self): + """Return a pre-order iterator for the tree.""" + yield self + + def _prefix_getter(self): + """ + The whitespace and comments preceding this token in the input. + """ + return self._prefix + + def _prefix_setter(self, prefix): + self.changed() + self._prefix = prefix + + prefix = property(_prefix_getter, _prefix_setter) + +def convert(gr, raw_node): + """ + Convert raw node information to a Node or Leaf instance. + + This is passed to the parser driver which calls it whenever a reduction of a + grammar rule produces a new complete node, so that the tree is build + strictly bottom-up. + """ + type, value, context, children = raw_node + if children or type in gr.number2symbol: + # If there's exactly one child, return that child instead of + # creating a new node. + if len(children) == 1: + return children[0] + return Node(type, children, context=context) + else: + return Leaf(type, value, context=context) + + +class BasePattern(object): + + """ + A pattern is a tree matching pattern. + + It looks for a specific node type (token or symbol), and + optionally for a specific content. + + This is an abstract base class. There are three concrete + subclasses: + + - LeafPattern matches a single leaf node; + - NodePattern matches a single node (usually non-leaf); + - WildcardPattern matches a sequence of nodes of variable length. + """ + + # Defaults for instance variables + type = None # Node type (token if < 256, symbol if >= 256) + content = None # Optional content matching pattern + name = None # Optional name used to store match in results dict + + def __new__(cls, *args, **kwds): + """Constructor that prevents BasePattern from being instantiated.""" + assert cls is not BasePattern, "Cannot instantiate BasePattern" + return object.__new__(cls) + + def __repr__(self): + args = [type_repr(self.type), self.content, self.name] + while args and args[-1] is None: + del args[-1] + return "%s(%s)" % (self.__class__.__name__, ", ".join(map(repr, args))) + + def optimize(self): + """ + A subclass can define this as a hook for optimizations. + + Returns either self or another node with the same effect. + """ + return self + + def match(self, node, results=None): + """ + Does this pattern exactly match a node? + + Returns True if it matches, False if not. + + If results is not None, it must be a dict which will be + updated with the nodes matching named subpatterns. + + Default implementation for non-wildcard patterns. + """ + if self.type is not None and node.type != self.type: + return False + if self.content is not None: + r = None + if results is not None: + r = {} + if not self._submatch(node, r): + return False + if r: + results.update(r) + if results is not None and self.name: + results[self.name] = node + return True + + def match_seq(self, nodes, results=None): + """ + Does this pattern exactly match a sequence of nodes? + + Default implementation for non-wildcard patterns. + """ + if len(nodes) != 1: + return False + return self.match(nodes[0], results) + + def generate_matches(self, nodes): + """ + Generator yielding all matches for this pattern. + + Default implementation for non-wildcard patterns. + """ + r = {} + if nodes and self.match(nodes[0], r): + yield 1, r + + +class LeafPattern(BasePattern): + + def __init__(self, type=None, content=None, name=None): + """ + Initializer. Takes optional type, content, and name. + + The type, if given must be a token type (< 256). If not given, + this matches any *leaf* node; the content may still be required. + + The content, if given, must be a string. + + If a name is given, the matching node is stored in the results + dict under that key. + """ + if type is not None: + assert 0 <= type < 256, type + if content is not None: + assert isinstance(content, basestring), repr(content) + self.type = type + self.content = content + self.name = name + + def match(self, node, results=None): + """Override match() to insist on a leaf node.""" + if not isinstance(node, Leaf): + return False + return BasePattern.match(self, node, results) + + def _submatch(self, node, results=None): + """ + Match the pattern's content to the node's children. + + This assumes the node type matches and self.content is not None. + + Returns True if it matches, False if not. + + If results is not None, it must be a dict which will be + updated with the nodes matching named subpatterns. + + When returning False, the results dict may still be updated. + """ + return self.content == node.value + + +class NodePattern(BasePattern): + + wildcards = False + + def __init__(self, type=None, content=None, name=None): + """ + Initializer. Takes optional type, content, and name. + + The type, if given, must be a symbol type (>= 256). If the + type is None this matches *any* single node (leaf or not), + except if content is not None, in which it only matches + non-leaf nodes that also match the content pattern. + + The content, if not None, must be a sequence of Patterns that + must match the node's children exactly. If the content is + given, the type must not be None. + + If a name is given, the matching node is stored in the results + dict under that key. + """ + if type is not None: + assert type >= 256, type + if content is not None: + assert not isinstance(content, basestring), repr(content) + content = list(content) + for i, item in enumerate(content): + assert isinstance(item, BasePattern), (i, item) + if isinstance(item, WildcardPattern): + self.wildcards = True + self.type = type + self.content = content + self.name = name + + def _submatch(self, node, results=None): + """ + Match the pattern's content to the node's children. + + This assumes the node type matches and self.content is not None. + + Returns True if it matches, False if not. + + If results is not None, it must be a dict which will be + updated with the nodes matching named subpatterns. + + When returning False, the results dict may still be updated. + """ + if self.wildcards: + for c, r in generate_matches(self.content, node.children): + if c == len(node.children): + if results is not None: + results.update(r) + return True + return False + if len(self.content) != len(node.children): + return False + for subpattern, child in zip(self.content, node.children): + if not subpattern.match(child, results): + return False + return True + + +class WildcardPattern(BasePattern): + + """ + A wildcard pattern can match zero or more nodes. + + This has all the flexibility needed to implement patterns like: + + .* .+ .? .{m,n} + (a b c | d e | f) + (...)* (...)+ (...)? (...){m,n} + + except it always uses non-greedy matching. + """ + + def __init__(self, content=None, min=0, max=HUGE, name=None): + """ + Initializer. + + Args: + content: optional sequence of subsequences of patterns; + if absent, matches one node; + if present, each subsequence is an alternative [*] + min: optional minimum number of times to match, default 0 + max: optional maximum number of times to match, default HUGE + name: optional name assigned to this match + + [*] Thus, if content is [[a, b, c], [d, e], [f, g, h]] this is + equivalent to (a b c | d e | f g h); if content is None, + this is equivalent to '.' in regular expression terms. + The min and max parameters work as follows: + min=0, max=maxint: .* + min=1, max=maxint: .+ + min=0, max=1: .? + min=1, max=1: . + If content is not None, replace the dot with the parenthesized + list of alternatives, e.g. (a b c | d e | f g h)* + """ + assert 0 <= min <= max <= HUGE, (min, max) + if content is not None: + content = tuple(map(tuple, content)) # Protect against alterations + # Check sanity of alternatives + assert len(content), repr(content) # Can't have zero alternatives + for alt in content: + assert len(alt), repr(alt) # Can have empty alternatives + self.content = content + self.min = min + self.max = max + self.name = name + + def optimize(self): + """Optimize certain stacked wildcard patterns.""" + subpattern = None + if (self.content is not None and + len(self.content) == 1 and len(self.content[0]) == 1): + subpattern = self.content[0][0] + if self.min == 1 and self.max == 1: + if self.content is None: + return NodePattern(name=self.name) + if subpattern is not None and self.name == subpattern.name: + return subpattern.optimize() + if (self.min <= 1 and isinstance(subpattern, WildcardPattern) and + subpattern.min <= 1 and self.name == subpattern.name): + return WildcardPattern(subpattern.content, + self.min*subpattern.min, + self.max*subpattern.max, + subpattern.name) + return self + + def match(self, node, results=None): + """Does this pattern exactly match a node?""" + return self.match_seq([node], results) + + def match_seq(self, nodes, results=None): + """Does this pattern exactly match a sequence of nodes?""" + for c, r in self.generate_matches(nodes): + if c == len(nodes): + if results is not None: + results.update(r) + if self.name: + results[self.name] = list(nodes) + return True + return False + + def generate_matches(self, nodes): + """ + Generator yielding matches for a sequence of nodes. + + Args: + nodes: sequence of nodes + + Yields: + (count, results) tuples where: + count: the match comprises nodes[:count]; + results: dict containing named submatches. + """ + if self.content is None: + # Shortcut for special case (see __init__.__doc__) + for count in xrange(self.min, 1 + min(len(nodes), self.max)): + r = {} + if self.name: + r[self.name] = nodes[:count] + yield count, r + elif self.name == "bare_name": + yield self._bare_name_matches(nodes) + else: + # The reason for this is that hitting the recursion limit usually + # results in some ugly messages about how RuntimeErrors are being + # ignored. We don't do this on non-CPython implementation because + # they don't have this problem. + if hasattr(sys, "getrefcount"): + save_stderr = sys.stderr + sys.stderr = StringIO() + try: + for count, r in self._recursive_matches(nodes, 0): + if self.name: + r[self.name] = nodes[:count] + yield count, r + except RuntimeError: + # We fall back to the iterative pattern matching scheme if the recursive + # scheme hits the recursion limit. + for count, r in self._iterative_matches(nodes): + if self.name: + r[self.name] = nodes[:count] + yield count, r + finally: + if hasattr(sys, "getrefcount"): + sys.stderr = save_stderr + + def _iterative_matches(self, nodes): + """Helper to iteratively yield the matches.""" + nodelen = len(nodes) + if 0 >= self.min: + yield 0, {} + + results = [] + # generate matches that use just one alt from self.content + for alt in self.content: + for c, r in generate_matches(alt, nodes): + yield c, r + results.append((c, r)) + + # for each match, iterate down the nodes + while results: + new_results = [] + for c0, r0 in results: + # stop if the entire set of nodes has been matched + if c0 < nodelen and c0 <= self.max: + for alt in self.content: + for c1, r1 in generate_matches(alt, nodes[c0:]): + if c1 > 0: + r = {} + r.update(r0) + r.update(r1) + yield c0 + c1, r + new_results.append((c0 + c1, r)) + results = new_results + + def _bare_name_matches(self, nodes): + """Special optimized matcher for bare_name.""" + count = 0 + r = {} + done = False + max = len(nodes) + while not done and count < max: + done = True + for leaf in self.content: + if leaf[0].match(nodes[count], r): + count += 1 + done = False + break + r[self.name] = nodes[:count] + return count, r + + def _recursive_matches(self, nodes, count): + """Helper to recursively yield the matches.""" + assert self.content is not None + if count >= self.min: + yield 0, {} + if count < self.max: + for alt in self.content: + for c0, r0 in generate_matches(alt, nodes): + for c1, r1 in self._recursive_matches(nodes[c0:], count+1): + r = {} + r.update(r0) + r.update(r1) + yield c0 + c1, r + + +class NegatedPattern(BasePattern): + + def __init__(self, content=None): + """ + Initializer. + + The argument is either a pattern or None. If it is None, this + only matches an empty sequence (effectively '$' in regex + lingo). If it is not None, this matches whenever the argument + pattern doesn't have any matches. + """ + if content is not None: + assert isinstance(content, BasePattern), repr(content) + self.content = content + + def match(self, node): + # We never match a node in its entirety + return False + + def match_seq(self, nodes): + # We only match an empty sequence of nodes in its entirety + return len(nodes) == 0 + + def generate_matches(self, nodes): + if self.content is None: + # Return a match if there is an empty sequence + if len(nodes) == 0: + yield 0, {} + else: + # Return a match if the argument pattern has no matches + for c, r in self.content.generate_matches(nodes): + return + yield 0, {} + + +def generate_matches(patterns, nodes): + """ + Generator yielding matches for a sequence of patterns and nodes. + + Args: + patterns: a sequence of patterns + nodes: a sequence of nodes + + Yields: + (count, results) tuples where: + count: the entire sequence of patterns matches nodes[:count]; + results: dict containing named submatches. + """ + if not patterns: + yield 0, {} + else: + p, rest = patterns[0], patterns[1:] + for c0, r0 in p.generate_matches(nodes): + if not rest: + yield c0, r0 + else: + for c1, r1 in generate_matches(rest, nodes[c0:]): + r = {} + r.update(r0) + r.update(r1) + yield c0 + c1, r diff --git a/PythonHome/Lib/lib2to3/pytree.pyc b/PythonHome/Lib/lib2to3/pytree.pyc deleted file mode 100644 index 39d02218ba3c01b7597ce5a0e031ddc12b2fa2af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29163 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 diff --git a/PythonHome/Lib/lib2to3/refactor.py b/PythonHome/Lib/lib2to3/refactor.py new file mode 100644 index 0000000000..a4c168df9e --- /dev/null +++ b/PythonHome/Lib/lib2to3/refactor.py @@ -0,0 +1,747 @@ +# Copyright 2006 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Refactoring framework. + +Used as a main program, this can refactor any number of files and/or +recursively descend down directories. Imported as a module, this +provides infrastructure to write your own refactoring tool. +""" + +from __future__ import with_statement + +__author__ = "Guido van Rossum " + + +# Python imports +import os +import sys +import logging +import operator +import collections +import StringIO +from itertools import chain + +# Local imports +from .pgen2 import driver, tokenize, token +from .fixer_util import find_root +from . import pytree, pygram +from . import btm_utils as bu +from . import btm_matcher as bm + + +def get_all_fix_names(fixer_pkg, remove_prefix=True): + """Return a sorted list of all available fix names in the given package.""" + pkg = __import__(fixer_pkg, [], [], ["*"]) + fixer_dir = os.path.dirname(pkg.__file__) + fix_names = [] + for name in sorted(os.listdir(fixer_dir)): + if name.startswith("fix_") and name.endswith(".py"): + if remove_prefix: + name = name[4:] + fix_names.append(name[:-3]) + return fix_names + + +class _EveryNode(Exception): + pass + + +def _get_head_types(pat): + """ Accepts a pytree Pattern Node and returns a set + of the pattern types which will match first. """ + + if isinstance(pat, (pytree.NodePattern, pytree.LeafPattern)): + # NodePatters must either have no type and no content + # or a type and content -- so they don't get any farther + # Always return leafs + if pat.type is None: + raise _EveryNode + return set([pat.type]) + + if isinstance(pat, pytree.NegatedPattern): + if pat.content: + return _get_head_types(pat.content) + raise _EveryNode # Negated Patterns don't have a type + + if isinstance(pat, pytree.WildcardPattern): + # Recurse on each node in content + r = set() + for p in pat.content: + for x in p: + r.update(_get_head_types(x)) + return r + + raise Exception("Oh no! I don't understand pattern %s" %(pat)) + + +def _get_headnode_dict(fixer_list): + """ Accepts a list of fixers and returns a dictionary + of head node type --> fixer list. """ + head_nodes = collections.defaultdict(list) + every = [] + for fixer in fixer_list: + if fixer.pattern: + try: + heads = _get_head_types(fixer.pattern) + except _EveryNode: + every.append(fixer) + else: + for node_type in heads: + head_nodes[node_type].append(fixer) + else: + if fixer._accept_type is not None: + head_nodes[fixer._accept_type].append(fixer) + else: + every.append(fixer) + for node_type in chain(pygram.python_grammar.symbol2number.itervalues(), + pygram.python_grammar.tokens): + head_nodes[node_type].extend(every) + return dict(head_nodes) + + +def get_fixers_from_package(pkg_name): + """ + Return the fully qualified names for fixers in the package pkg_name. + """ + return [pkg_name + "." + fix_name + for fix_name in get_all_fix_names(pkg_name, False)] + +def _identity(obj): + return obj + +if sys.version_info < (3, 0): + import codecs + _open_with_encoding = codecs.open + # codecs.open doesn't translate newlines sadly. + def _from_system_newlines(input): + return input.replace(u"\r\n", u"\n") + def _to_system_newlines(input): + if os.linesep != "\n": + return input.replace(u"\n", os.linesep) + else: + return input +else: + _open_with_encoding = open + _from_system_newlines = _identity + _to_system_newlines = _identity + + +def _detect_future_features(source): + have_docstring = False + gen = tokenize.generate_tokens(StringIO.StringIO(source).readline) + def advance(): + tok = gen.next() + return tok[0], tok[1] + ignore = frozenset((token.NEWLINE, tokenize.NL, token.COMMENT)) + features = set() + try: + while True: + tp, value = advance() + if tp in ignore: + continue + elif tp == token.STRING: + if have_docstring: + break + have_docstring = True + elif tp == token.NAME and value == u"from": + tp, value = advance() + if tp != token.NAME or value != u"__future__": + break + tp, value = advance() + if tp != token.NAME or value != u"import": + break + tp, value = advance() + if tp == token.OP and value == u"(": + tp, value = advance() + while tp == token.NAME: + features.add(value) + tp, value = advance() + if tp != token.OP or value != u",": + break + tp, value = advance() + else: + break + except StopIteration: + pass + return frozenset(features) + + +class FixerError(Exception): + """A fixer could not be loaded.""" + + +class RefactoringTool(object): + + _default_options = {"print_function" : False, + "write_unchanged_files" : False} + + CLASS_PREFIX = "Fix" # The prefix for fixer classes + FILE_PREFIX = "fix_" # The prefix for modules with a fixer within + + def __init__(self, fixer_names, options=None, explicit=None): + """Initializer. + + Args: + fixer_names: a list of fixers to import + options: an dict with configuration. + explicit: a list of fixers to run even if they are explicit. + """ + self.fixers = fixer_names + self.explicit = explicit or [] + self.options = self._default_options.copy() + if options is not None: + self.options.update(options) + if self.options["print_function"]: + self.grammar = pygram.python_grammar_no_print_statement + else: + self.grammar = pygram.python_grammar + # When this is True, the refactor*() methods will call write_file() for + # files processed even if they were not changed during refactoring. If + # and only if the refactor method's write parameter was True. + self.write_unchanged_files = self.options.get("write_unchanged_files") + self.errors = [] + self.logger = logging.getLogger("RefactoringTool") + self.fixer_log = [] + self.wrote = False + self.driver = driver.Driver(self.grammar, + convert=pytree.convert, + logger=self.logger) + self.pre_order, self.post_order = self.get_fixers() + + + self.files = [] # List of files that were or should be modified + + self.BM = bm.BottomMatcher() + self.bmi_pre_order = [] # Bottom Matcher incompatible fixers + self.bmi_post_order = [] + + for fixer in chain(self.post_order, self.pre_order): + if fixer.BM_compatible: + self.BM.add_fixer(fixer) + # remove fixers that will be handled by the bottom-up + # matcher + elif fixer in self.pre_order: + self.bmi_pre_order.append(fixer) + elif fixer in self.post_order: + self.bmi_post_order.append(fixer) + + self.bmi_pre_order_heads = _get_headnode_dict(self.bmi_pre_order) + self.bmi_post_order_heads = _get_headnode_dict(self.bmi_post_order) + + + + def get_fixers(self): + """Inspects the options to load the requested patterns and handlers. + + Returns: + (pre_order, post_order), where pre_order is the list of fixers that + want a pre-order AST traversal, and post_order is the list that want + post-order traversal. + """ + pre_order_fixers = [] + post_order_fixers = [] + for fix_mod_path in self.fixers: + mod = __import__(fix_mod_path, {}, {}, ["*"]) + fix_name = fix_mod_path.rsplit(".", 1)[-1] + if fix_name.startswith(self.FILE_PREFIX): + fix_name = fix_name[len(self.FILE_PREFIX):] + parts = fix_name.split("_") + class_name = self.CLASS_PREFIX + "".join([p.title() for p in parts]) + try: + fix_class = getattr(mod, class_name) + except AttributeError: + raise FixerError("Can't find %s.%s" % (fix_name, class_name)) + fixer = fix_class(self.options, self.fixer_log) + if fixer.explicit and self.explicit is not True and \ + fix_mod_path not in self.explicit: + self.log_message("Skipping implicit fixer: %s", fix_name) + continue + + self.log_debug("Adding transformation: %s", fix_name) + if fixer.order == "pre": + pre_order_fixers.append(fixer) + elif fixer.order == "post": + post_order_fixers.append(fixer) + else: + raise FixerError("Illegal fixer order: %r" % fixer.order) + + key_func = operator.attrgetter("run_order") + pre_order_fixers.sort(key=key_func) + post_order_fixers.sort(key=key_func) + return (pre_order_fixers, post_order_fixers) + + def log_error(self, msg, *args, **kwds): + """Called when an error occurs.""" + raise + + def log_message(self, msg, *args): + """Hook to log a message.""" + if args: + msg = msg % args + self.logger.info(msg) + + def log_debug(self, msg, *args): + if args: + msg = msg % args + self.logger.debug(msg) + + def print_output(self, old_text, new_text, filename, equal): + """Called with the old version, new version, and filename of a + refactored file.""" + pass + + def refactor(self, items, write=False, doctests_only=False): + """Refactor a list of files and directories.""" + + for dir_or_file in items: + if os.path.isdir(dir_or_file): + self.refactor_dir(dir_or_file, write, doctests_only) + else: + self.refactor_file(dir_or_file, write, doctests_only) + + def refactor_dir(self, dir_name, write=False, doctests_only=False): + """Descends down a directory and refactor every Python file found. + + Python files are assumed to have a .py extension. + + Files and subdirectories starting with '.' are skipped. + """ + py_ext = os.extsep + "py" + for dirpath, dirnames, filenames in os.walk(dir_name): + self.log_debug("Descending into %s", dirpath) + dirnames.sort() + filenames.sort() + for name in filenames: + if (not name.startswith(".") and + os.path.splitext(name)[1] == py_ext): + fullname = os.path.join(dirpath, name) + self.refactor_file(fullname, write, doctests_only) + # Modify dirnames in-place to remove subdirs with leading dots + dirnames[:] = [dn for dn in dirnames if not dn.startswith(".")] + + def _read_python_source(self, filename): + """ + Do our best to decode a Python source file correctly. + """ + try: + f = open(filename, "rb") + except IOError as err: + self.log_error("Can't open %s: %s", filename, err) + return None, None + try: + encoding = tokenize.detect_encoding(f.readline)[0] + finally: + f.close() + with _open_with_encoding(filename, "r", encoding=encoding) as f: + return _from_system_newlines(f.read()), encoding + + def refactor_file(self, filename, write=False, doctests_only=False): + """Refactors a file.""" + input, encoding = self._read_python_source(filename) + if input is None: + # Reading the file failed. + return + input += u"\n" # Silence certain parse errors + if doctests_only: + self.log_debug("Refactoring doctests in %s", filename) + output = self.refactor_docstring(input, filename) + if self.write_unchanged_files or output != input: + self.processed_file(output, filename, input, write, encoding) + else: + self.log_debug("No doctest changes in %s", filename) + else: + tree = self.refactor_string(input, filename) + if self.write_unchanged_files or (tree and tree.was_changed): + # The [:-1] is to take off the \n we added earlier + self.processed_file(unicode(tree)[:-1], filename, + write=write, encoding=encoding) + else: + self.log_debug("No changes in %s", filename) + + def refactor_string(self, data, name): + """Refactor a given input string. + + Args: + data: a string holding the code to be refactored. + name: a human-readable name for use in error/log messages. + + Returns: + An AST corresponding to the refactored input stream; None if + there were errors during the parse. + """ + features = _detect_future_features(data) + if "print_function" in features: + self.driver.grammar = pygram.python_grammar_no_print_statement + try: + tree = self.driver.parse_string(data) + except Exception as err: + self.log_error("Can't parse %s: %s: %s", + name, err.__class__.__name__, err) + return + finally: + self.driver.grammar = self.grammar + tree.future_features = features + self.log_debug("Refactoring %s", name) + self.refactor_tree(tree, name) + return tree + + def refactor_stdin(self, doctests_only=False): + input = sys.stdin.read() + if doctests_only: + self.log_debug("Refactoring doctests in stdin") + output = self.refactor_docstring(input, "") + if self.write_unchanged_files or output != input: + self.processed_file(output, "", input) + else: + self.log_debug("No doctest changes in stdin") + else: + tree = self.refactor_string(input, "") + if self.write_unchanged_files or (tree and tree.was_changed): + self.processed_file(unicode(tree), "", input) + else: + self.log_debug("No changes in stdin") + + def refactor_tree(self, tree, name): + """Refactors a parse tree (modifying the tree in place). + + For compatible patterns the bottom matcher module is + used. Otherwise the tree is traversed node-to-node for + matches. + + Args: + tree: a pytree.Node instance representing the root of the tree + to be refactored. + name: a human-readable name for this tree. + + Returns: + True if the tree was modified, False otherwise. + """ + + for fixer in chain(self.pre_order, self.post_order): + fixer.start_tree(tree, name) + + #use traditional matching for the incompatible fixers + self.traverse_by(self.bmi_pre_order_heads, tree.pre_order()) + self.traverse_by(self.bmi_post_order_heads, tree.post_order()) + + # obtain a set of candidate nodes + match_set = self.BM.run(tree.leaves()) + + while any(match_set.values()): + for fixer in self.BM.fixers: + if fixer in match_set and match_set[fixer]: + #sort by depth; apply fixers from bottom(of the AST) to top + match_set[fixer].sort(key=pytree.Base.depth, reverse=True) + + if fixer.keep_line_order: + #some fixers(eg fix_imports) must be applied + #with the original file's line order + match_set[fixer].sort(key=pytree.Base.get_lineno) + + for node in list(match_set[fixer]): + if node in match_set[fixer]: + match_set[fixer].remove(node) + + try: + find_root(node) + except ValueError: + # this node has been cut off from a + # previous transformation ; skip + continue + + if node.fixers_applied and fixer in node.fixers_applied: + # do not apply the same fixer again + continue + + results = fixer.match(node) + + if results: + new = fixer.transform(node, results) + if new is not None: + node.replace(new) + #new.fixers_applied.append(fixer) + for node in new.post_order(): + # do not apply the fixer again to + # this or any subnode + if not node.fixers_applied: + node.fixers_applied = [] + node.fixers_applied.append(fixer) + + # update the original match set for + # the added code + new_matches = self.BM.run(new.leaves()) + for fxr in new_matches: + if not fxr in match_set: + match_set[fxr]=[] + + match_set[fxr].extend(new_matches[fxr]) + + for fixer in chain(self.pre_order, self.post_order): + fixer.finish_tree(tree, name) + return tree.was_changed + + def traverse_by(self, fixers, traversal): + """Traverse an AST, applying a set of fixers to each node. + + This is a helper method for refactor_tree(). + + Args: + fixers: a list of fixer instances. + traversal: a generator that yields AST nodes. + + Returns: + None + """ + if not fixers: + return + for node in traversal: + for fixer in fixers[node.type]: + results = fixer.match(node) + if results: + new = fixer.transform(node, results) + if new is not None: + node.replace(new) + node = new + + def processed_file(self, new_text, filename, old_text=None, write=False, + encoding=None): + """ + Called when a file has been refactored and there may be changes. + """ + self.files.append(filename) + if old_text is None: + old_text = self._read_python_source(filename)[0] + if old_text is None: + return + equal = old_text == new_text + self.print_output(old_text, new_text, filename, equal) + if equal: + self.log_debug("No changes to %s", filename) + if not self.write_unchanged_files: + return + if write: + self.write_file(new_text, filename, old_text, encoding) + else: + self.log_debug("Not writing changes to %s", filename) + + def write_file(self, new_text, filename, old_text, encoding=None): + """Writes a string to a file. + + It first shows a unified diff between the old text and the new text, and + then rewrites the file; the latter is only done if the write option is + set. + """ + try: + f = _open_with_encoding(filename, "w", encoding=encoding) + except os.error as err: + self.log_error("Can't create %s: %s", filename, err) + return + try: + f.write(_to_system_newlines(new_text)) + except os.error as err: + self.log_error("Can't write %s: %s", filename, err) + finally: + f.close() + self.log_debug("Wrote changes to %s", filename) + self.wrote = True + + PS1 = ">>> " + PS2 = "... " + + def refactor_docstring(self, input, filename): + """Refactors a docstring, looking for doctests. + + This returns a modified version of the input string. It looks + for doctests, which start with a ">>>" prompt, and may be + continued with "..." prompts, as long as the "..." is indented + the same as the ">>>". + + (Unfortunately we can't use the doctest module's parser, + since, like most parsers, it is not geared towards preserving + the original source.) + """ + result = [] + block = None + block_lineno = None + indent = None + lineno = 0 + for line in input.splitlines(True): + lineno += 1 + if line.lstrip().startswith(self.PS1): + if block is not None: + result.extend(self.refactor_doctest(block, block_lineno, + indent, filename)) + block_lineno = lineno + block = [line] + i = line.find(self.PS1) + indent = line[:i] + elif (indent is not None and + (line.startswith(indent + self.PS2) or + line == indent + self.PS2.rstrip() + u"\n")): + block.append(line) + else: + if block is not None: + result.extend(self.refactor_doctest(block, block_lineno, + indent, filename)) + block = None + indent = None + result.append(line) + if block is not None: + result.extend(self.refactor_doctest(block, block_lineno, + indent, filename)) + return u"".join(result) + + def refactor_doctest(self, block, lineno, indent, filename): + """Refactors one doctest. + + A doctest is given as a block of lines, the first of which starts + with ">>>" (possibly indented), while the remaining lines start + with "..." (identically indented). + + """ + try: + tree = self.parse_block(block, lineno, indent) + except Exception as err: + if self.logger.isEnabledFor(logging.DEBUG): + for line in block: + self.log_debug("Source: %s", line.rstrip(u"\n")) + self.log_error("Can't parse docstring in %s line %s: %s: %s", + filename, lineno, err.__class__.__name__, err) + return block + if self.refactor_tree(tree, filename): + new = unicode(tree).splitlines(True) + # Undo the adjustment of the line numbers in wrap_toks() below. + clipped, new = new[:lineno-1], new[lineno-1:] + assert clipped == [u"\n"] * (lineno-1), clipped + if not new[-1].endswith(u"\n"): + new[-1] += u"\n" + block = [indent + self.PS1 + new.pop(0)] + if new: + block += [indent + self.PS2 + line for line in new] + return block + + def summarize(self): + if self.wrote: + were = "were" + else: + were = "need to be" + if not self.files: + self.log_message("No files %s modified.", were) + else: + self.log_message("Files that %s modified:", were) + for file in self.files: + self.log_message(file) + if self.fixer_log: + self.log_message("Warnings/messages while refactoring:") + for message in self.fixer_log: + self.log_message(message) + if self.errors: + if len(self.errors) == 1: + self.log_message("There was 1 error:") + else: + self.log_message("There were %d errors:", len(self.errors)) + for msg, args, kwds in self.errors: + self.log_message(msg, *args, **kwds) + + def parse_block(self, block, lineno, indent): + """Parses a block into a tree. + + This is necessary to get correct line number / offset information + in the parser diagnostics and embedded into the parse tree. + """ + tree = self.driver.parse_tokens(self.wrap_toks(block, lineno, indent)) + tree.future_features = frozenset() + return tree + + def wrap_toks(self, block, lineno, indent): + """Wraps a tokenize stream to systematically modify start/end.""" + tokens = tokenize.generate_tokens(self.gen_lines(block, indent).next) + for type, value, (line0, col0), (line1, col1), line_text in tokens: + line0 += lineno - 1 + line1 += lineno - 1 + # Don't bother updating the columns; this is too complicated + # since line_text would also have to be updated and it would + # still break for tokens spanning lines. Let the user guess + # that the column numbers for doctests are relative to the + # end of the prompt string (PS1 or PS2). + yield type, value, (line0, col0), (line1, col1), line_text + + + def gen_lines(self, block, indent): + """Generates lines as expected by tokenize from a list of lines. + + This strips the first len(indent + self.PS1) characters off each line. + """ + prefix1 = indent + self.PS1 + prefix2 = indent + self.PS2 + prefix = prefix1 + for line in block: + if line.startswith(prefix): + yield line[len(prefix):] + elif line == prefix.rstrip() + u"\n": + yield u"\n" + else: + raise AssertionError("line=%r, prefix=%r" % (line, prefix)) + prefix = prefix2 + while True: + yield "" + + +class MultiprocessingUnsupported(Exception): + pass + + +class MultiprocessRefactoringTool(RefactoringTool): + + def __init__(self, *args, **kwargs): + super(MultiprocessRefactoringTool, self).__init__(*args, **kwargs) + self.queue = None + self.output_lock = None + + def refactor(self, items, write=False, doctests_only=False, + num_processes=1): + if num_processes == 1: + return super(MultiprocessRefactoringTool, self).refactor( + items, write, doctests_only) + try: + import multiprocessing + except ImportError: + raise MultiprocessingUnsupported + if self.queue is not None: + raise RuntimeError("already doing multiple processes") + self.queue = multiprocessing.JoinableQueue() + self.output_lock = multiprocessing.Lock() + processes = [multiprocessing.Process(target=self._child) + for i in xrange(num_processes)] + try: + for p in processes: + p.start() + super(MultiprocessRefactoringTool, self).refactor(items, write, + doctests_only) + finally: + self.queue.join() + for i in xrange(num_processes): + self.queue.put(None) + for p in processes: + if p.is_alive(): + p.join() + self.queue = None + + def _child(self): + task = self.queue.get() + while task is not None: + args, kwargs = task + try: + super(MultiprocessRefactoringTool, self).refactor_file( + *args, **kwargs) + finally: + self.queue.task_done() + task = self.queue.get() + + def refactor_file(self, *args, **kwargs): + if self.queue is not None: + self.queue.put((args, kwargs)) + else: + return super(MultiprocessRefactoringTool, self).refactor_file( + *args, **kwargs) diff --git a/PythonHome/Lib/lib2to3/refactor.pyc b/PythonHome/Lib/lib2to3/refactor.pyc deleted file mode 100644 index 3132fe3ae0ffa0c57d5df36e3de6b6e4e83581f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23342 zcmbuH3v66hdf(5Tp(u?cij*jkqMlc>Wz)7yubq7)Ue}2%%8qtzT6<|Py^OTe;mjp9 zcO8|JN4&{CwTz|H}ORfjiEnza2Q& zaBh(_aE+2{1#Z3M7E3N@l-*+4N{3u)$Sn>P`8{rNPmv#Xi^D~JuUp((A1^%1u?;?@tj#Y1j=)Gdzscl%sx%&i}Gi--Ml#kG#O z^>Md2?$(dG#iPD-zm*QxWB(N{qpoqPsC&9s`j~5+aq**8_iV59qGmQf9df?uw@9LRxmM3QNwd8YE+@71c&n4F z&FtU*Y8p4fS{l~E^;)wXZX}%*-d+r|o6R(=*VAahFFHVN6|L8@`pr10s|)p@aW3EC9N!|7IroNhEA|2WRswf-$lWfvEO4tOw_0{@ zkPf-KfxBH+wcA5(d&x0ZRTy?}l=X_w?2V7Q+k4y_fHlZkQc-f%9>G_uq(=(xs1R5> zOYJs;54qKf742~$je^aqj?V(+^V6DbdW9s4IlVSOmHGp3HPcK`Q){)t+UvDutG3jN zfuZfN4Jhi=0k}9^VUvNuT79jy63;MW=N`?5NU2#(br>@nJ53cd|BudmKe8dgt}Hx&f3nw=>OHZ~FB#LjF{>rQ1Z6o2IU_B%LBRbN$8U z()Ctz>8Y&qJ=Y7MXZhJ--mb)1mAzys+rFD~6sAW=T1!qV{g5!bTpeumy z&RnMv*HuaXw7bvUp_za>hW-UEn)kCX;8k(edS|ozCa)XHR;#`i?{_od=rr|a_@)NX zL0tpu40~|>Z+Y-=?V(s{Syc9J$t9Ns??5y#y0*_H-y^L0R3K2~*!(LYLEz^5UF@@# znZ2&KWKBS#suf?a*MZ@ZMmt~)enVZ}1!n@c{eir}?2Si-Ufbt{ShF{#gjS%%>Ot$X zz@}jHOKxHFr$GbFV?-% z6ZWV^8fW{%{2%Be9091UcDAzt;%wb))^CPeP4LRd1~`?Z*-V%|$WSle4BMS^;Z-KEkal0^+f18ny{^ZR06h~u(wy@7+4GBWZMk^X8EO^=!gHN= zY$t6%&%BKm&&4ay;YQIyxLEJBGw5&Mz8TjVRa=dfEi_w=dM)X-(Nww{4Z1PJ zxw5U@Yj)bxHhh`4T8v;Sv2?@I?LLUUJ32+G_!Qst42c^$IW!tng0a#O(vhH2I#S|^ z+{s|5WRR=*=zIB&AewOjyVbx!cQ|bzM>H3B`Rf9J*&AOlcqt2>lQ-SYxMQ=R!91$= zkXvY) zmj$32WbZvSsdZ1^r`*E!(~eE$@Ie3|dUZt5pFbWFO58W>sJdX{!RGI}g=|dY@HB7C zF8w5%G638K$%jM%b@#z_qgmG(){>n;@D?Nhv0#C~A$6rH`EvM!`!rJpTS|h z(`q4E&_`;|4WyKA3j$ux3>?+M$hv?77LJkAo!Dnqi{BUL<^p1Vxd6)PUDZ z2UYRxb@+kEd%Cl})M-8C#UPI~^!|FS)s0hQC?*g1Y`hJeH*7YVmggA4Gh0*DW~fJl zf2}$-i6R!Eww%?ooT{V-{;Fpa-YtA*VhTMxv*w!3oECGQ#Fa;lPgH_(FbvEQLP0JLgfLR$Ml;rtVfl zJ4>s(o`NKWDq?XvYi2ub9*l*$peeG~Ek)VE4(@G&wBzFH`99FFHcb6p+c$o{UX z@Ao3-Ub0EN(W=#BUm%{`Y;Sb4UC&YIMrw6)sZBhezDgpYWG=ihV7w7srN9;veMC9FyOB_`aq3mG zPW8SOY*Czw*1KRd8298~JEl!4-{IZwGb3gT-~*0`-yE3?#n$zYt& zA6bv@R(s0&9kSY|1C9UAwGY|IpRn4nK4wAw-dWIgyH>2r&-!bDbPrh2u(6=~8su9* z*G&88tm|Q$$d}$}BAeHP1$N~c--U(tVOa2(vEXmQfrED7UgMM)jbogj)``#6NesaS zcjI?Bdx;C5H9XUS8P0LWQye}!JB9F?L#?5y*CqwO#t+)?29Iy*4xZ6}Sc%&Pw(l;r z7|_=mXteeC({$m9QE)KmiuQ<9b;VlHb-GfctJSW+*y~7!K+~39G=>^o=3Qhnkx<4A z;skLEgh0_vjd;#yG8|le*&Y(OkucmVGD+tawc;$&$TqLJD+@1Pox5V1*xZX&bou3% zUb-^(N_0VWRPmLh>viJ!SE8$PFId^!rI&o8m#-P6tTh_Obmz0q##PvC&BQ((hq2le zi$Fa#PJOe6&eiDDu^TYW=wn5d=1RMRFujlG<+!GuNNrZxhOrCd+nz}1XrgN*@3HS< z3e`rOA$t^iTlD-XwVow$Fw~R5X!#5xWSQ?M=Q2z>91QWq8wryG>5ib&KmT~Z9uJu@kgi6H@)0W^%T0pV8PyhxAO^!Dg+&mvpSK7eH4_{am>Z@+rh3fs z<5qt{*1^R|nEgQgXA_UWprK%t#GgfR;!qTV1=ohp$ln@*Pg->+HHz0zj8c*=-z=_@+lI z^me1Wz6AAz)j>K@BrpI$;2^s29545aq+5|lT@nj?;9=^i;@YUhJesD>W8Rcwv8JkX zuo!kk%Y&42)R0)c8Y^BMc1Wx$K~*~HR*zXfoc55*Cfq7p3t?skV>B$O+EIHv?wJ1d zk~N&N^hD9&Ntc~+tEW{#_0JULXNyeewr{)aob_|U(kZX{EQ=3|=bU%RD}hEm<5nNY z`9iSyl=zWKr;HcBZZ*!j)d$~RYtYR?cES2NTWrQdE-wj-60F3-IV(zk zn`6D&Ze~pc=UZ`t4Y#lmTuN5br+ZH-HQCi$h@K8>rbl_>t?6VKS3OI(r%lJy>y-Mk z-_|p%3)#&OwSBp{()C2xi{Qnu@%BcmS#M_VJVMfKhv+ozuxa*-ov?;kw`kJuC=#EH zR+Zc&F}lQ$3FoR{HD8CZmU;(ePMjkz^y=QD z6nJ&-9Jzbdy=uFI6;J5bGbLLGxi%PmfEI>!s0cP~n^Y`fomxdr7-nQlk~%Ni{G)X> ztC0AUp^|Z5V@F#_CyOHq>DJe*nViiO6SY(*j^0;DtQYKz)lPz0$6jt=_sk!K|7M~$ zez&x4jP$uqmUY%&^5$iG@!U)HVrji8lV#pkti?)t-I-$SyLhQu@2sO#H!WZsKc@1qKa zVNj)7{Uud@MveA~As>MyOWPeS9UM9aQ<3n!&Z9b69+*%LWKv96q@__=94!Nn^7;ox> z*Bz3?1Yl3_Oc*U}@EGk8%lC*nNFRWzz#$RZ_ZdwaX7nTOHr7$dF(yyvq>KNgYERzY zXGSQ9G?Oqh>Fo+esE3h&510h}pJjx?JOX=_p0Q76*xZgOx%drF*hg$oGZEdUFAPYd zF8O|2`>2yF4fo*DFJ{!O?JeFO7Q3cn79DI(m_vct!)MK>pi*@PyWMYkK|6qNtwQ5b zi)411u(5c}WKkP_RBFRLuQl_7d8K^XG+KaluELzLZ?R(s#0GgVY$Hcv$Pa!m$kdB?&F z>CA;RJxSsGT61GVZakQfF%ZwLo~DXP;g=c>y=BODidhKzHs(IPHM+~!z}Ix4?vQ;#Q{STD&uToWBv`jEjWOMsSmqX=IUzmyw|7ufBMtdM� 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')): + return [] + + fullname = filename + try: + stat = os.stat(fullname) + except OSError: + basename = filename + + # Try for a __loader__, if available + if module_globals and '__loader__' in module_globals: + name = module_globals.get('__name__') + loader = module_globals['__loader__'] + get_source = getattr(loader, 'get_source', None) + + if name and get_source: + try: + data = get_source(name) + except (ImportError, IOError): + pass + else: + if data is None: + # No luck, the PEP302 loader cannot find the source + # for this module. + return [] + cache[filename] = ( + len(data), None, + [line+'\n' for line in data.splitlines()], fullname + ) + return cache[filename][2] + + # Try looking through the module search path, which is only useful + # when handling a relative filename. + if os.path.isabs(filename): + return [] + + for dirname in sys.path: + # When using imputil, sys.path may contain things other than + # strings; ignore them when it happens. + try: + fullname = os.path.join(dirname, basename) + except (TypeError, AttributeError): + # Not sufficiently string-like to do anything useful with. + continue + try: + stat = os.stat(fullname) + break + except os.error: + pass + else: + return [] + try: + with open(fullname, 'rU') as fp: + lines = fp.readlines() + except IOError: + return [] + if lines and not lines[-1].endswith('\n'): + lines[-1] += '\n' + size, mtime = stat.st_size, stat.st_mtime + cache[filename] = size, mtime, lines, fullname + return lines diff --git a/PythonHome/Lib/linecache.pyc b/PythonHome/Lib/linecache.pyc index 56a85cd1bbc93d47be5d5d2ec25556a9dfaa4187..16dc4886c54319a5b72e8e73d5ac16cec675c3b8 100644 GIT binary patch delta 346 zcmaDWu~TY88zUpj6s-NrAaa2`4xIz!Tx?h0nRc0r6mQWB{43k zNu}vA0hJ{g`FS4sxv7)Gn7T;UwfQ}hI3pR_L|NFGNY^%5o6UofdvgifSr#%h2XJ2{ JLzfAUB>?w%cAWqK delta 141 zcmdlf^;Tj-8zUq0lPj3I(8V?zGmA4~2v)POGocGk a-puB~$iDdx+gTP2sbAbz(Zwe5S^@y;q9?-u diff --git a/PythonHome/Lib/locale.py b/PythonHome/Lib/locale.py new file mode 100644 index 0000000000..25dccaf22f --- /dev/null +++ b/PythonHome/Lib/locale.py @@ -0,0 +1,1947 @@ +""" Locale support. + + The module provides low-level access to the C lib's locale APIs + and adds high level number formatting APIs as well as a locale + aliasing engine to complement these. + + The aliasing engine includes support for many commonly used locale + names and maps them to values suitable for passing to the C lib's + setlocale() function. It also includes default encodings for all + supported locale names. + +""" + +import sys +import encodings +import encodings.aliases +import re +import operator +import functools + +try: + _unicode = unicode +except NameError: + # If Python is built without Unicode support, the unicode type + # will not exist. Fake one. + class _unicode(object): + pass + +# Try importing the _locale module. +# +# If this fails, fall back on a basic 'C' locale emulation. + +# Yuck: LC_MESSAGES is non-standard: can't tell whether it exists before +# trying the import. So __all__ is also fiddled at the end of the file. +__all__ = ["getlocale", "getdefaultlocale", "getpreferredencoding", "Error", + "setlocale", "resetlocale", "localeconv", "strcoll", "strxfrm", + "str", "atof", "atoi", "format", "format_string", "currency", + "normalize", "LC_CTYPE", "LC_COLLATE", "LC_TIME", "LC_MONETARY", + "LC_NUMERIC", "LC_ALL", "CHAR_MAX"] + +try: + + from _locale import * + +except ImportError: + + # Locale emulation + + CHAR_MAX = 127 + LC_ALL = 6 + LC_COLLATE = 3 + LC_CTYPE = 0 + LC_MESSAGES = 5 + LC_MONETARY = 4 + LC_NUMERIC = 1 + LC_TIME = 2 + Error = ValueError + + def localeconv(): + """ localeconv() -> dict. + Returns numeric and monetary locale-specific parameters. + """ + # 'C' locale default values + return {'grouping': [127], + 'currency_symbol': '', + 'n_sign_posn': 127, + 'p_cs_precedes': 127, + 'n_cs_precedes': 127, + 'mon_grouping': [], + 'n_sep_by_space': 127, + 'decimal_point': '.', + 'negative_sign': '', + 'positive_sign': '', + 'p_sep_by_space': 127, + 'int_curr_symbol': '', + 'p_sign_posn': 127, + 'thousands_sep': '', + 'mon_thousands_sep': '', + 'frac_digits': 127, + 'mon_decimal_point': '', + 'int_frac_digits': 127} + + def setlocale(category, value=None): + """ setlocale(integer,string=None) -> string. + Activates/queries locale processing. + """ + if value not in (None, '', 'C'): + raise Error, '_locale emulation only supports "C" locale' + return 'C' + + def strcoll(a,b): + """ strcoll(string,string) -> int. + Compares two strings according to the locale. + """ + return cmp(a,b) + + def strxfrm(s): + """ strxfrm(string) -> string. + Returns a string that behaves for cmp locale-aware. + """ + return s + + +_localeconv = localeconv + +# With this dict, you can override some items of localeconv's return value. +# This is useful for testing purposes. +_override_localeconv = {} + +@functools.wraps(_localeconv) +def localeconv(): + d = _localeconv() + if _override_localeconv: + d.update(_override_localeconv) + return d + + +### Number formatting APIs + +# Author: Martin von Loewis +# improved by Georg Brandl + +# Iterate over grouping intervals +def _grouping_intervals(grouping): + last_interval = None + for interval in grouping: + # if grouping is -1, we are done + if interval == CHAR_MAX: + return + # 0: re-use last group ad infinitum + if interval == 0: + if last_interval is None: + raise ValueError("invalid grouping") + while True: + yield last_interval + yield interval + last_interval = interval + +#perform the grouping from right to left +def _group(s, monetary=False): + conv = localeconv() + thousands_sep = conv[monetary and 'mon_thousands_sep' or 'thousands_sep'] + grouping = conv[monetary and 'mon_grouping' or 'grouping'] + if not grouping: + return (s, 0) + if s[-1] == ' ': + stripped = s.rstrip() + right_spaces = s[len(stripped):] + s = stripped + else: + right_spaces = '' + left_spaces = '' + groups = [] + for interval in _grouping_intervals(grouping): + if not s or s[-1] not in "0123456789": + # only non-digit characters remain (sign, spaces) + left_spaces = s + s = '' + break + groups.append(s[-interval:]) + s = s[:-interval] + if s: + groups.append(s) + groups.reverse() + return ( + left_spaces + thousands_sep.join(groups) + right_spaces, + len(thousands_sep) * (len(groups) - 1) + ) + +# Strip a given amount of excess padding from the given string +def _strip_padding(s, amount): + lpos = 0 + while amount and s[lpos] == ' ': + lpos += 1 + amount -= 1 + rpos = len(s) - 1 + while amount and s[rpos] == ' ': + rpos -= 1 + amount -= 1 + return s[lpos:rpos+1] + +_percent_re = re.compile(r'%(?:\((?P.*?)\))?' + r'(?P[-#0-9 +*.hlL]*?)[eEfFgGdiouxXcrs%]') + +def format(percent, value, grouping=False, monetary=False, *additional): + """Returns the locale-aware substitution of a %? specifier + (percent). + + additional is for format strings which contain one or more + '*' modifiers.""" + # this is only for one-percent-specifier strings and this should be checked + match = _percent_re.match(percent) + if not match or len(match.group())!= len(percent): + raise ValueError(("format() must be given exactly one %%char " + "format specifier, %s not valid") % repr(percent)) + return _format(percent, value, grouping, monetary, *additional) + +def _format(percent, value, grouping=False, monetary=False, *additional): + if additional: + formatted = percent % ((value,) + additional) + else: + formatted = percent % value + # floats and decimal ints need special action! + if percent[-1] in 'eEfFgG': + seps = 0 + parts = formatted.split('.') + if grouping: + parts[0], seps = _group(parts[0], monetary=monetary) + decimal_point = localeconv()[monetary and 'mon_decimal_point' + or 'decimal_point'] + formatted = decimal_point.join(parts) + if seps: + formatted = _strip_padding(formatted, seps) + elif percent[-1] in 'diu': + seps = 0 + if grouping: + formatted, seps = _group(formatted, monetary=monetary) + if seps: + formatted = _strip_padding(formatted, seps) + return formatted + +def format_string(f, val, grouping=False): + """Formats a string in the same way that the % formatting would use, + but takes the current locale into account. + Grouping is applied if the third parameter is true.""" + percents = list(_percent_re.finditer(f)) + new_f = _percent_re.sub('%s', f) + + if operator.isMappingType(val): + new_val = [] + for perc in percents: + if perc.group()[-1]=='%': + new_val.append('%') + else: + new_val.append(format(perc.group(), val, grouping)) + else: + if not isinstance(val, tuple): + val = (val,) + new_val = [] + i = 0 + for perc in percents: + if perc.group()[-1]=='%': + new_val.append('%') + else: + starcount = perc.group('modifiers').count('*') + new_val.append(_format(perc.group(), + val[i], + grouping, + False, + *val[i+1:i+1+starcount])) + i += (1 + starcount) + val = tuple(new_val) + + return new_f % val + +def currency(val, symbol=True, grouping=False, international=False): + """Formats val according to the currency settings + in the current locale.""" + conv = localeconv() + + # check for illegal values + digits = conv[international and 'int_frac_digits' or 'frac_digits'] + if digits == 127: + raise ValueError("Currency formatting is not possible using " + "the 'C' locale.") + + s = format('%%.%if' % digits, abs(val), grouping, monetary=True) + # '<' and '>' are markers if the sign must be inserted between symbol and value + s = '<' + s + '>' + + if symbol: + smb = conv[international and 'int_curr_symbol' or 'currency_symbol'] + precedes = conv[val<0 and 'n_cs_precedes' or 'p_cs_precedes'] + separated = conv[val<0 and 'n_sep_by_space' or 'p_sep_by_space'] + + if precedes: + s = smb + (separated and ' ' or '') + s + else: + s = s + (separated and ' ' or '') + smb + + sign_pos = conv[val<0 and 'n_sign_posn' or 'p_sign_posn'] + sign = conv[val<0 and 'negative_sign' or 'positive_sign'] + + if sign_pos == 0: + s = '(' + s + ')' + elif sign_pos == 1: + s = sign + s + elif sign_pos == 2: + s = s + sign + elif sign_pos == 3: + s = s.replace('<', sign) + elif sign_pos == 4: + s = s.replace('>', sign) + else: + # the default if nothing specified; + # this should be the most fitting sign position + s = sign + s + + return s.replace('<', '').replace('>', '') + +def str(val): + """Convert float to integer, taking the locale into account.""" + return format("%.12g", val) + +def atof(string, func=float): + "Parses a string as a float according to the locale settings." + #First, get rid of the grouping + ts = localeconv()['thousands_sep'] + if ts: + string = string.replace(ts, '') + #next, replace the decimal point with a dot + dd = localeconv()['decimal_point'] + if dd: + string = string.replace(dd, '.') + #finally, parse the string + return func(string) + +def atoi(str): + "Converts a string to an integer according to the locale settings." + return atof(str, int) + +def _test(): + setlocale(LC_ALL, "") + #do grouping + s1 = format("%d", 123456789,1) + print s1, "is", atoi(s1) + #standard formatting + s1 = str(3.14) + print s1, "is", atof(s1) + +### Locale name aliasing engine + +# Author: Marc-Andre Lemburg, mal@lemburg.com +# Various tweaks by Fredrik Lundh + +# store away the low-level version of setlocale (it's +# overridden below) +_setlocale = setlocale + +# Avoid relying on the locale-dependent .lower() method +# (see issue #1813). +_ascii_lower_map = ''.join( + chr(x + 32 if x >= ord('A') and x <= ord('Z') else x) + for x in range(256) +) + +def _replace_encoding(code, encoding): + if '.' in code: + langname = code[:code.index('.')] + else: + langname = code + # Convert the encoding to a C lib compatible encoding string + norm_encoding = encodings.normalize_encoding(encoding) + #print('norm encoding: %r' % norm_encoding) + norm_encoding = encodings.aliases.aliases.get(norm_encoding, + norm_encoding) + #print('aliased encoding: %r' % norm_encoding) + encoding = locale_encoding_alias.get(norm_encoding, + norm_encoding) + #print('found encoding %r' % encoding) + return langname + '.' + encoding + +def normalize(localename): + + """ Returns a normalized locale code for the given locale + name. + + The returned locale code is formatted for use with + setlocale(). + + If normalization fails, the original name is returned + unchanged. + + If the given encoding is not known, the function defaults to + the default encoding for the locale code just like setlocale() + does. + + """ + # Normalize the locale name and extract the encoding and modifier + if isinstance(localename, _unicode): + localename = localename.encode('ascii') + code = localename.translate(_ascii_lower_map) + if ':' in code: + # ':' is sometimes used as encoding delimiter. + code = code.replace(':', '.') + if '@' in code: + code, modifier = code.split('@', 1) + else: + modifier = '' + if '.' in code: + langname, encoding = code.split('.')[:2] + else: + langname = code + encoding = '' + + # First lookup: fullname (possibly with encoding and modifier) + lang_enc = langname + if encoding: + norm_encoding = encoding.replace('-', '') + norm_encoding = norm_encoding.replace('_', '') + lang_enc += '.' + norm_encoding + lookup_name = lang_enc + if modifier: + lookup_name += '@' + modifier + code = locale_alias.get(lookup_name, None) + if code is not None: + return code + #print('first lookup failed') + + if modifier: + # Second try: fullname without modifier (possibly with encoding) + code = locale_alias.get(lang_enc, None) + if code is not None: + #print('lookup without modifier succeeded') + if '@' not in code: + return code + '@' + modifier + if code.split('@', 1)[1].translate(_ascii_lower_map) == modifier: + return code + #print('second lookup failed') + + if encoding: + # Third try: langname (without encoding, possibly with modifier) + lookup_name = langname + if modifier: + lookup_name += '@' + modifier + code = locale_alias.get(lookup_name, None) + if code is not None: + #print('lookup without encoding succeeded') + if '@' not in code: + return _replace_encoding(code, encoding) + code, modifier = code.split('@', 1) + return _replace_encoding(code, encoding) + '@' + modifier + + if modifier: + # Fourth try: langname (without encoding and modifier) + code = locale_alias.get(langname, None) + if code is not None: + #print('lookup without modifier and encoding succeeded') + if '@' not in code: + return _replace_encoding(code, encoding) + '@' + modifier + code, defmod = code.split('@', 1) + if defmod.translate(_ascii_lower_map) == modifier: + return _replace_encoding(code, encoding) + '@' + defmod + + return localename + +def _parse_localename(localename): + + """ Parses the locale code for localename and returns the + result as tuple (language code, encoding). + + The localename is normalized and passed through the locale + alias engine. A ValueError is raised in case the locale name + cannot be parsed. + + The language code corresponds to RFC 1766. code and encoding + can be None in case the values cannot be determined or are + unknown to this implementation. + + """ + code = normalize(localename) + if '@' in code: + # Deal with locale modifiers + code, modifier = code.split('@', 1) + if modifier == 'euro' and '.' not in code: + # Assume Latin-9 for @euro locales. This is bogus, + # since some systems may use other encodings for these + # locales. Also, we ignore other modifiers. + return code, 'iso-8859-15' + + if '.' in code: + return tuple(code.split('.')[:2]) + elif code == 'C': + return None, None + raise ValueError, 'unknown locale: %s' % localename + +def _build_localename(localetuple): + + """ Builds a locale code from the given tuple (language code, + encoding). + + No aliasing or normalizing takes place. + + """ + language, encoding = localetuple + if language is None: + language = 'C' + if encoding is None: + return language + else: + return language + '.' + encoding + +def getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): + + """ Tries to determine the default locale settings and returns + them as tuple (language code, encoding). + + According to POSIX, a program which has not called + setlocale(LC_ALL, "") runs using the portable 'C' locale. + Calling setlocale(LC_ALL, "") lets it use the default locale as + defined by the LANG variable. Since we don't want to interfere + with the current locale setting we thus emulate the behavior + in the way described above. + + To maintain compatibility with other platforms, not only the + LANG variable is tested, but a list of variables given as + envvars parameter. The first found to be defined will be + used. envvars defaults to the search path used in GNU gettext; + it must always contain the variable name 'LANG'. + + Except for the code 'C', the language code corresponds to RFC + 1766. code and encoding can be None in case the values cannot + be determined. + + """ + + try: + # check if it's supported by the _locale module + import _locale + code, encoding = _locale._getdefaultlocale() + except (ImportError, AttributeError): + pass + else: + # make sure the code/encoding values are valid + if sys.platform == "win32" and code and code[:2] == "0x": + # map windows language identifier to language name + code = windows_locale.get(int(code, 0)) + # ...add other platform-specific processing here, if + # necessary... + return code, encoding + + # fall back on POSIX behaviour + import os + lookup = os.environ.get + for variable in envvars: + localename = lookup(variable,None) + if localename: + if variable == 'LANGUAGE': + localename = localename.split(':')[0] + break + else: + localename = 'C' + return _parse_localename(localename) + + +def getlocale(category=LC_CTYPE): + + """ Returns the current setting for the given locale category as + tuple (language code, encoding). + + category may be one of the LC_* value except LC_ALL. It + defaults to LC_CTYPE. + + Except for the code 'C', the language code corresponds to RFC + 1766. code and encoding can be None in case the values cannot + be determined. + + """ + localename = _setlocale(category) + if category == LC_ALL and ';' in localename: + raise TypeError, 'category LC_ALL is not supported' + return _parse_localename(localename) + +def setlocale(category, locale=None): + + """ Set the locale for the given category. The locale can be + a string, an iterable of two strings (language code and encoding), + or None. + + Iterables are converted to strings using the locale aliasing + engine. Locale strings are passed directly to the C lib. + + category may be given as one of the LC_* values. + + """ + if locale and type(locale) is not type(""): + # convert to string + locale = normalize(_build_localename(locale)) + return _setlocale(category, locale) + +def resetlocale(category=LC_ALL): + + """ Sets the locale for category to the default setting. + + The default setting is determined by calling + getdefaultlocale(). category defaults to LC_ALL. + + """ + _setlocale(category, _build_localename(getdefaultlocale())) + +if sys.platform.startswith("win"): + # On Win32, this will return the ANSI code page + def getpreferredencoding(do_setlocale = True): + """Return the charset that the user is likely using.""" + import _locale + return _locale._getdefaultlocale()[1] +else: + # On Unix, if CODESET is available, use that. + try: + CODESET + except NameError: + # Fall back to parsing environment variables :-( + def getpreferredencoding(do_setlocale = True): + """Return the charset that the user is likely using, + by looking at environment variables.""" + return getdefaultlocale()[1] + else: + def getpreferredencoding(do_setlocale = True): + """Return the charset that the user is likely using, + according to the system configuration.""" + if do_setlocale: + oldloc = setlocale(LC_CTYPE) + try: + setlocale(LC_CTYPE, "") + except Error: + pass + result = nl_langinfo(CODESET) + setlocale(LC_CTYPE, oldloc) + return result + else: + return nl_langinfo(CODESET) + + +### Database +# +# The following data was extracted from the locale.alias file which +# comes with X11 and then hand edited removing the explicit encoding +# definitions and adding some more aliases. The file is usually +# available as /usr/lib/X11/locale/locale.alias. +# + +# +# The local_encoding_alias table maps lowercase encoding alias names +# to C locale encoding names (case-sensitive). Note that normalize() +# first looks up the encoding in the encodings.aliases dictionary and +# then applies this mapping to find the correct C lib name for the +# encoding. +# +locale_encoding_alias = { + + # Mappings for non-standard encoding names used in locale names + '437': 'C', + 'c': 'C', + 'en': 'ISO8859-1', + 'jis': 'JIS7', + 'jis7': 'JIS7', + 'ajec': 'eucJP', + + # Mappings from Python codec names to C lib encoding names + 'ascii': 'ISO8859-1', + 'latin_1': 'ISO8859-1', + 'iso8859_1': 'ISO8859-1', + 'iso8859_10': 'ISO8859-10', + 'iso8859_11': 'ISO8859-11', + 'iso8859_13': 'ISO8859-13', + 'iso8859_14': 'ISO8859-14', + 'iso8859_15': 'ISO8859-15', + 'iso8859_16': 'ISO8859-16', + 'iso8859_2': 'ISO8859-2', + 'iso8859_3': 'ISO8859-3', + 'iso8859_4': 'ISO8859-4', + 'iso8859_5': 'ISO8859-5', + 'iso8859_6': 'ISO8859-6', + 'iso8859_7': 'ISO8859-7', + 'iso8859_8': 'ISO8859-8', + 'iso8859_9': 'ISO8859-9', + 'iso2022_jp': 'JIS7', + 'shift_jis': 'SJIS', + 'tactis': 'TACTIS', + 'euc_jp': 'eucJP', + 'euc_kr': 'eucKR', + 'utf_8': 'UTF-8', + 'koi8_r': 'KOI8-R', + 'koi8_u': 'KOI8-U', + # XXX This list is still incomplete. If you know more + # mappings, please file a bug report. Thanks. +} + +# +# The locale_alias table maps lowercase alias names to C locale names +# (case-sensitive). Encodings are always separated from the locale +# name using a dot ('.'); they should only be given in case the +# language name is needed to interpret the given encoding alias +# correctly (CJK codes often have this need). +# +# Note that the normalize() function which uses this tables +# removes '_' and '-' characters from the encoding part of the +# locale name before doing the lookup. This saves a lot of +# space in the table. +# +# MAL 2004-12-10: +# Updated alias mapping to most recent locale.alias file +# from X.org distribution using makelocalealias.py. +# +# These are the differences compared to the old mapping (Python 2.4 +# and older): +# +# updated 'bg' -> 'bg_BG.ISO8859-5' to 'bg_BG.CP1251' +# updated 'bg_bg' -> 'bg_BG.ISO8859-5' to 'bg_BG.CP1251' +# updated 'bulgarian' -> 'bg_BG.ISO8859-5' to 'bg_BG.CP1251' +# updated 'cz' -> 'cz_CZ.ISO8859-2' to 'cs_CZ.ISO8859-2' +# updated 'cz_cz' -> 'cz_CZ.ISO8859-2' to 'cs_CZ.ISO8859-2' +# updated 'czech' -> 'cs_CS.ISO8859-2' to 'cs_CZ.ISO8859-2' +# updated 'dutch' -> 'nl_BE.ISO8859-1' to 'nl_NL.ISO8859-1' +# updated 'et' -> 'et_EE.ISO8859-4' to 'et_EE.ISO8859-15' +# updated 'et_ee' -> 'et_EE.ISO8859-4' to 'et_EE.ISO8859-15' +# updated 'fi' -> 'fi_FI.ISO8859-1' to 'fi_FI.ISO8859-15' +# updated 'fi_fi' -> 'fi_FI.ISO8859-1' to 'fi_FI.ISO8859-15' +# updated 'iw' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8' +# updated 'iw_il' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8' +# updated 'japanese' -> 'ja_JP.SJIS' to 'ja_JP.eucJP' +# updated 'lt' -> 'lt_LT.ISO8859-4' to 'lt_LT.ISO8859-13' +# updated 'lv' -> 'lv_LV.ISO8859-4' to 'lv_LV.ISO8859-13' +# updated 'sl' -> 'sl_CS.ISO8859-2' to 'sl_SI.ISO8859-2' +# updated 'slovene' -> 'sl_CS.ISO8859-2' to 'sl_SI.ISO8859-2' +# updated 'th_th' -> 'th_TH.TACTIS' to 'th_TH.ISO8859-11' +# updated 'zh_cn' -> 'zh_CN.eucCN' to 'zh_CN.gb2312' +# updated 'zh_cn.big5' -> 'zh_TW.eucTW' to 'zh_TW.big5' +# updated 'zh_tw' -> 'zh_TW.eucTW' to 'zh_TW.big5' +# +# MAL 2008-05-30: +# Updated alias mapping to most recent locale.alias file +# from X.org distribution using makelocalealias.py. +# +# These are the differences compared to the old mapping (Python 2.5 +# and older): +# +# updated 'cs_cs.iso88592' -> 'cs_CZ.ISO8859-2' to 'cs_CS.ISO8859-2' +# updated 'serbocroatian' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2' +# updated 'sh' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2' +# updated 'sh_hr.iso88592' -> 'sh_HR.ISO8859-2' to 'hr_HR.ISO8859-2' +# updated 'sh_sp' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2' +# updated 'sh_yu' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2' +# updated 'sp' -> 'sp_YU.ISO8859-5' to 'sr_CS.ISO8859-5' +# updated 'sp_yu' -> 'sp_YU.ISO8859-5' to 'sr_CS.ISO8859-5' +# updated 'sr' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' +# updated 'sr@cyrillic' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' +# updated 'sr_sp' -> 'sr_SP.ISO8859-2' to 'sr_CS.ISO8859-2' +# updated 'sr_yu' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' +# updated 'sr_yu.cp1251@cyrillic' -> 'sr_YU.CP1251' to 'sr_CS.CP1251' +# updated 'sr_yu.iso88592' -> 'sr_YU.ISO8859-2' to 'sr_CS.ISO8859-2' +# updated 'sr_yu.iso88595' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' +# updated 'sr_yu.iso88595@cyrillic' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' +# updated 'sr_yu.microsoftcp1251@cyrillic' -> 'sr_YU.CP1251' to 'sr_CS.CP1251' +# updated 'sr_yu.utf8@cyrillic' -> 'sr_YU.UTF-8' to 'sr_CS.UTF-8' +# updated 'sr_yu@cyrillic' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' +# +# AP 2010-04-12: +# Updated alias mapping to most recent locale.alias file +# from X.org distribution using makelocalealias.py. +# +# These are the differences compared to the old mapping (Python 2.6.5 +# and older): +# +# updated 'ru' -> 'ru_RU.ISO8859-5' to 'ru_RU.UTF-8' +# updated 'ru_ru' -> 'ru_RU.ISO8859-5' to 'ru_RU.UTF-8' +# updated 'serbocroatian' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin' +# updated 'sh' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin' +# updated 'sh_yu' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin' +# updated 'sr' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8' +# updated 'sr@cyrillic' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8' +# updated 'sr@latn' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin' +# updated 'sr_cs.utf8@latn' -> 'sr_CS.UTF-8' to 'sr_RS.UTF-8@latin' +# updated 'sr_cs@latn' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin' +# updated 'sr_yu' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8@latin' +# updated 'sr_yu.utf8@cyrillic' -> 'sr_CS.UTF-8' to 'sr_RS.UTF-8' +# updated 'sr_yu@cyrillic' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8' +# +# SS 2013-12-20: +# Updated alias mapping to most recent locale.alias file +# from X.org distribution using makelocalealias.py. +# +# These are the differences compared to the old mapping (Python 2.7.6 +# and older): +# +# updated 'a3' -> 'a3_AZ.KOI8-C' to 'az_AZ.KOI8-C' +# updated 'a3_az' -> 'a3_AZ.KOI8-C' to 'az_AZ.KOI8-C' +# updated 'a3_az.koi8c' -> 'a3_AZ.KOI8-C' to 'az_AZ.KOI8-C' +# updated 'cs_cs.iso88592' -> 'cs_CS.ISO8859-2' to 'cs_CZ.ISO8859-2' +# updated 'hebrew' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8' +# updated 'hebrew.iso88598' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8' +# updated 'sd' -> 'sd_IN@devanagari.UTF-8' to 'sd_IN.UTF-8' +# updated 'sr@latn' -> 'sr_RS.UTF-8@latin' to 'sr_CS.UTF-8@latin' +# updated 'sr_cs' -> 'sr_RS.UTF-8' to 'sr_CS.UTF-8' +# updated 'sr_cs.utf8@latn' -> 'sr_RS.UTF-8@latin' to 'sr_CS.UTF-8@latin' +# updated 'sr_cs@latn' -> 'sr_RS.UTF-8@latin' to 'sr_CS.UTF-8@latin' + +locale_alias = { + 'a3': 'az_AZ.KOI8-C', + 'a3_az': 'az_AZ.KOI8-C', + 'a3_az.koi8c': 'az_AZ.KOI8-C', + 'a3_az.koic': 'az_AZ.KOI8-C', + 'af': 'af_ZA.ISO8859-1', + 'af_za': 'af_ZA.ISO8859-1', + 'af_za.iso88591': 'af_ZA.ISO8859-1', + 'am': 'am_ET.UTF-8', + 'am_et': 'am_ET.UTF-8', + 'american': 'en_US.ISO8859-1', + 'american.iso88591': 'en_US.ISO8859-1', + 'ar': 'ar_AA.ISO8859-6', + 'ar_aa': 'ar_AA.ISO8859-6', + 'ar_aa.iso88596': 'ar_AA.ISO8859-6', + 'ar_ae': 'ar_AE.ISO8859-6', + 'ar_ae.iso88596': 'ar_AE.ISO8859-6', + 'ar_bh': 'ar_BH.ISO8859-6', + 'ar_bh.iso88596': 'ar_BH.ISO8859-6', + 'ar_dz': 'ar_DZ.ISO8859-6', + 'ar_dz.iso88596': 'ar_DZ.ISO8859-6', + 'ar_eg': 'ar_EG.ISO8859-6', + 'ar_eg.iso88596': 'ar_EG.ISO8859-6', + 'ar_in': 'ar_IN.UTF-8', + 'ar_iq': 'ar_IQ.ISO8859-6', + 'ar_iq.iso88596': 'ar_IQ.ISO8859-6', + 'ar_jo': 'ar_JO.ISO8859-6', + 'ar_jo.iso88596': 'ar_JO.ISO8859-6', + 'ar_kw': 'ar_KW.ISO8859-6', + 'ar_kw.iso88596': 'ar_KW.ISO8859-6', + 'ar_lb': 'ar_LB.ISO8859-6', + 'ar_lb.iso88596': 'ar_LB.ISO8859-6', + 'ar_ly': 'ar_LY.ISO8859-6', + 'ar_ly.iso88596': 'ar_LY.ISO8859-6', + 'ar_ma': 'ar_MA.ISO8859-6', + 'ar_ma.iso88596': 'ar_MA.ISO8859-6', + 'ar_om': 'ar_OM.ISO8859-6', + 'ar_om.iso88596': 'ar_OM.ISO8859-6', + 'ar_qa': 'ar_QA.ISO8859-6', + 'ar_qa.iso88596': 'ar_QA.ISO8859-6', + 'ar_sa': 'ar_SA.ISO8859-6', + 'ar_sa.iso88596': 'ar_SA.ISO8859-6', + 'ar_sd': 'ar_SD.ISO8859-6', + 'ar_sd.iso88596': 'ar_SD.ISO8859-6', + 'ar_sy': 'ar_SY.ISO8859-6', + 'ar_sy.iso88596': 'ar_SY.ISO8859-6', + 'ar_tn': 'ar_TN.ISO8859-6', + 'ar_tn.iso88596': 'ar_TN.ISO8859-6', + 'ar_ye': 'ar_YE.ISO8859-6', + 'ar_ye.iso88596': 'ar_YE.ISO8859-6', + 'arabic': 'ar_AA.ISO8859-6', + 'arabic.iso88596': 'ar_AA.ISO8859-6', + 'as': 'as_IN.UTF-8', + 'as_in': 'as_IN.UTF-8', + 'az': 'az_AZ.ISO8859-9E', + 'az_az': 'az_AZ.ISO8859-9E', + 'az_az.iso88599e': 'az_AZ.ISO8859-9E', + 'be': 'be_BY.CP1251', + 'be@latin': 'be_BY.UTF-8@latin', + 'be_by': 'be_BY.CP1251', + 'be_by.cp1251': 'be_BY.CP1251', + 'be_by.microsoftcp1251': 'be_BY.CP1251', + 'be_by.utf8@latin': 'be_BY.UTF-8@latin', + 'be_by@latin': 'be_BY.UTF-8@latin', + 'bg': 'bg_BG.CP1251', + 'bg_bg': 'bg_BG.CP1251', + 'bg_bg.cp1251': 'bg_BG.CP1251', + 'bg_bg.iso88595': 'bg_BG.ISO8859-5', + 'bg_bg.koi8r': 'bg_BG.KOI8-R', + 'bg_bg.microsoftcp1251': 'bg_BG.CP1251', + 'bn_in': 'bn_IN.UTF-8', + 'bo_in': 'bo_IN.UTF-8', + 'bokmal': 'nb_NO.ISO8859-1', + 'bokm\xe5l': 'nb_NO.ISO8859-1', + 'br': 'br_FR.ISO8859-1', + 'br_fr': 'br_FR.ISO8859-1', + 'br_fr.iso88591': 'br_FR.ISO8859-1', + 'br_fr.iso885914': 'br_FR.ISO8859-14', + 'br_fr.iso885915': 'br_FR.ISO8859-15', + 'br_fr.iso885915@euro': 'br_FR.ISO8859-15', + 'br_fr.utf8@euro': 'br_FR.UTF-8', + 'br_fr@euro': 'br_FR.ISO8859-15', + 'bs': 'bs_BA.ISO8859-2', + 'bs_ba': 'bs_BA.ISO8859-2', + 'bs_ba.iso88592': 'bs_BA.ISO8859-2', + 'bulgarian': 'bg_BG.CP1251', + 'c': 'C', + 'c-french': 'fr_CA.ISO8859-1', + 'c-french.iso88591': 'fr_CA.ISO8859-1', + 'c.ascii': 'C', + 'c.en': 'C', + 'c.iso88591': 'en_US.ISO8859-1', + 'c_c': 'C', + 'c_c.c': 'C', + 'ca': 'ca_ES.ISO8859-1', + 'ca_ad': 'ca_AD.ISO8859-1', + 'ca_ad.iso88591': 'ca_AD.ISO8859-1', + 'ca_ad.iso885915': 'ca_AD.ISO8859-15', + 'ca_ad.iso885915@euro': 'ca_AD.ISO8859-15', + 'ca_ad.utf8@euro': 'ca_AD.UTF-8', + 'ca_ad@euro': 'ca_AD.ISO8859-15', + 'ca_es': 'ca_ES.ISO8859-1', + 'ca_es.iso88591': 'ca_ES.ISO8859-1', + 'ca_es.iso885915': 'ca_ES.ISO8859-15', + 'ca_es.iso885915@euro': 'ca_ES.ISO8859-15', + 'ca_es.utf8@euro': 'ca_ES.UTF-8', + 'ca_es@euro': 'ca_ES.ISO8859-15', + 'ca_fr': 'ca_FR.ISO8859-1', + 'ca_fr.iso88591': 'ca_FR.ISO8859-1', + 'ca_fr.iso885915': 'ca_FR.ISO8859-15', + 'ca_fr.iso885915@euro': 'ca_FR.ISO8859-15', + 'ca_fr.utf8@euro': 'ca_FR.UTF-8', + 'ca_fr@euro': 'ca_FR.ISO8859-15', + 'ca_it': 'ca_IT.ISO8859-1', + 'ca_it.iso88591': 'ca_IT.ISO8859-1', + 'ca_it.iso885915': 'ca_IT.ISO8859-15', + 'ca_it.iso885915@euro': 'ca_IT.ISO8859-15', + 'ca_it.utf8@euro': 'ca_IT.UTF-8', + 'ca_it@euro': 'ca_IT.ISO8859-15', + 'catalan': 'ca_ES.ISO8859-1', + 'cextend': 'en_US.ISO8859-1', + 'cextend.en': 'en_US.ISO8859-1', + 'chinese-s': 'zh_CN.eucCN', + 'chinese-t': 'zh_TW.eucTW', + 'croatian': 'hr_HR.ISO8859-2', + 'cs': 'cs_CZ.ISO8859-2', + 'cs_cs': 'cs_CZ.ISO8859-2', + 'cs_cs.iso88592': 'cs_CZ.ISO8859-2', + 'cs_cz': 'cs_CZ.ISO8859-2', + 'cs_cz.iso88592': 'cs_CZ.ISO8859-2', + 'cy': 'cy_GB.ISO8859-1', + 'cy_gb': 'cy_GB.ISO8859-1', + 'cy_gb.iso88591': 'cy_GB.ISO8859-1', + 'cy_gb.iso885914': 'cy_GB.ISO8859-14', + 'cy_gb.iso885915': 'cy_GB.ISO8859-15', + 'cy_gb@euro': 'cy_GB.ISO8859-15', + 'cz': 'cs_CZ.ISO8859-2', + 'cz_cz': 'cs_CZ.ISO8859-2', + 'czech': 'cs_CZ.ISO8859-2', + 'da': 'da_DK.ISO8859-1', + 'da.iso885915': 'da_DK.ISO8859-15', + 'da_dk': 'da_DK.ISO8859-1', + 'da_dk.88591': 'da_DK.ISO8859-1', + 'da_dk.885915': 'da_DK.ISO8859-15', + 'da_dk.iso88591': 'da_DK.ISO8859-1', + 'da_dk.iso885915': 'da_DK.ISO8859-15', + 'da_dk@euro': 'da_DK.ISO8859-15', + 'danish': 'da_DK.ISO8859-1', + 'danish.iso88591': 'da_DK.ISO8859-1', + 'dansk': 'da_DK.ISO8859-1', + 'de': 'de_DE.ISO8859-1', + 'de.iso885915': 'de_DE.ISO8859-15', + 'de_at': 'de_AT.ISO8859-1', + 'de_at.iso88591': 'de_AT.ISO8859-1', + 'de_at.iso885915': 'de_AT.ISO8859-15', + 'de_at.iso885915@euro': 'de_AT.ISO8859-15', + 'de_at.utf8@euro': 'de_AT.UTF-8', + 'de_at@euro': 'de_AT.ISO8859-15', + 'de_be': 'de_BE.ISO8859-1', + 'de_be.iso88591': 'de_BE.ISO8859-1', + 'de_be.iso885915': 'de_BE.ISO8859-15', + 'de_be.iso885915@euro': 'de_BE.ISO8859-15', + 'de_be.utf8@euro': 'de_BE.UTF-8', + 'de_be@euro': 'de_BE.ISO8859-15', + 'de_ch': 'de_CH.ISO8859-1', + 'de_ch.iso88591': 'de_CH.ISO8859-1', + 'de_ch.iso885915': 'de_CH.ISO8859-15', + 'de_ch@euro': 'de_CH.ISO8859-15', + 'de_de': 'de_DE.ISO8859-1', + 'de_de.88591': 'de_DE.ISO8859-1', + 'de_de.885915': 'de_DE.ISO8859-15', + 'de_de.885915@euro': 'de_DE.ISO8859-15', + 'de_de.iso88591': 'de_DE.ISO8859-1', + 'de_de.iso885915': 'de_DE.ISO8859-15', + 'de_de.iso885915@euro': 'de_DE.ISO8859-15', + 'de_de.utf8@euro': 'de_DE.UTF-8', + 'de_de@euro': 'de_DE.ISO8859-15', + 'de_lu': 'de_LU.ISO8859-1', + 'de_lu.iso88591': 'de_LU.ISO8859-1', + 'de_lu.iso885915': 'de_LU.ISO8859-15', + 'de_lu.iso885915@euro': 'de_LU.ISO8859-15', + 'de_lu.utf8@euro': 'de_LU.UTF-8', + 'de_lu@euro': 'de_LU.ISO8859-15', + 'deutsch': 'de_DE.ISO8859-1', + 'dutch': 'nl_NL.ISO8859-1', + 'dutch.iso88591': 'nl_BE.ISO8859-1', + 'ee': 'ee_EE.ISO8859-4', + 'ee_ee': 'ee_EE.ISO8859-4', + 'ee_ee.iso88594': 'ee_EE.ISO8859-4', + 'eesti': 'et_EE.ISO8859-1', + 'el': 'el_GR.ISO8859-7', + 'el_gr': 'el_GR.ISO8859-7', + 'el_gr.iso88597': 'el_GR.ISO8859-7', + 'el_gr@euro': 'el_GR.ISO8859-15', + 'en': 'en_US.ISO8859-1', + 'en.iso88591': 'en_US.ISO8859-1', + 'en_au': 'en_AU.ISO8859-1', + 'en_au.iso88591': 'en_AU.ISO8859-1', + 'en_be': 'en_BE.ISO8859-1', + 'en_be@euro': 'en_BE.ISO8859-15', + 'en_bw': 'en_BW.ISO8859-1', + 'en_bw.iso88591': 'en_BW.ISO8859-1', + 'en_ca': 'en_CA.ISO8859-1', + 'en_ca.iso88591': 'en_CA.ISO8859-1', + 'en_gb': 'en_GB.ISO8859-1', + 'en_gb.88591': 'en_GB.ISO8859-1', + 'en_gb.iso88591': 'en_GB.ISO8859-1', + 'en_gb.iso885915': 'en_GB.ISO8859-15', + 'en_gb@euro': 'en_GB.ISO8859-15', + 'en_hk': 'en_HK.ISO8859-1', + 'en_hk.iso88591': 'en_HK.ISO8859-1', + 'en_ie': 'en_IE.ISO8859-1', + 'en_ie.iso88591': 'en_IE.ISO8859-1', + 'en_ie.iso885915': 'en_IE.ISO8859-15', + 'en_ie.iso885915@euro': 'en_IE.ISO8859-15', + 'en_ie.utf8@euro': 'en_IE.UTF-8', + 'en_ie@euro': 'en_IE.ISO8859-15', + 'en_in': 'en_IN.ISO8859-1', + 'en_nz': 'en_NZ.ISO8859-1', + 'en_nz.iso88591': 'en_NZ.ISO8859-1', + 'en_ph': 'en_PH.ISO8859-1', + 'en_ph.iso88591': 'en_PH.ISO8859-1', + 'en_sg': 'en_SG.ISO8859-1', + 'en_sg.iso88591': 'en_SG.ISO8859-1', + 'en_uk': 'en_GB.ISO8859-1', + 'en_us': 'en_US.ISO8859-1', + 'en_us.88591': 'en_US.ISO8859-1', + 'en_us.885915': 'en_US.ISO8859-15', + 'en_us.iso88591': 'en_US.ISO8859-1', + 'en_us.iso885915': 'en_US.ISO8859-15', + 'en_us.iso885915@euro': 'en_US.ISO8859-15', + 'en_us@euro': 'en_US.ISO8859-15', + 'en_us@euro@euro': 'en_US.ISO8859-15', + 'en_za': 'en_ZA.ISO8859-1', + 'en_za.88591': 'en_ZA.ISO8859-1', + 'en_za.iso88591': 'en_ZA.ISO8859-1', + 'en_za.iso885915': 'en_ZA.ISO8859-15', + 'en_za@euro': 'en_ZA.ISO8859-15', + 'en_zw': 'en_ZW.ISO8859-1', + 'en_zw.iso88591': 'en_ZW.ISO8859-1', + 'eng_gb': 'en_GB.ISO8859-1', + 'eng_gb.8859': 'en_GB.ISO8859-1', + 'english': 'en_EN.ISO8859-1', + 'english.iso88591': 'en_EN.ISO8859-1', + 'english_uk': 'en_GB.ISO8859-1', + 'english_uk.8859': 'en_GB.ISO8859-1', + 'english_united-states': 'en_US.ISO8859-1', + 'english_united-states.437': 'C', + 'english_us': 'en_US.ISO8859-1', + 'english_us.8859': 'en_US.ISO8859-1', + 'english_us.ascii': 'en_US.ISO8859-1', + 'eo': 'eo_XX.ISO8859-3', + 'eo_eo': 'eo_EO.ISO8859-3', + 'eo_eo.iso88593': 'eo_EO.ISO8859-3', + 'eo_xx': 'eo_XX.ISO8859-3', + 'eo_xx.iso88593': 'eo_XX.ISO8859-3', + 'es': 'es_ES.ISO8859-1', + 'es_ar': 'es_AR.ISO8859-1', + 'es_ar.iso88591': 'es_AR.ISO8859-1', + 'es_bo': 'es_BO.ISO8859-1', + 'es_bo.iso88591': 'es_BO.ISO8859-1', + 'es_cl': 'es_CL.ISO8859-1', + 'es_cl.iso88591': 'es_CL.ISO8859-1', + 'es_co': 'es_CO.ISO8859-1', + 'es_co.iso88591': 'es_CO.ISO8859-1', + 'es_cr': 'es_CR.ISO8859-1', + 'es_cr.iso88591': 'es_CR.ISO8859-1', + 'es_do': 'es_DO.ISO8859-1', + 'es_do.iso88591': 'es_DO.ISO8859-1', + 'es_ec': 'es_EC.ISO8859-1', + 'es_ec.iso88591': 'es_EC.ISO8859-1', + 'es_es': 'es_ES.ISO8859-1', + 'es_es.88591': 'es_ES.ISO8859-1', + 'es_es.iso88591': 'es_ES.ISO8859-1', + 'es_es.iso885915': 'es_ES.ISO8859-15', + 'es_es.iso885915@euro': 'es_ES.ISO8859-15', + 'es_es.utf8@euro': 'es_ES.UTF-8', + 'es_es@euro': 'es_ES.ISO8859-15', + 'es_gt': 'es_GT.ISO8859-1', + 'es_gt.iso88591': 'es_GT.ISO8859-1', + 'es_hn': 'es_HN.ISO8859-1', + 'es_hn.iso88591': 'es_HN.ISO8859-1', + 'es_mx': 'es_MX.ISO8859-1', + 'es_mx.iso88591': 'es_MX.ISO8859-1', + 'es_ni': 'es_NI.ISO8859-1', + 'es_ni.iso88591': 'es_NI.ISO8859-1', + 'es_pa': 'es_PA.ISO8859-1', + 'es_pa.iso88591': 'es_PA.ISO8859-1', + 'es_pa.iso885915': 'es_PA.ISO8859-15', + 'es_pa@euro': 'es_PA.ISO8859-15', + 'es_pe': 'es_PE.ISO8859-1', + 'es_pe.iso88591': 'es_PE.ISO8859-1', + 'es_pe.iso885915': 'es_PE.ISO8859-15', + 'es_pe@euro': 'es_PE.ISO8859-15', + 'es_pr': 'es_PR.ISO8859-1', + 'es_pr.iso88591': 'es_PR.ISO8859-1', + 'es_py': 'es_PY.ISO8859-1', + 'es_py.iso88591': 'es_PY.ISO8859-1', + 'es_py.iso885915': 'es_PY.ISO8859-15', + 'es_py@euro': 'es_PY.ISO8859-15', + 'es_sv': 'es_SV.ISO8859-1', + 'es_sv.iso88591': 'es_SV.ISO8859-1', + 'es_sv.iso885915': 'es_SV.ISO8859-15', + 'es_sv@euro': 'es_SV.ISO8859-15', + 'es_us': 'es_US.ISO8859-1', + 'es_us.iso88591': 'es_US.ISO8859-1', + 'es_uy': 'es_UY.ISO8859-1', + 'es_uy.iso88591': 'es_UY.ISO8859-1', + 'es_uy.iso885915': 'es_UY.ISO8859-15', + 'es_uy@euro': 'es_UY.ISO8859-15', + 'es_ve': 'es_VE.ISO8859-1', + 'es_ve.iso88591': 'es_VE.ISO8859-1', + 'es_ve.iso885915': 'es_VE.ISO8859-15', + 'es_ve@euro': 'es_VE.ISO8859-15', + 'estonian': 'et_EE.ISO8859-1', + 'et': 'et_EE.ISO8859-15', + 'et_ee': 'et_EE.ISO8859-15', + 'et_ee.iso88591': 'et_EE.ISO8859-1', + 'et_ee.iso885913': 'et_EE.ISO8859-13', + 'et_ee.iso885915': 'et_EE.ISO8859-15', + 'et_ee.iso88594': 'et_EE.ISO8859-4', + 'et_ee@euro': 'et_EE.ISO8859-15', + 'eu': 'eu_ES.ISO8859-1', + 'eu_es': 'eu_ES.ISO8859-1', + 'eu_es.iso88591': 'eu_ES.ISO8859-1', + 'eu_es.iso885915': 'eu_ES.ISO8859-15', + 'eu_es.iso885915@euro': 'eu_ES.ISO8859-15', + 'eu_es.utf8@euro': 'eu_ES.UTF-8', + 'eu_es@euro': 'eu_ES.ISO8859-15', + 'fa': 'fa_IR.UTF-8', + 'fa_ir': 'fa_IR.UTF-8', + 'fa_ir.isiri3342': 'fa_IR.ISIRI-3342', + 'fi': 'fi_FI.ISO8859-15', + 'fi.iso885915': 'fi_FI.ISO8859-15', + 'fi_fi': 'fi_FI.ISO8859-15', + 'fi_fi.88591': 'fi_FI.ISO8859-1', + 'fi_fi.iso88591': 'fi_FI.ISO8859-1', + 'fi_fi.iso885915': 'fi_FI.ISO8859-15', + 'fi_fi.iso885915@euro': 'fi_FI.ISO8859-15', + 'fi_fi.utf8@euro': 'fi_FI.UTF-8', + 'fi_fi@euro': 'fi_FI.ISO8859-15', + 'finnish': 'fi_FI.ISO8859-1', + 'finnish.iso88591': 'fi_FI.ISO8859-1', + 'fo': 'fo_FO.ISO8859-1', + 'fo_fo': 'fo_FO.ISO8859-1', + 'fo_fo.iso88591': 'fo_FO.ISO8859-1', + 'fo_fo.iso885915': 'fo_FO.ISO8859-15', + 'fo_fo@euro': 'fo_FO.ISO8859-15', + 'fr': 'fr_FR.ISO8859-1', + 'fr.iso885915': 'fr_FR.ISO8859-15', + 'fr_be': 'fr_BE.ISO8859-1', + 'fr_be.88591': 'fr_BE.ISO8859-1', + 'fr_be.iso88591': 'fr_BE.ISO8859-1', + 'fr_be.iso885915': 'fr_BE.ISO8859-15', + 'fr_be.iso885915@euro': 'fr_BE.ISO8859-15', + 'fr_be.utf8@euro': 'fr_BE.UTF-8', + 'fr_be@euro': 'fr_BE.ISO8859-15', + 'fr_ca': 'fr_CA.ISO8859-1', + 'fr_ca.88591': 'fr_CA.ISO8859-1', + 'fr_ca.iso88591': 'fr_CA.ISO8859-1', + 'fr_ca.iso885915': 'fr_CA.ISO8859-15', + 'fr_ca@euro': 'fr_CA.ISO8859-15', + 'fr_ch': 'fr_CH.ISO8859-1', + 'fr_ch.88591': 'fr_CH.ISO8859-1', + 'fr_ch.iso88591': 'fr_CH.ISO8859-1', + 'fr_ch.iso885915': 'fr_CH.ISO8859-15', + 'fr_ch@euro': 'fr_CH.ISO8859-15', + 'fr_fr': 'fr_FR.ISO8859-1', + 'fr_fr.88591': 'fr_FR.ISO8859-1', + 'fr_fr.iso88591': 'fr_FR.ISO8859-1', + 'fr_fr.iso885915': 'fr_FR.ISO8859-15', + 'fr_fr.iso885915@euro': 'fr_FR.ISO8859-15', + 'fr_fr.utf8@euro': 'fr_FR.UTF-8', + 'fr_fr@euro': 'fr_FR.ISO8859-15', + 'fr_lu': 'fr_LU.ISO8859-1', + 'fr_lu.88591': 'fr_LU.ISO8859-1', + 'fr_lu.iso88591': 'fr_LU.ISO8859-1', + 'fr_lu.iso885915': 'fr_LU.ISO8859-15', + 'fr_lu.iso885915@euro': 'fr_LU.ISO8859-15', + 'fr_lu.utf8@euro': 'fr_LU.UTF-8', + 'fr_lu@euro': 'fr_LU.ISO8859-15', + 'fran\xe7ais': 'fr_FR.ISO8859-1', + 'fre_fr': 'fr_FR.ISO8859-1', + 'fre_fr.8859': 'fr_FR.ISO8859-1', + 'french': 'fr_FR.ISO8859-1', + 'french.iso88591': 'fr_CH.ISO8859-1', + 'french_france': 'fr_FR.ISO8859-1', + 'french_france.8859': 'fr_FR.ISO8859-1', + 'ga': 'ga_IE.ISO8859-1', + 'ga_ie': 'ga_IE.ISO8859-1', + 'ga_ie.iso88591': 'ga_IE.ISO8859-1', + 'ga_ie.iso885914': 'ga_IE.ISO8859-14', + 'ga_ie.iso885915': 'ga_IE.ISO8859-15', + 'ga_ie.iso885915@euro': 'ga_IE.ISO8859-15', + 'ga_ie.utf8@euro': 'ga_IE.UTF-8', + 'ga_ie@euro': 'ga_IE.ISO8859-15', + 'galego': 'gl_ES.ISO8859-1', + 'galician': 'gl_ES.ISO8859-1', + 'gd': 'gd_GB.ISO8859-1', + 'gd_gb': 'gd_GB.ISO8859-1', + 'gd_gb.iso88591': 'gd_GB.ISO8859-1', + 'gd_gb.iso885914': 'gd_GB.ISO8859-14', + 'gd_gb.iso885915': 'gd_GB.ISO8859-15', + 'gd_gb@euro': 'gd_GB.ISO8859-15', + 'ger_de': 'de_DE.ISO8859-1', + 'ger_de.8859': 'de_DE.ISO8859-1', + 'german': 'de_DE.ISO8859-1', + 'german.iso88591': 'de_CH.ISO8859-1', + 'german_germany': 'de_DE.ISO8859-1', + 'german_germany.8859': 'de_DE.ISO8859-1', + 'gl': 'gl_ES.ISO8859-1', + 'gl_es': 'gl_ES.ISO8859-1', + 'gl_es.iso88591': 'gl_ES.ISO8859-1', + 'gl_es.iso885915': 'gl_ES.ISO8859-15', + 'gl_es.iso885915@euro': 'gl_ES.ISO8859-15', + 'gl_es.utf8@euro': 'gl_ES.UTF-8', + 'gl_es@euro': 'gl_ES.ISO8859-15', + 'greek': 'el_GR.ISO8859-7', + 'greek.iso88597': 'el_GR.ISO8859-7', + 'gu_in': 'gu_IN.UTF-8', + 'gv': 'gv_GB.ISO8859-1', + 'gv_gb': 'gv_GB.ISO8859-1', + 'gv_gb.iso88591': 'gv_GB.ISO8859-1', + 'gv_gb.iso885914': 'gv_GB.ISO8859-14', + 'gv_gb.iso885915': 'gv_GB.ISO8859-15', + 'gv_gb@euro': 'gv_GB.ISO8859-15', + 'he': 'he_IL.ISO8859-8', + 'he_il': 'he_IL.ISO8859-8', + 'he_il.cp1255': 'he_IL.CP1255', + 'he_il.iso88598': 'he_IL.ISO8859-8', + 'he_il.microsoftcp1255': 'he_IL.CP1255', + 'hebrew': 'he_IL.ISO8859-8', + 'hebrew.iso88598': 'he_IL.ISO8859-8', + 'hi': 'hi_IN.ISCII-DEV', + 'hi_in': 'hi_IN.ISCII-DEV', + 'hi_in.isciidev': 'hi_IN.ISCII-DEV', + 'hne': 'hne_IN.UTF-8', + 'hne_in': 'hne_IN.UTF-8', + 'hr': 'hr_HR.ISO8859-2', + 'hr_hr': 'hr_HR.ISO8859-2', + 'hr_hr.iso88592': 'hr_HR.ISO8859-2', + 'hrvatski': 'hr_HR.ISO8859-2', + 'hu': 'hu_HU.ISO8859-2', + 'hu_hu': 'hu_HU.ISO8859-2', + 'hu_hu.iso88592': 'hu_HU.ISO8859-2', + 'hungarian': 'hu_HU.ISO8859-2', + 'icelandic': 'is_IS.ISO8859-1', + 'icelandic.iso88591': 'is_IS.ISO8859-1', + 'id': 'id_ID.ISO8859-1', + 'id_id': 'id_ID.ISO8859-1', + 'in': 'id_ID.ISO8859-1', + 'in_id': 'id_ID.ISO8859-1', + 'is': 'is_IS.ISO8859-1', + 'is_is': 'is_IS.ISO8859-1', + 'is_is.iso88591': 'is_IS.ISO8859-1', + 'is_is.iso885915': 'is_IS.ISO8859-15', + 'is_is@euro': 'is_IS.ISO8859-15', + 'iso-8859-1': 'en_US.ISO8859-1', + 'iso-8859-15': 'en_US.ISO8859-15', + 'iso8859-1': 'en_US.ISO8859-1', + 'iso8859-15': 'en_US.ISO8859-15', + 'iso_8859_1': 'en_US.ISO8859-1', + 'iso_8859_15': 'en_US.ISO8859-15', + 'it': 'it_IT.ISO8859-1', + 'it.iso885915': 'it_IT.ISO8859-15', + 'it_ch': 'it_CH.ISO8859-1', + 'it_ch.iso88591': 'it_CH.ISO8859-1', + 'it_ch.iso885915': 'it_CH.ISO8859-15', + 'it_ch@euro': 'it_CH.ISO8859-15', + 'it_it': 'it_IT.ISO8859-1', + 'it_it.88591': 'it_IT.ISO8859-1', + 'it_it.iso88591': 'it_IT.ISO8859-1', + 'it_it.iso885915': 'it_IT.ISO8859-15', + 'it_it.iso885915@euro': 'it_IT.ISO8859-15', + 'it_it.utf8@euro': 'it_IT.UTF-8', + 'it_it@euro': 'it_IT.ISO8859-15', + 'italian': 'it_IT.ISO8859-1', + 'italian.iso88591': 'it_IT.ISO8859-1', + 'iu': 'iu_CA.NUNACOM-8', + 'iu_ca': 'iu_CA.NUNACOM-8', + 'iu_ca.nunacom8': 'iu_CA.NUNACOM-8', + 'iw': 'he_IL.ISO8859-8', + 'iw_il': 'he_IL.ISO8859-8', + 'iw_il.iso88598': 'he_IL.ISO8859-8', + 'ja': 'ja_JP.eucJP', + 'ja.jis': 'ja_JP.JIS7', + 'ja.sjis': 'ja_JP.SJIS', + 'ja_jp': 'ja_JP.eucJP', + 'ja_jp.ajec': 'ja_JP.eucJP', + 'ja_jp.euc': 'ja_JP.eucJP', + 'ja_jp.eucjp': 'ja_JP.eucJP', + 'ja_jp.iso-2022-jp': 'ja_JP.JIS7', + 'ja_jp.iso2022jp': 'ja_JP.JIS7', + 'ja_jp.jis': 'ja_JP.JIS7', + 'ja_jp.jis7': 'ja_JP.JIS7', + 'ja_jp.mscode': 'ja_JP.SJIS', + 'ja_jp.pck': 'ja_JP.SJIS', + 'ja_jp.sjis': 'ja_JP.SJIS', + 'ja_jp.ujis': 'ja_JP.eucJP', + 'japan': 'ja_JP.eucJP', + 'japanese': 'ja_JP.eucJP', + 'japanese-euc': 'ja_JP.eucJP', + 'japanese.euc': 'ja_JP.eucJP', + 'japanese.sjis': 'ja_JP.SJIS', + 'jp_jp': 'ja_JP.eucJP', + 'ka': 'ka_GE.GEORGIAN-ACADEMY', + 'ka_ge': 'ka_GE.GEORGIAN-ACADEMY', + 'ka_ge.georgianacademy': 'ka_GE.GEORGIAN-ACADEMY', + 'ka_ge.georgianps': 'ka_GE.GEORGIAN-PS', + 'ka_ge.georgianrs': 'ka_GE.GEORGIAN-ACADEMY', + 'kl': 'kl_GL.ISO8859-1', + 'kl_gl': 'kl_GL.ISO8859-1', + 'kl_gl.iso88591': 'kl_GL.ISO8859-1', + 'kl_gl.iso885915': 'kl_GL.ISO8859-15', + 'kl_gl@euro': 'kl_GL.ISO8859-15', + 'km_kh': 'km_KH.UTF-8', + 'kn': 'kn_IN.UTF-8', + 'kn_in': 'kn_IN.UTF-8', + 'ko': 'ko_KR.eucKR', + 'ko_kr': 'ko_KR.eucKR', + 'ko_kr.euc': 'ko_KR.eucKR', + 'ko_kr.euckr': 'ko_KR.eucKR', + 'korean': 'ko_KR.eucKR', + 'korean.euc': 'ko_KR.eucKR', + 'ks': 'ks_IN.UTF-8', + 'ks_in': 'ks_IN.UTF-8', + 'ks_in@devanagari': 'ks_IN.UTF-8@devanagari', + 'kw': 'kw_GB.ISO8859-1', + 'kw_gb': 'kw_GB.ISO8859-1', + 'kw_gb.iso88591': 'kw_GB.ISO8859-1', + 'kw_gb.iso885914': 'kw_GB.ISO8859-14', + 'kw_gb.iso885915': 'kw_GB.ISO8859-15', + 'kw_gb@euro': 'kw_GB.ISO8859-15', + 'ky': 'ky_KG.UTF-8', + 'ky_kg': 'ky_KG.UTF-8', + 'lithuanian': 'lt_LT.ISO8859-13', + 'lo': 'lo_LA.MULELAO-1', + 'lo_la': 'lo_LA.MULELAO-1', + 'lo_la.cp1133': 'lo_LA.IBM-CP1133', + 'lo_la.ibmcp1133': 'lo_LA.IBM-CP1133', + 'lo_la.mulelao1': 'lo_LA.MULELAO-1', + 'lt': 'lt_LT.ISO8859-13', + 'lt_lt': 'lt_LT.ISO8859-13', + 'lt_lt.iso885913': 'lt_LT.ISO8859-13', + 'lt_lt.iso88594': 'lt_LT.ISO8859-4', + 'lv': 'lv_LV.ISO8859-13', + 'lv_lv': 'lv_LV.ISO8859-13', + 'lv_lv.iso885913': 'lv_LV.ISO8859-13', + 'lv_lv.iso88594': 'lv_LV.ISO8859-4', + 'mai': 'mai_IN.UTF-8', + 'mai_in': 'mai_IN.UTF-8', + 'mi': 'mi_NZ.ISO8859-1', + 'mi_nz': 'mi_NZ.ISO8859-1', + 'mi_nz.iso88591': 'mi_NZ.ISO8859-1', + 'mk': 'mk_MK.ISO8859-5', + 'mk_mk': 'mk_MK.ISO8859-5', + 'mk_mk.cp1251': 'mk_MK.CP1251', + 'mk_mk.iso88595': 'mk_MK.ISO8859-5', + 'mk_mk.microsoftcp1251': 'mk_MK.CP1251', + 'ml': 'ml_IN.UTF-8', + 'ml_in': 'ml_IN.UTF-8', + 'mr': 'mr_IN.UTF-8', + 'mr_in': 'mr_IN.UTF-8', + 'ms': 'ms_MY.ISO8859-1', + 'ms_my': 'ms_MY.ISO8859-1', + 'ms_my.iso88591': 'ms_MY.ISO8859-1', + 'mt': 'mt_MT.ISO8859-3', + 'mt_mt': 'mt_MT.ISO8859-3', + 'mt_mt.iso88593': 'mt_MT.ISO8859-3', + 'nb': 'nb_NO.ISO8859-1', + 'nb_no': 'nb_NO.ISO8859-1', + 'nb_no.88591': 'nb_NO.ISO8859-1', + 'nb_no.iso88591': 'nb_NO.ISO8859-1', + 'nb_no.iso885915': 'nb_NO.ISO8859-15', + 'nb_no@euro': 'nb_NO.ISO8859-15', + 'ne_np': 'ne_NP.UTF-8', + 'nl': 'nl_NL.ISO8859-1', + 'nl.iso885915': 'nl_NL.ISO8859-15', + 'nl_be': 'nl_BE.ISO8859-1', + 'nl_be.88591': 'nl_BE.ISO8859-1', + 'nl_be.iso88591': 'nl_BE.ISO8859-1', + 'nl_be.iso885915': 'nl_BE.ISO8859-15', + 'nl_be.iso885915@euro': 'nl_BE.ISO8859-15', + 'nl_be.utf8@euro': 'nl_BE.UTF-8', + 'nl_be@euro': 'nl_BE.ISO8859-15', + 'nl_nl': 'nl_NL.ISO8859-1', + 'nl_nl.88591': 'nl_NL.ISO8859-1', + 'nl_nl.iso88591': 'nl_NL.ISO8859-1', + 'nl_nl.iso885915': 'nl_NL.ISO8859-15', + 'nl_nl.iso885915@euro': 'nl_NL.ISO8859-15', + 'nl_nl.utf8@euro': 'nl_NL.UTF-8', + 'nl_nl@euro': 'nl_NL.ISO8859-15', + 'nn': 'nn_NO.ISO8859-1', + 'nn_no': 'nn_NO.ISO8859-1', + 'nn_no.88591': 'nn_NO.ISO8859-1', + 'nn_no.iso88591': 'nn_NO.ISO8859-1', + 'nn_no.iso885915': 'nn_NO.ISO8859-15', + 'nn_no@euro': 'nn_NO.ISO8859-15', + 'no': 'no_NO.ISO8859-1', + 'no@nynorsk': 'ny_NO.ISO8859-1', + 'no_no': 'no_NO.ISO8859-1', + 'no_no.88591': 'no_NO.ISO8859-1', + 'no_no.iso88591': 'no_NO.ISO8859-1', + 'no_no.iso885915': 'no_NO.ISO8859-15', + 'no_no.iso88591@bokmal': 'no_NO.ISO8859-1', + 'no_no.iso88591@nynorsk': 'no_NO.ISO8859-1', + 'no_no@euro': 'no_NO.ISO8859-15', + 'norwegian': 'no_NO.ISO8859-1', + 'norwegian.iso88591': 'no_NO.ISO8859-1', + 'nr': 'nr_ZA.ISO8859-1', + 'nr_za': 'nr_ZA.ISO8859-1', + 'nr_za.iso88591': 'nr_ZA.ISO8859-1', + 'nso': 'nso_ZA.ISO8859-15', + 'nso_za': 'nso_ZA.ISO8859-15', + 'nso_za.iso885915': 'nso_ZA.ISO8859-15', + 'ny': 'ny_NO.ISO8859-1', + 'ny_no': 'ny_NO.ISO8859-1', + 'ny_no.88591': 'ny_NO.ISO8859-1', + 'ny_no.iso88591': 'ny_NO.ISO8859-1', + 'ny_no.iso885915': 'ny_NO.ISO8859-15', + 'ny_no@euro': 'ny_NO.ISO8859-15', + 'nynorsk': 'nn_NO.ISO8859-1', + 'oc': 'oc_FR.ISO8859-1', + 'oc_fr': 'oc_FR.ISO8859-1', + 'oc_fr.iso88591': 'oc_FR.ISO8859-1', + 'oc_fr.iso885915': 'oc_FR.ISO8859-15', + 'oc_fr@euro': 'oc_FR.ISO8859-15', + 'or': 'or_IN.UTF-8', + 'or_in': 'or_IN.UTF-8', + 'pa': 'pa_IN.UTF-8', + 'pa_in': 'pa_IN.UTF-8', + 'pd': 'pd_US.ISO8859-1', + 'pd_de': 'pd_DE.ISO8859-1', + 'pd_de.iso88591': 'pd_DE.ISO8859-1', + 'pd_de.iso885915': 'pd_DE.ISO8859-15', + 'pd_de@euro': 'pd_DE.ISO8859-15', + 'pd_us': 'pd_US.ISO8859-1', + 'pd_us.iso88591': 'pd_US.ISO8859-1', + 'pd_us.iso885915': 'pd_US.ISO8859-15', + 'pd_us@euro': 'pd_US.ISO8859-15', + 'ph': 'ph_PH.ISO8859-1', + 'ph_ph': 'ph_PH.ISO8859-1', + 'ph_ph.iso88591': 'ph_PH.ISO8859-1', + 'pl': 'pl_PL.ISO8859-2', + 'pl_pl': 'pl_PL.ISO8859-2', + 'pl_pl.iso88592': 'pl_PL.ISO8859-2', + 'polish': 'pl_PL.ISO8859-2', + 'portuguese': 'pt_PT.ISO8859-1', + 'portuguese.iso88591': 'pt_PT.ISO8859-1', + 'portuguese_brazil': 'pt_BR.ISO8859-1', + 'portuguese_brazil.8859': 'pt_BR.ISO8859-1', + 'posix': 'C', + 'posix-utf2': 'C', + 'pp': 'pp_AN.ISO8859-1', + 'pp_an': 'pp_AN.ISO8859-1', + 'pp_an.iso88591': 'pp_AN.ISO8859-1', + 'pt': 'pt_PT.ISO8859-1', + 'pt.iso885915': 'pt_PT.ISO8859-15', + 'pt_br': 'pt_BR.ISO8859-1', + 'pt_br.88591': 'pt_BR.ISO8859-1', + 'pt_br.iso88591': 'pt_BR.ISO8859-1', + 'pt_br.iso885915': 'pt_BR.ISO8859-15', + 'pt_br@euro': 'pt_BR.ISO8859-15', + 'pt_pt': 'pt_PT.ISO8859-1', + 'pt_pt.88591': 'pt_PT.ISO8859-1', + 'pt_pt.iso88591': 'pt_PT.ISO8859-1', + 'pt_pt.iso885915': 'pt_PT.ISO8859-15', + 'pt_pt.iso885915@euro': 'pt_PT.ISO8859-15', + 'pt_pt.utf8@euro': 'pt_PT.UTF-8', + 'pt_pt@euro': 'pt_PT.ISO8859-15', + 'ro': 'ro_RO.ISO8859-2', + 'ro_ro': 'ro_RO.ISO8859-2', + 'ro_ro.iso88592': 'ro_RO.ISO8859-2', + 'romanian': 'ro_RO.ISO8859-2', + 'ru': 'ru_RU.UTF-8', + 'ru.koi8r': 'ru_RU.KOI8-R', + 'ru_ru': 'ru_RU.UTF-8', + 'ru_ru.cp1251': 'ru_RU.CP1251', + 'ru_ru.iso88595': 'ru_RU.ISO8859-5', + 'ru_ru.koi8r': 'ru_RU.KOI8-R', + 'ru_ru.microsoftcp1251': 'ru_RU.CP1251', + 'ru_ua': 'ru_UA.KOI8-U', + 'ru_ua.cp1251': 'ru_UA.CP1251', + 'ru_ua.koi8u': 'ru_UA.KOI8-U', + 'ru_ua.microsoftcp1251': 'ru_UA.CP1251', + 'rumanian': 'ro_RO.ISO8859-2', + 'russian': 'ru_RU.ISO8859-5', + 'rw': 'rw_RW.ISO8859-1', + 'rw_rw': 'rw_RW.ISO8859-1', + 'rw_rw.iso88591': 'rw_RW.ISO8859-1', + 'sd': 'sd_IN.UTF-8', + 'sd@devanagari': 'sd_IN.UTF-8@devanagari', + 'sd_in': 'sd_IN.UTF-8', + 'sd_in@devanagari': 'sd_IN.UTF-8@devanagari', + 'se_no': 'se_NO.UTF-8', + 'serbocroatian': 'sr_RS.UTF-8@latin', + 'sh': 'sr_RS.UTF-8@latin', + 'sh_ba.iso88592@bosnia': 'sr_CS.ISO8859-2', + 'sh_hr': 'sh_HR.ISO8859-2', + 'sh_hr.iso88592': 'hr_HR.ISO8859-2', + 'sh_sp': 'sr_CS.ISO8859-2', + 'sh_yu': 'sr_RS.UTF-8@latin', + 'si': 'si_LK.UTF-8', + 'si_lk': 'si_LK.UTF-8', + 'sinhala': 'si_LK.UTF-8', + 'sk': 'sk_SK.ISO8859-2', + 'sk_sk': 'sk_SK.ISO8859-2', + 'sk_sk.iso88592': 'sk_SK.ISO8859-2', + 'sl': 'sl_SI.ISO8859-2', + 'sl_cs': 'sl_CS.ISO8859-2', + 'sl_si': 'sl_SI.ISO8859-2', + 'sl_si.iso88592': 'sl_SI.ISO8859-2', + 'slovak': 'sk_SK.ISO8859-2', + 'slovene': 'sl_SI.ISO8859-2', + 'slovenian': 'sl_SI.ISO8859-2', + 'sp': 'sr_CS.ISO8859-5', + 'sp_yu': 'sr_CS.ISO8859-5', + 'spanish': 'es_ES.ISO8859-1', + 'spanish.iso88591': 'es_ES.ISO8859-1', + 'spanish_spain': 'es_ES.ISO8859-1', + 'spanish_spain.8859': 'es_ES.ISO8859-1', + 'sq': 'sq_AL.ISO8859-2', + 'sq_al': 'sq_AL.ISO8859-2', + 'sq_al.iso88592': 'sq_AL.ISO8859-2', + 'sr': 'sr_RS.UTF-8', + 'sr@cyrillic': 'sr_RS.UTF-8', + 'sr@latin': 'sr_RS.UTF-8@latin', + 'sr@latn': 'sr_CS.UTF-8@latin', + 'sr_cs': 'sr_CS.UTF-8', + 'sr_cs.iso88592': 'sr_CS.ISO8859-2', + 'sr_cs.iso88592@latn': 'sr_CS.ISO8859-2', + 'sr_cs.iso88595': 'sr_CS.ISO8859-5', + 'sr_cs.utf8@latn': 'sr_CS.UTF-8@latin', + 'sr_cs@latn': 'sr_CS.UTF-8@latin', + 'sr_me': 'sr_ME.UTF-8', + 'sr_rs': 'sr_RS.UTF-8', + 'sr_rs.utf8@latn': 'sr_RS.UTF-8@latin', + 'sr_rs@latin': 'sr_RS.UTF-8@latin', + 'sr_rs@latn': 'sr_RS.UTF-8@latin', + 'sr_sp': 'sr_CS.ISO8859-2', + 'sr_yu': 'sr_RS.UTF-8@latin', + 'sr_yu.cp1251@cyrillic': 'sr_CS.CP1251', + 'sr_yu.iso88592': 'sr_CS.ISO8859-2', + 'sr_yu.iso88595': 'sr_CS.ISO8859-5', + 'sr_yu.iso88595@cyrillic': 'sr_CS.ISO8859-5', + 'sr_yu.microsoftcp1251@cyrillic': 'sr_CS.CP1251', + 'sr_yu.utf8@cyrillic': 'sr_RS.UTF-8', + 'sr_yu@cyrillic': 'sr_RS.UTF-8', + 'ss': 'ss_ZA.ISO8859-1', + 'ss_za': 'ss_ZA.ISO8859-1', + 'ss_za.iso88591': 'ss_ZA.ISO8859-1', + 'st': 'st_ZA.ISO8859-1', + 'st_za': 'st_ZA.ISO8859-1', + 'st_za.iso88591': 'st_ZA.ISO8859-1', + 'sv': 'sv_SE.ISO8859-1', + 'sv.iso885915': 'sv_SE.ISO8859-15', + 'sv_fi': 'sv_FI.ISO8859-1', + 'sv_fi.iso88591': 'sv_FI.ISO8859-1', + 'sv_fi.iso885915': 'sv_FI.ISO8859-15', + 'sv_fi.iso885915@euro': 'sv_FI.ISO8859-15', + 'sv_fi.utf8@euro': 'sv_FI.UTF-8', + 'sv_fi@euro': 'sv_FI.ISO8859-15', + 'sv_se': 'sv_SE.ISO8859-1', + 'sv_se.88591': 'sv_SE.ISO8859-1', + 'sv_se.iso88591': 'sv_SE.ISO8859-1', + 'sv_se.iso885915': 'sv_SE.ISO8859-15', + 'sv_se@euro': 'sv_SE.ISO8859-15', + 'swedish': 'sv_SE.ISO8859-1', + 'swedish.iso88591': 'sv_SE.ISO8859-1', + 'ta': 'ta_IN.TSCII-0', + 'ta_in': 'ta_IN.TSCII-0', + 'ta_in.tscii': 'ta_IN.TSCII-0', + 'ta_in.tscii0': 'ta_IN.TSCII-0', + 'te': 'te_IN.UTF-8', + 'tg': 'tg_TJ.KOI8-C', + 'tg_tj': 'tg_TJ.KOI8-C', + 'tg_tj.koi8c': 'tg_TJ.KOI8-C', + 'th': 'th_TH.ISO8859-11', + 'th_th': 'th_TH.ISO8859-11', + 'th_th.iso885911': 'th_TH.ISO8859-11', + 'th_th.tactis': 'th_TH.TIS620', + 'th_th.tis620': 'th_TH.TIS620', + 'thai': 'th_TH.ISO8859-11', + 'tl': 'tl_PH.ISO8859-1', + 'tl_ph': 'tl_PH.ISO8859-1', + 'tl_ph.iso88591': 'tl_PH.ISO8859-1', + 'tn': 'tn_ZA.ISO8859-15', + 'tn_za': 'tn_ZA.ISO8859-15', + 'tn_za.iso885915': 'tn_ZA.ISO8859-15', + 'tr': 'tr_TR.ISO8859-9', + 'tr_tr': 'tr_TR.ISO8859-9', + 'tr_tr.iso88599': 'tr_TR.ISO8859-9', + 'ts': 'ts_ZA.ISO8859-1', + 'ts_za': 'ts_ZA.ISO8859-1', + 'ts_za.iso88591': 'ts_ZA.ISO8859-1', + 'tt': 'tt_RU.TATAR-CYR', + 'tt_ru': 'tt_RU.TATAR-CYR', + 'tt_ru.koi8c': 'tt_RU.KOI8-C', + 'tt_ru.tatarcyr': 'tt_RU.TATAR-CYR', + 'turkish': 'tr_TR.ISO8859-9', + 'turkish.iso88599': 'tr_TR.ISO8859-9', + 'uk': 'uk_UA.KOI8-U', + 'uk_ua': 'uk_UA.KOI8-U', + 'uk_ua.cp1251': 'uk_UA.CP1251', + 'uk_ua.iso88595': 'uk_UA.ISO8859-5', + 'uk_ua.koi8u': 'uk_UA.KOI8-U', + 'uk_ua.microsoftcp1251': 'uk_UA.CP1251', + 'univ': 'en_US.utf', + 'universal': 'en_US.utf', + 'universal.utf8@ucs4': 'en_US.UTF-8', + 'ur': 'ur_PK.CP1256', + 'ur_in': 'ur_IN.UTF-8', + 'ur_pk': 'ur_PK.CP1256', + 'ur_pk.cp1256': 'ur_PK.CP1256', + 'ur_pk.microsoftcp1256': 'ur_PK.CP1256', + 'uz': 'uz_UZ.UTF-8', + 'uz_uz': 'uz_UZ.UTF-8', + 'uz_uz.iso88591': 'uz_UZ.ISO8859-1', + 'uz_uz.utf8@cyrillic': 'uz_UZ.UTF-8', + 'uz_uz@cyrillic': 'uz_UZ.UTF-8', + 've': 've_ZA.UTF-8', + 've_za': 've_ZA.UTF-8', + 'vi': 'vi_VN.TCVN', + 'vi_vn': 'vi_VN.TCVN', + 'vi_vn.tcvn': 'vi_VN.TCVN', + 'vi_vn.tcvn5712': 'vi_VN.TCVN', + 'vi_vn.viscii': 'vi_VN.VISCII', + 'vi_vn.viscii111': 'vi_VN.VISCII', + 'wa': 'wa_BE.ISO8859-1', + 'wa_be': 'wa_BE.ISO8859-1', + 'wa_be.iso88591': 'wa_BE.ISO8859-1', + 'wa_be.iso885915': 'wa_BE.ISO8859-15', + 'wa_be.iso885915@euro': 'wa_BE.ISO8859-15', + 'wa_be@euro': 'wa_BE.ISO8859-15', + 'xh': 'xh_ZA.ISO8859-1', + 'xh_za': 'xh_ZA.ISO8859-1', + 'xh_za.iso88591': 'xh_ZA.ISO8859-1', + 'yi': 'yi_US.CP1255', + 'yi_us': 'yi_US.CP1255', + 'yi_us.cp1255': 'yi_US.CP1255', + 'yi_us.microsoftcp1255': 'yi_US.CP1255', + 'zh': 'zh_CN.eucCN', + 'zh_cn': 'zh_CN.gb2312', + 'zh_cn.big5': 'zh_TW.big5', + 'zh_cn.euc': 'zh_CN.eucCN', + 'zh_cn.gb18030': 'zh_CN.gb18030', + 'zh_cn.gb2312': 'zh_CN.gb2312', + 'zh_cn.gbk': 'zh_CN.gbk', + 'zh_hk': 'zh_HK.big5hkscs', + 'zh_hk.big5': 'zh_HK.big5', + 'zh_hk.big5hk': 'zh_HK.big5hkscs', + 'zh_hk.big5hkscs': 'zh_HK.big5hkscs', + 'zh_tw': 'zh_TW.big5', + 'zh_tw.big5': 'zh_TW.big5', + 'zh_tw.euc': 'zh_TW.eucTW', + 'zh_tw.euctw': 'zh_TW.eucTW', + 'zu': 'zu_ZA.ISO8859-1', + 'zu_za': 'zu_ZA.ISO8859-1', + 'zu_za.iso88591': 'zu_ZA.ISO8859-1', +} + +# +# This maps Windows language identifiers to locale strings. +# +# This list has been updated from +# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_238z.asp +# to include every locale up to Windows Vista. +# +# NOTE: this mapping is incomplete. If your language is missing, please +# submit a bug report to the Python bug tracker at http://bugs.python.org/ +# Make sure you include the missing language identifier and the suggested +# locale code. +# + +windows_locale = { + 0x0436: "af_ZA", # Afrikaans + 0x041c: "sq_AL", # Albanian + 0x0484: "gsw_FR",# Alsatian - France + 0x045e: "am_ET", # Amharic - Ethiopia + 0x0401: "ar_SA", # Arabic - Saudi Arabia + 0x0801: "ar_IQ", # Arabic - Iraq + 0x0c01: "ar_EG", # Arabic - Egypt + 0x1001: "ar_LY", # Arabic - Libya + 0x1401: "ar_DZ", # Arabic - Algeria + 0x1801: "ar_MA", # Arabic - Morocco + 0x1c01: "ar_TN", # Arabic - Tunisia + 0x2001: "ar_OM", # Arabic - Oman + 0x2401: "ar_YE", # Arabic - Yemen + 0x2801: "ar_SY", # Arabic - Syria + 0x2c01: "ar_JO", # Arabic - Jordan + 0x3001: "ar_LB", # Arabic - Lebanon + 0x3401: "ar_KW", # Arabic - Kuwait + 0x3801: "ar_AE", # Arabic - United Arab Emirates + 0x3c01: "ar_BH", # Arabic - Bahrain + 0x4001: "ar_QA", # Arabic - Qatar + 0x042b: "hy_AM", # Armenian + 0x044d: "as_IN", # Assamese - India + 0x042c: "az_AZ", # Azeri - Latin + 0x082c: "az_AZ", # Azeri - Cyrillic + 0x046d: "ba_RU", # Bashkir + 0x042d: "eu_ES", # Basque - Russia + 0x0423: "be_BY", # Belarusian + 0x0445: "bn_IN", # Begali + 0x201a: "bs_BA", # Bosnian - Cyrillic + 0x141a: "bs_BA", # Bosnian - Latin + 0x047e: "br_FR", # Breton - France + 0x0402: "bg_BG", # Bulgarian +# 0x0455: "my_MM", # Burmese - Not supported + 0x0403: "ca_ES", # Catalan + 0x0004: "zh_CHS",# Chinese - Simplified + 0x0404: "zh_TW", # Chinese - Taiwan + 0x0804: "zh_CN", # Chinese - PRC + 0x0c04: "zh_HK", # Chinese - Hong Kong S.A.R. + 0x1004: "zh_SG", # Chinese - Singapore + 0x1404: "zh_MO", # Chinese - Macao S.A.R. + 0x7c04: "zh_CHT",# Chinese - Traditional + 0x0483: "co_FR", # Corsican - France + 0x041a: "hr_HR", # Croatian + 0x101a: "hr_BA", # Croatian - Bosnia + 0x0405: "cs_CZ", # Czech + 0x0406: "da_DK", # Danish + 0x048c: "gbz_AF",# Dari - Afghanistan + 0x0465: "div_MV",# Divehi - Maldives + 0x0413: "nl_NL", # Dutch - The Netherlands + 0x0813: "nl_BE", # Dutch - Belgium + 0x0409: "en_US", # English - United States + 0x0809: "en_GB", # English - United Kingdom + 0x0c09: "en_AU", # English - Australia + 0x1009: "en_CA", # English - Canada + 0x1409: "en_NZ", # English - New Zealand + 0x1809: "en_IE", # English - Ireland + 0x1c09: "en_ZA", # English - South Africa + 0x2009: "en_JA", # English - Jamaica + 0x2409: "en_CB", # English - Carribbean + 0x2809: "en_BZ", # English - Belize + 0x2c09: "en_TT", # English - Trinidad + 0x3009: "en_ZW", # English - Zimbabwe + 0x3409: "en_PH", # English - Philippines + 0x4009: "en_IN", # English - India + 0x4409: "en_MY", # English - Malaysia + 0x4809: "en_IN", # English - Singapore + 0x0425: "et_EE", # Estonian + 0x0438: "fo_FO", # Faroese + 0x0464: "fil_PH",# Filipino + 0x040b: "fi_FI", # Finnish + 0x040c: "fr_FR", # French - France + 0x080c: "fr_BE", # French - Belgium + 0x0c0c: "fr_CA", # French - Canada + 0x100c: "fr_CH", # French - Switzerland + 0x140c: "fr_LU", # French - Luxembourg + 0x180c: "fr_MC", # French - Monaco + 0x0462: "fy_NL", # Frisian - Netherlands + 0x0456: "gl_ES", # Galician + 0x0437: "ka_GE", # Georgian + 0x0407: "de_DE", # German - Germany + 0x0807: "de_CH", # German - Switzerland + 0x0c07: "de_AT", # German - Austria + 0x1007: "de_LU", # German - Luxembourg + 0x1407: "de_LI", # German - Liechtenstein + 0x0408: "el_GR", # Greek + 0x046f: "kl_GL", # Greenlandic - Greenland + 0x0447: "gu_IN", # Gujarati + 0x0468: "ha_NG", # Hausa - Latin + 0x040d: "he_IL", # Hebrew + 0x0439: "hi_IN", # Hindi + 0x040e: "hu_HU", # Hungarian + 0x040f: "is_IS", # Icelandic + 0x0421: "id_ID", # Indonesian + 0x045d: "iu_CA", # Inuktitut - Syllabics + 0x085d: "iu_CA", # Inuktitut - Latin + 0x083c: "ga_IE", # Irish - Ireland + 0x0410: "it_IT", # Italian - Italy + 0x0810: "it_CH", # Italian - Switzerland + 0x0411: "ja_JP", # Japanese + 0x044b: "kn_IN", # Kannada - India + 0x043f: "kk_KZ", # Kazakh + 0x0453: "kh_KH", # Khmer - Cambodia + 0x0486: "qut_GT",# K'iche - Guatemala + 0x0487: "rw_RW", # Kinyarwanda - Rwanda + 0x0457: "kok_IN",# Konkani + 0x0412: "ko_KR", # Korean + 0x0440: "ky_KG", # Kyrgyz + 0x0454: "lo_LA", # Lao - Lao PDR + 0x0426: "lv_LV", # Latvian + 0x0427: "lt_LT", # Lithuanian + 0x082e: "dsb_DE",# Lower Sorbian - Germany + 0x046e: "lb_LU", # Luxembourgish + 0x042f: "mk_MK", # FYROM Macedonian + 0x043e: "ms_MY", # Malay - Malaysia + 0x083e: "ms_BN", # Malay - Brunei Darussalam + 0x044c: "ml_IN", # Malayalam - India + 0x043a: "mt_MT", # Maltese + 0x0481: "mi_NZ", # Maori + 0x047a: "arn_CL",# Mapudungun + 0x044e: "mr_IN", # Marathi + 0x047c: "moh_CA",# Mohawk - Canada + 0x0450: "mn_MN", # Mongolian - Cyrillic + 0x0850: "mn_CN", # Mongolian - PRC + 0x0461: "ne_NP", # Nepali + 0x0414: "nb_NO", # Norwegian - Bokmal + 0x0814: "nn_NO", # Norwegian - Nynorsk + 0x0482: "oc_FR", # Occitan - France + 0x0448: "or_IN", # Oriya - India + 0x0463: "ps_AF", # Pashto - Afghanistan + 0x0429: "fa_IR", # Persian + 0x0415: "pl_PL", # Polish + 0x0416: "pt_BR", # Portuguese - Brazil + 0x0816: "pt_PT", # Portuguese - Portugal + 0x0446: "pa_IN", # Punjabi + 0x046b: "quz_BO",# Quechua (Bolivia) + 0x086b: "quz_EC",# Quechua (Ecuador) + 0x0c6b: "quz_PE",# Quechua (Peru) + 0x0418: "ro_RO", # Romanian - Romania + 0x0417: "rm_CH", # Romansh + 0x0419: "ru_RU", # Russian + 0x243b: "smn_FI",# Sami Finland + 0x103b: "smj_NO",# Sami Norway + 0x143b: "smj_SE",# Sami Sweden + 0x043b: "se_NO", # Sami Northern Norway + 0x083b: "se_SE", # Sami Northern Sweden + 0x0c3b: "se_FI", # Sami Northern Finland + 0x203b: "sms_FI",# Sami Skolt + 0x183b: "sma_NO",# Sami Southern Norway + 0x1c3b: "sma_SE",# Sami Southern Sweden + 0x044f: "sa_IN", # Sanskrit + 0x0c1a: "sr_SP", # Serbian - Cyrillic + 0x1c1a: "sr_BA", # Serbian - Bosnia Cyrillic + 0x081a: "sr_SP", # Serbian - Latin + 0x181a: "sr_BA", # Serbian - Bosnia Latin + 0x045b: "si_LK", # Sinhala - Sri Lanka + 0x046c: "ns_ZA", # Northern Sotho + 0x0432: "tn_ZA", # Setswana - Southern Africa + 0x041b: "sk_SK", # Slovak + 0x0424: "sl_SI", # Slovenian + 0x040a: "es_ES", # Spanish - Spain + 0x080a: "es_MX", # Spanish - Mexico + 0x0c0a: "es_ES", # Spanish - Spain (Modern) + 0x100a: "es_GT", # Spanish - Guatemala + 0x140a: "es_CR", # Spanish - Costa Rica + 0x180a: "es_PA", # Spanish - Panama + 0x1c0a: "es_DO", # Spanish - Dominican Republic + 0x200a: "es_VE", # Spanish - Venezuela + 0x240a: "es_CO", # Spanish - Colombia + 0x280a: "es_PE", # Spanish - Peru + 0x2c0a: "es_AR", # Spanish - Argentina + 0x300a: "es_EC", # Spanish - Ecuador + 0x340a: "es_CL", # Spanish - Chile + 0x380a: "es_UR", # Spanish - Uruguay + 0x3c0a: "es_PY", # Spanish - Paraguay + 0x400a: "es_BO", # Spanish - Bolivia + 0x440a: "es_SV", # Spanish - El Salvador + 0x480a: "es_HN", # Spanish - Honduras + 0x4c0a: "es_NI", # Spanish - Nicaragua + 0x500a: "es_PR", # Spanish - Puerto Rico + 0x540a: "es_US", # Spanish - United States +# 0x0430: "", # Sutu - Not supported + 0x0441: "sw_KE", # Swahili + 0x041d: "sv_SE", # Swedish - Sweden + 0x081d: "sv_FI", # Swedish - Finland + 0x045a: "syr_SY",# Syriac + 0x0428: "tg_TJ", # Tajik - Cyrillic + 0x085f: "tmz_DZ",# Tamazight - Latin + 0x0449: "ta_IN", # Tamil + 0x0444: "tt_RU", # Tatar + 0x044a: "te_IN", # Telugu + 0x041e: "th_TH", # Thai + 0x0851: "bo_BT", # Tibetan - Bhutan + 0x0451: "bo_CN", # Tibetan - PRC + 0x041f: "tr_TR", # Turkish + 0x0442: "tk_TM", # Turkmen - Cyrillic + 0x0480: "ug_CN", # Uighur - Arabic + 0x0422: "uk_UA", # Ukrainian + 0x042e: "wen_DE",# Upper Sorbian - Germany + 0x0420: "ur_PK", # Urdu + 0x0820: "ur_IN", # Urdu - India + 0x0443: "uz_UZ", # Uzbek - Latin + 0x0843: "uz_UZ", # Uzbek - Cyrillic + 0x042a: "vi_VN", # Vietnamese + 0x0452: "cy_GB", # Welsh + 0x0488: "wo_SN", # Wolof - Senegal + 0x0434: "xh_ZA", # Xhosa - South Africa + 0x0485: "sah_RU",# Yakut - Cyrillic + 0x0478: "ii_CN", # Yi - PRC + 0x046a: "yo_NG", # Yoruba - Nigeria + 0x0435: "zu_ZA", # Zulu +} + +def _print_locale(): + + """ Test function. + """ + categories = {} + def _init_categories(categories=categories): + for k,v in globals().items(): + if k[:3] == 'LC_': + categories[k] = v + _init_categories() + del categories['LC_ALL'] + + print 'Locale defaults as determined by getdefaultlocale():' + print '-'*72 + lang, enc = getdefaultlocale() + print 'Language: ', lang or '(undefined)' + print 'Encoding: ', enc or '(undefined)' + print + + print 'Locale settings on startup:' + print '-'*72 + for name,category in categories.items(): + print name, '...' + lang, enc = getlocale(category) + print ' Language: ', lang or '(undefined)' + print ' Encoding: ', enc or '(undefined)' + print + + print + print 'Locale settings after calling resetlocale():' + print '-'*72 + resetlocale() + for name,category in categories.items(): + print name, '...' + lang, enc = getlocale(category) + print ' Language: ', lang or '(undefined)' + print ' Encoding: ', enc or '(undefined)' + print + + try: + setlocale(LC_ALL, "") + except: + print 'NOTE:' + print 'setlocale(LC_ALL, "") does not support the default locale' + print 'given in the OS environment variables.' + else: + print + print 'Locale settings after calling setlocale(LC_ALL, ""):' + print '-'*72 + for name,category in categories.items(): + print name, '...' + lang, enc = getlocale(category) + print ' Language: ', lang or '(undefined)' + print ' Encoding: ', enc or '(undefined)' + print + +### + +try: + LC_MESSAGES +except NameError: + pass +else: + __all__.append("LC_MESSAGES") + +if __name__=='__main__': + print 'Locale aliasing:' + print + _print_locale() + print + print 'Number formatting:' + print + _test() diff --git a/PythonHome/Lib/locale.pyc b/PythonHome/Lib/locale.pyc index b4536a1a020df588a95c0b0829e85c5acebdf9ba..65cb23ba39fbb1dd243199125a9f2c6bf3419791 100644 GIT binary patch delta 1824 zcmey}!@PSc^M(dxLu&>G23M!OaSmC&347^P{7_VH(vGV}Kzz`El$;4C9~1VTf&h9*>!tHrFQZ2?yF{wQ~-J VLpHPTF~$_k-ggvJF!5j%Cjfz~)k^>X diff --git a/PythonHome/Lib/logging/__init__.py b/PythonHome/Lib/logging/__init__.py new file mode 100644 index 0000000000..b2a7711dc3 --- /dev/null +++ b/PythonHome/Lib/logging/__init__.py @@ -0,0 +1,1737 @@ +# Copyright 2001-2014 by Vinay Sajip. 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 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. + +""" +Logging package for Python. Based on PEP 282 and comments thereto in +comp.lang.python. + +Copyright (C) 2001-2014 Vinay Sajip. All Rights Reserved. + +To use, simply 'import logging' and log away! +""" + +import sys, os, time, cStringIO, traceback, warnings, weakref, collections + +__all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR', + 'FATAL', 'FileHandler', 'Filter', 'Formatter', 'Handler', 'INFO', + 'LogRecord', 'Logger', 'LoggerAdapter', 'NOTSET', 'NullHandler', + 'StreamHandler', 'WARN', 'WARNING', 'addLevelName', 'basicConfig', + 'captureWarnings', 'critical', 'debug', 'disable', 'error', + 'exception', 'fatal', 'getLevelName', 'getLogger', 'getLoggerClass', + 'info', 'log', 'makeLogRecord', 'setLoggerClass', 'warn', 'warning'] + +try: + import codecs +except ImportError: + codecs = None + +try: + import thread + import threading +except ImportError: + thread = None + +__author__ = "Vinay Sajip " +__status__ = "production" +# Note: the attributes below are no longer maintained. +__version__ = "0.5.1.2" +__date__ = "07 February 2010" + +#--------------------------------------------------------------------------- +# Miscellaneous module data +#--------------------------------------------------------------------------- +try: + unicode + _unicode = True +except NameError: + _unicode = False + +# +# _srcfile is used when walking the stack to check when we've got the first +# caller stack frame. +# +if hasattr(sys, 'frozen'): #support for py2exe + _srcfile = "logging%s__init__%s" % (os.sep, __file__[-4:]) +elif __file__[-4:].lower() in ['.pyc', '.pyo']: + _srcfile = __file__[:-4] + '.py' +else: + _srcfile = __file__ +_srcfile = os.path.normcase(_srcfile) + +# next bit filched from 1.5.2's inspect.py +def currentframe(): + """Return the frame object for the caller's stack frame.""" + try: + raise Exception + except: + return sys.exc_info()[2].tb_frame.f_back + +if hasattr(sys, '_getframe'): currentframe = lambda: sys._getframe(3) +# done filching + +# _srcfile is only used in conjunction with sys._getframe(). +# To provide compatibility with older versions of Python, set _srcfile +# to None if _getframe() is not available; this value will prevent +# findCaller() from being called. +#if not hasattr(sys, "_getframe"): +# _srcfile = None + +# +#_startTime is used as the base when calculating the relative time of events +# +_startTime = time.time() + +# +#raiseExceptions is used to see if exceptions during handling should be +#propagated +# +raiseExceptions = 1 + +# +# If you don't want threading information in the log, set this to zero +# +logThreads = 1 + +# +# If you don't want multiprocessing information in the log, set this to zero +# +logMultiprocessing = 1 + +# +# If you don't want process information in the log, set this to zero +# +logProcesses = 1 + +#--------------------------------------------------------------------------- +# Level related stuff +#--------------------------------------------------------------------------- +# +# Default levels and level names, these can be replaced with any positive set +# of values having corresponding names. There is a pseudo-level, NOTSET, which +# is only really there as a lower limit for user-defined levels. Handlers and +# loggers are initialized with NOTSET so that they will log all messages, even +# at user-defined levels. +# + +CRITICAL = 50 +FATAL = CRITICAL +ERROR = 40 +WARNING = 30 +WARN = WARNING +INFO = 20 +DEBUG = 10 +NOTSET = 0 + +_levelNames = { + CRITICAL : 'CRITICAL', + ERROR : 'ERROR', + WARNING : 'WARNING', + INFO : 'INFO', + DEBUG : 'DEBUG', + NOTSET : 'NOTSET', + 'CRITICAL' : CRITICAL, + 'ERROR' : ERROR, + 'WARN' : WARNING, + 'WARNING' : WARNING, + 'INFO' : INFO, + 'DEBUG' : DEBUG, + 'NOTSET' : NOTSET, +} + +def getLevelName(level): + """ + Return the textual representation of logging level 'level'. + + If the level is one of the predefined levels (CRITICAL, ERROR, WARNING, + INFO, DEBUG) then you get the corresponding string. If you have + associated levels with names using addLevelName then the name you have + associated with 'level' is returned. + + If a numeric value corresponding to one of the defined levels is passed + in, the corresponding string representation is returned. + + Otherwise, the string "Level %s" % level is returned. + """ + return _levelNames.get(level, ("Level %s" % level)) + +def addLevelName(level, levelName): + """ + Associate 'levelName' with 'level'. + + This is used when converting levels to text during message formatting. + """ + _acquireLock() + try: #unlikely to cause an exception, but you never know... + _levelNames[level] = levelName + _levelNames[levelName] = level + finally: + _releaseLock() + +def _checkLevel(level): + if isinstance(level, (int, long)): + rv = level + elif str(level) == level: + if level not in _levelNames: + raise ValueError("Unknown level: %r" % level) + rv = _levelNames[level] + else: + raise TypeError("Level not an integer or a valid string: %r" % level) + return rv + +#--------------------------------------------------------------------------- +# Thread-related stuff +#--------------------------------------------------------------------------- + +# +#_lock is used to serialize access to shared data structures in this module. +#This needs to be an RLock because fileConfig() creates and configures +#Handlers, and so might arbitrary user threads. Since Handler code updates the +#shared dictionary _handlers, it needs to acquire the lock. But if configuring, +#the lock would already have been acquired - so we need an RLock. +#The same argument applies to Loggers and Manager.loggerDict. +# +if thread: + _lock = threading.RLock() +else: + _lock = None + +def _acquireLock(): + """ + Acquire the module-level lock for serializing access to shared data. + + This should be released with _releaseLock(). + """ + if _lock: + _lock.acquire() + +def _releaseLock(): + """ + Release the module-level lock acquired by calling _acquireLock(). + """ + if _lock: + _lock.release() + +#--------------------------------------------------------------------------- +# The logging record +#--------------------------------------------------------------------------- + +class LogRecord(object): + """ + A LogRecord instance represents an event being logged. + + LogRecord instances are created every time something is logged. They + contain all the information pertinent to the event being logged. The + main information passed in is in msg and args, which are combined + using str(msg) % args to create the message field of the record. The + record also includes information such as when the record was created, + the source line where the logging call was made, and any exception + information to be logged. + """ + def __init__(self, name, level, pathname, lineno, + msg, args, exc_info, func=None): + """ + Initialize a logging record with interesting information. + """ + ct = time.time() + self.name = name + self.msg = msg + # + # The following statement allows passing of a dictionary as a sole + # argument, so that you can do something like + # logging.debug("a %(a)d b %(b)s", {'a':1, 'b':2}) + # Suggested by Stefan Behnel. + # Note that without the test for args[0], we get a problem because + # during formatting, we test to see if the arg is present using + # 'if self.args:'. If the event being logged is e.g. 'Value is %d' + # and if the passed arg fails 'if self.args:' then no formatting + # is done. For example, logger.warn('Value is %d', 0) would log + # 'Value is %d' instead of 'Value is 0'. + # For the use case of passing a dictionary, this should not be a + # problem. + # Issue #21172: a request was made to relax the isinstance check + # to hasattr(args[0], '__getitem__'). However, the docs on string + # formatting still seem to suggest a mapping object is required. + # Thus, while not removing the isinstance check, it does now look + # for collections.Mapping rather than, as before, dict. + if (args and len(args) == 1 and isinstance(args[0], collections.Mapping) + and args[0]): + args = args[0] + self.args = args + self.levelname = getLevelName(level) + self.levelno = level + self.pathname = pathname + try: + self.filename = os.path.basename(pathname) + self.module = os.path.splitext(self.filename)[0] + except (TypeError, ValueError, AttributeError): + self.filename = pathname + self.module = "Unknown module" + self.exc_info = exc_info + self.exc_text = None # used to cache the traceback text + self.lineno = lineno + self.funcName = func + self.created = ct + self.msecs = (ct - long(ct)) * 1000 + self.relativeCreated = (self.created - _startTime) * 1000 + if logThreads and thread: + self.thread = thread.get_ident() + self.threadName = threading.current_thread().name + else: + self.thread = None + self.threadName = None + if not logMultiprocessing: + self.processName = None + else: + self.processName = 'MainProcess' + mp = sys.modules.get('multiprocessing') + if mp is not None: + # Errors may occur if multiprocessing has not finished loading + # yet - e.g. if a custom import hook causes third-party code + # to run when multiprocessing calls import. See issue 8200 + # for an example + try: + self.processName = mp.current_process().name + except StandardError: + pass + if logProcesses and hasattr(os, 'getpid'): + self.process = os.getpid() + else: + self.process = None + + def __str__(self): + return ''%(self.name, self.levelno, + self.pathname, self.lineno, self.msg) + + def getMessage(self): + """ + Return the message for this LogRecord. + + Return the message for this LogRecord after merging any user-supplied + arguments with the message. + """ + if not _unicode: #if no unicode support... + msg = str(self.msg) + else: + msg = self.msg + if not isinstance(msg, basestring): + try: + msg = str(self.msg) + except UnicodeError: + msg = self.msg #Defer encoding till later + if self.args: + msg = msg % self.args + return msg + +def makeLogRecord(dict): + """ + Make a LogRecord whose attributes are defined by the specified dictionary, + This function is useful for converting a logging event received over + a socket connection (which is sent as a dictionary) into a LogRecord + instance. + """ + rv = LogRecord(None, None, "", 0, "", (), None, None) + rv.__dict__.update(dict) + return rv + +#--------------------------------------------------------------------------- +# Formatter classes and functions +#--------------------------------------------------------------------------- + +class Formatter(object): + """ + Formatter instances are used to convert a LogRecord to text. + + Formatters need to know how a LogRecord is constructed. They are + responsible for converting a LogRecord to (usually) a string which can + be interpreted by either a human or an external system. The base Formatter + allows a formatting string to be specified. If none is supplied, the + default value of "%s(message)\\n" is used. + + The Formatter can be initialized with a format string which makes use of + knowledge of the LogRecord attributes - e.g. the default value mentioned + above makes use of the fact that the user's message and arguments are pre- + formatted into a LogRecord's message attribute. Currently, the useful + attributes in a LogRecord are described by: + + %(name)s Name of the logger (logging channel) + %(levelno)s Numeric logging level for the message (DEBUG, INFO, + WARNING, ERROR, CRITICAL) + %(levelname)s Text logging level for the message ("DEBUG", "INFO", + "WARNING", "ERROR", "CRITICAL") + %(pathname)s Full pathname of the source file where the logging + call was issued (if available) + %(filename)s Filename portion of pathname + %(module)s Module (name portion of filename) + %(lineno)d Source line number where the logging call was issued + (if available) + %(funcName)s Function name + %(created)f Time when the LogRecord was created (time.time() + return value) + %(asctime)s Textual time when the LogRecord was created + %(msecs)d Millisecond portion of the creation time + %(relativeCreated)d Time in milliseconds when the LogRecord was created, + relative to the time the logging module was loaded + (typically at application startup time) + %(thread)d Thread ID (if available) + %(threadName)s Thread name (if available) + %(process)d Process ID (if available) + %(message)s The result of record.getMessage(), computed just as + the record is emitted + """ + + converter = time.localtime + + def __init__(self, fmt=None, datefmt=None): + """ + Initialize the formatter with specified format strings. + + Initialize the formatter either with the specified format string, or a + default as described above. Allow for specialized date formatting with + the optional datefmt argument (if omitted, you get the ISO8601 format). + """ + if fmt: + self._fmt = fmt + else: + self._fmt = "%(message)s" + self.datefmt = datefmt + + def formatTime(self, record, datefmt=None): + """ + Return the creation time of the specified LogRecord as formatted text. + + This method should be called from format() by a formatter which + wants to make use of a formatted time. This method can be overridden + in formatters to provide for any specific requirement, but the + basic behaviour is as follows: if datefmt (a string) is specified, + it is used with time.strftime() to format the creation time of the + record. Otherwise, the ISO8601 format is used. The resulting + string is returned. This function uses a user-configurable function + to convert the creation time to a tuple. By default, time.localtime() + is used; to change this for a particular formatter instance, set the + 'converter' attribute to a function with the same signature as + time.localtime() or time.gmtime(). To change it for all formatters, + for example if you want all logging times to be shown in GMT, + set the 'converter' attribute in the Formatter class. + """ + ct = self.converter(record.created) + if datefmt: + s = time.strftime(datefmt, ct) + else: + t = time.strftime("%Y-%m-%d %H:%M:%S", ct) + s = "%s,%03d" % (t, record.msecs) + return s + + def formatException(self, ei): + """ + Format and return the specified exception information as a string. + + This default implementation just uses + traceback.print_exception() + """ + sio = cStringIO.StringIO() + traceback.print_exception(ei[0], ei[1], ei[2], None, sio) + s = sio.getvalue() + sio.close() + if s[-1:] == "\n": + s = s[:-1] + return s + + def usesTime(self): + """ + Check if the format uses the creation time of the record. + """ + return self._fmt.find("%(asctime)") >= 0 + + def format(self, record): + """ + Format the specified record as text. + + The record's attribute dictionary is used as the operand to a + string formatting operation which yields the returned string. + Before formatting the dictionary, a couple of preparatory steps + are carried out. The message attribute of the record is computed + using LogRecord.getMessage(). If the formatting string uses the + time (as determined by a call to usesTime(), formatTime() is + called to format the event time. If there is exception information, + it is formatted using formatException() and appended to the message. + """ + record.message = record.getMessage() + if self.usesTime(): + record.asctime = self.formatTime(record, self.datefmt) + s = self._fmt % record.__dict__ + if record.exc_info: + # Cache the traceback text to avoid converting it multiple times + # (it's constant anyway) + if not record.exc_text: + record.exc_text = self.formatException(record.exc_info) + if record.exc_text: + if s[-1:] != "\n": + s = s + "\n" + try: + s = s + record.exc_text + except UnicodeError: + # Sometimes filenames have non-ASCII chars, which can lead + # to errors when s is Unicode and record.exc_text is str + # See issue 8924. + # We also use replace for when there are multiple + # encodings, e.g. UTF-8 for the filesystem and latin-1 + # for a script. See issue 13232. + s = s + record.exc_text.decode(sys.getfilesystemencoding(), + 'replace') + return s + +# +# The default formatter to use when no other is specified +# +_defaultFormatter = Formatter() + +class BufferingFormatter(object): + """ + A formatter suitable for formatting a number of records. + """ + def __init__(self, linefmt=None): + """ + Optionally specify a formatter which will be used to format each + individual record. + """ + if linefmt: + self.linefmt = linefmt + else: + self.linefmt = _defaultFormatter + + def formatHeader(self, records): + """ + Return the header string for the specified records. + """ + return "" + + def formatFooter(self, records): + """ + Return the footer string for the specified records. + """ + return "" + + def format(self, records): + """ + Format the specified records and return the result as a string. + """ + rv = "" + if len(records) > 0: + rv = rv + self.formatHeader(records) + for record in records: + rv = rv + self.linefmt.format(record) + rv = rv + self.formatFooter(records) + return rv + +#--------------------------------------------------------------------------- +# Filter classes and functions +#--------------------------------------------------------------------------- + +class Filter(object): + """ + Filter instances are used to perform arbitrary filtering of LogRecords. + + Loggers and Handlers can optionally use Filter instances to filter + records as desired. The base filter class only allows events which are + below a certain point in the logger hierarchy. For example, a filter + initialized with "A.B" will allow events logged by loggers "A.B", + "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If + initialized with the empty string, all events are passed. + """ + def __init__(self, name=''): + """ + Initialize a filter. + + Initialize with the name of the logger which, together with its + children, will have its events allowed through the filter. If no + name is specified, allow every event. + """ + self.name = name + self.nlen = len(name) + + def filter(self, record): + """ + Determine if the specified record is to be logged. + + Is the specified record to be logged? Returns 0 for no, nonzero for + yes. If deemed appropriate, the record may be modified in-place. + """ + if self.nlen == 0: + return 1 + elif self.name == record.name: + return 1 + elif record.name.find(self.name, 0, self.nlen) != 0: + return 0 + return (record.name[self.nlen] == ".") + +class Filterer(object): + """ + A base class for loggers and handlers which allows them to share + common code. + """ + def __init__(self): + """ + Initialize the list of filters to be an empty list. + """ + self.filters = [] + + def addFilter(self, filter): + """ + Add the specified filter to this handler. + """ + if not (filter in self.filters): + self.filters.append(filter) + + def removeFilter(self, filter): + """ + Remove the specified filter from this handler. + """ + if filter in self.filters: + self.filters.remove(filter) + + def filter(self, record): + """ + Determine if a record is loggable by consulting all the filters. + + The default is to allow the record to be logged; any filter can veto + this and the record is then dropped. Returns a zero value if a record + is to be dropped, else non-zero. + """ + rv = 1 + for f in self.filters: + if not f.filter(record): + rv = 0 + break + return rv + +#--------------------------------------------------------------------------- +# Handler classes and functions +#--------------------------------------------------------------------------- + +_handlers = weakref.WeakValueDictionary() #map of handler names to handlers +_handlerList = [] # added to allow handlers to be removed in reverse of order initialized + +def _removeHandlerRef(wr): + """ + Remove a handler reference from the internal cleanup list. + """ + # This function can be called during module teardown, when globals are + # set to None. It can also be called from another thread. So we need to + # pre-emptively grab the necessary globals and check if they're None, + # to prevent race conditions and failures during interpreter shutdown. + acquire, release, handlers = _acquireLock, _releaseLock, _handlerList + if acquire and release and handlers: + acquire() + try: + if wr in handlers: + handlers.remove(wr) + finally: + release() + +def _addHandlerRef(handler): + """ + Add a handler to the internal cleanup list using a weak reference. + """ + _acquireLock() + try: + _handlerList.append(weakref.ref(handler, _removeHandlerRef)) + finally: + _releaseLock() + +class Handler(Filterer): + """ + Handler instances dispatch logging events to specific destinations. + + The base handler class. Acts as a placeholder which defines the Handler + interface. Handlers can optionally use Formatter instances to format + records as desired. By default, no formatter is specified; in this case, + the 'raw' message as determined by record.message is logged. + """ + def __init__(self, level=NOTSET): + """ + Initializes the instance - basically setting the formatter to None + and the filter list to empty. + """ + Filterer.__init__(self) + self._name = None + self.level = _checkLevel(level) + self.formatter = None + # Add the handler to the global _handlerList (for cleanup on shutdown) + _addHandlerRef(self) + self.createLock() + + def get_name(self): + return self._name + + def set_name(self, name): + _acquireLock() + try: + if self._name in _handlers: + del _handlers[self._name] + self._name = name + if name: + _handlers[name] = self + finally: + _releaseLock() + + name = property(get_name, set_name) + + def createLock(self): + """ + Acquire a thread lock for serializing access to the underlying I/O. + """ + if thread: + self.lock = threading.RLock() + else: + self.lock = None + + def acquire(self): + """ + Acquire the I/O thread lock. + """ + if self.lock: + self.lock.acquire() + + def release(self): + """ + Release the I/O thread lock. + """ + if self.lock: + self.lock.release() + + def setLevel(self, level): + """ + Set the logging level of this handler. + """ + self.level = _checkLevel(level) + + def format(self, record): + """ + Format the specified record. + + If a formatter is set, use it. Otherwise, use the default formatter + for the module. + """ + if self.formatter: + fmt = self.formatter + else: + fmt = _defaultFormatter + return fmt.format(record) + + def emit(self, record): + """ + Do whatever it takes to actually log the specified logging record. + + This version is intended to be implemented by subclasses and so + raises a NotImplementedError. + """ + raise NotImplementedError('emit must be implemented ' + 'by Handler subclasses') + + def handle(self, record): + """ + Conditionally emit the specified logging record. + + Emission depends on filters which may have been added to the handler. + Wrap the actual emission of the record with acquisition/release of + the I/O thread lock. Returns whether the filter passed the record for + emission. + """ + rv = self.filter(record) + if rv: + self.acquire() + try: + self.emit(record) + finally: + self.release() + return rv + + def setFormatter(self, fmt): + """ + Set the formatter for this handler. + """ + self.formatter = fmt + + def flush(self): + """ + Ensure all logging output has been flushed. + + This version does nothing and is intended to be implemented by + subclasses. + """ + pass + + def close(self): + """ + Tidy up any resources used by the handler. + + This version removes the handler from an internal map of handlers, + _handlers, which is used for handler lookup by name. Subclasses + should ensure that this gets called from overridden close() + methods. + """ + #get the module data lock, as we're updating a shared structure. + _acquireLock() + try: #unlikely to raise an exception, but you never know... + if self._name and self._name in _handlers: + del _handlers[self._name] + finally: + _releaseLock() + + def handleError(self, record): + """ + Handle errors which occur during an emit() call. + + This method should be called from handlers when an exception is + encountered during an emit() call. If raiseExceptions is false, + exceptions get silently ignored. This is what is mostly wanted + for a logging system - most users will not care about errors in + the logging system, they are more interested in application errors. + You could, however, replace this with a custom handler if you wish. + The record which was being processed is passed in to this method. + """ + if raiseExceptions and sys.stderr: # see issue 13807 + ei = sys.exc_info() + try: + traceback.print_exception(ei[0], ei[1], ei[2], + None, sys.stderr) + sys.stderr.write('Logged from file %s, line %s\n' % ( + record.filename, record.lineno)) + except IOError: + pass # see issue 5971 + finally: + del ei + +class StreamHandler(Handler): + """ + A handler class which writes logging records, appropriately formatted, + to a stream. Note that this class does not close the stream, as + sys.stdout or sys.stderr may be used. + """ + + def __init__(self, stream=None): + """ + Initialize the handler. + + If stream is not specified, sys.stderr is used. + """ + Handler.__init__(self) + if stream is None: + stream = sys.stderr + self.stream = stream + + def flush(self): + """ + Flushes the stream. + """ + self.acquire() + try: + if self.stream and hasattr(self.stream, "flush"): + self.stream.flush() + finally: + self.release() + + def emit(self, record): + """ + Emit a record. + + If a formatter is specified, it is used to format the record. + The record is then written to the stream with a trailing newline. If + exception information is present, it is formatted using + traceback.print_exception and appended to the stream. If the stream + has an 'encoding' attribute, it is used to determine how to do the + output to the stream. + """ + try: + msg = self.format(record) + stream = self.stream + fs = "%s\n" + if not _unicode: #if no unicode support... + stream.write(fs % msg) + else: + try: + if (isinstance(msg, unicode) and + getattr(stream, 'encoding', None)): + ufs = u'%s\n' + try: + stream.write(ufs % msg) + except UnicodeEncodeError: + #Printing to terminals sometimes fails. For example, + #with an encoding of 'cp1251', the above write will + #work if written to a stream opened or wrapped by + #the codecs module, but fail when writing to a + #terminal even when the codepage is set to cp1251. + #An extra encoding step seems to be needed. + stream.write((ufs % msg).encode(stream.encoding)) + else: + stream.write(fs % msg) + except UnicodeError: + stream.write(fs % msg.encode("UTF-8")) + self.flush() + except (KeyboardInterrupt, SystemExit): + raise + except: + self.handleError(record) + +class FileHandler(StreamHandler): + """ + A handler class which writes formatted logging records to disk files. + """ + def __init__(self, filename, mode='a', encoding=None, delay=0): + """ + Open the specified file and use it as the stream for logging. + """ + #keep the absolute path, otherwise derived classes which use this + #may come a cropper when the current directory changes + if codecs is None: + encoding = None + self.baseFilename = os.path.abspath(filename) + self.mode = mode + self.encoding = encoding + self.delay = delay + if delay: + #We don't open the stream, but we still need to call the + #Handler constructor to set level, formatter, lock etc. + Handler.__init__(self) + self.stream = None + else: + StreamHandler.__init__(self, self._open()) + + def close(self): + """ + Closes the stream. + """ + self.acquire() + try: + if self.stream: + self.flush() + if hasattr(self.stream, "close"): + self.stream.close() + self.stream = None + # Issue #19523: call unconditionally to + # prevent a handler leak when delay is set + StreamHandler.close(self) + finally: + self.release() + + def _open(self): + """ + Open the current base file with the (original) mode and encoding. + Return the resulting stream. + """ + if self.encoding is None: + stream = open(self.baseFilename, self.mode) + else: + stream = codecs.open(self.baseFilename, self.mode, self.encoding) + return stream + + def emit(self, record): + """ + Emit a record. + + If the stream was not opened because 'delay' was specified in the + constructor, open it before calling the superclass's emit. + """ + if self.stream is None: + self.stream = self._open() + StreamHandler.emit(self, record) + +#--------------------------------------------------------------------------- +# Manager classes and functions +#--------------------------------------------------------------------------- + +class PlaceHolder(object): + """ + PlaceHolder instances are used in the Manager logger hierarchy to take + the place of nodes for which no loggers have been defined. This class is + intended for internal use only and not as part of the public API. + """ + def __init__(self, alogger): + """ + Initialize with the specified logger being a child of this placeholder. + """ + #self.loggers = [alogger] + self.loggerMap = { alogger : None } + + def append(self, alogger): + """ + Add the specified logger as a child of this placeholder. + """ + #if alogger not in self.loggers: + if alogger not in self.loggerMap: + #self.loggers.append(alogger) + self.loggerMap[alogger] = None + +# +# Determine which class to use when instantiating loggers. +# +_loggerClass = None + +def setLoggerClass(klass): + """ + Set the class to be used when instantiating a logger. The class should + define __init__() such that only a name argument is required, and the + __init__() should call Logger.__init__() + """ + if klass != Logger: + if not issubclass(klass, Logger): + raise TypeError("logger not derived from logging.Logger: " + + klass.__name__) + global _loggerClass + _loggerClass = klass + +def getLoggerClass(): + """ + Return the class to be used when instantiating a logger. + """ + + return _loggerClass + +class Manager(object): + """ + There is [under normal circumstances] just one Manager instance, which + holds the hierarchy of loggers. + """ + def __init__(self, rootnode): + """ + Initialize the manager with the root node of the logger hierarchy. + """ + self.root = rootnode + self.disable = 0 + self.emittedNoHandlerWarning = 0 + self.loggerDict = {} + self.loggerClass = None + + def getLogger(self, name): + """ + Get a logger with the specified name (channel name), creating it + if it doesn't yet exist. This name is a dot-separated hierarchical + name, such as "a", "a.b", "a.b.c" or similar. + + If a PlaceHolder existed for the specified name [i.e. the logger + didn't exist but a child of it did], replace it with the created + logger and fix up the parent/child references which pointed to the + placeholder to now point to the logger. + """ + rv = None + if not isinstance(name, basestring): + raise TypeError('A logger name must be string or Unicode') + if isinstance(name, unicode): + name = name.encode('utf-8') + _acquireLock() + try: + if name in self.loggerDict: + rv = self.loggerDict[name] + if isinstance(rv, PlaceHolder): + ph = rv + rv = (self.loggerClass or _loggerClass)(name) + rv.manager = self + self.loggerDict[name] = rv + self._fixupChildren(ph, rv) + self._fixupParents(rv) + else: + rv = (self.loggerClass or _loggerClass)(name) + rv.manager = self + self.loggerDict[name] = rv + self._fixupParents(rv) + finally: + _releaseLock() + return rv + + def setLoggerClass(self, klass): + """ + Set the class to be used when instantiating a logger with this Manager. + """ + if klass != Logger: + if not issubclass(klass, Logger): + raise TypeError("logger not derived from logging.Logger: " + + klass.__name__) + self.loggerClass = klass + + def _fixupParents(self, alogger): + """ + Ensure that there are either loggers or placeholders all the way + from the specified logger to the root of the logger hierarchy. + """ + name = alogger.name + i = name.rfind(".") + rv = None + while (i > 0) and not rv: + substr = name[:i] + if substr not in self.loggerDict: + self.loggerDict[substr] = PlaceHolder(alogger) + else: + obj = self.loggerDict[substr] + if isinstance(obj, Logger): + rv = obj + else: + assert isinstance(obj, PlaceHolder) + obj.append(alogger) + i = name.rfind(".", 0, i - 1) + if not rv: + rv = self.root + alogger.parent = rv + + def _fixupChildren(self, ph, alogger): + """ + Ensure that children of the placeholder ph are connected to the + specified logger. + """ + name = alogger.name + namelen = len(name) + for c in ph.loggerMap.keys(): + #The if means ... if not c.parent.name.startswith(nm) + if c.parent.name[:namelen] != name: + alogger.parent = c.parent + c.parent = alogger + +#--------------------------------------------------------------------------- +# Logger classes and functions +#--------------------------------------------------------------------------- + +class Logger(Filterer): + """ + Instances of the Logger class represent a single logging channel. A + "logging channel" indicates an area of an application. Exactly how an + "area" is defined is up to the application developer. Since an + application can have any number of areas, logging channels are identified + by a unique string. Application areas can be nested (e.g. an area + of "input processing" might include sub-areas "read CSV files", "read + XLS files" and "read Gnumeric files"). To cater for this natural nesting, + channel names are organized into a namespace hierarchy where levels are + separated by periods, much like the Java or Python package namespace. So + in the instance given above, channel names might be "input" for the upper + level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels. + There is no arbitrary limit to the depth of nesting. + """ + def __init__(self, name, level=NOTSET): + """ + Initialize the logger with a name and an optional level. + """ + Filterer.__init__(self) + self.name = name + self.level = _checkLevel(level) + self.parent = None + self.propagate = 1 + self.handlers = [] + self.disabled = 0 + + def setLevel(self, level): + """ + Set the logging level of this logger. + """ + self.level = _checkLevel(level) + + def debug(self, msg, *args, **kwargs): + """ + Log 'msg % args' with severity 'DEBUG'. + + To pass exception information, use the keyword argument exc_info with + a true value, e.g. + + logger.debug("Houston, we have a %s", "thorny problem", exc_info=1) + """ + if self.isEnabledFor(DEBUG): + self._log(DEBUG, msg, args, **kwargs) + + def info(self, msg, *args, **kwargs): + """ + Log 'msg % args' with severity 'INFO'. + + To pass exception information, use the keyword argument exc_info with + a true value, e.g. + + logger.info("Houston, we have a %s", "interesting problem", exc_info=1) + """ + if self.isEnabledFor(INFO): + self._log(INFO, msg, args, **kwargs) + + def warning(self, msg, *args, **kwargs): + """ + Log 'msg % args' with severity 'WARNING'. + + To pass exception information, use the keyword argument exc_info with + a true value, e.g. + + logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1) + """ + if self.isEnabledFor(WARNING): + self._log(WARNING, msg, args, **kwargs) + + warn = warning + + def error(self, msg, *args, **kwargs): + """ + Log 'msg % args' with severity 'ERROR'. + + To pass exception information, use the keyword argument exc_info with + a true value, e.g. + + logger.error("Houston, we have a %s", "major problem", exc_info=1) + """ + if self.isEnabledFor(ERROR): + self._log(ERROR, msg, args, **kwargs) + + def exception(self, msg, *args, **kwargs): + """ + Convenience method for logging an ERROR with exception information. + """ + kwargs['exc_info'] = 1 + self.error(msg, *args, **kwargs) + + def critical(self, msg, *args, **kwargs): + """ + Log 'msg % args' with severity 'CRITICAL'. + + To pass exception information, use the keyword argument exc_info with + a true value, e.g. + + logger.critical("Houston, we have a %s", "major disaster", exc_info=1) + """ + if self.isEnabledFor(CRITICAL): + self._log(CRITICAL, msg, args, **kwargs) + + fatal = critical + + def log(self, level, msg, *args, **kwargs): + """ + Log 'msg % args' with the integer severity 'level'. + + To pass exception information, use the keyword argument exc_info with + a true value, e.g. + + logger.log(level, "We have a %s", "mysterious problem", exc_info=1) + """ + if not isinstance(level, int): + if raiseExceptions: + raise TypeError("level must be an integer") + else: + return + if self.isEnabledFor(level): + self._log(level, msg, args, **kwargs) + + def findCaller(self): + """ + Find the stack frame of the caller so that we can note the source + file name, line number and function name. + """ + f = currentframe() + #On some versions of IronPython, currentframe() returns None if + #IronPython isn't run with -X:Frames. + if f is not None: + f = f.f_back + rv = "(unknown file)", 0, "(unknown function)" + while hasattr(f, "f_code"): + co = f.f_code + filename = os.path.normcase(co.co_filename) + if filename == _srcfile: + f = f.f_back + continue + rv = (co.co_filename, f.f_lineno, co.co_name) + break + return rv + + def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None): + """ + A factory method which can be overridden in subclasses to create + specialized LogRecords. + """ + rv = LogRecord(name, level, fn, lno, msg, args, exc_info, func) + if extra is not None: + for key in extra: + if (key in ["message", "asctime"]) or (key in rv.__dict__): + raise KeyError("Attempt to overwrite %r in LogRecord" % key) + rv.__dict__[key] = extra[key] + return rv + + def _log(self, level, msg, args, exc_info=None, extra=None): + """ + Low-level logging routine which creates a LogRecord and then calls + all the handlers of this logger to handle the record. + """ + if _srcfile: + #IronPython doesn't track Python frames, so findCaller raises an + #exception on some versions of IronPython. We trap it here so that + #IronPython can use logging. + try: + fn, lno, func = self.findCaller() + except ValueError: + fn, lno, func = "(unknown file)", 0, "(unknown function)" + else: + fn, lno, func = "(unknown file)", 0, "(unknown function)" + if exc_info: + if not isinstance(exc_info, tuple): + exc_info = sys.exc_info() + record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info, func, extra) + self.handle(record) + + def handle(self, record): + """ + Call the handlers for the specified record. + + This method is used for unpickled records received from a socket, as + well as those created locally. Logger-level filtering is applied. + """ + if (not self.disabled) and self.filter(record): + self.callHandlers(record) + + def addHandler(self, hdlr): + """ + Add the specified handler to this logger. + """ + _acquireLock() + try: + if not (hdlr in self.handlers): + self.handlers.append(hdlr) + finally: + _releaseLock() + + def removeHandler(self, hdlr): + """ + Remove the specified handler from this logger. + """ + _acquireLock() + try: + if hdlr in self.handlers: + self.handlers.remove(hdlr) + finally: + _releaseLock() + + def callHandlers(self, record): + """ + Pass a record to all relevant handlers. + + Loop through all handlers for this logger and its parents in the + logger hierarchy. If no handler was found, output a one-off error + message to sys.stderr. Stop searching up the hierarchy whenever a + logger with the "propagate" attribute set to zero is found - that + will be the last logger whose handlers are called. + """ + c = self + found = 0 + while c: + for hdlr in c.handlers: + found = found + 1 + if record.levelno >= hdlr.level: + hdlr.handle(record) + if not c.propagate: + c = None #break out + else: + c = c.parent + if (found == 0) and raiseExceptions and not self.manager.emittedNoHandlerWarning: + sys.stderr.write("No handlers could be found for logger" + " \"%s\"\n" % self.name) + self.manager.emittedNoHandlerWarning = 1 + + def getEffectiveLevel(self): + """ + Get the effective level for this logger. + + Loop through this logger and its parents in the logger hierarchy, + looking for a non-zero logging level. Return the first one found. + """ + logger = self + while logger: + if logger.level: + return logger.level + logger = logger.parent + return NOTSET + + def isEnabledFor(self, level): + """ + Is this logger enabled for level 'level'? + """ + if self.manager.disable >= level: + return 0 + return level >= self.getEffectiveLevel() + + def getChild(self, suffix): + """ + Get a logger which is a descendant to this one. + + This is a convenience method, such that + + logging.getLogger('abc').getChild('def.ghi') + + is the same as + + logging.getLogger('abc.def.ghi') + + It's useful, for example, when the parent logger is named using + __name__ rather than a literal string. + """ + if self.root is not self: + suffix = '.'.join((self.name, suffix)) + return self.manager.getLogger(suffix) + +class RootLogger(Logger): + """ + A root logger is not that different to any other logger, except that + it must have a logging level and there is only one instance of it in + the hierarchy. + """ + def __init__(self, level): + """ + Initialize the logger with the name "root". + """ + Logger.__init__(self, "root", level) + +_loggerClass = Logger + +class LoggerAdapter(object): + """ + An adapter for loggers which makes it easier to specify contextual + information in logging output. + """ + + def __init__(self, logger, extra): + """ + Initialize the adapter with a logger and a dict-like object which + provides contextual information. This constructor signature allows + easy stacking of LoggerAdapters, if so desired. + + You can effectively pass keyword arguments as shown in the + following example: + + adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2")) + """ + self.logger = logger + self.extra = extra + + def process(self, msg, kwargs): + """ + Process the logging message and keyword arguments passed in to + a logging call to insert contextual information. You can either + manipulate the message itself, the keyword args or both. Return + the message and kwargs modified (or not) to suit your needs. + + Normally, you'll only need to override this one method in a + LoggerAdapter subclass for your specific needs. + """ + kwargs["extra"] = self.extra + return msg, kwargs + + def debug(self, msg, *args, **kwargs): + """ + Delegate a debug call to the underlying logger, after adding + contextual information from this adapter instance. + """ + msg, kwargs = self.process(msg, kwargs) + self.logger.debug(msg, *args, **kwargs) + + def info(self, msg, *args, **kwargs): + """ + Delegate an info call to the underlying logger, after adding + contextual information from this adapter instance. + """ + msg, kwargs = self.process(msg, kwargs) + self.logger.info(msg, *args, **kwargs) + + def warning(self, msg, *args, **kwargs): + """ + Delegate a warning call to the underlying logger, after adding + contextual information from this adapter instance. + """ + msg, kwargs = self.process(msg, kwargs) + self.logger.warning(msg, *args, **kwargs) + + def error(self, msg, *args, **kwargs): + """ + Delegate an error call to the underlying logger, after adding + contextual information from this adapter instance. + """ + msg, kwargs = self.process(msg, kwargs) + self.logger.error(msg, *args, **kwargs) + + def exception(self, msg, *args, **kwargs): + """ + Delegate an exception call to the underlying logger, after adding + contextual information from this adapter instance. + """ + msg, kwargs = self.process(msg, kwargs) + kwargs["exc_info"] = 1 + self.logger.error(msg, *args, **kwargs) + + def critical(self, msg, *args, **kwargs): + """ + Delegate a critical call to the underlying logger, after adding + contextual information from this adapter instance. + """ + msg, kwargs = self.process(msg, kwargs) + self.logger.critical(msg, *args, **kwargs) + + def log(self, level, msg, *args, **kwargs): + """ + Delegate a log call to the underlying logger, after adding + contextual information from this adapter instance. + """ + msg, kwargs = self.process(msg, kwargs) + self.logger.log(level, msg, *args, **kwargs) + + def isEnabledFor(self, level): + """ + See if the underlying logger is enabled for the specified level. + """ + return self.logger.isEnabledFor(level) + +root = RootLogger(WARNING) +Logger.root = root +Logger.manager = Manager(Logger.root) + +#--------------------------------------------------------------------------- +# Configuration classes and functions +#--------------------------------------------------------------------------- + +BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s" + +def basicConfig(**kwargs): + """ + Do basic configuration for the logging system. + + This function does nothing if the root logger already has handlers + configured. It is a convenience method intended for use by simple scripts + to do one-shot configuration of the logging package. + + The default behaviour is to create a StreamHandler which writes to + sys.stderr, set a formatter using the BASIC_FORMAT format string, and + add the handler to the root logger. + + A number of optional keyword arguments may be specified, which can alter + the default behaviour. + + filename Specifies that a FileHandler be created, using the specified + filename, rather than a StreamHandler. + filemode Specifies the mode to open the file, if filename is specified + (if filemode is unspecified, it defaults to 'a'). + format Use the specified format string for the handler. + datefmt Use the specified date/time format. + level Set the root logger level to the specified level. + stream Use the specified stream to initialize the StreamHandler. Note + that this argument is incompatible with 'filename' - if both + are present, 'stream' is ignored. + + Note that you could specify a stream created using open(filename, mode) + rather than passing the filename and mode in. However, it should be + remembered that StreamHandler does not close its stream (since it may be + using sys.stdout or sys.stderr), whereas FileHandler closes its stream + when the handler is closed. + """ + # Add thread safety in case someone mistakenly calls + # basicConfig() from multiple threads + _acquireLock() + try: + if len(root.handlers) == 0: + filename = kwargs.get("filename") + if filename: + mode = kwargs.get("filemode", 'a') + hdlr = FileHandler(filename, mode) + else: + stream = kwargs.get("stream") + hdlr = StreamHandler(stream) + fs = kwargs.get("format", BASIC_FORMAT) + dfs = kwargs.get("datefmt", None) + fmt = Formatter(fs, dfs) + hdlr.setFormatter(fmt) + root.addHandler(hdlr) + level = kwargs.get("level") + if level is not None: + root.setLevel(level) + finally: + _releaseLock() + +#--------------------------------------------------------------------------- +# Utility functions at module level. +# Basically delegate everything to the root logger. +#--------------------------------------------------------------------------- + +def getLogger(name=None): + """ + Return a logger with the specified name, creating it if necessary. + + If no name is specified, return the root logger. + """ + if name: + return Logger.manager.getLogger(name) + else: + return root + +#def getRootLogger(): +# """ +# Return the root logger. +# +# Note that getLogger('') now does the same thing, so this function is +# deprecated and may disappear in the future. +# """ +# return root + +def critical(msg, *args, **kwargs): + """ + Log a message with severity 'CRITICAL' on the root logger. + """ + if len(root.handlers) == 0: + basicConfig() + root.critical(msg, *args, **kwargs) + +fatal = critical + +def error(msg, *args, **kwargs): + """ + Log a message with severity 'ERROR' on the root logger. + """ + if len(root.handlers) == 0: + basicConfig() + root.error(msg, *args, **kwargs) + +def exception(msg, *args, **kwargs): + """ + Log a message with severity 'ERROR' on the root logger, + with exception information. + """ + kwargs['exc_info'] = 1 + error(msg, *args, **kwargs) + +def warning(msg, *args, **kwargs): + """ + Log a message with severity 'WARNING' on the root logger. + """ + if len(root.handlers) == 0: + basicConfig() + root.warning(msg, *args, **kwargs) + +warn = warning + +def info(msg, *args, **kwargs): + """ + Log a message with severity 'INFO' on the root logger. + """ + if len(root.handlers) == 0: + basicConfig() + root.info(msg, *args, **kwargs) + +def debug(msg, *args, **kwargs): + """ + Log a message with severity 'DEBUG' on the root logger. + """ + if len(root.handlers) == 0: + basicConfig() + root.debug(msg, *args, **kwargs) + +def log(level, msg, *args, **kwargs): + """ + Log 'msg % args' with the integer severity 'level' on the root logger. + """ + if len(root.handlers) == 0: + basicConfig() + root.log(level, msg, *args, **kwargs) + +def disable(level): + """ + Disable all logging calls of severity 'level' and below. + """ + root.manager.disable = level + +def shutdown(handlerList=_handlerList): + """ + Perform any cleanup actions in the logging system (e.g. flushing + buffers). + + Should be called at application exit. + """ + for wr in reversed(handlerList[:]): + #errors might occur, for example, if files are locked + #we just ignore them if raiseExceptions is not set + try: + h = wr() + if h: + try: + h.acquire() + h.flush() + h.close() + except (IOError, ValueError): + # Ignore errors which might be caused + # because handlers have been closed but + # references to them are still around at + # application exit. + pass + finally: + h.release() + except: + if raiseExceptions: + raise + #else, swallow + +#Let's try and shutdown automatically on application exit... +import atexit +atexit.register(shutdown) + +# Null handler + +class NullHandler(Handler): + """ + This handler does nothing. It's intended to be used to avoid the + "No handlers could be found for logger XXX" one-off warning. This is + important for library code, which may contain code to log events. If a user + of the library does not configure logging, the one-off warning might be + produced; to avoid this, the library developer simply needs to instantiate + a NullHandler and add it to the top-level logger of the library module or + package. + """ + def handle(self, record): + pass + + def emit(self, record): + pass + + def createLock(self): + self.lock = None + +# Warnings integration + +_warnings_showwarning = None + +def _showwarning(message, category, filename, lineno, file=None, line=None): + """ + Implementation of showwarnings which redirects to logging, which will first + check to see if the file parameter is None. If a file is specified, it will + delegate to the original warnings implementation of showwarning. Otherwise, + it will call warnings.formatwarning and will log the resulting string to a + warnings logger named "py.warnings" with level logging.WARNING. + """ + if file is not None: + if _warnings_showwarning is not None: + _warnings_showwarning(message, category, filename, lineno, file, line) + else: + s = warnings.formatwarning(message, category, filename, lineno, line) + logger = getLogger("py.warnings") + if not logger.handlers: + logger.addHandler(NullHandler()) + logger.warning("%s", s) + +def captureWarnings(capture): + """ + If capture is true, redirect all warnings to the logging package. + If capture is False, ensure that warnings are not redirected to logging + but to their original destinations. + """ + global _warnings_showwarning + if capture: + if _warnings_showwarning is None: + _warnings_showwarning = warnings.showwarning + warnings.showwarning = _showwarning + else: + if _warnings_showwarning is not None: + warnings.showwarning = _warnings_showwarning + _warnings_showwarning = None diff --git a/PythonHome/Lib/logging/__init__.pyc b/PythonHome/Lib/logging/__init__.pyc index 8b2538ec4a54cce1b1febc75af8ada9d1b55469d..2d2c96ec5085597dddc0b0d5b35feab4bce9b940 100644 GIT binary patch delta 7027 zcmbW5|4+4yD`pUK58)=!%b>T=a21A%fPE@4zNrMDIp5mAI;2{sza)-m?SLrf!~;gVxdEq1y(JX0EsGme;&|{L zK%DcM2yRkBs6_o?O^9a>jC)+WT?YwkXl{50BFsH*i0A}F+49B6*BD7fJNhxZ8j%;J z2SkUXf)uXg5j_i$<=q>qgJ*H^u1at{iHP_lpjhtBv-rm#*`ogqkn+Y6!wJZ=VDe_7 z4b(L4z73F^P>bG;w0nG!1;JCI$Z!lnc`f-QkAtW@B^t4Euk4?|K=Lv6B5s{2K?*lo zdEgqd_PIY_Q(FPY+?wvRwb=Dk65gh_n5cbG26DRJ8Fr(RSjlD zNhc?fEzTR&dS)+L>SUpxe4u+5ZNhA8=tOZosy*+#0gUH0ZedTo6E~UR5%{0DE-n|6rXwJBbbtxKs{66)gP!|$B>FXRU{ybST9L*@cL{N zt-euyR$V1&jH%aiG7R^^uC{lw7|Q9aQ#Pr;rZwH6~Q2 z61qF!t%7127a(0?;nF4oqT=nF(L9J$8`c8+nUSsK4^p8#5^12#3qv*JM$3>A$I2v1 zzP|)PIau3+6)5U>2)~<#w8QtchDZLW;h!BVK~%^?QN(n%W2;xJ?lMiCBwLqu#?-O@ zr=7CL53N+!>%c@sdLJ?fdH7oUKZBYVUZ9%tsV-^Ok-M2O* KURKV3|MwqN8tCW% delta 2944 zcmZ`*ZA^_}81C(ylw%F~n1h$oB11lA$Vxe-X|z7h>KrBcW?50Fsfl6;CAOys&9p-b zeYp*BMni@CV4B3y^yT}EgG|GC?|z>9_V>D;>$>jydG6zb%Kp0#G94nBmxJ?y6Q87YhlEiCTfJed9Tw+10Zx=5#2sK zRPV%U;)fNF-#CMPb3}1cJ0~#LC(|orPtD`jLgSWb)*RNRjbXch`{}_v5wqRE5wiG} z5$>1`TQaAxxuR!BqvPWKY3BS#@b4?cQ2>o&*)uQM!eciCzIv7c7HyCw7cl8n} z0tF+lJ)$YtjZfV?R!~*fLle;Hm1Pu9EVw<9jex59{}A$>NxY)qF7vaa%nCR+_%VtS z84fj41#~opFsqfOQyy5jrbYV0^&AcpnmyfE;>c4SpU~Ixg$R`S6~52j6Wq}H*Aau= z&j;|vPue~?F7AK6TwmHa90ILs-YEYSf93bJS5N_d@v>eYWe;AMx+0ipS$yq^WpJ%1 j><;E|(Dk^|E24Y|A^qJkS`yBp@k1#s34c{XY`^{iZr!y{ diff --git a/PythonHome/Lib/logging/config.py b/PythonHome/Lib/logging/config.py new file mode 100644 index 0000000000..8b3795675d --- /dev/null +++ b/PythonHome/Lib/logging/config.py @@ -0,0 +1,919 @@ +# Copyright 2001-2014 by Vinay Sajip. 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 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. + +""" +Configuration functions for the logging package for Python. The core package +is based on PEP 282 and comments thereto in comp.lang.python, and influenced +by Apache's log4j system. + +Copyright (C) 2001-2014 Vinay Sajip. All Rights Reserved. + +To use, simply 'import logging' and log away! +""" + +import cStringIO +import errno +import io +import logging +import logging.handlers +import os +import re +import socket +import struct +import sys +import traceback +import types + +try: + import thread + import threading +except ImportError: + thread = None + +from SocketServer import ThreadingTCPServer, StreamRequestHandler + + +DEFAULT_LOGGING_CONFIG_PORT = 9030 + +RESET_ERROR = errno.ECONNRESET + +# +# The following code implements a socket listener for on-the-fly +# reconfiguration of logging. +# +# _listener holds the server object doing the listening +_listener = None + +def fileConfig(fname, defaults=None, disable_existing_loggers=True): + """ + Read the logging configuration from a ConfigParser-format file. + + This can be called several times from an application, allowing an end user + the ability to select from various pre-canned configurations (if the + developer provides a mechanism to present the choices and load the chosen + configuration). + """ + import ConfigParser + + cp = ConfigParser.ConfigParser(defaults) + if hasattr(fname, 'readline'): + cp.readfp(fname) + else: + cp.read(fname) + + formatters = _create_formatters(cp) + + # critical section + logging._acquireLock() + try: + logging._handlers.clear() + del logging._handlerList[:] + # Handlers add themselves to logging._handlers + handlers = _install_handlers(cp, formatters) + _install_loggers(cp, handlers, disable_existing_loggers) + finally: + logging._releaseLock() + + +def _resolve(name): + """Resolve a dotted name to a global object.""" + name = name.split('.') + used = name.pop(0) + found = __import__(used) + for n in name: + used = used + '.' + n + try: + found = getattr(found, n) + except AttributeError: + __import__(used) + found = getattr(found, n) + return found + +def _strip_spaces(alist): + return map(lambda x: x.strip(), alist) + +def _encoded(s): + return s if isinstance(s, str) else s.encode('utf-8') + +def _create_formatters(cp): + """Create and return formatters""" + flist = cp.get("formatters", "keys") + if not len(flist): + return {} + flist = flist.split(",") + flist = _strip_spaces(flist) + formatters = {} + for form in flist: + sectname = "formatter_%s" % form + opts = cp.options(sectname) + if "format" in opts: + fs = cp.get(sectname, "format", 1) + else: + fs = None + if "datefmt" in opts: + dfs = cp.get(sectname, "datefmt", 1) + else: + dfs = None + c = logging.Formatter + if "class" in opts: + class_name = cp.get(sectname, "class") + if class_name: + c = _resolve(class_name) + f = c(fs, dfs) + formatters[form] = f + return formatters + + +def _install_handlers(cp, formatters): + """Install and return handlers""" + hlist = cp.get("handlers", "keys") + if not len(hlist): + return {} + hlist = hlist.split(",") + hlist = _strip_spaces(hlist) + handlers = {} + fixups = [] #for inter-handler references + for hand in hlist: + sectname = "handler_%s" % hand + klass = cp.get(sectname, "class") + opts = cp.options(sectname) + if "formatter" in opts: + fmt = cp.get(sectname, "formatter") + else: + fmt = "" + try: + klass = eval(klass, vars(logging)) + except (AttributeError, NameError): + klass = _resolve(klass) + args = cp.get(sectname, "args") + args = eval(args, vars(logging)) + h = klass(*args) + if "level" in opts: + level = cp.get(sectname, "level") + h.setLevel(logging._levelNames[level]) + if len(fmt): + h.setFormatter(formatters[fmt]) + if issubclass(klass, logging.handlers.MemoryHandler): + if "target" in opts: + target = cp.get(sectname,"target") + else: + target = "" + if len(target): #the target handler may not be loaded yet, so keep for later... + fixups.append((h, target)) + handlers[hand] = h + #now all handlers are loaded, fixup inter-handler references... + for h, t in fixups: + h.setTarget(handlers[t]) + return handlers + + +def _install_loggers(cp, handlers, disable_existing_loggers): + """Create and install loggers""" + + # configure the root first + llist = cp.get("loggers", "keys") + llist = llist.split(",") + llist = list(map(lambda x: x.strip(), llist)) + llist.remove("root") + sectname = "logger_root" + root = logging.root + log = root + opts = cp.options(sectname) + if "level" in opts: + level = cp.get(sectname, "level") + log.setLevel(logging._levelNames[level]) + for h in root.handlers[:]: + root.removeHandler(h) + hlist = cp.get(sectname, "handlers") + if len(hlist): + hlist = hlist.split(",") + hlist = _strip_spaces(hlist) + for hand in hlist: + log.addHandler(handlers[hand]) + + #and now the others... + #we don't want to lose the existing loggers, + #since other threads may have pointers to them. + #existing is set to contain all existing loggers, + #and as we go through the new configuration we + #remove any which are configured. At the end, + #what's left in existing is the set of loggers + #which were in the previous configuration but + #which are not in the new configuration. + existing = list(root.manager.loggerDict.keys()) + #The list needs to be sorted so that we can + #avoid disabling child loggers of explicitly + #named loggers. With a sorted list it is easier + #to find the child loggers. + existing.sort() + #We'll keep the list of existing loggers + #which are children of named loggers here... + child_loggers = [] + #now set up the new ones... + for log in llist: + sectname = "logger_%s" % log + qn = cp.get(sectname, "qualname") + opts = cp.options(sectname) + if "propagate" in opts: + propagate = cp.getint(sectname, "propagate") + else: + propagate = 1 + logger = logging.getLogger(qn) + if qn in existing: + i = existing.index(qn) + 1 # start with the entry after qn + prefixed = qn + "." + pflen = len(prefixed) + num_existing = len(existing) + while i < num_existing: + if existing[i][:pflen] == prefixed: + child_loggers.append(existing[i]) + i += 1 + existing.remove(qn) + if "level" in opts: + level = cp.get(sectname, "level") + logger.setLevel(logging._levelNames[level]) + for h in logger.handlers[:]: + logger.removeHandler(h) + logger.propagate = propagate + logger.disabled = 0 + hlist = cp.get(sectname, "handlers") + if len(hlist): + hlist = hlist.split(",") + hlist = _strip_spaces(hlist) + for hand in hlist: + logger.addHandler(handlers[hand]) + + #Disable any old loggers. There's no point deleting + #them as other threads may continue to hold references + #and by disabling them, you stop them doing any logging. + #However, don't disable children of named loggers, as that's + #probably not what was intended by the user. + for log in existing: + logger = root.manager.loggerDict[log] + if log in child_loggers: + logger.level = logging.NOTSET + logger.handlers = [] + logger.propagate = 1 + else: + logger.disabled = disable_existing_loggers + + + +IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I) + + +def valid_ident(s): + m = IDENTIFIER.match(s) + if not m: + raise ValueError('Not a valid Python identifier: %r' % s) + return True + + +class ConvertingMixin(object): + """For ConvertingXXX's, this mixin class provides common functions""" + + def convert_with_key(self, key, value, replace=True): + result = self.configurator.convert(value) + #If the converted value is different, save for next time + if value is not result: + if replace: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def convert(self, value): + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + return result + + +# The ConvertingXXX classes are wrappers around standard Python containers, +# and they serve to convert any suitable values in the container. The +# conversion converts base dicts, lists and tuples to their wrapped +# equivalents, whereas strings which match a conversion format are converted +# appropriately. +# +# Each wrapper should have a configurator attribute holding the actual +# configurator to use for conversion. + +class ConvertingDict(dict, ConvertingMixin): + """A converting dictionary wrapper.""" + + def __getitem__(self, key): + value = dict.__getitem__(self, key) + return self.convert_with_key(key, value) + + def get(self, key, default=None): + value = dict.get(self, key, default) + return self.convert_with_key(key, value) + + def pop(self, key, default=None): + value = dict.pop(self, key, default) + return self.convert_with_key(key, value, replace=False) + +class ConvertingList(list, ConvertingMixin): + """A converting list wrapper.""" + def __getitem__(self, key): + value = list.__getitem__(self, key) + return self.convert_with_key(key, value) + + def pop(self, idx=-1): + value = list.pop(self, idx) + return self.convert(value) + +class ConvertingTuple(tuple, ConvertingMixin): + """A converting tuple wrapper.""" + def __getitem__(self, key): + value = tuple.__getitem__(self, key) + # Can't replace a tuple entry. + return self.convert_with_key(key, value, replace=False) + +class BaseConfigurator(object): + """ + The configurator base class which defines some useful defaults. + """ + + CONVERT_PATTERN = re.compile(r'^(?P[a-z]+)://(?P.*)$') + + WORD_PATTERN = re.compile(r'^\s*(\w+)\s*') + DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*') + INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*') + DIGIT_PATTERN = re.compile(r'^\d+$') + + value_converters = { + 'ext' : 'ext_convert', + 'cfg' : 'cfg_convert', + } + + # We might want to use a different one, e.g. importlib + importer = __import__ + + def __init__(self, config): + self.config = ConvertingDict(config) + self.config.configurator = self + # Issue 12718: winpdb replaces __import__ with a Python function, which + # ends up being treated as a bound method. To avoid problems, we + # set the importer on the instance, but leave it defined in the class + # so existing code doesn't break + if type(__import__) == types.FunctionType: + self.importer = __import__ + + def resolve(self, s): + """ + Resolve strings to objects using standard import and attribute + syntax. + """ + name = s.split('.') + used = name.pop(0) + try: + found = self.importer(used) + for frag in name: + used += '.' + frag + try: + found = getattr(found, frag) + except AttributeError: + self.importer(used) + found = getattr(found, frag) + return found + except ImportError: + e, tb = sys.exc_info()[1:] + v = ValueError('Cannot resolve %r: %s' % (s, e)) + v.__cause__, v.__traceback__ = e, tb + raise v + + def ext_convert(self, value): + """Default converter for the ext:// protocol.""" + return self.resolve(value) + + def cfg_convert(self, value): + """Default converter for the cfg:// protocol.""" + rest = value + m = self.WORD_PATTERN.match(rest) + if m is None: + raise ValueError("Unable to convert %r" % value) + else: + rest = rest[m.end():] + d = self.config[m.groups()[0]] + #print d, rest + while rest: + m = self.DOT_PATTERN.match(rest) + if m: + d = d[m.groups()[0]] + else: + m = self.INDEX_PATTERN.match(rest) + if m: + idx = m.groups()[0] + if not self.DIGIT_PATTERN.match(idx): + d = d[idx] + else: + try: + n = int(idx) # try as number first (most likely) + d = d[n] + except TypeError: + d = d[idx] + if m: + rest = rest[m.end():] + else: + raise ValueError('Unable to convert ' + '%r at %r' % (value, rest)) + #rest should be empty + return d + + def convert(self, value): + """ + Convert values to an appropriate type. dicts, lists and tuples are + replaced by their converting alternatives. Strings are checked to + see if they have a conversion format and are converted if they do. + """ + if not isinstance(value, ConvertingDict) and isinstance(value, dict): + value = ConvertingDict(value) + value.configurator = self + elif not isinstance(value, ConvertingList) and isinstance(value, list): + value = ConvertingList(value) + value.configurator = self + elif not isinstance(value, ConvertingTuple) and\ + isinstance(value, tuple): + value = ConvertingTuple(value) + value.configurator = self + elif isinstance(value, basestring): # str for py3k + m = self.CONVERT_PATTERN.match(value) + if m: + d = m.groupdict() + prefix = d['prefix'] + converter = self.value_converters.get(prefix, None) + if converter: + suffix = d['suffix'] + converter = getattr(self, converter) + value = converter(suffix) + return value + + def configure_custom(self, config): + """Configure an object with a user-supplied factory.""" + c = config.pop('()') + if not hasattr(c, '__call__') and hasattr(types, 'ClassType') and type(c) != types.ClassType: + c = self.resolve(c) + props = config.pop('.', None) + # Check for valid identifiers + kwargs = dict([(k, config[k]) for k in config if valid_ident(k)]) + result = c(**kwargs) + if props: + for name, value in props.items(): + setattr(result, name, value) + return result + + def as_tuple(self, value): + """Utility function which converts lists to tuples.""" + if isinstance(value, list): + value = tuple(value) + return value + +class DictConfigurator(BaseConfigurator): + """ + Configure logging using a dictionary-like object to describe the + configuration. + """ + + def configure(self): + """Do the configuration.""" + + config = self.config + if 'version' not in config: + raise ValueError("dictionary doesn't specify a version") + if config['version'] != 1: + raise ValueError("Unsupported version: %s" % config['version']) + incremental = config.pop('incremental', False) + EMPTY_DICT = {} + logging._acquireLock() + try: + if incremental: + handlers = config.get('handlers', EMPTY_DICT) + for name in handlers: + if name not in logging._handlers: + raise ValueError('No handler found with ' + 'name %r' % name) + else: + try: + handler = logging._handlers[name] + handler_config = handlers[name] + level = handler_config.get('level', None) + if level: + handler.setLevel(logging._checkLevel(level)) + except StandardError as e: + raise ValueError('Unable to configure handler ' + '%r: %s' % (name, e)) + loggers = config.get('loggers', EMPTY_DICT) + for name in loggers: + try: + self.configure_logger(name, loggers[name], True) + except StandardError as e: + raise ValueError('Unable to configure logger ' + '%r: %s' % (name, e)) + root = config.get('root', None) + if root: + try: + self.configure_root(root, True) + except StandardError as e: + raise ValueError('Unable to configure root ' + 'logger: %s' % e) + else: + disable_existing = config.pop('disable_existing_loggers', True) + + logging._handlers.clear() + del logging._handlerList[:] + + # Do formatters first - they don't refer to anything else + formatters = config.get('formatters', EMPTY_DICT) + for name in formatters: + try: + formatters[name] = self.configure_formatter( + formatters[name]) + except StandardError as e: + raise ValueError('Unable to configure ' + 'formatter %r: %s' % (name, e)) + # Next, do filters - they don't refer to anything else, either + filters = config.get('filters', EMPTY_DICT) + for name in filters: + try: + filters[name] = self.configure_filter(filters[name]) + except StandardError as e: + raise ValueError('Unable to configure ' + 'filter %r: %s' % (name, e)) + + # Next, do handlers - they refer to formatters and filters + # As handlers can refer to other handlers, sort the keys + # to allow a deterministic order of configuration + handlers = config.get('handlers', EMPTY_DICT) + deferred = [] + for name in sorted(handlers): + try: + handler = self.configure_handler(handlers[name]) + handler.name = name + handlers[name] = handler + except StandardError as e: + if 'target not configured yet' in str(e): + deferred.append(name) + else: + raise ValueError('Unable to configure handler ' + '%r: %s' % (name, e)) + + # Now do any that were deferred + for name in deferred: + try: + handler = self.configure_handler(handlers[name]) + handler.name = name + handlers[name] = handler + except StandardError as e: + raise ValueError('Unable to configure handler ' + '%r: %s' % (name, e)) + + # Next, do loggers - they refer to handlers and filters + + #we don't want to lose the existing loggers, + #since other threads may have pointers to them. + #existing is set to contain all existing loggers, + #and as we go through the new configuration we + #remove any which are configured. At the end, + #what's left in existing is the set of loggers + #which were in the previous configuration but + #which are not in the new configuration. + root = logging.root + existing = root.manager.loggerDict.keys() + #The list needs to be sorted so that we can + #avoid disabling child loggers of explicitly + #named loggers. With a sorted list it is easier + #to find the child loggers. + existing.sort() + #We'll keep the list of existing loggers + #which are children of named loggers here... + child_loggers = [] + #now set up the new ones... + loggers = config.get('loggers', EMPTY_DICT) + for name in loggers: + name = _encoded(name) + if name in existing: + i = existing.index(name) + prefixed = name + "." + pflen = len(prefixed) + num_existing = len(existing) + i = i + 1 # look at the entry after name + while (i < num_existing) and\ + (existing[i][:pflen] == prefixed): + child_loggers.append(existing[i]) + i = i + 1 + existing.remove(name) + try: + self.configure_logger(name, loggers[name]) + except StandardError as e: + raise ValueError('Unable to configure logger ' + '%r: %s' % (name, e)) + + #Disable any old loggers. There's no point deleting + #them as other threads may continue to hold references + #and by disabling them, you stop them doing any logging. + #However, don't disable children of named loggers, as that's + #probably not what was intended by the user. + for log in existing: + logger = root.manager.loggerDict[log] + if log in child_loggers: + logger.level = logging.NOTSET + logger.handlers = [] + logger.propagate = True + elif disable_existing: + logger.disabled = True + + # And finally, do the root logger + root = config.get('root', None) + if root: + try: + self.configure_root(root) + except StandardError as e: + raise ValueError('Unable to configure root ' + 'logger: %s' % e) + finally: + logging._releaseLock() + + def configure_formatter(self, config): + """Configure a formatter from a dictionary.""" + if '()' in config: + factory = config['()'] # for use in exception handler + try: + result = self.configure_custom(config) + except TypeError as te: + if "'format'" not in str(te): + raise + #Name of parameter changed from fmt to format. + #Retry with old name. + #This is so that code can be used with older Python versions + #(e.g. by Django) + config['fmt'] = config.pop('format') + config['()'] = factory + result = self.configure_custom(config) + else: + fmt = config.get('format', None) + dfmt = config.get('datefmt', None) + result = logging.Formatter(fmt, dfmt) + return result + + def configure_filter(self, config): + """Configure a filter from a dictionary.""" + if '()' in config: + result = self.configure_custom(config) + else: + name = config.get('name', '') + result = logging.Filter(name) + return result + + def add_filters(self, filterer, filters): + """Add filters to a filterer from a list of names.""" + for f in filters: + try: + filterer.addFilter(self.config['filters'][f]) + except StandardError as e: + raise ValueError('Unable to add filter %r: %s' % (f, e)) + + def configure_handler(self, config): + """Configure a handler from a dictionary.""" + formatter = config.pop('formatter', None) + if formatter: + try: + formatter = self.config['formatters'][formatter] + except StandardError as e: + raise ValueError('Unable to set formatter ' + '%r: %s' % (formatter, e)) + level = config.pop('level', None) + filters = config.pop('filters', None) + if '()' in config: + c = config.pop('()') + if not hasattr(c, '__call__') and hasattr(types, 'ClassType') and type(c) != types.ClassType: + c = self.resolve(c) + factory = c + else: + cname = config.pop('class') + klass = self.resolve(cname) + #Special case for handler which refers to another handler + if issubclass(klass, logging.handlers.MemoryHandler) and\ + 'target' in config: + try: + th = self.config['handlers'][config['target']] + if not isinstance(th, logging.Handler): + config['class'] = cname # restore for deferred configuration + raise StandardError('target not configured yet') + config['target'] = th + except StandardError as e: + raise ValueError('Unable to set target handler ' + '%r: %s' % (config['target'], e)) + elif issubclass(klass, logging.handlers.SMTPHandler) and\ + 'mailhost' in config: + config['mailhost'] = self.as_tuple(config['mailhost']) + elif issubclass(klass, logging.handlers.SysLogHandler) and\ + 'address' in config: + config['address'] = self.as_tuple(config['address']) + factory = klass + kwargs = dict([(k, config[k]) for k in config if valid_ident(k)]) + try: + result = factory(**kwargs) + except TypeError as te: + if "'stream'" not in str(te): + raise + #The argument name changed from strm to stream + #Retry with old name. + #This is so that code can be used with older Python versions + #(e.g. by Django) + kwargs['strm'] = kwargs.pop('stream') + result = factory(**kwargs) + if formatter: + result.setFormatter(formatter) + if level is not None: + result.setLevel(logging._checkLevel(level)) + if filters: + self.add_filters(result, filters) + return result + + def add_handlers(self, logger, handlers): + """Add handlers to a logger from a list of names.""" + for h in handlers: + try: + logger.addHandler(self.config['handlers'][h]) + except StandardError as e: + raise ValueError('Unable to add handler %r: %s' % (h, e)) + + def common_logger_config(self, logger, config, incremental=False): + """ + Perform configuration which is common to root and non-root loggers. + """ + level = config.get('level', None) + if level is not None: + logger.setLevel(logging._checkLevel(level)) + if not incremental: + #Remove any existing handlers + for h in logger.handlers[:]: + logger.removeHandler(h) + handlers = config.get('handlers', None) + if handlers: + self.add_handlers(logger, handlers) + filters = config.get('filters', None) + if filters: + self.add_filters(logger, filters) + + def configure_logger(self, name, config, incremental=False): + """Configure a non-root logger from a dictionary.""" + logger = logging.getLogger(name) + self.common_logger_config(logger, config, incremental) + propagate = config.get('propagate', None) + if propagate is not None: + logger.propagate = propagate + + def configure_root(self, config, incremental=False): + """Configure a root logger from a dictionary.""" + root = logging.getLogger() + self.common_logger_config(root, config, incremental) + +dictConfigClass = DictConfigurator + +def dictConfig(config): + """Configure logging using a dictionary.""" + dictConfigClass(config).configure() + + +def listen(port=DEFAULT_LOGGING_CONFIG_PORT): + """ + Start up a socket server on the specified port, and listen for new + configurations. + + These will be sent as a file suitable for processing by fileConfig(). + Returns a Thread object on which you can call start() to start the server, + and which you can join() when appropriate. To stop the server, call + stopListening(). + """ + if not thread: + raise NotImplementedError("listen() needs threading to work") + + class ConfigStreamHandler(StreamRequestHandler): + """ + Handler for a logging configuration request. + + It expects a completely new logging configuration and uses fileConfig + to install it. + """ + def handle(self): + """ + Handle a request. + + Each request is expected to be a 4-byte length, packed using + struct.pack(">L", n), followed by the config file. + Uses fileConfig() to do the grunt work. + """ + import tempfile + try: + conn = self.connection + chunk = conn.recv(4) + if len(chunk) == 4: + slen = struct.unpack(">L", chunk)[0] + chunk = self.connection.recv(slen) + while len(chunk) < slen: + chunk = chunk + conn.recv(slen - len(chunk)) + try: + import json + d =json.loads(chunk) + assert isinstance(d, dict) + dictConfig(d) + except: + #Apply new configuration. + + file = cStringIO.StringIO(chunk) + try: + fileConfig(file) + except (KeyboardInterrupt, SystemExit): + raise + except: + traceback.print_exc() + if self.server.ready: + self.server.ready.set() + except socket.error as e: + if e.errno != RESET_ERROR: + raise + + class ConfigSocketReceiver(ThreadingTCPServer): + """ + A simple TCP socket-based logging config receiver. + """ + + allow_reuse_address = 1 + + def __init__(self, host='localhost', port=DEFAULT_LOGGING_CONFIG_PORT, + handler=None, ready=None): + ThreadingTCPServer.__init__(self, (host, port), handler) + logging._acquireLock() + self.abort = 0 + logging._releaseLock() + self.timeout = 1 + self.ready = ready + + def serve_until_stopped(self): + import select + abort = 0 + while not abort: + rd, wr, ex = select.select([self.socket.fileno()], + [], [], + self.timeout) + if rd: + self.handle_request() + logging._acquireLock() + abort = self.abort + logging._releaseLock() + self.socket.close() + + class Server(threading.Thread): + + def __init__(self, rcvr, hdlr, port): + super(Server, self).__init__() + self.rcvr = rcvr + self.hdlr = hdlr + self.port = port + self.ready = threading.Event() + + def run(self): + server = self.rcvr(port=self.port, handler=self.hdlr, + ready=self.ready) + if self.port == 0: + self.port = server.server_address[1] + self.ready.set() + global _listener + logging._acquireLock() + _listener = server + logging._releaseLock() + server.serve_until_stopped() + + return Server(ConfigSocketReceiver, ConfigStreamHandler, port) + +def stopListening(): + """ + Stop the listening server which was created with a call to listen(). + """ + global _listener + logging._acquireLock() + try: + if _listener: + _listener.abort = 1 + _listener = None + finally: + logging._releaseLock() diff --git a/PythonHome/Lib/logging/config.pyc b/PythonHome/Lib/logging/config.pyc deleted file mode 100644 index a0369b5b107b942b9ad38099f27aba90e1324039..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25686 zcmc(ndvILWec#XB#cM$jBmur4QPPSMO;94Chh@uASlJXoS+ppSxqt*3Cb?ejUJwf| zc7b~rB%qKAEh>)VSDHti^bb36CU#r5nNHhu>@;@AZPRpGcUpHk?LVD%YCHBMp0=LE zP7}{~>VCezbMNkgq*6ldOiAwHx#yne@BH59cW(asTL-^1`@!joOaJup|9ki)+j7oT zotq;KTs7zFftw@a^Eo${%kp_Qm(TJ&ZmuWG_jcv`++1H)-tXr6v;2UY8_4nnH&@8= zgKlmx%WrXWTeAF+n;UZL`?ANaZf_XaZC8~>;Ld91 zc~{@zmPXv%h+7(UbE7V(GUJ^t%DKf|Zf>`udU=o1Xs@gGx;I$on5*`=Hvq&vuG(*z zdtG(FGR&i3nfqLI&@%VC>K4m9;G%xFSaj7P%RK0A($#)f-D+9gd zbng9g2V9kb-{ztNZXW3FXumk_!=Axahdarwf{eIk4_gUc+!hq@V`-B(|1kMc}Z#L#@ zmsaC)tJZ83=T{pQWs>52GcL9kqGG*y=~At6skmIOTrOXVto+P+YoXbgD9-S{(u||* zgC3ziDm2Vu+^+J z=Ig6bqY_mIFRmAlG3r8eFwrcYS}Z2(Nh?~K7-Z7R>v8SULaR7_{7~`9#~**<$divh z@l^4ZTBE#PoGvfcmM4nG>h)r%N=Y${k|@3sRcSiYEUqTe;bKx-TCT4b5At6#Ze`0n zXp>;HV)<%${lUT7kNGn-4h6Z^2+7Ps9F?oUW9ImoX>}R5c2YduqIfBcR#u~=^#Uud zM{(`>hn%bAdE3vghu?92$>&K@+H>xD-d)SPMdz*s?q=Yw_qbNzu2CT`G>e~c*LvJy zP9?kz8e8p|HvYNQqi412b*)~v*eC1@UVYjgK-vL&)|-NRvNfp6*Lv0Q^*-0yVvl|9 zTF%|fyI>ZyP|YE0bJmbVb516OBt`y&EPMk-R5oHx+*~S_iyocMlw$yX1RPo_w~F(% zdIaRv$;<*MQYklz7r~rzy$-4*5l}4Gi>=yH1ln0QjbeFuxn8RnQi2%udh@D~kcJWH z#0JLJoe;Equ~x6O){9_O64j#$dO^VBLbc6vLjI?3GNpZY3uk~0*RVGny zE=Mu-n^$U8W>PLLMU{neqn0eGZ~93a|8RzLkg85J@-GT0)nFa#C)!;#OZ;eSVqE_ALz$OBFh4MI{g6Rum`JEG1U! zvsA9Etk&Y_RI_rqRiJT+#RxGI_8H8qN9EX8Ov_Kzl2&VnD%KiF3z&BrZ0|1BAnHXE zFU5cyiq|0Hnz;2n-zYCdw$y4gUtX=ZlGa|{RclH4Vm&HFYmCHpmeQWWyc&weD$Ag$ zb6u+vys~+ZlXsRR50X3n%sJ19o_zXTy>{_jy7+S*`r<0q7s%(qdz3cGJ?f({l-m|; z3%2LB=7#cvK|a_T^i#4kR{`0LR0a3r{E|FR6NUXme$kb0#0-6~EQsS0e$IEO=`NMi-nAFyI<&Cq5yUu3 ziRM{K5Rp-$%}qo>?hc?SQVeKVF&iVfGOGNvAYi&5c$|VN(UewO^GDugXl4XdON<>L zk_}rJ)wmKex>=1nU`jT<2-|MoO|{Or-SgkVv*u!3dmr22x62DoNigURNogdR>~}1G zng=Zh>hfd>v3ZIO^cs3w`}ZoDJpVNjXBAnPce|0e>bXmhqAVgLFZa3l6X~FcO$yN+ zk&{Ty2KsM78I;Jh<`=taq7nO={aMX^2f!Bl-E|b?fvm}ox|$%TSy91VE4cVa4!%i7 zix_Y#KXMJ$P6>j#->M?Mz)tD z6e;2M;Y3WlU8Qs&vAy*LHPtXyP({?tFSU$1D)n-bOpO=xPS^~au>b2(BNUSl4`!`k zE7Bxw#HnT@3bo-TiJs5q6h27NxHdZ+)k|&pyeOhGSIxylNdhZt^Bek3Ok&I@HhPu+ zHQkD#tj)1xl~p*uS=0>2t+K?M#LID&Z;2Dj?%|KO9jIE^oe%RJPvu$p1yZVa19$?v}BYm!Gq(K`A z%hH2jtM$EAE2oLn?;V=NwXIsWMql~5CZHmAsMj4`Ipb#64oI1vJb#}%$E>%w>kQAV zMy$@TpY_VOgIStP8@4C+f*dEkmeozHnWhu&;(d5Ti7?OvR{9Pa4WFRQ2&qlEuy=|i ziOcaNui(|C(i%CpD2rO-qOkBuC2v>KCf4vN9<6P3rChfR%5!4m8t&6O5&IO%g-L&- z*_0w%r)&@raLL9~Ew33SQL9bnsT@gGFB)aq>ROUvFGWkuc>M*hm)cy>`_b@iM0%L< zGZ#4-gYaxYTw=kvgurCY=4)%K%bwK;PT^1Jh3Z`vy9%Gtqqr4ZEPPH6;tLC*=rf$m zo;NLrL#+WccF7AQZUdk2oI*TdDA)zB$OmI+FWcb~yC@OI*h9M0p7ef*_rtkSp3P>| z%Gv^Og{gbm=mQ*b5twk!i*v3qAYQl^sh{UKgSos2i%CjiC zYV!tY8uEkE9tg;E76Ze8qV3i7LASPF`N{KpL|U-8MW_pE-;&Z*5X_1rAQ2hS$Q_cs zX%?~=$dKre$3XmZt6Tfm0RWji|NDU?I7{ejD*=Fw$$5Uj5KOllC=Bg^@*BoHP@$;2 z#hAx7V;)29`Zj~hPIqlstGd2j873gE`(jQr*_FP+nY8CRjAdAUq&?S1WCdPhnl!>p zuvsg=)2%({u2FBNyNvPojQZel?AoX+QvEV)?MM#Rw76Tt=nbumJ?)Uc>S=~p`5|nF zk&zTODZTA%@Qqw&SK1rAU7mwGZZL1UHkhZ*27fF!du^M$w%wKX$R(!C-Y)F9eaolr ze#;qXZ8hkBFt7ED*|hGFB-Q-zO9C{T z@ydO9sZ=&;^0WBzrpIMbn7!DgRHc@&xr@4uZmCyoc3ly3$$r!7uPv4;INh4cXE!Ry|(kr|l%jHX` zd#3z_dnl^$!#tA2^3p?s!-g^zd_Yg$O|jIx;+4E`R+S}ILNUhhq!Q!RVwf>Z|4NiH zeJ_g+Qfxw^T&-r(pr5j(as!`ZY_I&RCu^0KLE2`J;JUNHk#Ds|%ftrRQ|6&y%b9(n z8m)ydkqdEvOSuOBy&s}#EvHV;OrMxB2#srsUd~uf4nOOpZYz~cv6Y!5VLB#OJZxw5 z?zEDhQX`F$c{xnbRTgUXYUb}S#dW3OCnV7MrI}2sSzDYQ*P-U3UnFhcgx=1!F*p%Hg`vo>D?$L zl43Yb_&bbT>$ES>W2cXO{afwr5T!%8L@>SZf%1`8OXrn7e&i=g=O204C`O7ig3c?= zhsmJSAQRwF;)P_;mB+>C5rP!%ru6kd_7VG$*{=`MY^vERmhu19Yt^E65EXIgHCna# zS`maX_&Th_bnmDDn0Ze zO49$w`6UY^UTkQ0Oe>Zd4gbWKg$Y}g`Vl{&N2;-FM^pK13I>}6NCEeJ-dHoWP4Jdr z)^yk7O8su7YG!W_+bU2`jSEah0p7Q#(+VhG9D)L^%yy}@z8tlL=AGq=UEET1N^Z`L zpq^P>u1CfVmdi1iVg!zn?7d}LIG*MC@Mkm&fr4FJjcoWhTCU@NNf}^*t8>$6Au*G# zqI9*^S|~AaQMe&ealuH=Tb-i10+>?C$fUg=r>NH15AX9}Gi-0PA1|14Wcze0@Lw?C z=N!OadBI>VubGFrpc{%;gzHLPRr1qH7|VtDL0$M7i8+eG8+!bZlA9{yw<+GF5e{q3 zLu%RP9@~O(u}5QxC9~)8O^R+yrKM(d6<4x%RhCNCW~EdLVHhraLy0=<%))Ya=Q9qk z(oznmL?ibFeYv3_TlVdg_!t$sDG|2B*g8V>ln6>mbNKlxW9xS}IX+KE^CpyzkO)ib1{jq5qpU>ovr={Dc&5lD+H*-NMe!|yj zZr*Xff-xQq*v2)UFV~aEzrCRs2KJ9C_aTx^!(N@A>|Vr_9l(S?s~$hBI`MMyWDHh{<9iyfQ$&E&@eCUpt^49S~V&NqXk}}Sq&|^}fjUBx6*dePT>QZ6a*a1ce zh0Hs)0V7%x(6^&Rn_7j(Zwh4-gl|r&Mw>Q32Svh<(P0Pro>V`iGJZa}OR5o`yuS;OOZvof9Lb^trGXvIxV;BLeWTF7Po{ehP$T6fGVKAe zl|CARBDvB>J6j>`dC9%O?lu?ZWuG&m8qe*RwK9&OdtSna3VeVX``pCHCyZ zBZnR~<>bP-nTBTI} z8)frs<(2tM8_Ib$mLjUq?>N8YJtQEzQ~*#LWyn&A)4-L?35ew96^Knph@3=6r3z_HNzh(*U6v>Dp@U&y1tkn@2Y&34fWS zgUxq`$f=H3Yt&k$QY?g4=Q53kdXdjse1V^Mivi&WWPrdT%V}%8oS?MN<@0WRJyS6Z zZFP21l9e)fepUf9*eJBbXSnBSl#%pw9w_9HCY^h&Vw75h_Py>2mc8euc#S@m z^mwn5eI$n1CoRg#8`R=KisaG;M{51kZC0nF3I{x%3Xe7_C6N|7F zpUD8vyZJln(R2f?Y7Ii1j9k62PadIo(zBt=4j}Z1(;N#gf*ZhnWRka1>rD4ITVd3>(69Q7$&9b>X;9?@oJoN-^ zFU(FIOHuU-tQ@6;7tGwFiWGkKK!XX~&Rhj5Qu*&D3iBS)jCoK-?>kf5B!qW8T)54b9_ z-3htt?2l?`v$OC`Mv9-fZJ8@&0|wx+m87H$#qz@Vfw%eo@*RiIZ`koIvT0QQMH>C8P+4Y;;{Z)A$I;yOU{6l&$3Fg7ssp#JxjgTNA=4dlv{9ExFHwL{ zUsFHMFL{j4yjW#!H*;=CXl~R1E8$s>Y_XR%Wb9Qb?;1bIs)71y*2tbsl<3j;yb!Lt z*;le^b_hQde=d8rgBU%UN9@*SAI_@TkxKli(Gds_Qg;bLl_L&0pW@WZlWt(REb`zu z$RbIRM@-ls1IFW`B+(mGfqP8L^P)of2HiK3zp_FOM6lr3b=lT>0c&pt}kq@vpU z70^T0q}uFAMWYn2DO%R+hf{V~6bgyGkL)ALnez-lI&XlQ%j^?8nhQ&D(q3YFXXNRr zS5Aa&iZWvL#~GqZ^WsRcH?U?Zq7I$Rs5kRo0{0e@GfE5pwr22mG_EwLYF4$Zv=ff?bf?AkTMF;J!(7Fc!(!R^UWl*bYW* zL-ETZH+lOFOZ5mIo2Z}=F>@Jq{IaooFw~2XoVhT4rx-IHfAKf>+mWAQzxLblH+q(7 z$nlB^0EX>xV{q;ZIk&Q6h;Cg%0Bo0}1VjB7w|2w?94Fce@!V&z9v0Olfns_asv1tB zVCDC?zQF4GGIi|<)(T;mITk61*#~A8ih2~_gN)|Acm7ycr=w>u0S6&Oq_+Z!7lAe z3VirivYI**^wCw94dpLiRg8%_dc6wvA!=?Gk<3g57d=c$mDQxxT>1|}tey0xpwFj3 zqmkS@K&U=KBMAA-6stV%kMlF7EalL~vE%#A)17f>ZGo5+ox0?4l9yXPQarolQ1mup zN)cQ#Fm8mr^~`9(I{>sYPr#zx|4R+bcC(z6Y=m!Vxzgu-jO(~oev4Dav{)kfB&l>^ zf?($G@2c8wD*2p}&nx*GO8%Y_*=(U{;J>QeXO&3p3nehUEB_xU_j@FrO|#tHS!&@Y zX?a0Y-%qBGT~?; zR4KZXQwVkm=1C4u28790+KUha4C!(w&fd)bL5<#5F@RxB>}qP;dHLZzL9Pw`I}WUu!^cR~eG zI2K`kn9r}i+6!-t|13~d0A{>QLLWu^Z;I_rp8t(h15hI(T$s)mZ9IZsh%NL}TKNUH zeoA_bLSm#8(@&}%Tdu9XG`f`PFiUrtsyz_|gdGN2 zKL#&s*8&VX!=9z?Y&v1ihrmuitAxC76TuRAPc?t>VP9E2r8@{jYUK zB5dW>kxm6?shf?2tIDs1np=o<>|H0QhkYXqg=j?j&Z+M|ZTI~@I(?&A7206?Q+oYQ zZ{tt$=}rx&jR{Qhz$9Qv+oXr>?#XnWXkUJvge$Smt+%X`cpwI0kwDbvj?S(;mCGP{ zBiDu~AuzYD^Qqif>SpVtD?ie(jWm4ANCYsl;&dd-G16z+BYn3s5;bof=`)P-{#gn?phW^#VRJxzh?XRhyfW;d)(rU5RH!eT#3-B4C$D}&V07qU(DNbtHeza z1!du8inm(J6OOdFN3H25Sox*=o1oav{8@UNU8_18OrAft$%%ZrJ(0ig6M2(iKFu(n z&d+M2_gWkq@u6dG@gBE$uP{K-N`yJ>Gi(rm*cnf;-AMoE9_hcQIkxUg*XH$iT5H+= ztw-J5pS`ke;b!3;g_RMZH!5HdR;D~*vE%_O9#&mZ8F6dx*2A@37HsyP)Dw?m1fLaY zC_f@)I}E7)jR4zez4GavSq)yyU=F3P`xvlp%JigjtS8&Q$9mi7dIz#R)^m2{SkLU* zdChn7{LAh-o1B5}+HN=zTTIaoTm5Ujg71Uw+8$ThZ#o~Dhb)+o%)@TwCwqw&i+{2g z5>}l9D&b#74!4s%+mMmHRyzwdXA}QsXW|=Z{yV*L7R*DVYyk>_lxi7jLo!f-rsX~%1$iUh-lU{Osb;5YagQVlk1 z=ly@-EA(c%!=38-*rwD~XyH?KI(Vn53RO!Z>ooOngnljJ*T8Y77VY@ww10yk*9~>u z;Z0}c-={4SDb7AXx+vFXCdPr{della?1P$!DaG=f*cqyw5cv>k>EzxHlUm_*?H9-y z=u2jf`Y`FO6i%nUSnmpzN!K1R4G*&@28&tgys;oYIc7q0?Tl_{)&{~YI<;S?w^9u+ z>~deH({vZT4u43UzocYVNlD2El^ju0R&rQLRmt0xoKrHdCDXgOOq#$&-i9SN87q|O1AnmFJo7y5;n+Z)R)lBW@+oa^-`fB zO!!aK;{XYVJy9G-)v%^kC|)jHQUZy(u&HEO$%2wPi7CRC+?_U@+0>pgz9+T#J9Ojn zx)s6|Lkt(Wp>)YmE~>4R5gCr6>|^Tsg8Qswuf59$_qLxDF}~BDcIHNi!0XSewR+j* z>)_tfbK0U;qm1%AN|ewrHAcAJ*ca^0t4>zN^AOH4i|JEqZ>{@CKH2FzagZsNFHdBk z=DD{!c8}-n%t7Gi% z0~&r31I%uYIpWNOrK5&BeZ7kC+zpQDZ$(y`hRO32Atp*X`;5L}Moqf4xM7gNK--KO z?V7<>ZX1KJwx8Wow30ft6WHUKE1+1`eQ_B0o5R_2tYb9whv^1XgQ5Uv4DWgC!oR*j zp=Urhl@qhsG^qXsjebj@5{nn8MgR@LczK?L{A~+QM&;ToTHNIMDPa`fxDY73-RG$R zo!bKSXIJ_m0Dqlo#uI?fRR9fO>d8(8b(GN0@nSzZg#uj-WJ0cERh&g$)|sC*eds{W z;%J)lb}u-YFrH|k6&*=RxOE2Y>?}{+8&l(*hoXnwKcn1E>3rWUxv+xBG537w;>F zy_n_VZ_W(G-_SG2>94=&5!2bKiVblE4om+VHfOt)A|m0kDU-0{;>J-k;ThXZ932(2 zIy)m)P3&w81yXclbMFI+_zQOB%}?$N!TMAN5N^&eWp27~Ajef33_DU9VvFWnQV%fJ z^}gVa3LW_(MB6RF7}gLAtcV%tA^CZX-xQK4!oK5;&@AT8Hm+=(p}&;(?Lc=${0zTs zCmCk|iLq)m%)rT}m&kn1D6!w`rhlCKig#-O*M4qF#uxdDZlka$;sS`U~D*GG;aX z(#)Ck*_^3%P&&PyaQP%F{)if1QPL6l@6+Q8O8%*m|41?}rWW2%VzYdYa;ECG!EN67 z@aw!V=Y2(HS{Uk4OtG~Peo1Y9SIJE!|Bghn_Q~C;vf;m^{y(I@l+uS`=&C}j0}%jGphHNWTlKi z$;xa2-_xcIQs^)gQei0sAK)h-3yqR5lfY=im*A^*R*lLHV<9hw^R&1i@)E9&n!J(W zyp3k# zNSB)-=^X5KS+U}8{tE|P$E!xN0;s23Gk2xzh5uEFk+HqKp+{Mg9tFOtoZuhYc3U&` zKhAG6#A%4BVZs?QEu;tg;cYRt z+f*es-D^Vfooh4M9&iQei{0No1fzX9-cL2bYKV>xBX|MfO!{w`VX)ce=qD}bE zX}Lp7)b7i0v5!vOa>^L~TlN13N@VC5Hk&l?$o(;u*_H@k)@5fNmb*&<^N(r%#{rYs zNv2Qdguh>%CN?j!6Zd^-!fyEU0VtJCFPfm)L%xK3-~v28df%RI0aT)=oe zz!z5JFEBz?$Z>r`Fz?=ArG$*@e6UBnSfzH%X{E4M>Xi1UG#Q_FQ6d`V06Za#*IjhUXG9l4~$>379uh{8>eR4^A2eZNu_aleMs(G>siZJBh6@w5!kGoWkcJnT&+c(9Y9C806VW3BlgHIs%fi`U*otiAn?)9z zN^Fnb`wbaSzm*o+r)$*Ke{U~4cV&|P$bP-KTC5O9p{NLjx5lmUL$ZM_>lb3nI&2dY z8z=SSfSYd2v?rtm&lbLag@!rlCs^|rLyd9#BWi-W}^_Pv>S^Y zEt>`-{NJ!Ugi+a73DZqdtCOu_w8lw-La!twb@?&kTZruLoAe*I1+%Cva@=d;L9T@ny~+nd-QTcqC#6&T4r|bnx_|osine zzsjkpLufCyOlk4z3N6>(-f2wXWx{wrW&RYT8AiU5l<#^kL+zmjmrZBapUq~5v5jOS zavp`m&jxx!AtA-^#ytL4GDaa=YyfF9IuvUBl!bZwusYwU->q}ji*1V*W9LSPI4kD! z5ZmQsXor}-&h7g{iZ#VEpMIr+=d;wvyDeFM|bNy zP93geg%2RLiIK%<95Z*qtAR#%HL&1u32E&`@<$}?-RocxxNtkF==BM{!I`}(qE>m_ zfkm+M5PG@z)RBwpMD}q@{Zeb;uzd`ax5kAxjDuaa%IE0#VAT71DTkmXm|hY2;*1+ zcU5VFY)fW)VvW!C zsgrhKygdrWl)yQ%DWk*aW_#Q&( zL>Qh9yF$Xgtq}!A!N^)v7FHV`28q7?^Gjj2nMjW#lMT@&W=KGqjpjeiJ!K46S@(7xY8 zNE7_tHfxf$Z7MqEKU*6W`TT4uz>g@9RG%UBx{v4mkgK0dhZ^jp*ifb3L~P2TQqctU z(~^uupCW^XBFg|h!gO2sl^7u!E-DHJ!A-A#@xBBzrN{>wu^1I$@flaT)`3vgQs_Mp{bvH8Q>y znN1l0n#2Wd>X2II#_(hm>{pRM7W_3Y1I=G0Bk2XDoAhGAc$C)`rT-_d30PRx;?yRO zfYPNvE=T^U5V-ZYb9V0;u_Y0MxA%g*!u|!MFm$NO-()a`Ph=@tAw@(^iRbUay!O3Y z0BX<$UVWq3U~F-1DFe`#aKrz}r0rSs*l311meqB*%EvZMH|RRY4yfU`Kr64*`KE1` z<<+aVs=~&@TB`Qn)!6=vHvgeaX+@@gmf+sCI$yMGa{0Y_NjqXDEyS$vlPHc@Kb@KC zbTd6n`&pWIZaSNeWnT(rS-L@#x(ZtgjGjF4{IQo$&6G}^e(!rvPQABu{PfiGC*NB- zb2^;y2lj@JL#*trafcr>#;m42NJcS{{0+7Z80@Ew8CQ5=e*`)GOmU2iE2Mh7lOBHu zov$KH*N*|5!R#0r==39oTxcb!VdT|*?f}Y)hZ;?bQU*%RkV}s#akAR%+Zx(z;zu~f z5g@$ut6YgKvrw(aVUIT5C^ge-%g z-!Z|&z9i#or!0-lLkqkK@d4K|pTx3w#`Kw(M&*nO#V4k0tsPd>#q&(48cYNZ4;b+@ zBSde0Ww;vt8RZ>nG=P`9alzJ@o7iwv5b&`6KDiFc-kmHnZ2*PoHNkg;4jg`4iBrC= zn;V4A25%FdMjm^zJ$!3hDim1NkirzAhWm}N7>Rg;$takw_i$OTZsAH%)hkXkbY5zV zlC>7zF!a6?1M45Ej>ynM!e#q~E n!f+wa-}?%W7S8R;7y5TUIJRwUaIAm#$9DhNO;D?MsQJGEo%BYg diff --git a/PythonHome/Lib/logging/handlers.py b/PythonHome/Lib/logging/handlers.py new file mode 100644 index 0000000000..b7bf931aa4 --- /dev/null +++ b/PythonHome/Lib/logging/handlers.py @@ -0,0 +1,1222 @@ +# Copyright 2001-2013 by Vinay Sajip. 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 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. + +""" +Additional handlers for the logging package for Python. The core package is +based on PEP 282 and comments thereto in comp.lang.python. + +Copyright (C) 2001-2013 Vinay Sajip. All Rights Reserved. + +To use, simply 'import logging.handlers' and log away! +""" + +import errno, logging, socket, os, cPickle, struct, time, re +from stat import ST_DEV, ST_INO, ST_MTIME + +try: + import codecs +except ImportError: + codecs = None +try: + unicode + _unicode = True +except NameError: + _unicode = False + +# +# Some constants... +# + +DEFAULT_TCP_LOGGING_PORT = 9020 +DEFAULT_UDP_LOGGING_PORT = 9021 +DEFAULT_HTTP_LOGGING_PORT = 9022 +DEFAULT_SOAP_LOGGING_PORT = 9023 +SYSLOG_UDP_PORT = 514 +SYSLOG_TCP_PORT = 514 + +_MIDNIGHT = 24 * 60 * 60 # number of seconds in a day + +class BaseRotatingHandler(logging.FileHandler): + """ + Base class for handlers that rotate log files at a certain point. + Not meant to be instantiated directly. Instead, use RotatingFileHandler + or TimedRotatingFileHandler. + """ + def __init__(self, filename, mode, encoding=None, delay=0): + """ + Use the specified filename for streamed logging + """ + if codecs is None: + encoding = None + logging.FileHandler.__init__(self, filename, mode, encoding, delay) + self.mode = mode + self.encoding = encoding + + def emit(self, record): + """ + Emit a record. + + Output the record to the file, catering for rollover as described + in doRollover(). + """ + try: + if self.shouldRollover(record): + self.doRollover() + logging.FileHandler.emit(self, record) + except (KeyboardInterrupt, SystemExit): + raise + except: + self.handleError(record) + +class RotatingFileHandler(BaseRotatingHandler): + """ + Handler for logging to a set of files, which switches from one file + to the next when the current file reaches a certain size. + """ + def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0): + """ + Open the specified file and use it as the stream for logging. + + By default, the file grows indefinitely. You can specify particular + values of maxBytes and backupCount to allow the file to rollover at + a predetermined size. + + Rollover occurs whenever the current log file is nearly maxBytes in + length. If backupCount is >= 1, the system will successively create + new files with the same pathname as the base file, but with extensions + ".1", ".2" etc. appended to it. For example, with a backupCount of 5 + and a base file name of "app.log", you would get "app.log", + "app.log.1", "app.log.2", ... through to "app.log.5". The file being + written to is always "app.log" - when it gets filled up, it is closed + and renamed to "app.log.1", and if files "app.log.1", "app.log.2" etc. + exist, then they are renamed to "app.log.2", "app.log.3" etc. + respectively. + + If maxBytes is zero, rollover never occurs. + """ + # If rotation/rollover is wanted, it doesn't make sense to use another + # mode. If for example 'w' were specified, then if there were multiple + # runs of the calling application, the logs from previous runs would be + # lost if the 'w' is respected, because the log file would be truncated + # on each run. + if maxBytes > 0: + mode = 'a' + BaseRotatingHandler.__init__(self, filename, mode, encoding, delay) + self.maxBytes = maxBytes + self.backupCount = backupCount + + def doRollover(self): + """ + Do a rollover, as described in __init__(). + """ + if self.stream: + self.stream.close() + self.stream = None + if self.backupCount > 0: + for i in range(self.backupCount - 1, 0, -1): + sfn = "%s.%d" % (self.baseFilename, i) + dfn = "%s.%d" % (self.baseFilename, i + 1) + if os.path.exists(sfn): + #print "%s -> %s" % (sfn, dfn) + if os.path.exists(dfn): + os.remove(dfn) + os.rename(sfn, dfn) + dfn = self.baseFilename + ".1" + if os.path.exists(dfn): + os.remove(dfn) + # Issue 18940: A file may not have been created if delay is True. + if os.path.exists(self.baseFilename): + os.rename(self.baseFilename, dfn) + if not self.delay: + self.stream = self._open() + + def shouldRollover(self, record): + """ + Determine if rollover should occur. + + Basically, see if the supplied record would cause the file to exceed + the size limit we have. + """ + if self.stream is None: # delay was set... + self.stream = self._open() + if self.maxBytes > 0: # are we rolling over? + msg = "%s\n" % self.format(record) + self.stream.seek(0, 2) #due to non-posix-compliant Windows feature + if self.stream.tell() + len(msg) >= self.maxBytes: + return 1 + return 0 + +class TimedRotatingFileHandler(BaseRotatingHandler): + """ + Handler for logging to a file, rotating the log file at certain timed + intervals. + + If backupCount is > 0, when rollover is done, no more than backupCount + files are kept - the oldest ones are deleted. + """ + def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False): + BaseRotatingHandler.__init__(self, filename, 'a', encoding, delay) + self.when = when.upper() + self.backupCount = backupCount + self.utc = utc + # Calculate the real rollover interval, which is just the number of + # seconds between rollovers. Also set the filename suffix used when + # a rollover occurs. Current 'when' events supported: + # S - Seconds + # M - Minutes + # H - Hours + # D - Days + # midnight - roll over at midnight + # W{0-6} - roll over on a certain day; 0 - Monday + # + # Case of the 'when' specifier is not important; lower or upper case + # will work. + if self.when == 'S': + self.interval = 1 # one second + self.suffix = "%Y-%m-%d_%H-%M-%S" + self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}$" + elif self.when == 'M': + self.interval = 60 # one minute + self.suffix = "%Y-%m-%d_%H-%M" + self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}$" + elif self.when == 'H': + self.interval = 60 * 60 # one hour + self.suffix = "%Y-%m-%d_%H" + self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}$" + elif self.when == 'D' or self.when == 'MIDNIGHT': + self.interval = 60 * 60 * 24 # one day + self.suffix = "%Y-%m-%d" + self.extMatch = r"^\d{4}-\d{2}-\d{2}$" + elif self.when.startswith('W'): + self.interval = 60 * 60 * 24 * 7 # one week + if len(self.when) != 2: + raise ValueError("You must specify a day for weekly rollover from 0 to 6 (0 is Monday): %s" % self.when) + if self.when[1] < '0' or self.when[1] > '6': + raise ValueError("Invalid day specified for weekly rollover: %s" % self.when) + self.dayOfWeek = int(self.when[1]) + self.suffix = "%Y-%m-%d" + self.extMatch = r"^\d{4}-\d{2}-\d{2}$" + else: + raise ValueError("Invalid rollover interval specified: %s" % self.when) + + self.extMatch = re.compile(self.extMatch) + self.interval = self.interval * interval # multiply by units requested + if os.path.exists(filename): + t = os.stat(filename)[ST_MTIME] + else: + t = int(time.time()) + self.rolloverAt = self.computeRollover(t) + + def computeRollover(self, currentTime): + """ + Work out the rollover time based on the specified time. + """ + result = currentTime + self.interval + # If we are rolling over at midnight or weekly, then the interval is already known. + # What we need to figure out is WHEN the next interval is. In other words, + # if you are rolling over at midnight, then your base interval is 1 day, + # but you want to start that one day clock at midnight, not now. So, we + # have to fudge the rolloverAt value in order to trigger the first rollover + # at the right time. After that, the regular interval will take care of + # the rest. Note that this code doesn't care about leap seconds. :) + if self.when == 'MIDNIGHT' or self.when.startswith('W'): + # This could be done with less code, but I wanted it to be clear + if self.utc: + t = time.gmtime(currentTime) + else: + t = time.localtime(currentTime) + currentHour = t[3] + currentMinute = t[4] + currentSecond = t[5] + # r is the number of seconds left between now and midnight + r = _MIDNIGHT - ((currentHour * 60 + currentMinute) * 60 + + currentSecond) + result = currentTime + r + # If we are rolling over on a certain day, add in the number of days until + # the next rollover, but offset by 1 since we just calculated the time + # until the next day starts. There are three cases: + # Case 1) The day to rollover is today; in this case, do nothing + # Case 2) The day to rollover is further in the interval (i.e., today is + # day 2 (Wednesday) and rollover is on day 6 (Sunday). Days to + # next rollover is simply 6 - 2 - 1, or 3. + # Case 3) The day to rollover is behind us in the interval (i.e., today + # is day 5 (Saturday) and rollover is on day 3 (Thursday). + # Days to rollover is 6 - 5 + 3, or 4. In this case, it's the + # number of days left in the current week (1) plus the number + # of days in the next week until the rollover day (3). + # The calculations described in 2) and 3) above need to have a day added. + # This is because the above time calculation takes us to midnight on this + # day, i.e. the start of the next day. + if self.when.startswith('W'): + day = t[6] # 0 is Monday + if day != self.dayOfWeek: + if day < self.dayOfWeek: + daysToWait = self.dayOfWeek - day + else: + daysToWait = 6 - day + self.dayOfWeek + 1 + newRolloverAt = result + (daysToWait * (60 * 60 * 24)) + if not self.utc: + dstNow = t[-1] + dstAtRollover = time.localtime(newRolloverAt)[-1] + if dstNow != dstAtRollover: + if not dstNow: # DST kicks in before next rollover, so we need to deduct an hour + addend = -3600 + else: # DST bows out before next rollover, so we need to add an hour + addend = 3600 + newRolloverAt += addend + result = newRolloverAt + return result + + def shouldRollover(self, record): + """ + Determine if rollover should occur. + + record is not used, as we are just comparing times, but it is needed so + the method signatures are the same + """ + t = int(time.time()) + if t >= self.rolloverAt: + return 1 + #print "No need to rollover: %d, %d" % (t, self.rolloverAt) + return 0 + + def getFilesToDelete(self): + """ + Determine the files to delete when rolling over. + + More specific than the earlier method, which just used glob.glob(). + """ + dirName, baseName = os.path.split(self.baseFilename) + fileNames = os.listdir(dirName) + result = [] + prefix = baseName + "." + plen = len(prefix) + for fileName in fileNames: + if fileName[:plen] == prefix: + suffix = fileName[plen:] + if self.extMatch.match(suffix): + result.append(os.path.join(dirName, fileName)) + result.sort() + if len(result) < self.backupCount: + result = [] + else: + result = result[:len(result) - self.backupCount] + return result + + def doRollover(self): + """ + do a rollover; in this case, a date/time stamp is appended to the filename + when the rollover happens. However, you want the file to be named for the + start of the interval, not the current time. If there is a backup count, + then we have to get a list of matching filenames, sort them and remove + the one with the oldest suffix. + """ + if self.stream: + self.stream.close() + self.stream = None + # get the time that this sequence started at and make it a TimeTuple + currentTime = int(time.time()) + dstNow = time.localtime(currentTime)[-1] + t = self.rolloverAt - self.interval + if self.utc: + timeTuple = time.gmtime(t) + else: + timeTuple = time.localtime(t) + dstThen = timeTuple[-1] + if dstNow != dstThen: + if dstNow: + addend = 3600 + else: + addend = -3600 + timeTuple = time.localtime(t + addend) + dfn = self.baseFilename + "." + time.strftime(self.suffix, timeTuple) + if os.path.exists(dfn): + os.remove(dfn) + # Issue 18940: A file may not have been created if delay is True. + if os.path.exists(self.baseFilename): + os.rename(self.baseFilename, dfn) + if self.backupCount > 0: + for s in self.getFilesToDelete(): + os.remove(s) + if not self.delay: + self.stream = self._open() + newRolloverAt = self.computeRollover(currentTime) + while newRolloverAt <= currentTime: + newRolloverAt = newRolloverAt + self.interval + #If DST changes and midnight or weekly rollover, adjust for this. + if (self.when == 'MIDNIGHT' or self.when.startswith('W')) and not self.utc: + dstAtRollover = time.localtime(newRolloverAt)[-1] + if dstNow != dstAtRollover: + if not dstNow: # DST kicks in before next rollover, so we need to deduct an hour + addend = -3600 + else: # DST bows out before next rollover, so we need to add an hour + addend = 3600 + newRolloverAt += addend + self.rolloverAt = newRolloverAt + +class WatchedFileHandler(logging.FileHandler): + """ + A handler for logging to a file, which watches the file + to see if it has changed while in use. This can happen because of + usage of programs such as newsyslog and logrotate which perform + log file rotation. This handler, intended for use under Unix, + watches the file to see if it has changed since the last emit. + (A file has changed if its device or inode have changed.) + If it has changed, the old file stream is closed, and the file + opened to get a new stream. + + This handler is not appropriate for use under Windows, because + under Windows open files cannot be moved or renamed - logging + opens the files with exclusive locks - and so there is no need + for such a handler. Furthermore, ST_INO is not supported under + Windows; stat always returns zero for this value. + + This handler is based on a suggestion and patch by Chad J. + Schroeder. + """ + def __init__(self, filename, mode='a', encoding=None, delay=0): + logging.FileHandler.__init__(self, filename, mode, encoding, delay) + self.dev, self.ino = -1, -1 + self._statstream() + + def _statstream(self): + if self.stream: + sres = os.fstat(self.stream.fileno()) + self.dev, self.ino = sres[ST_DEV], sres[ST_INO] + + def emit(self, record): + """ + Emit a record. + + First check if the underlying file has changed, and if it + has, close the old stream and reopen the file to get the + current stream. + """ + # Reduce the chance of race conditions by stat'ing by path only + # once and then fstat'ing our new fd if we opened a new log stream. + # See issue #14632: Thanks to John Mulligan for the problem report + # and patch. + try: + # stat the file by path, checking for existence + sres = os.stat(self.baseFilename) + except OSError as err: + if err.errno == errno.ENOENT: + sres = None + else: + raise + # compare file system stat with that of our stream file handle + if not sres or sres[ST_DEV] != self.dev or sres[ST_INO] != self.ino: + if self.stream is not None: + # we have an open file handle, clean it up + self.stream.flush() + self.stream.close() + self.stream = None # See Issue #21742: _open () might fail. + # open a new file handle and get new stat info from that fd + self.stream = self._open() + self._statstream() + logging.FileHandler.emit(self, record) + +class SocketHandler(logging.Handler): + """ + A handler class which writes logging records, in pickle format, to + a streaming socket. The socket is kept open across logging calls. + If the peer resets it, an attempt is made to reconnect on the next call. + The pickle which is sent is that of the LogRecord's attribute dictionary + (__dict__), so that the receiver does not need to have the logging module + installed in order to process the logging event. + + To unpickle the record at the receiving end into a LogRecord, use the + makeLogRecord function. + """ + + def __init__(self, host, port): + """ + Initializes the handler with a specific host address and port. + + The attribute 'closeOnError' is set to 1 - which means that if + a socket error occurs, the socket is silently closed and then + reopened on the next logging call. + """ + logging.Handler.__init__(self) + self.host = host + self.port = port + self.sock = None + self.closeOnError = 0 + self.retryTime = None + # + # Exponential backoff parameters. + # + self.retryStart = 1.0 + self.retryMax = 30.0 + self.retryFactor = 2.0 + + def makeSocket(self, timeout=1): + """ + A factory method which allows subclasses to define the precise + type of socket they want. + """ + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + if hasattr(s, 'settimeout'): + s.settimeout(timeout) + s.connect((self.host, self.port)) + return s + + def createSocket(self): + """ + Try to create a socket, using an exponential backoff with + a max retry time. Thanks to Robert Olson for the original patch + (SF #815911) which has been slightly refactored. + """ + now = time.time() + # Either retryTime is None, in which case this + # is the first time back after a disconnect, or + # we've waited long enough. + if self.retryTime is None: + attempt = 1 + else: + attempt = (now >= self.retryTime) + if attempt: + try: + self.sock = self.makeSocket() + self.retryTime = None # next time, no delay before trying + except socket.error: + #Creation failed, so set the retry time and return. + if self.retryTime is None: + self.retryPeriod = self.retryStart + else: + self.retryPeriod = self.retryPeriod * self.retryFactor + if self.retryPeriod > self.retryMax: + self.retryPeriod = self.retryMax + self.retryTime = now + self.retryPeriod + + def send(self, s): + """ + Send a pickled string to the socket. + + This function allows for partial sends which can happen when the + network is busy. + """ + if self.sock is None: + self.createSocket() + #self.sock can be None either because we haven't reached the retry + #time yet, or because we have reached the retry time and retried, + #but are still unable to connect. + if self.sock: + try: + if hasattr(self.sock, "sendall"): + self.sock.sendall(s) + else: + sentsofar = 0 + left = len(s) + while left > 0: + sent = self.sock.send(s[sentsofar:]) + sentsofar = sentsofar + sent + left = left - sent + except socket.error: + self.sock.close() + self.sock = None # so we can call createSocket next time + + def makePickle(self, record): + """ + Pickles the record in binary format with a length prefix, and + returns it ready for transmission across the socket. + """ + ei = record.exc_info + if ei: + # just to get traceback text into record.exc_text ... + dummy = self.format(record) + record.exc_info = None # to avoid Unpickleable error + # See issue #14436: If msg or args are objects, they may not be + # available on the receiving end. So we convert the msg % args + # to a string, save it as msg and zap the args. + d = dict(record.__dict__) + d['msg'] = record.getMessage() + d['args'] = None + s = cPickle.dumps(d, 1) + if ei: + record.exc_info = ei # for next handler + slen = struct.pack(">L", len(s)) + return slen + s + + def handleError(self, record): + """ + Handle an error during logging. + + An error has occurred during logging. Most likely cause - + connection lost. Close the socket so that we can retry on the + next event. + """ + if self.closeOnError and self.sock: + self.sock.close() + self.sock = None #try to reconnect next time + else: + logging.Handler.handleError(self, record) + + def emit(self, record): + """ + Emit a record. + + Pickles the record and writes it to the socket in binary format. + If there is an error with the socket, silently drop the packet. + If there was a problem with the socket, re-establishes the + socket. + """ + try: + s = self.makePickle(record) + self.send(s) + except (KeyboardInterrupt, SystemExit): + raise + except: + self.handleError(record) + + def close(self): + """ + Closes the socket. + """ + self.acquire() + try: + if self.sock: + self.sock.close() + self.sock = None + finally: + self.release() + logging.Handler.close(self) + +class DatagramHandler(SocketHandler): + """ + A handler class which writes logging records, in pickle format, to + a datagram socket. The pickle which is sent is that of the LogRecord's + attribute dictionary (__dict__), so that the receiver does not need to + have the logging module installed in order to process the logging event. + + To unpickle the record at the receiving end into a LogRecord, use the + makeLogRecord function. + + """ + def __init__(self, host, port): + """ + Initializes the handler with a specific host address and port. + """ + SocketHandler.__init__(self, host, port) + self.closeOnError = 0 + + def makeSocket(self): + """ + The factory method of SocketHandler is here overridden to create + a UDP socket (SOCK_DGRAM). + """ + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + return s + + def send(self, s): + """ + Send a pickled string to a socket. + + This function no longer allows for partial sends which can happen + when the network is busy - UDP does not guarantee delivery and + can deliver packets out of sequence. + """ + if self.sock is None: + self.createSocket() + self.sock.sendto(s, (self.host, self.port)) + +class SysLogHandler(logging.Handler): + """ + A handler class which sends formatted logging records to a syslog + server. Based on Sam Rushing's syslog module: + http://www.nightmare.com/squirl/python-ext/misc/syslog.py + Contributed by Nicolas Untz (after which minor refactoring changes + have been made). + """ + + # from : + # ====================================================================== + # priorities/facilities are encoded into a single 32-bit quantity, where + # the bottom 3 bits are the priority (0-7) and the top 28 bits are the + # facility (0-big number). Both the priorities and the facilities map + # roughly one-to-one to strings in the syslogd(8) source code. This + # mapping is included in this file. + # + # priorities (these are ordered) + + LOG_EMERG = 0 # system is unusable + LOG_ALERT = 1 # action must be taken immediately + LOG_CRIT = 2 # critical conditions + LOG_ERR = 3 # error conditions + LOG_WARNING = 4 # warning conditions + LOG_NOTICE = 5 # normal but significant condition + LOG_INFO = 6 # informational + LOG_DEBUG = 7 # debug-level messages + + # facility codes + LOG_KERN = 0 # kernel messages + LOG_USER = 1 # random user-level messages + LOG_MAIL = 2 # mail system + LOG_DAEMON = 3 # system daemons + LOG_AUTH = 4 # security/authorization messages + LOG_SYSLOG = 5 # messages generated internally by syslogd + LOG_LPR = 6 # line printer subsystem + LOG_NEWS = 7 # network news subsystem + LOG_UUCP = 8 # UUCP subsystem + LOG_CRON = 9 # clock daemon + LOG_AUTHPRIV = 10 # security/authorization messages (private) + LOG_FTP = 11 # FTP daemon + + # other codes through 15 reserved for system use + LOG_LOCAL0 = 16 # reserved for local use + LOG_LOCAL1 = 17 # reserved for local use + LOG_LOCAL2 = 18 # reserved for local use + LOG_LOCAL3 = 19 # reserved for local use + LOG_LOCAL4 = 20 # reserved for local use + LOG_LOCAL5 = 21 # reserved for local use + LOG_LOCAL6 = 22 # reserved for local use + LOG_LOCAL7 = 23 # reserved for local use + + priority_names = { + "alert": LOG_ALERT, + "crit": LOG_CRIT, + "critical": LOG_CRIT, + "debug": LOG_DEBUG, + "emerg": LOG_EMERG, + "err": LOG_ERR, + "error": LOG_ERR, # DEPRECATED + "info": LOG_INFO, + "notice": LOG_NOTICE, + "panic": LOG_EMERG, # DEPRECATED + "warn": LOG_WARNING, # DEPRECATED + "warning": LOG_WARNING, + } + + facility_names = { + "auth": LOG_AUTH, + "authpriv": LOG_AUTHPRIV, + "cron": LOG_CRON, + "daemon": LOG_DAEMON, + "ftp": LOG_FTP, + "kern": LOG_KERN, + "lpr": LOG_LPR, + "mail": LOG_MAIL, + "news": LOG_NEWS, + "security": LOG_AUTH, # DEPRECATED + "syslog": LOG_SYSLOG, + "user": LOG_USER, + "uucp": LOG_UUCP, + "local0": LOG_LOCAL0, + "local1": LOG_LOCAL1, + "local2": LOG_LOCAL2, + "local3": LOG_LOCAL3, + "local4": LOG_LOCAL4, + "local5": LOG_LOCAL5, + "local6": LOG_LOCAL6, + "local7": LOG_LOCAL7, + } + + #The map below appears to be trivially lowercasing the key. However, + #there's more to it than meets the eye - in some locales, lowercasing + #gives unexpected results. See SF #1524081: in the Turkish locale, + #"INFO".lower() != "info" + priority_map = { + "DEBUG" : "debug", + "INFO" : "info", + "WARNING" : "warning", + "ERROR" : "error", + "CRITICAL" : "critical" + } + + def __init__(self, address=('localhost', SYSLOG_UDP_PORT), + facility=LOG_USER, socktype=None): + """ + Initialize a handler. + + If address is specified as a string, a UNIX socket is used. To log to a + local syslogd, "SysLogHandler(address="/dev/log")" can be used. + If facility is not specified, LOG_USER is used. If socktype is + specified as socket.SOCK_DGRAM or socket.SOCK_STREAM, that specific + socket type will be used. For Unix sockets, you can also specify a + socktype of None, in which case socket.SOCK_DGRAM will be used, falling + back to socket.SOCK_STREAM. + """ + logging.Handler.__init__(self) + + self.address = address + self.facility = facility + self.socktype = socktype + + if isinstance(address, basestring): + self.unixsocket = 1 + self._connect_unixsocket(address) + else: + self.unixsocket = 0 + if socktype is None: + socktype = socket.SOCK_DGRAM + self.socket = socket.socket(socket.AF_INET, socktype) + if socktype == socket.SOCK_STREAM: + self.socket.connect(address) + self.socktype = socktype + self.formatter = None + + def _connect_unixsocket(self, address): + use_socktype = self.socktype + if use_socktype is None: + use_socktype = socket.SOCK_DGRAM + self.socket = socket.socket(socket.AF_UNIX, use_socktype) + try: + self.socket.connect(address) + # it worked, so set self.socktype to the used type + self.socktype = use_socktype + except socket.error: + self.socket.close() + if self.socktype is not None: + # user didn't specify falling back, so fail + raise + use_socktype = socket.SOCK_STREAM + self.socket = socket.socket(socket.AF_UNIX, use_socktype) + try: + self.socket.connect(address) + # it worked, so set self.socktype to the used type + self.socktype = use_socktype + except socket.error: + self.socket.close() + raise + + # curious: when talking to the unix-domain '/dev/log' socket, a + # zero-terminator seems to be required. this string is placed + # into a class variable so that it can be overridden if + # necessary. + log_format_string = '<%d>%s\000' + + def encodePriority(self, facility, priority): + """ + Encode the facility and priority. You can pass in strings or + integers - if strings are passed, the facility_names and + priority_names mapping dictionaries are used to convert them to + integers. + """ + if isinstance(facility, basestring): + facility = self.facility_names[facility] + if isinstance(priority, basestring): + priority = self.priority_names[priority] + return (facility << 3) | priority + + def close (self): + """ + Closes the socket. + """ + self.acquire() + try: + if self.unixsocket: + self.socket.close() + finally: + self.release() + logging.Handler.close(self) + + def mapPriority(self, levelName): + """ + Map a logging level name to a key in the priority_names map. + This is useful in two scenarios: when custom levels are being + used, and in the case where you can't do a straightforward + mapping by lowercasing the logging level name because of locale- + specific issues (see SF #1524081). + """ + return self.priority_map.get(levelName, "warning") + + def emit(self, record): + """ + Emit a record. + + The record is formatted, and then sent to the syslog server. If + exception information is present, it is NOT sent to the server. + """ + msg = self.format(record) + '\000' + """ + We need to convert record level to lowercase, maybe this will + change in the future. + """ + prio = '<%d>' % self.encodePriority(self.facility, + self.mapPriority(record.levelname)) + # Message is a string. Convert to bytes as required by RFC 5424 + if type(msg) is unicode: + msg = msg.encode('utf-8') + msg = prio + msg + try: + if self.unixsocket: + try: + self.socket.send(msg) + except socket.error: + self.socket.close() # See issue 17981 + self._connect_unixsocket(self.address) + self.socket.send(msg) + elif self.socktype == socket.SOCK_DGRAM: + self.socket.sendto(msg, self.address) + else: + self.socket.sendall(msg) + except (KeyboardInterrupt, SystemExit): + raise + except: + self.handleError(record) + +class SMTPHandler(logging.Handler): + """ + A handler class which sends an SMTP email for each logging event. + """ + def __init__(self, mailhost, fromaddr, toaddrs, subject, + credentials=None, secure=None): + """ + Initialize the handler. + + Initialize the instance with the from and to addresses and subject + line of the email. To specify a non-standard SMTP port, use the + (host, port) tuple format for the mailhost argument. To specify + authentication credentials, supply a (username, password) tuple + for the credentials argument. To specify the use of a secure + protocol (TLS), pass in a tuple for the secure argument. This will + only be used when authentication credentials are supplied. The tuple + will be either an empty tuple, or a single-value tuple with the name + of a keyfile, or a 2-value tuple with the names of the keyfile and + certificate file. (This tuple is passed to the `starttls` method). + """ + logging.Handler.__init__(self) + if isinstance(mailhost, tuple): + self.mailhost, self.mailport = mailhost + else: + self.mailhost, self.mailport = mailhost, None + if isinstance(credentials, tuple): + self.username, self.password = credentials + else: + self.username = None + self.fromaddr = fromaddr + if isinstance(toaddrs, basestring): + toaddrs = [toaddrs] + self.toaddrs = toaddrs + self.subject = subject + self.secure = secure + self._timeout = 5.0 + + def getSubject(self, record): + """ + Determine the subject for the email. + + If you want to specify a subject line which is record-dependent, + override this method. + """ + return self.subject + + def emit(self, record): + """ + Emit a record. + + Format the record and send it to the specified addressees. + """ + try: + import smtplib + from email.utils import formatdate + port = self.mailport + if not port: + port = smtplib.SMTP_PORT + smtp = smtplib.SMTP(self.mailhost, port, timeout=self._timeout) + msg = self.format(record) + msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\nDate: %s\r\n\r\n%s" % ( + self.fromaddr, + ",".join(self.toaddrs), + self.getSubject(record), + formatdate(), msg) + if self.username: + if self.secure is not None: + smtp.ehlo() + smtp.starttls(*self.secure) + smtp.ehlo() + smtp.login(self.username, self.password) + smtp.sendmail(self.fromaddr, self.toaddrs, msg) + smtp.quit() + except (KeyboardInterrupt, SystemExit): + raise + except: + self.handleError(record) + +class NTEventLogHandler(logging.Handler): + """ + A handler class which sends events to the NT Event Log. Adds a + registry entry for the specified application name. If no dllname is + provided, win32service.pyd (which contains some basic message + placeholders) is used. Note that use of these placeholders will make + your event logs big, as the entire message source is held in the log. + If you want slimmer logs, you have to pass in the name of your own DLL + which contains the message definitions you want to use in the event log. + """ + def __init__(self, appname, dllname=None, logtype="Application"): + logging.Handler.__init__(self) + try: + import win32evtlogutil, win32evtlog + self.appname = appname + self._welu = win32evtlogutil + if not dllname: + dllname = os.path.split(self._welu.__file__) + dllname = os.path.split(dllname[0]) + dllname = os.path.join(dllname[0], r'win32service.pyd') + self.dllname = dllname + self.logtype = logtype + self._welu.AddSourceToRegistry(appname, dllname, logtype) + self.deftype = win32evtlog.EVENTLOG_ERROR_TYPE + self.typemap = { + logging.DEBUG : win32evtlog.EVENTLOG_INFORMATION_TYPE, + logging.INFO : win32evtlog.EVENTLOG_INFORMATION_TYPE, + logging.WARNING : win32evtlog.EVENTLOG_WARNING_TYPE, + logging.ERROR : win32evtlog.EVENTLOG_ERROR_TYPE, + logging.CRITICAL: win32evtlog.EVENTLOG_ERROR_TYPE, + } + except ImportError: + print("The Python Win32 extensions for NT (service, event "\ + "logging) appear not to be available.") + self._welu = None + + def getMessageID(self, record): + """ + Return the message ID for the event record. If you are using your + own messages, you could do this by having the msg passed to the + logger being an ID rather than a formatting string. Then, in here, + you could use a dictionary lookup to get the message ID. This + version returns 1, which is the base message ID in win32service.pyd. + """ + return 1 + + def getEventCategory(self, record): + """ + Return the event category for the record. + + Override this if you want to specify your own categories. This version + returns 0. + """ + return 0 + + def getEventType(self, record): + """ + Return the event type for the record. + + Override this if you want to specify your own types. This version does + a mapping using the handler's typemap attribute, which is set up in + __init__() to a dictionary which contains mappings for DEBUG, INFO, + WARNING, ERROR and CRITICAL. If you are using your own levels you will + either need to override this method or place a suitable dictionary in + the handler's typemap attribute. + """ + return self.typemap.get(record.levelno, self.deftype) + + def emit(self, record): + """ + Emit a record. + + Determine the message ID, event category and event type. Then + log the message in the NT event log. + """ + if self._welu: + try: + id = self.getMessageID(record) + cat = self.getEventCategory(record) + type = self.getEventType(record) + msg = self.format(record) + self._welu.ReportEvent(self.appname, id, cat, type, [msg]) + except (KeyboardInterrupt, SystemExit): + raise + except: + self.handleError(record) + + def close(self): + """ + Clean up this handler. + + You can remove the application name from the registry as a + source of event log entries. However, if you do this, you will + not be able to see the events as you intended in the Event Log + Viewer - it needs to be able to access the registry to get the + DLL name. + """ + #self._welu.RemoveSourceFromRegistry(self.appname, self.logtype) + logging.Handler.close(self) + +class HTTPHandler(logging.Handler): + """ + A class which sends records to a Web server, using either GET or + POST semantics. + """ + def __init__(self, host, url, method="GET"): + """ + Initialize the instance with the host, the request URL, and the method + ("GET" or "POST") + """ + logging.Handler.__init__(self) + method = method.upper() + if method not in ["GET", "POST"]: + raise ValueError("method must be GET or POST") + self.host = host + self.url = url + self.method = method + + def mapLogRecord(self, record): + """ + Default implementation of mapping the log record into a dict + that is sent as the CGI data. Overwrite in your class. + Contributed by Franz Glasner. + """ + return record.__dict__ + + def emit(self, record): + """ + Emit a record. + + Send the record to the Web server as a percent-encoded dictionary + """ + try: + import httplib, urllib + host = self.host + h = httplib.HTTP(host) + url = self.url + data = urllib.urlencode(self.mapLogRecord(record)) + if self.method == "GET": + if (url.find('?') >= 0): + sep = '&' + else: + sep = '?' + url = url + "%c%s" % (sep, data) + h.putrequest(self.method, url) + # support multiple hosts on one IP address... + # need to strip optional :port from host, if present + i = host.find(":") + if i >= 0: + host = host[:i] + h.putheader("Host", host) + if self.method == "POST": + h.putheader("Content-type", + "application/x-www-form-urlencoded") + h.putheader("Content-length", str(len(data))) + h.endheaders(data if self.method == "POST" else None) + h.getreply() #can't do anything with the result + except (KeyboardInterrupt, SystemExit): + raise + except: + self.handleError(record) + +class BufferingHandler(logging.Handler): + """ + A handler class which buffers logging records in memory. Whenever each + record is added to the buffer, a check is made to see if the buffer should + be flushed. If it should, then flush() is expected to do what's needed. + """ + def __init__(self, capacity): + """ + Initialize the handler with the buffer size. + """ + logging.Handler.__init__(self) + self.capacity = capacity + self.buffer = [] + + def shouldFlush(self, record): + """ + Should the handler flush its buffer? + + Returns true if the buffer is up to capacity. This method can be + overridden to implement custom flushing strategies. + """ + return (len(self.buffer) >= self.capacity) + + def emit(self, record): + """ + Emit a record. + + Append the record. If shouldFlush() tells us to, call flush() to process + the buffer. + """ + self.buffer.append(record) + if self.shouldFlush(record): + self.flush() + + def flush(self): + """ + Override to implement custom flushing behaviour. + + This version just zaps the buffer to empty. + """ + self.acquire() + try: + self.buffer = [] + finally: + self.release() + + def close(self): + """ + Close the handler. + + This version just flushes and chains to the parent class' close(). + """ + self.flush() + logging.Handler.close(self) + +class MemoryHandler(BufferingHandler): + """ + A handler class which buffers logging records in memory, periodically + flushing them to a target handler. Flushing occurs whenever the buffer + is full, or when an event of a certain severity or greater is seen. + """ + def __init__(self, capacity, flushLevel=logging.ERROR, target=None): + """ + Initialize the handler with the buffer size, the level at which + flushing should occur and an optional target. + + Note that without a target being set either here or via setTarget(), + a MemoryHandler is no use to anyone! + """ + BufferingHandler.__init__(self, capacity) + self.flushLevel = flushLevel + self.target = target + + def shouldFlush(self, record): + """ + Check for buffer full or a record at the flushLevel or higher. + """ + return (len(self.buffer) >= self.capacity) or \ + (record.levelno >= self.flushLevel) + + def setTarget(self, target): + """ + Set the target handler for this handler. + """ + self.target = target + + def flush(self): + """ + For a MemoryHandler, flushing means just sending the buffered + records to the target, if there is one. Override if you want + different behaviour. + """ + self.acquire() + try: + if self.target: + for record in self.buffer: + self.target.handle(record) + self.buffer = [] + finally: + self.release() + + def close(self): + """ + Flush, set the target to None and lose the buffer. + """ + self.flush() + self.acquire() + try: + self.target = None + BufferingHandler.close(self) + finally: + self.release() diff --git a/PythonHome/Lib/logging/handlers.pyc b/PythonHome/Lib/logging/handlers.pyc deleted file mode 100644 index fb92502ccc925d87cefe1c439d6ea8c8f8b5d5e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38918 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 G=l&n?yQ41v diff --git a/PythonHome/Lib/macpath.py b/PythonHome/Lib/macpath.py new file mode 100644 index 0000000000..cd4cb8581a --- /dev/null +++ b/PythonHome/Lib/macpath.py @@ -0,0 +1,215 @@ +"""Pathname and path-related operations for the Macintosh.""" + +import os +import warnings +from stat import * +import genericpath +from genericpath import * + +__all__ = ["normcase","isabs","join","splitdrive","split","splitext", + "basename","dirname","commonprefix","getsize","getmtime", + "getatime","getctime", "islink","exists","lexists","isdir","isfile", + "walk","expanduser","expandvars","normpath","abspath", + "curdir","pardir","sep","pathsep","defpath","altsep","extsep", + "devnull","realpath","supports_unicode_filenames"] + +# strings representing various path-related bits and pieces +curdir = ':' +pardir = '::' +extsep = '.' +sep = ':' +pathsep = '\n' +defpath = ':' +altsep = None +devnull = 'Dev:Null' + +# Normalize the case of a pathname. Dummy in Posix, but .lower() here. + +def normcase(path): + return path.lower() + + +def isabs(s): + """Return true if a path is absolute. + On the Mac, relative paths begin with a colon, + but as a special case, paths with no colons at all are also relative. + Anything else is absolute (the string up to the first colon is the + volume name).""" + + return ':' in s and s[0] != ':' + + +def join(s, *p): + path = s + for t in p: + if (not s) or isabs(t): + path = t + continue + if t[:1] == ':': + t = t[1:] + if ':' not in path: + path = ':' + path + if path[-1:] != ':': + path = path + ':' + path = path + t + return path + + +def split(s): + """Split a pathname into two parts: the directory leading up to the final + bit, and the basename (the filename, without colons, in that directory). + The result (s, t) is such that join(s, t) yields the original argument.""" + + if ':' not in s: return '', s + colon = 0 + for i in range(len(s)): + if s[i] == ':': colon = i + 1 + path, file = s[:colon-1], s[colon:] + if path and not ':' in path: + path = path + ':' + return path, file + + +def splitext(p): + return genericpath._splitext(p, sep, altsep, extsep) +splitext.__doc__ = genericpath._splitext.__doc__ + +def splitdrive(p): + """Split a pathname into a drive specification and the rest of the + path. Useful on DOS/Windows/NT; on the Mac, the drive is always + empty (don't use the volume name -- it doesn't have the same + syntactic and semantic oddities as DOS drive letters, such as there + being a separate current directory per drive).""" + + return '', p + + +# Short interfaces to split() + +def dirname(s): return split(s)[0] +def basename(s): return split(s)[1] + +def ismount(s): + if not isabs(s): + return False + components = split(s) + return len(components) == 2 and components[1] == '' + +def islink(s): + """Return true if the pathname refers to a symbolic link.""" + + try: + import Carbon.File + return Carbon.File.ResolveAliasFile(s, 0)[2] + except: + return False + +# Is `stat`/`lstat` a meaningful difference on the Mac? This is safe in any +# case. + +def lexists(path): + """Test whether a path exists. Returns True for broken symbolic links""" + + try: + st = os.lstat(path) + except os.error: + return False + return True + +def expandvars(path): + """Dummy to retain interface-compatibility with other operating systems.""" + return path + + +def expanduser(path): + """Dummy to retain interface-compatibility with other operating systems.""" + return path + +class norm_error(Exception): + """Path cannot be normalized""" + +def normpath(s): + """Normalize a pathname. Will return the same result for + equivalent paths.""" + + if ":" not in s: + return ":"+s + + comps = s.split(":") + i = 1 + while i < len(comps)-1: + if comps[i] == "" and comps[i-1] != "": + if i > 1: + del comps[i-1:i+1] + i = i - 1 + else: + # best way to handle this is to raise an exception + raise norm_error, 'Cannot use :: immediately after volume name' + else: + i = i + 1 + + s = ":".join(comps) + + # remove trailing ":" except for ":" and "Volume:" + if s[-1] == ":" and len(comps) > 2 and s != ":"*len(s): + s = s[:-1] + return s + + +def walk(top, func, arg): + """Directory tree walk with callback function. + + For each directory in the directory tree rooted at top (including top + itself, but excluding '.' and '..'), call func(arg, dirname, fnames). + dirname is the name of the directory, and fnames a list of the names of + the files and subdirectories in dirname (excluding '.' and '..'). func + may modify the fnames list in-place (e.g. via del or slice assignment), + and walk will only recurse into the subdirectories whose names remain in + fnames; this can be used to implement a filter, or to impose a specific + order of visiting. No semantics are defined for, or required of, arg, + beyond that arg is always passed to func. It can be used, e.g., to pass + a filename pattern, or a mutable object designed to accumulate + statistics. Passing None for arg is common.""" + warnings.warnpy3k("In 3.x, os.path.walk is removed in favor of os.walk.", + stacklevel=2) + try: + names = os.listdir(top) + except os.error: + return + func(arg, top, names) + for name in names: + name = join(top, name) + if isdir(name) and not islink(name): + walk(name, func, arg) + + +def abspath(path): + """Return an absolute path.""" + if not isabs(path): + if isinstance(path, unicode): + cwd = os.getcwdu() + else: + cwd = os.getcwd() + path = join(cwd, path) + return normpath(path) + +# realpath is a no-op on systems without islink support +def realpath(path): + path = abspath(path) + try: + import Carbon.File + except ImportError: + return path + if not path: + return path + components = path.split(':') + path = components[0] + ':' + for c in components[1:]: + path = join(path, c) + try: + path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname() + except Carbon.File.Error: + pass + return path + +supports_unicode_filenames = True diff --git a/PythonHome/Lib/macpath.pyc b/PythonHome/Lib/macpath.pyc deleted file mode 100644 index 7b81857965fbd21d6b5e30fd8257395764a4ac93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7362 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 L+NIi4wYmQQU)MoI diff --git a/PythonHome/Lib/macurl2path.py b/PythonHome/Lib/macurl2path.py new file mode 100644 index 0000000000..6f8260f104 --- /dev/null +++ b/PythonHome/Lib/macurl2path.py @@ -0,0 +1,77 @@ +"""Macintosh-specific module for conversion between pathnames and URLs. + +Do not import directly; use urllib instead.""" + +import urllib +import os + +__all__ = ["url2pathname","pathname2url"] + +def url2pathname(pathname): + """OS-specific conversion from a relative URL of the 'file' scheme + to a file system path; not recommended for general use.""" + # + # XXXX The .. handling should be fixed... + # + tp = urllib.splittype(pathname)[0] + if tp and tp != 'file': + raise RuntimeError, 'Cannot convert non-local URL to pathname' + # Turn starting /// into /, an empty hostname means current host + if pathname[:3] == '///': + pathname = pathname[2:] + elif pathname[:2] == '//': + raise RuntimeError, 'Cannot convert non-local URL to pathname' + components = pathname.split('/') + # Remove . and embedded .. + i = 0 + while i < len(components): + if components[i] == '.': + del components[i] + elif components[i] == '..' and i > 0 and \ + components[i-1] not in ('', '..'): + del components[i-1:i+1] + i = i-1 + elif components[i] == '' and i > 0 and components[i-1] != '': + del components[i] + else: + i = i+1 + if not components[0]: + # Absolute unix path, don't start with colon + rv = ':'.join(components[1:]) + else: + # relative unix path, start with colon. First replace + # leading .. by empty strings (giving ::file) + i = 0 + while i < len(components) and components[i] == '..': + components[i] = '' + i = i + 1 + rv = ':' + ':'.join(components) + # and finally unquote slashes and other funny characters + return urllib.unquote(rv) + +def pathname2url(pathname): + """OS-specific conversion from a file system path to a relative URL + of the 'file' scheme; not recommended for general use.""" + if '/' in pathname: + raise RuntimeError, "Cannot convert pathname containing slashes" + components = pathname.split(':') + # Remove empty first and/or last component + if components[0] == '': + del components[0] + if components[-1] == '': + del components[-1] + # Replace empty string ('::') by .. (will result in '/../' later) + for i in range(len(components)): + if components[i] == '': + components[i] = '..' + # Truncate names longer than 31 bytes + components = map(_pncomp2url, components) + + if os.path.isabs(pathname): + return '/' + '/'.join(components) + else: + return '/'.join(components) + +def _pncomp2url(component): + component = urllib.quote(component[:31], safe='') # We want to quote slashes + return component diff --git a/PythonHome/Lib/macurl2path.pyc b/PythonHome/Lib/macurl2path.pyc deleted file mode 100644 index 0ad92dd51b6b4f16d5f2acbc0a73b3e44e047496..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2184 zcma)7O>ZMb5Un0Nlf-d8_A{{*l$H=$Yo)be1+282MW77_#1f>jAW~RlCNu4%?QxGY z-3}X(To(Sz-Z*pT06&5M!5P7;9@_~45iEC2byam$clCQSmEV_ZKka?fNoev5@caCC5dU=>w^abt+C<`cM3JT^+UIc{oky4b#a(coKn#IgBdC zGYtDHERLuz=#1!lfA+>XCW4B0SmI!V3hU1I;#EL~I228h=*J+SV%N_@+BzpPo0Ew| zYuMSpy0DKvE^wuDB!sNc%b)42Las_@0ow;e#g2duVN+CCG+L5+ixl>IJb4>KW$5ze-P;?1&0yp06fz_Pl(=i*8*L7y&0>3`Y{Z!KEb(ylukHzEcbg1>h)))==0RD+ z=1@gTJmqS`c;tA}9T|ojztug=a_a%hh5a&Z;{zM<7oo|^q7@cvEN-w3<2pz(oZiK- zn;cxJdmu6hF@grX$W7Wnz z<=av6*mIYuR+5f$d;ZP{_J8(&2dh5i++2V}LzJ%s&fV>%dD87htVeetJjc7;ILlzg loFc9naf*vl|4m{4R@g4T^B;IzaPz|eeGBTr;{C<-zX0Jg#qt0E diff --git a/PythonHome/Lib/mailbox.py b/PythonHome/Lib/mailbox.py new file mode 100644 index 0000000000..ba49753087 --- /dev/null +++ b/PythonHome/Lib/mailbox.py @@ -0,0 +1,2236 @@ +"""Read/write support for Maildir, mbox, MH, Babyl, and MMDF mailboxes.""" + +# Notes for authors of new mailbox subclasses: +# +# Remember to fsync() changes to disk before closing a modified file +# or returning from a flush() method. See functions _sync_flush() and +# _sync_close(). + +import sys +import os +import time +import calendar +import socket +import errno +import copy +import email +import email.message +import email.generator +import StringIO +try: + if sys.platform == 'os2emx': + # OS/2 EMX fcntl() not adequate + raise ImportError + import fcntl +except ImportError: + fcntl = None + +import warnings +with warnings.catch_warnings(): + if sys.py3kwarning: + warnings.filterwarnings("ignore", ".*rfc822 has been removed", + DeprecationWarning) + import rfc822 + +__all__ = [ 'Mailbox', 'Maildir', 'mbox', 'MH', 'Babyl', 'MMDF', + 'Message', 'MaildirMessage', 'mboxMessage', 'MHMessage', + 'BabylMessage', 'MMDFMessage', 'UnixMailbox', + 'PortableUnixMailbox', 'MmdfMailbox', 'MHMailbox', 'BabylMailbox' ] + +class Mailbox: + """A group of messages in a particular place.""" + + def __init__(self, path, factory=None, create=True): + """Initialize a Mailbox instance.""" + self._path = os.path.abspath(os.path.expanduser(path)) + self._factory = factory + + def add(self, message): + """Add message and return assigned key.""" + raise NotImplementedError('Method must be implemented by subclass') + + def remove(self, key): + """Remove the keyed message; raise KeyError if it doesn't exist.""" + raise NotImplementedError('Method must be implemented by subclass') + + def __delitem__(self, key): + self.remove(key) + + def discard(self, key): + """If the keyed message exists, remove it.""" + try: + self.remove(key) + except KeyError: + pass + + def __setitem__(self, key, message): + """Replace the keyed message; raise KeyError if it doesn't exist.""" + raise NotImplementedError('Method must be implemented by subclass') + + def get(self, key, default=None): + """Return the keyed message, or default if it doesn't exist.""" + try: + return self.__getitem__(key) + except KeyError: + return default + + def __getitem__(self, key): + """Return the keyed message; raise KeyError if it doesn't exist.""" + if not self._factory: + return self.get_message(key) + else: + return self._factory(self.get_file(key)) + + def get_message(self, key): + """Return a Message representation or raise a KeyError.""" + raise NotImplementedError('Method must be implemented by subclass') + + def get_string(self, key): + """Return a string representation or raise a KeyError.""" + raise NotImplementedError('Method must be implemented by subclass') + + def get_file(self, key): + """Return a file-like representation or raise a KeyError.""" + raise NotImplementedError('Method must be implemented by subclass') + + def iterkeys(self): + """Return an iterator over keys.""" + raise NotImplementedError('Method must be implemented by subclass') + + def keys(self): + """Return a list of keys.""" + return list(self.iterkeys()) + + def itervalues(self): + """Return an iterator over all messages.""" + for key in self.iterkeys(): + try: + value = self[key] + except KeyError: + continue + yield value + + def __iter__(self): + return self.itervalues() + + def values(self): + """Return a list of messages. Memory intensive.""" + return list(self.itervalues()) + + def iteritems(self): + """Return an iterator over (key, message) tuples.""" + for key in self.iterkeys(): + try: + value = self[key] + except KeyError: + continue + yield (key, value) + + def items(self): + """Return a list of (key, message) tuples. Memory intensive.""" + return list(self.iteritems()) + + def has_key(self, key): + """Return True if the keyed message exists, False otherwise.""" + raise NotImplementedError('Method must be implemented by subclass') + + def __contains__(self, key): + return self.has_key(key) + + def __len__(self): + """Return a count of messages in the mailbox.""" + raise NotImplementedError('Method must be implemented by subclass') + + def clear(self): + """Delete all messages.""" + for key in self.iterkeys(): + self.discard(key) + + def pop(self, key, default=None): + """Delete the keyed message and return it, or default.""" + try: + result = self[key] + except KeyError: + return default + self.discard(key) + return result + + def popitem(self): + """Delete an arbitrary (key, message) pair and return it.""" + for key in self.iterkeys(): + return (key, self.pop(key)) # This is only run once. + else: + raise KeyError('No messages in mailbox') + + def update(self, arg=None): + """Change the messages that correspond to certain keys.""" + if hasattr(arg, 'iteritems'): + source = arg.iteritems() + elif hasattr(arg, 'items'): + source = arg.items() + else: + source = arg + bad_key = False + for key, message in source: + try: + self[key] = message + except KeyError: + bad_key = True + if bad_key: + raise KeyError('No message with key(s)') + + def flush(self): + """Write any pending changes to the disk.""" + raise NotImplementedError('Method must be implemented by subclass') + + def lock(self): + """Lock the mailbox.""" + raise NotImplementedError('Method must be implemented by subclass') + + def unlock(self): + """Unlock the mailbox if it is locked.""" + raise NotImplementedError('Method must be implemented by subclass') + + def close(self): + """Flush and close the mailbox.""" + raise NotImplementedError('Method must be implemented by subclass') + + # Whether each message must end in a newline + _append_newline = False + + def _dump_message(self, message, target, mangle_from_=False): + # Most files are opened in binary mode to allow predictable seeking. + # To get native line endings on disk, the user-friendly \n line endings + # used in strings and by email.Message are translated here. + """Dump message contents to target file.""" + if isinstance(message, email.message.Message): + buffer = StringIO.StringIO() + gen = email.generator.Generator(buffer, mangle_from_, 0) + gen.flatten(message) + buffer.seek(0) + data = buffer.read().replace('\n', os.linesep) + target.write(data) + if self._append_newline and not data.endswith(os.linesep): + # Make sure the message ends with a newline + target.write(os.linesep) + elif isinstance(message, str): + if mangle_from_: + message = message.replace('\nFrom ', '\n>From ') + message = message.replace('\n', os.linesep) + target.write(message) + if self._append_newline and not message.endswith(os.linesep): + # Make sure the message ends with a newline + target.write(os.linesep) + elif hasattr(message, 'read'): + lastline = None + while True: + line = message.readline() + if line == '': + break + if mangle_from_ and line.startswith('From '): + line = '>From ' + line[5:] + line = line.replace('\n', os.linesep) + target.write(line) + lastline = line + if self._append_newline and lastline and not lastline.endswith(os.linesep): + # Make sure the message ends with a newline + target.write(os.linesep) + else: + raise TypeError('Invalid message type: %s' % type(message)) + + +class Maildir(Mailbox): + """A qmail-style Maildir mailbox.""" + + colon = ':' + + def __init__(self, dirname, factory=rfc822.Message, create=True): + """Initialize a Maildir instance.""" + Mailbox.__init__(self, dirname, factory, create) + self._paths = { + 'tmp': os.path.join(self._path, 'tmp'), + 'new': os.path.join(self._path, 'new'), + 'cur': os.path.join(self._path, 'cur'), + } + if not os.path.exists(self._path): + if create: + os.mkdir(self._path, 0700) + for path in self._paths.values(): + os.mkdir(path, 0o700) + else: + raise NoSuchMailboxError(self._path) + self._toc = {} + self._toc_mtimes = {'cur': 0, 'new': 0} + self._last_read = 0 # Records last time we read cur/new + self._skewfactor = 0.1 # Adjust if os/fs clocks are skewing + + def add(self, message): + """Add message and return assigned key.""" + tmp_file = self._create_tmp() + try: + self._dump_message(message, tmp_file) + except BaseException: + tmp_file.close() + os.remove(tmp_file.name) + raise + _sync_close(tmp_file) + if isinstance(message, MaildirMessage): + subdir = message.get_subdir() + suffix = self.colon + message.get_info() + if suffix == self.colon: + suffix = '' + else: + subdir = 'new' + suffix = '' + uniq = os.path.basename(tmp_file.name).split(self.colon)[0] + dest = os.path.join(self._path, subdir, uniq + suffix) + if isinstance(message, MaildirMessage): + os.utime(tmp_file.name, + (os.path.getatime(tmp_file.name), message.get_date())) + # No file modification should be done after the file is moved to its + # final position in order to prevent race conditions with changes + # from other programs + try: + if hasattr(os, 'link'): + os.link(tmp_file.name, dest) + os.remove(tmp_file.name) + else: + os.rename(tmp_file.name, dest) + except OSError, e: + os.remove(tmp_file.name) + if e.errno == errno.EEXIST: + raise ExternalClashError('Name clash with existing message: %s' + % dest) + else: + raise + return uniq + + def remove(self, key): + """Remove the keyed message; raise KeyError if it doesn't exist.""" + os.remove(os.path.join(self._path, self._lookup(key))) + + def discard(self, key): + """If the keyed message exists, remove it.""" + # This overrides an inapplicable implementation in the superclass. + try: + self.remove(key) + except KeyError: + pass + except OSError, e: + if e.errno != errno.ENOENT: + raise + + def __setitem__(self, key, message): + """Replace the keyed message; raise KeyError if it doesn't exist.""" + old_subpath = self._lookup(key) + temp_key = self.add(message) + temp_subpath = self._lookup(temp_key) + if isinstance(message, MaildirMessage): + # temp's subdir and suffix were specified by message. + dominant_subpath = temp_subpath + else: + # temp's subdir and suffix were defaults from add(). + dominant_subpath = old_subpath + subdir = os.path.dirname(dominant_subpath) + if self.colon in dominant_subpath: + suffix = self.colon + dominant_subpath.split(self.colon)[-1] + else: + suffix = '' + self.discard(key) + tmp_path = os.path.join(self._path, temp_subpath) + new_path = os.path.join(self._path, subdir, key + suffix) + if isinstance(message, MaildirMessage): + os.utime(tmp_path, + (os.path.getatime(tmp_path), message.get_date())) + # No file modification should be done after the file is moved to its + # final position in order to prevent race conditions with changes + # from other programs + os.rename(tmp_path, new_path) + + def get_message(self, key): + """Return a Message representation or raise a KeyError.""" + subpath = self._lookup(key) + f = open(os.path.join(self._path, subpath), 'r') + try: + if self._factory: + msg = self._factory(f) + else: + msg = MaildirMessage(f) + finally: + f.close() + subdir, name = os.path.split(subpath) + msg.set_subdir(subdir) + if self.colon in name: + msg.set_info(name.split(self.colon)[-1]) + msg.set_date(os.path.getmtime(os.path.join(self._path, subpath))) + return msg + + def get_string(self, key): + """Return a string representation or raise a KeyError.""" + f = open(os.path.join(self._path, self._lookup(key)), 'r') + try: + return f.read() + finally: + f.close() + + def get_file(self, key): + """Return a file-like representation or raise a KeyError.""" + f = open(os.path.join(self._path, self._lookup(key)), 'rb') + return _ProxyFile(f) + + def iterkeys(self): + """Return an iterator over keys.""" + self._refresh() + for key in self._toc: + try: + self._lookup(key) + except KeyError: + continue + yield key + + def has_key(self, key): + """Return True if the keyed message exists, False otherwise.""" + self._refresh() + return key in self._toc + + def __len__(self): + """Return a count of messages in the mailbox.""" + self._refresh() + return len(self._toc) + + def flush(self): + """Write any pending changes to disk.""" + # Maildir changes are always written immediately, so there's nothing + # to do. + pass + + def lock(self): + """Lock the mailbox.""" + return + + def unlock(self): + """Unlock the mailbox if it is locked.""" + return + + def close(self): + """Flush and close the mailbox.""" + return + + def list_folders(self): + """Return a list of folder names.""" + result = [] + for entry in os.listdir(self._path): + if len(entry) > 1 and entry[0] == '.' and \ + os.path.isdir(os.path.join(self._path, entry)): + result.append(entry[1:]) + return result + + def get_folder(self, folder): + """Return a Maildir instance for the named folder.""" + return Maildir(os.path.join(self._path, '.' + folder), + factory=self._factory, + create=False) + + def add_folder(self, folder): + """Create a folder and return a Maildir instance representing it.""" + path = os.path.join(self._path, '.' + folder) + result = Maildir(path, factory=self._factory) + maildirfolder_path = os.path.join(path, 'maildirfolder') + if not os.path.exists(maildirfolder_path): + os.close(os.open(maildirfolder_path, os.O_CREAT | os.O_WRONLY, + 0666)) + return result + + def remove_folder(self, folder): + """Delete the named folder, which must be empty.""" + path = os.path.join(self._path, '.' + folder) + for entry in os.listdir(os.path.join(path, 'new')) + \ + os.listdir(os.path.join(path, 'cur')): + if len(entry) < 1 or entry[0] != '.': + raise NotEmptyError('Folder contains message(s): %s' % folder) + for entry in os.listdir(path): + if entry != 'new' and entry != 'cur' and entry != 'tmp' and \ + os.path.isdir(os.path.join(path, entry)): + raise NotEmptyError("Folder contains subdirectory '%s': %s" % + (folder, entry)) + for root, dirs, files in os.walk(path, topdown=False): + for entry in files: + os.remove(os.path.join(root, entry)) + for entry in dirs: + os.rmdir(os.path.join(root, entry)) + os.rmdir(path) + + def clean(self): + """Delete old files in "tmp".""" + now = time.time() + for entry in os.listdir(os.path.join(self._path, 'tmp')): + path = os.path.join(self._path, 'tmp', entry) + if now - os.path.getatime(path) > 129600: # 60 * 60 * 36 + os.remove(path) + + _count = 1 # This is used to generate unique file names. + + def _create_tmp(self): + """Create a file in the tmp subdirectory and open and return it.""" + now = time.time() + hostname = socket.gethostname() + if '/' in hostname: + hostname = hostname.replace('/', r'\057') + if ':' in hostname: + hostname = hostname.replace(':', r'\072') + uniq = "%s.M%sP%sQ%s.%s" % (int(now), int(now % 1 * 1e6), os.getpid(), + Maildir._count, hostname) + path = os.path.join(self._path, 'tmp', uniq) + try: + os.stat(path) + except OSError, e: + if e.errno == errno.ENOENT: + Maildir._count += 1 + try: + return _create_carefully(path) + except OSError, e: + if e.errno != errno.EEXIST: + raise + else: + raise + + # Fall through to here if stat succeeded or open raised EEXIST. + raise ExternalClashError('Name clash prevented file creation: %s' % + path) + + def _refresh(self): + """Update table of contents mapping.""" + # If it has been less than two seconds since the last _refresh() call, + # we have to unconditionally re-read the mailbox just in case it has + # been modified, because os.path.mtime() has a 2 sec resolution in the + # most common worst case (FAT) and a 1 sec resolution typically. This + # results in a few unnecessary re-reads when _refresh() is called + # multiple times in that interval, but once the clock ticks over, we + # will only re-read as needed. Because the filesystem might be being + # served by an independent system with its own clock, we record and + # compare with the mtimes from the filesystem. Because the other + # system's clock might be skewing relative to our clock, we add an + # extra delta to our wait. The default is one tenth second, but is an + # instance variable and so can be adjusted if dealing with a + # particularly skewed or irregular system. + if time.time() - self._last_read > 2 + self._skewfactor: + refresh = False + for subdir in self._toc_mtimes: + mtime = os.path.getmtime(self._paths[subdir]) + if mtime > self._toc_mtimes[subdir]: + refresh = True + self._toc_mtimes[subdir] = mtime + if not refresh: + return + # Refresh toc + self._toc = {} + for subdir in self._toc_mtimes: + path = self._paths[subdir] + for entry in os.listdir(path): + p = os.path.join(path, entry) + if os.path.isdir(p): + continue + uniq = entry.split(self.colon)[0] + self._toc[uniq] = os.path.join(subdir, entry) + self._last_read = time.time() + + def _lookup(self, key): + """Use TOC to return subpath for given key, or raise a KeyError.""" + try: + if os.path.exists(os.path.join(self._path, self._toc[key])): + return self._toc[key] + except KeyError: + pass + self._refresh() + try: + return self._toc[key] + except KeyError: + raise KeyError('No message with key: %s' % key) + + # This method is for backward compatibility only. + def next(self): + """Return the next message in a one-time iteration.""" + if not hasattr(self, '_onetime_keys'): + self._onetime_keys = self.iterkeys() + while True: + try: + return self[self._onetime_keys.next()] + except StopIteration: + return None + except KeyError: + continue + + +class _singlefileMailbox(Mailbox): + """A single-file mailbox.""" + + def __init__(self, path, factory=None, create=True): + """Initialize a single-file mailbox.""" + Mailbox.__init__(self, path, factory, create) + try: + f = open(self._path, 'rb+') + except IOError, e: + if e.errno == errno.ENOENT: + if create: + f = open(self._path, 'wb+') + else: + raise NoSuchMailboxError(self._path) + elif e.errno in (errno.EACCES, errno.EROFS): + f = open(self._path, 'rb') + else: + raise + self._file = f + self._toc = None + self._next_key = 0 + self._pending = False # No changes require rewriting the file. + self._pending_sync = False # No need to sync the file + self._locked = False + self._file_length = None # Used to record mailbox size + + def add(self, message): + """Add message and return assigned key.""" + self._lookup() + self._toc[self._next_key] = self._append_message(message) + self._next_key += 1 + # _append_message appends the message to the mailbox file. We + # don't need a full rewrite + rename, sync is enough. + self._pending_sync = True + return self._next_key - 1 + + def remove(self, key): + """Remove the keyed message; raise KeyError if it doesn't exist.""" + self._lookup(key) + del self._toc[key] + self._pending = True + + def __setitem__(self, key, message): + """Replace the keyed message; raise KeyError if it doesn't exist.""" + self._lookup(key) + self._toc[key] = self._append_message(message) + self._pending = True + + def iterkeys(self): + """Return an iterator over keys.""" + self._lookup() + for key in self._toc.keys(): + yield key + + def has_key(self, key): + """Return True if the keyed message exists, False otherwise.""" + self._lookup() + return key in self._toc + + def __len__(self): + """Return a count of messages in the mailbox.""" + self._lookup() + return len(self._toc) + + def lock(self): + """Lock the mailbox.""" + if not self._locked: + _lock_file(self._file) + self._locked = True + + def unlock(self): + """Unlock the mailbox if it is locked.""" + if self._locked: + _unlock_file(self._file) + self._locked = False + + def flush(self): + """Write any pending changes to disk.""" + if not self._pending: + if self._pending_sync: + # Messages have only been added, so syncing the file + # is enough. + _sync_flush(self._file) + self._pending_sync = False + return + + # In order to be writing anything out at all, self._toc must + # already have been generated (and presumably has been modified + # by adding or deleting an item). + assert self._toc is not None + + # Check length of self._file; if it's changed, some other process + # has modified the mailbox since we scanned it. + self._file.seek(0, 2) + cur_len = self._file.tell() + if cur_len != self._file_length: + raise ExternalClashError('Size of mailbox file changed ' + '(expected %i, found %i)' % + (self._file_length, cur_len)) + + new_file = _create_temporary(self._path) + try: + new_toc = {} + self._pre_mailbox_hook(new_file) + for key in sorted(self._toc.keys()): + start, stop = self._toc[key] + self._file.seek(start) + self._pre_message_hook(new_file) + new_start = new_file.tell() + while True: + buffer = self._file.read(min(4096, + stop - self._file.tell())) + if buffer == '': + break + new_file.write(buffer) + new_toc[key] = (new_start, new_file.tell()) + self._post_message_hook(new_file) + self._file_length = new_file.tell() + except: + new_file.close() + os.remove(new_file.name) + raise + _sync_close(new_file) + # self._file is about to get replaced, so no need to sync. + self._file.close() + # Make sure the new file's mode is the same as the old file's + mode = os.stat(self._path).st_mode + os.chmod(new_file.name, mode) + try: + os.rename(new_file.name, self._path) + except OSError, e: + if e.errno == errno.EEXIST or \ + (os.name == 'os2' and e.errno == errno.EACCES): + os.remove(self._path) + os.rename(new_file.name, self._path) + else: + raise + self._file = open(self._path, 'rb+') + self._toc = new_toc + self._pending = False + self._pending_sync = False + if self._locked: + _lock_file(self._file, dotlock=False) + + def _pre_mailbox_hook(self, f): + """Called before writing the mailbox to file f.""" + return + + def _pre_message_hook(self, f): + """Called before writing each message to file f.""" + return + + def _post_message_hook(self, f): + """Called after writing each message to file f.""" + return + + def close(self): + """Flush and close the mailbox.""" + self.flush() + if self._locked: + self.unlock() + self._file.close() # Sync has been done by self.flush() above. + + def _lookup(self, key=None): + """Return (start, stop) or raise KeyError.""" + if self._toc is None: + self._generate_toc() + if key is not None: + try: + return self._toc[key] + except KeyError: + raise KeyError('No message with key: %s' % key) + + def _append_message(self, message): + """Append message to mailbox and return (start, stop) offsets.""" + self._file.seek(0, 2) + before = self._file.tell() + if len(self._toc) == 0 and not self._pending: + # This is the first message, and the _pre_mailbox_hook + # hasn't yet been called. If self._pending is True, + # messages have been removed, so _pre_mailbox_hook must + # have been called already. + self._pre_mailbox_hook(self._file) + try: + self._pre_message_hook(self._file) + offsets = self._install_message(message) + self._post_message_hook(self._file) + except BaseException: + self._file.truncate(before) + raise + self._file.flush() + self._file_length = self._file.tell() # Record current length of mailbox + return offsets + + + +class _mboxMMDF(_singlefileMailbox): + """An mbox or MMDF mailbox.""" + + _mangle_from_ = True + + def get_message(self, key): + """Return a Message representation or raise a KeyError.""" + start, stop = self._lookup(key) + self._file.seek(start) + from_line = self._file.readline().replace(os.linesep, '') + string = self._file.read(stop - self._file.tell()) + msg = self._message_factory(string.replace(os.linesep, '\n')) + msg.set_from(from_line[5:]) + return msg + + def get_string(self, key, from_=False): + """Return a string representation or raise a KeyError.""" + start, stop = self._lookup(key) + self._file.seek(start) + if not from_: + self._file.readline() + string = self._file.read(stop - self._file.tell()) + return string.replace(os.linesep, '\n') + + def get_file(self, key, from_=False): + """Return a file-like representation or raise a KeyError.""" + start, stop = self._lookup(key) + self._file.seek(start) + if not from_: + self._file.readline() + return _PartialFile(self._file, self._file.tell(), stop) + + def _install_message(self, message): + """Format a message and blindly write to self._file.""" + from_line = None + if isinstance(message, str) and message.startswith('From '): + newline = message.find('\n') + if newline != -1: + from_line = message[:newline] + message = message[newline + 1:] + else: + from_line = message + message = '' + elif isinstance(message, _mboxMMDFMessage): + from_line = 'From ' + message.get_from() + elif isinstance(message, email.message.Message): + from_line = message.get_unixfrom() # May be None. + if from_line is None: + from_line = 'From MAILER-DAEMON %s' % time.asctime(time.gmtime()) + start = self._file.tell() + self._file.write(from_line + os.linesep) + self._dump_message(message, self._file, self._mangle_from_) + stop = self._file.tell() + return (start, stop) + + +class mbox(_mboxMMDF): + """A classic mbox mailbox.""" + + _mangle_from_ = True + + # All messages must end in a newline character, and + # _post_message_hooks outputs an empty line between messages. + _append_newline = True + + def __init__(self, path, factory=None, create=True): + """Initialize an mbox mailbox.""" + self._message_factory = mboxMessage + _mboxMMDF.__init__(self, path, factory, create) + + def _post_message_hook(self, f): + """Called after writing each message to file f.""" + f.write(os.linesep) + + def _generate_toc(self): + """Generate key-to-(start, stop) table of contents.""" + starts, stops = [], [] + last_was_empty = False + self._file.seek(0) + while True: + line_pos = self._file.tell() + line = self._file.readline() + if line.startswith('From '): + if len(stops) < len(starts): + if last_was_empty: + stops.append(line_pos - len(os.linesep)) + else: + # The last line before the "From " line wasn't + # blank, but we consider it a start of a + # message anyway. + stops.append(line_pos) + starts.append(line_pos) + last_was_empty = False + elif not line: + if last_was_empty: + stops.append(line_pos - len(os.linesep)) + else: + stops.append(line_pos) + break + elif line == os.linesep: + last_was_empty = True + else: + last_was_empty = False + self._toc = dict(enumerate(zip(starts, stops))) + self._next_key = len(self._toc) + self._file_length = self._file.tell() + + +class MMDF(_mboxMMDF): + """An MMDF mailbox.""" + + def __init__(self, path, factory=None, create=True): + """Initialize an MMDF mailbox.""" + self._message_factory = MMDFMessage + _mboxMMDF.__init__(self, path, factory, create) + + def _pre_message_hook(self, f): + """Called before writing each message to file f.""" + f.write('\001\001\001\001' + os.linesep) + + def _post_message_hook(self, f): + """Called after writing each message to file f.""" + f.write(os.linesep + '\001\001\001\001' + os.linesep) + + def _generate_toc(self): + """Generate key-to-(start, stop) table of contents.""" + starts, stops = [], [] + self._file.seek(0) + next_pos = 0 + while True: + line_pos = next_pos + line = self._file.readline() + next_pos = self._file.tell() + if line.startswith('\001\001\001\001' + os.linesep): + starts.append(next_pos) + while True: + line_pos = next_pos + line = self._file.readline() + next_pos = self._file.tell() + if line == '\001\001\001\001' + os.linesep: + stops.append(line_pos - len(os.linesep)) + break + elif line == '': + stops.append(line_pos) + break + elif line == '': + break + self._toc = dict(enumerate(zip(starts, stops))) + self._next_key = len(self._toc) + self._file.seek(0, 2) + self._file_length = self._file.tell() + + +class MH(Mailbox): + """An MH mailbox.""" + + def __init__(self, path, factory=None, create=True): + """Initialize an MH instance.""" + Mailbox.__init__(self, path, factory, create) + if not os.path.exists(self._path): + if create: + os.mkdir(self._path, 0700) + os.close(os.open(os.path.join(self._path, '.mh_sequences'), + os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0600)) + else: + raise NoSuchMailboxError(self._path) + self._locked = False + + def add(self, message): + """Add message and return assigned key.""" + keys = self.keys() + if len(keys) == 0: + new_key = 1 + else: + new_key = max(keys) + 1 + new_path = os.path.join(self._path, str(new_key)) + f = _create_carefully(new_path) + closed = False + try: + if self._locked: + _lock_file(f) + try: + try: + self._dump_message(message, f) + except BaseException: + # Unlock and close so it can be deleted on Windows + if self._locked: + _unlock_file(f) + _sync_close(f) + closed = True + os.remove(new_path) + raise + if isinstance(message, MHMessage): + self._dump_sequences(message, new_key) + finally: + if self._locked: + _unlock_file(f) + finally: + if not closed: + _sync_close(f) + return new_key + + def remove(self, key): + """Remove the keyed message; raise KeyError if it doesn't exist.""" + path = os.path.join(self._path, str(key)) + try: + f = open(path, 'rb+') + except IOError, e: + if e.errno == errno.ENOENT: + raise KeyError('No message with key: %s' % key) + else: + raise + else: + f.close() + os.remove(path) + + def __setitem__(self, key, message): + """Replace the keyed message; raise KeyError if it doesn't exist.""" + path = os.path.join(self._path, str(key)) + try: + f = open(path, 'rb+') + except IOError, e: + if e.errno == errno.ENOENT: + raise KeyError('No message with key: %s' % key) + else: + raise + try: + if self._locked: + _lock_file(f) + try: + os.close(os.open(path, os.O_WRONLY | os.O_TRUNC)) + self._dump_message(message, f) + if isinstance(message, MHMessage): + self._dump_sequences(message, key) + finally: + if self._locked: + _unlock_file(f) + finally: + _sync_close(f) + + def get_message(self, key): + """Return a Message representation or raise a KeyError.""" + try: + if self._locked: + f = open(os.path.join(self._path, str(key)), 'r+') + else: + f = open(os.path.join(self._path, str(key)), 'r') + except IOError, e: + if e.errno == errno.ENOENT: + raise KeyError('No message with key: %s' % key) + else: + raise + try: + if self._locked: + _lock_file(f) + try: + msg = MHMessage(f) + finally: + if self._locked: + _unlock_file(f) + finally: + f.close() + for name, key_list in self.get_sequences().iteritems(): + if key in key_list: + msg.add_sequence(name) + return msg + + def get_string(self, key): + """Return a string representation or raise a KeyError.""" + try: + if self._locked: + f = open(os.path.join(self._path, str(key)), 'r+') + else: + f = open(os.path.join(self._path, str(key)), 'r') + except IOError, e: + if e.errno == errno.ENOENT: + raise KeyError('No message with key: %s' % key) + else: + raise + try: + if self._locked: + _lock_file(f) + try: + return f.read() + finally: + if self._locked: + _unlock_file(f) + finally: + f.close() + + def get_file(self, key): + """Return a file-like representation or raise a KeyError.""" + try: + f = open(os.path.join(self._path, str(key)), 'rb') + except IOError, e: + if e.errno == errno.ENOENT: + raise KeyError('No message with key: %s' % key) + else: + raise + return _ProxyFile(f) + + def iterkeys(self): + """Return an iterator over keys.""" + return iter(sorted(int(entry) for entry in os.listdir(self._path) + if entry.isdigit())) + + def has_key(self, key): + """Return True if the keyed message exists, False otherwise.""" + return os.path.exists(os.path.join(self._path, str(key))) + + def __len__(self): + """Return a count of messages in the mailbox.""" + return len(list(self.iterkeys())) + + def lock(self): + """Lock the mailbox.""" + if not self._locked: + self._file = open(os.path.join(self._path, '.mh_sequences'), 'rb+') + _lock_file(self._file) + self._locked = True + + def unlock(self): + """Unlock the mailbox if it is locked.""" + if self._locked: + _unlock_file(self._file) + _sync_close(self._file) + del self._file + self._locked = False + + def flush(self): + """Write any pending changes to the disk.""" + return + + def close(self): + """Flush and close the mailbox.""" + if self._locked: + self.unlock() + + def list_folders(self): + """Return a list of folder names.""" + result = [] + for entry in os.listdir(self._path): + if os.path.isdir(os.path.join(self._path, entry)): + result.append(entry) + return result + + def get_folder(self, folder): + """Return an MH instance for the named folder.""" + return MH(os.path.join(self._path, folder), + factory=self._factory, create=False) + + def add_folder(self, folder): + """Create a folder and return an MH instance representing it.""" + return MH(os.path.join(self._path, folder), + factory=self._factory) + + def remove_folder(self, folder): + """Delete the named folder, which must be empty.""" + path = os.path.join(self._path, folder) + entries = os.listdir(path) + if entries == ['.mh_sequences']: + os.remove(os.path.join(path, '.mh_sequences')) + elif entries == []: + pass + else: + raise NotEmptyError('Folder not empty: %s' % self._path) + os.rmdir(path) + + def get_sequences(self): + """Return a name-to-key-list dictionary to define each sequence.""" + results = {} + f = open(os.path.join(self._path, '.mh_sequences'), 'r') + try: + all_keys = set(self.keys()) + for line in f: + try: + name, contents = line.split(':') + keys = set() + for spec in contents.split(): + if spec.isdigit(): + keys.add(int(spec)) + else: + start, stop = (int(x) for x in spec.split('-')) + keys.update(range(start, stop + 1)) + results[name] = [key for key in sorted(keys) \ + if key in all_keys] + if len(results[name]) == 0: + del results[name] + except ValueError: + raise FormatError('Invalid sequence specification: %s' % + line.rstrip()) + finally: + f.close() + return results + + def set_sequences(self, sequences): + """Set sequences using the given name-to-key-list dictionary.""" + f = open(os.path.join(self._path, '.mh_sequences'), 'r+') + try: + os.close(os.open(f.name, os.O_WRONLY | os.O_TRUNC)) + for name, keys in sequences.iteritems(): + if len(keys) == 0: + continue + f.write('%s:' % name) + prev = None + completing = False + for key in sorted(set(keys)): + if key - 1 == prev: + if not completing: + completing = True + f.write('-') + elif completing: + completing = False + f.write('%s %s' % (prev, key)) + else: + f.write(' %s' % key) + prev = key + if completing: + f.write(str(prev) + '\n') + else: + f.write('\n') + finally: + _sync_close(f) + + def pack(self): + """Re-name messages to eliminate numbering gaps. Invalidates keys.""" + sequences = self.get_sequences() + prev = 0 + changes = [] + for key in self.iterkeys(): + if key - 1 != prev: + changes.append((key, prev + 1)) + if hasattr(os, 'link'): + os.link(os.path.join(self._path, str(key)), + os.path.join(self._path, str(prev + 1))) + os.unlink(os.path.join(self._path, str(key))) + else: + os.rename(os.path.join(self._path, str(key)), + os.path.join(self._path, str(prev + 1))) + prev += 1 + self._next_key = prev + 1 + if len(changes) == 0: + return + for name, key_list in sequences.items(): + for old, new in changes: + if old in key_list: + key_list[key_list.index(old)] = new + self.set_sequences(sequences) + + def _dump_sequences(self, message, key): + """Inspect a new MHMessage and update sequences appropriately.""" + pending_sequences = message.get_sequences() + all_sequences = self.get_sequences() + for name, key_list in all_sequences.iteritems(): + if name in pending_sequences: + key_list.append(key) + elif key in key_list: + del key_list[key_list.index(key)] + for sequence in pending_sequences: + if sequence not in all_sequences: + all_sequences[sequence] = [key] + self.set_sequences(all_sequences) + + +class Babyl(_singlefileMailbox): + """An Rmail-style Babyl mailbox.""" + + _special_labels = frozenset(('unseen', 'deleted', 'filed', 'answered', + 'forwarded', 'edited', 'resent')) + + def __init__(self, path, factory=None, create=True): + """Initialize a Babyl mailbox.""" + _singlefileMailbox.__init__(self, path, factory, create) + self._labels = {} + + def add(self, message): + """Add message and return assigned key.""" + key = _singlefileMailbox.add(self, message) + if isinstance(message, BabylMessage): + self._labels[key] = message.get_labels() + return key + + def remove(self, key): + """Remove the keyed message; raise KeyError if it doesn't exist.""" + _singlefileMailbox.remove(self, key) + if key in self._labels: + del self._labels[key] + + def __setitem__(self, key, message): + """Replace the keyed message; raise KeyError if it doesn't exist.""" + _singlefileMailbox.__setitem__(self, key, message) + if isinstance(message, BabylMessage): + self._labels[key] = message.get_labels() + + def get_message(self, key): + """Return a Message representation or raise a KeyError.""" + start, stop = self._lookup(key) + self._file.seek(start) + self._file.readline() # Skip '1,' line specifying labels. + original_headers = StringIO.StringIO() + while True: + line = self._file.readline() + if line == '*** EOOH ***' + os.linesep or line == '': + break + original_headers.write(line.replace(os.linesep, '\n')) + visible_headers = StringIO.StringIO() + while True: + line = self._file.readline() + if line == os.linesep or line == '': + break + visible_headers.write(line.replace(os.linesep, '\n')) + body = self._file.read(stop - self._file.tell()).replace(os.linesep, + '\n') + msg = BabylMessage(original_headers.getvalue() + body) + msg.set_visible(visible_headers.getvalue()) + if key in self._labels: + msg.set_labels(self._labels[key]) + return msg + + def get_string(self, key): + """Return a string representation or raise a KeyError.""" + start, stop = self._lookup(key) + self._file.seek(start) + self._file.readline() # Skip '1,' line specifying labels. + original_headers = StringIO.StringIO() + while True: + line = self._file.readline() + if line == '*** EOOH ***' + os.linesep or line == '': + break + original_headers.write(line.replace(os.linesep, '\n')) + while True: + line = self._file.readline() + if line == os.linesep or line == '': + break + return original_headers.getvalue() + \ + self._file.read(stop - self._file.tell()).replace(os.linesep, + '\n') + + def get_file(self, key): + """Return a file-like representation or raise a KeyError.""" + return StringIO.StringIO(self.get_string(key).replace('\n', + os.linesep)) + + def get_labels(self): + """Return a list of user-defined labels in the mailbox.""" + self._lookup() + labels = set() + for label_list in self._labels.values(): + labels.update(label_list) + labels.difference_update(self._special_labels) + return list(labels) + + def _generate_toc(self): + """Generate key-to-(start, stop) table of contents.""" + starts, stops = [], [] + self._file.seek(0) + next_pos = 0 + label_lists = [] + while True: + line_pos = next_pos + line = self._file.readline() + next_pos = self._file.tell() + if line == '\037\014' + os.linesep: + if len(stops) < len(starts): + stops.append(line_pos - len(os.linesep)) + starts.append(next_pos) + labels = [label.strip() for label + in self._file.readline()[1:].split(',') + if label.strip() != ''] + label_lists.append(labels) + elif line == '\037' or line == '\037' + os.linesep: + if len(stops) < len(starts): + stops.append(line_pos - len(os.linesep)) + elif line == '': + stops.append(line_pos - len(os.linesep)) + break + self._toc = dict(enumerate(zip(starts, stops))) + self._labels = dict(enumerate(label_lists)) + self._next_key = len(self._toc) + self._file.seek(0, 2) + self._file_length = self._file.tell() + + def _pre_mailbox_hook(self, f): + """Called before writing the mailbox to file f.""" + f.write('BABYL OPTIONS:%sVersion: 5%sLabels:%s%s\037' % + (os.linesep, os.linesep, ','.join(self.get_labels()), + os.linesep)) + + def _pre_message_hook(self, f): + """Called before writing each message to file f.""" + f.write('\014' + os.linesep) + + def _post_message_hook(self, f): + """Called after writing each message to file f.""" + f.write(os.linesep + '\037') + + def _install_message(self, message): + """Write message contents and return (start, stop).""" + start = self._file.tell() + if isinstance(message, BabylMessage): + special_labels = [] + labels = [] + for label in message.get_labels(): + if label in self._special_labels: + special_labels.append(label) + else: + labels.append(label) + self._file.write('1') + for label in special_labels: + self._file.write(', ' + label) + self._file.write(',,') + for label in labels: + self._file.write(' ' + label + ',') + self._file.write(os.linesep) + else: + self._file.write('1,,' + os.linesep) + if isinstance(message, email.message.Message): + orig_buffer = StringIO.StringIO() + orig_generator = email.generator.Generator(orig_buffer, False, 0) + orig_generator.flatten(message) + orig_buffer.seek(0) + while True: + line = orig_buffer.readline() + self._file.write(line.replace('\n', os.linesep)) + if line == '\n' or line == '': + break + self._file.write('*** EOOH ***' + os.linesep) + if isinstance(message, BabylMessage): + vis_buffer = StringIO.StringIO() + vis_generator = email.generator.Generator(vis_buffer, False, 0) + vis_generator.flatten(message.get_visible()) + while True: + line = vis_buffer.readline() + self._file.write(line.replace('\n', os.linesep)) + if line == '\n' or line == '': + break + else: + orig_buffer.seek(0) + while True: + line = orig_buffer.readline() + self._file.write(line.replace('\n', os.linesep)) + if line == '\n' or line == '': + break + while True: + buffer = orig_buffer.read(4096) # Buffer size is arbitrary. + if buffer == '': + break + self._file.write(buffer.replace('\n', os.linesep)) + elif isinstance(message, str): + body_start = message.find('\n\n') + 2 + if body_start - 2 != -1: + self._file.write(message[:body_start].replace('\n', + os.linesep)) + self._file.write('*** EOOH ***' + os.linesep) + self._file.write(message[:body_start].replace('\n', + os.linesep)) + self._file.write(message[body_start:].replace('\n', + os.linesep)) + else: + self._file.write('*** EOOH ***' + os.linesep + os.linesep) + self._file.write(message.replace('\n', os.linesep)) + elif hasattr(message, 'readline'): + original_pos = message.tell() + first_pass = True + while True: + line = message.readline() + self._file.write(line.replace('\n', os.linesep)) + if line == '\n' or line == '': + if first_pass: + first_pass = False + self._file.write('*** EOOH ***' + os.linesep) + message.seek(original_pos) + else: + break + while True: + buffer = message.read(4096) # Buffer size is arbitrary. + if buffer == '': + break + self._file.write(buffer.replace('\n', os.linesep)) + else: + raise TypeError('Invalid message type: %s' % type(message)) + stop = self._file.tell() + return (start, stop) + + +class Message(email.message.Message): + """Message with mailbox-format-specific properties.""" + + def __init__(self, message=None): + """Initialize a Message instance.""" + if isinstance(message, email.message.Message): + self._become_message(copy.deepcopy(message)) + if isinstance(message, Message): + message._explain_to(self) + elif isinstance(message, str): + self._become_message(email.message_from_string(message)) + elif hasattr(message, "read"): + self._become_message(email.message_from_file(message)) + elif message is None: + email.message.Message.__init__(self) + else: + raise TypeError('Invalid message type: %s' % type(message)) + + def _become_message(self, message): + """Assume the non-format-specific state of message.""" + for name in ('_headers', '_unixfrom', '_payload', '_charset', + 'preamble', 'epilogue', 'defects', '_default_type'): + self.__dict__[name] = message.__dict__[name] + + def _explain_to(self, message): + """Copy format-specific state to message insofar as possible.""" + if isinstance(message, Message): + return # There's nothing format-specific to explain. + else: + raise TypeError('Cannot convert to specified type') + + +class MaildirMessage(Message): + """Message with Maildir-specific properties.""" + + def __init__(self, message=None): + """Initialize a MaildirMessage instance.""" + self._subdir = 'new' + self._info = '' + self._date = time.time() + Message.__init__(self, message) + + def get_subdir(self): + """Return 'new' or 'cur'.""" + return self._subdir + + def set_subdir(self, subdir): + """Set subdir to 'new' or 'cur'.""" + if subdir == 'new' or subdir == 'cur': + self._subdir = subdir + else: + raise ValueError("subdir must be 'new' or 'cur': %s" % subdir) + + def get_flags(self): + """Return as a string the flags that are set.""" + if self._info.startswith('2,'): + return self._info[2:] + else: + return '' + + def set_flags(self, flags): + """Set the given flags and unset all others.""" + self._info = '2,' + ''.join(sorted(flags)) + + def add_flag(self, flag): + """Set the given flag(s) without changing others.""" + self.set_flags(''.join(set(self.get_flags()) | set(flag))) + + def remove_flag(self, flag): + """Unset the given string flag(s) without changing others.""" + if self.get_flags() != '': + self.set_flags(''.join(set(self.get_flags()) - set(flag))) + + def get_date(self): + """Return delivery date of message, in seconds since the epoch.""" + return self._date + + def set_date(self, date): + """Set delivery date of message, in seconds since the epoch.""" + try: + self._date = float(date) + except ValueError: + raise TypeError("can't convert to float: %s" % date) + + def get_info(self): + """Get the message's "info" as a string.""" + return self._info + + def set_info(self, info): + """Set the message's "info" string.""" + if isinstance(info, str): + self._info = info + else: + raise TypeError('info must be a string: %s' % type(info)) + + def _explain_to(self, message): + """Copy Maildir-specific state to message insofar as possible.""" + if isinstance(message, MaildirMessage): + message.set_flags(self.get_flags()) + message.set_subdir(self.get_subdir()) + message.set_date(self.get_date()) + elif isinstance(message, _mboxMMDFMessage): + flags = set(self.get_flags()) + if 'S' in flags: + message.add_flag('R') + if self.get_subdir() == 'cur': + message.add_flag('O') + if 'T' in flags: + message.add_flag('D') + if 'F' in flags: + message.add_flag('F') + if 'R' in flags: + message.add_flag('A') + message.set_from('MAILER-DAEMON', time.gmtime(self.get_date())) + elif isinstance(message, MHMessage): + flags = set(self.get_flags()) + if 'S' not in flags: + message.add_sequence('unseen') + if 'R' in flags: + message.add_sequence('replied') + if 'F' in flags: + message.add_sequence('flagged') + elif isinstance(message, BabylMessage): + flags = set(self.get_flags()) + if 'S' not in flags: + message.add_label('unseen') + if 'T' in flags: + message.add_label('deleted') + if 'R' in flags: + message.add_label('answered') + if 'P' in flags: + message.add_label('forwarded') + elif isinstance(message, Message): + pass + else: + raise TypeError('Cannot convert to specified type: %s' % + type(message)) + + +class _mboxMMDFMessage(Message): + """Message with mbox- or MMDF-specific properties.""" + + def __init__(self, message=None): + """Initialize an mboxMMDFMessage instance.""" + self.set_from('MAILER-DAEMON', True) + if isinstance(message, email.message.Message): + unixfrom = message.get_unixfrom() + if unixfrom is not None and unixfrom.startswith('From '): + self.set_from(unixfrom[5:]) + Message.__init__(self, message) + + def get_from(self): + """Return contents of "From " line.""" + return self._from + + def set_from(self, from_, time_=None): + """Set "From " line, formatting and appending time_ if specified.""" + if time_ is not None: + if time_ is True: + time_ = time.gmtime() + from_ += ' ' + time.asctime(time_) + self._from = from_ + + def get_flags(self): + """Return as a string the flags that are set.""" + return self.get('Status', '') + self.get('X-Status', '') + + def set_flags(self, flags): + """Set the given flags and unset all others.""" + flags = set(flags) + status_flags, xstatus_flags = '', '' + for flag in ('R', 'O'): + if flag in flags: + status_flags += flag + flags.remove(flag) + for flag in ('D', 'F', 'A'): + if flag in flags: + xstatus_flags += flag + flags.remove(flag) + xstatus_flags += ''.join(sorted(flags)) + try: + self.replace_header('Status', status_flags) + except KeyError: + self.add_header('Status', status_flags) + try: + self.replace_header('X-Status', xstatus_flags) + except KeyError: + self.add_header('X-Status', xstatus_flags) + + def add_flag(self, flag): + """Set the given flag(s) without changing others.""" + self.set_flags(''.join(set(self.get_flags()) | set(flag))) + + def remove_flag(self, flag): + """Unset the given string flag(s) without changing others.""" + if 'Status' in self or 'X-Status' in self: + self.set_flags(''.join(set(self.get_flags()) - set(flag))) + + def _explain_to(self, message): + """Copy mbox- or MMDF-specific state to message insofar as possible.""" + if isinstance(message, MaildirMessage): + flags = set(self.get_flags()) + if 'O' in flags: + message.set_subdir('cur') + if 'F' in flags: + message.add_flag('F') + if 'A' in flags: + message.add_flag('R') + if 'R' in flags: + message.add_flag('S') + if 'D' in flags: + message.add_flag('T') + del message['status'] + del message['x-status'] + maybe_date = ' '.join(self.get_from().split()[-5:]) + try: + message.set_date(calendar.timegm(time.strptime(maybe_date, + '%a %b %d %H:%M:%S %Y'))) + except (ValueError, OverflowError): + pass + elif isinstance(message, _mboxMMDFMessage): + message.set_flags(self.get_flags()) + message.set_from(self.get_from()) + elif isinstance(message, MHMessage): + flags = set(self.get_flags()) + if 'R' not in flags: + message.add_sequence('unseen') + if 'A' in flags: + message.add_sequence('replied') + if 'F' in flags: + message.add_sequence('flagged') + del message['status'] + del message['x-status'] + elif isinstance(message, BabylMessage): + flags = set(self.get_flags()) + if 'R' not in flags: + message.add_label('unseen') + if 'D' in flags: + message.add_label('deleted') + if 'A' in flags: + message.add_label('answered') + del message['status'] + del message['x-status'] + elif isinstance(message, Message): + pass + else: + raise TypeError('Cannot convert to specified type: %s' % + type(message)) + + +class mboxMessage(_mboxMMDFMessage): + """Message with mbox-specific properties.""" + + +class MHMessage(Message): + """Message with MH-specific properties.""" + + def __init__(self, message=None): + """Initialize an MHMessage instance.""" + self._sequences = [] + Message.__init__(self, message) + + def get_sequences(self): + """Return a list of sequences that include the message.""" + return self._sequences[:] + + def set_sequences(self, sequences): + """Set the list of sequences that include the message.""" + self._sequences = list(sequences) + + def add_sequence(self, sequence): + """Add sequence to list of sequences including the message.""" + if isinstance(sequence, str): + if not sequence in self._sequences: + self._sequences.append(sequence) + else: + raise TypeError('sequence must be a string: %s' % type(sequence)) + + def remove_sequence(self, sequence): + """Remove sequence from the list of sequences including the message.""" + try: + self._sequences.remove(sequence) + except ValueError: + pass + + def _explain_to(self, message): + """Copy MH-specific state to message insofar as possible.""" + if isinstance(message, MaildirMessage): + sequences = set(self.get_sequences()) + if 'unseen' in sequences: + message.set_subdir('cur') + else: + message.set_subdir('cur') + message.add_flag('S') + if 'flagged' in sequences: + message.add_flag('F') + if 'replied' in sequences: + message.add_flag('R') + elif isinstance(message, _mboxMMDFMessage): + sequences = set(self.get_sequences()) + if 'unseen' not in sequences: + message.add_flag('RO') + else: + message.add_flag('O') + if 'flagged' in sequences: + message.add_flag('F') + if 'replied' in sequences: + message.add_flag('A') + elif isinstance(message, MHMessage): + for sequence in self.get_sequences(): + message.add_sequence(sequence) + elif isinstance(message, BabylMessage): + sequences = set(self.get_sequences()) + if 'unseen' in sequences: + message.add_label('unseen') + if 'replied' in sequences: + message.add_label('answered') + elif isinstance(message, Message): + pass + else: + raise TypeError('Cannot convert to specified type: %s' % + type(message)) + + +class BabylMessage(Message): + """Message with Babyl-specific properties.""" + + def __init__(self, message=None): + """Initialize an BabylMessage instance.""" + self._labels = [] + self._visible = Message() + Message.__init__(self, message) + + def get_labels(self): + """Return a list of labels on the message.""" + return self._labels[:] + + def set_labels(self, labels): + """Set the list of labels on the message.""" + self._labels = list(labels) + + def add_label(self, label): + """Add label to list of labels on the message.""" + if isinstance(label, str): + if label not in self._labels: + self._labels.append(label) + else: + raise TypeError('label must be a string: %s' % type(label)) + + def remove_label(self, label): + """Remove label from the list of labels on the message.""" + try: + self._labels.remove(label) + except ValueError: + pass + + def get_visible(self): + """Return a Message representation of visible headers.""" + return Message(self._visible) + + def set_visible(self, visible): + """Set the Message representation of visible headers.""" + self._visible = Message(visible) + + def update_visible(self): + """Update and/or sensibly generate a set of visible headers.""" + for header in self._visible.keys(): + if header in self: + self._visible.replace_header(header, self[header]) + else: + del self._visible[header] + for header in ('Date', 'From', 'Reply-To', 'To', 'CC', 'Subject'): + if header in self and header not in self._visible: + self._visible[header] = self[header] + + def _explain_to(self, message): + """Copy Babyl-specific state to message insofar as possible.""" + if isinstance(message, MaildirMessage): + labels = set(self.get_labels()) + if 'unseen' in labels: + message.set_subdir('cur') + else: + message.set_subdir('cur') + message.add_flag('S') + if 'forwarded' in labels or 'resent' in labels: + message.add_flag('P') + if 'answered' in labels: + message.add_flag('R') + if 'deleted' in labels: + message.add_flag('T') + elif isinstance(message, _mboxMMDFMessage): + labels = set(self.get_labels()) + if 'unseen' not in labels: + message.add_flag('RO') + else: + message.add_flag('O') + if 'deleted' in labels: + message.add_flag('D') + if 'answered' in labels: + message.add_flag('A') + elif isinstance(message, MHMessage): + labels = set(self.get_labels()) + if 'unseen' in labels: + message.add_sequence('unseen') + if 'answered' in labels: + message.add_sequence('replied') + elif isinstance(message, BabylMessage): + message.set_visible(self.get_visible()) + for label in self.get_labels(): + message.add_label(label) + elif isinstance(message, Message): + pass + else: + raise TypeError('Cannot convert to specified type: %s' % + type(message)) + + +class MMDFMessage(_mboxMMDFMessage): + """Message with MMDF-specific properties.""" + + +class _ProxyFile: + """A read-only wrapper of a file.""" + + def __init__(self, f, pos=None): + """Initialize a _ProxyFile.""" + self._file = f + if pos is None: + self._pos = f.tell() + else: + self._pos = pos + + def read(self, size=None): + """Read bytes.""" + return self._read(size, self._file.read) + + def readline(self, size=None): + """Read a line.""" + return self._read(size, self._file.readline) + + def readlines(self, sizehint=None): + """Read multiple lines.""" + result = [] + for line in self: + result.append(line) + if sizehint is not None: + sizehint -= len(line) + if sizehint <= 0: + break + return result + + def __iter__(self): + """Iterate over lines.""" + return iter(self.readline, "") + + def tell(self): + """Return the position.""" + return self._pos + + def seek(self, offset, whence=0): + """Change position.""" + if whence == 1: + self._file.seek(self._pos) + self._file.seek(offset, whence) + self._pos = self._file.tell() + + def close(self): + """Close the file.""" + if hasattr(self, '_file'): + if hasattr(self._file, 'close'): + self._file.close() + del self._file + + def _read(self, size, read_method): + """Read size bytes using read_method.""" + if size is None: + size = -1 + self._file.seek(self._pos) + result = read_method(size) + self._pos = self._file.tell() + return result + + +class _PartialFile(_ProxyFile): + """A read-only wrapper of part of a file.""" + + def __init__(self, f, start=None, stop=None): + """Initialize a _PartialFile.""" + _ProxyFile.__init__(self, f, start) + self._start = start + self._stop = stop + + def tell(self): + """Return the position with respect to start.""" + return _ProxyFile.tell(self) - self._start + + def seek(self, offset, whence=0): + """Change position, possibly with respect to start or stop.""" + if whence == 0: + self._pos = self._start + whence = 1 + elif whence == 2: + self._pos = self._stop + whence = 1 + _ProxyFile.seek(self, offset, whence) + + def _read(self, size, read_method): + """Read size bytes using read_method, honoring start and stop.""" + remaining = self._stop - self._pos + if remaining <= 0: + return '' + if size is None or size < 0 or size > remaining: + size = remaining + return _ProxyFile._read(self, size, read_method) + + def close(self): + # do *not* close the underlying file object for partial files, + # since it's global to the mailbox object + if hasattr(self, '_file'): + del self._file + + +def _lock_file(f, dotlock=True): + """Lock file f using lockf and dot locking.""" + dotlock_done = False + try: + if fcntl: + try: + fcntl.lockf(f, fcntl.LOCK_EX | fcntl.LOCK_NB) + except IOError, e: + if e.errno in (errno.EAGAIN, errno.EACCES, errno.EROFS): + raise ExternalClashError('lockf: lock unavailable: %s' % + f.name) + else: + raise + if dotlock: + try: + pre_lock = _create_temporary(f.name + '.lock') + pre_lock.close() + except IOError, e: + if e.errno in (errno.EACCES, errno.EROFS): + return # Without write access, just skip dotlocking. + else: + raise + try: + if hasattr(os, 'link'): + os.link(pre_lock.name, f.name + '.lock') + dotlock_done = True + os.unlink(pre_lock.name) + else: + os.rename(pre_lock.name, f.name + '.lock') + dotlock_done = True + except OSError, e: + if e.errno == errno.EEXIST or \ + (os.name == 'os2' and e.errno == errno.EACCES): + os.remove(pre_lock.name) + raise ExternalClashError('dot lock unavailable: %s' % + f.name) + else: + raise + except: + if fcntl: + fcntl.lockf(f, fcntl.LOCK_UN) + if dotlock_done: + os.remove(f.name + '.lock') + raise + +def _unlock_file(f): + """Unlock file f using lockf and dot locking.""" + if fcntl: + fcntl.lockf(f, fcntl.LOCK_UN) + if os.path.exists(f.name + '.lock'): + os.remove(f.name + '.lock') + +def _create_carefully(path): + """Create a file if it doesn't exist and open for reading and writing.""" + fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDWR, 0666) + try: + return open(path, 'rb+') + finally: + os.close(fd) + +def _create_temporary(path): + """Create a temp file based on path and open for reading and writing.""" + return _create_carefully('%s.%s.%s.%s' % (path, int(time.time()), + socket.gethostname(), + os.getpid())) + +def _sync_flush(f): + """Ensure changes to file f are physically on disk.""" + f.flush() + if hasattr(os, 'fsync'): + os.fsync(f.fileno()) + +def _sync_close(f): + """Close file f, ensuring all changes are physically on disk.""" + _sync_flush(f) + f.close() + +## Start: classes from the original module (for backward compatibility). + +# Note that the Maildir class, whose name is unchanged, itself offers a next() +# method for backward compatibility. + +class _Mailbox: + + def __init__(self, fp, factory=rfc822.Message): + self.fp = fp + self.seekp = 0 + self.factory = factory + + def __iter__(self): + return iter(self.next, None) + + def next(self): + while 1: + self.fp.seek(self.seekp) + try: + self._search_start() + except EOFError: + self.seekp = self.fp.tell() + return None + start = self.fp.tell() + self._search_end() + self.seekp = stop = self.fp.tell() + if start != stop: + break + return self.factory(_PartialFile(self.fp, start, stop)) + +# Recommended to use PortableUnixMailbox instead! +class UnixMailbox(_Mailbox): + + def _search_start(self): + while 1: + pos = self.fp.tell() + line = self.fp.readline() + if not line: + raise EOFError + if line[:5] == 'From ' and self._isrealfromline(line): + self.fp.seek(pos) + return + + def _search_end(self): + self.fp.readline() # Throw away header line + while 1: + pos = self.fp.tell() + line = self.fp.readline() + if not line: + return + if line[:5] == 'From ' and self._isrealfromline(line): + self.fp.seek(pos) + return + + # An overridable mechanism to test for From-line-ness. You can either + # specify a different regular expression or define a whole new + # _isrealfromline() method. Note that this only gets called for lines + # starting with the 5 characters "From ". + # + # BAW: According to + #http://home.netscape.com/eng/mozilla/2.0/relnotes/demo/content-length.html + # the only portable, reliable way to find message delimiters in a BSD (i.e + # Unix mailbox) style folder is to search for "\n\nFrom .*\n", or at the + # beginning of the file, "^From .*\n". While _fromlinepattern below seems + # like a good idea, in practice, there are too many variations for more + # strict parsing of the line to be completely accurate. + # + # _strict_isrealfromline() is the old version which tries to do stricter + # parsing of the From_ line. _portable_isrealfromline() simply returns + # true, since it's never called if the line doesn't already start with + # "From ". + # + # This algorithm, and the way it interacts with _search_start() and + # _search_end() may not be completely correct, because it doesn't check + # that the two characters preceding "From " are \n\n or the beginning of + # the file. Fixing this would require a more extensive rewrite than is + # necessary. For convenience, we've added a PortableUnixMailbox class + # which does no checking of the format of the 'From' line. + + _fromlinepattern = (r"From \s*[^\s]+\s+\w\w\w\s+\w\w\w\s+\d?\d\s+" + r"\d?\d:\d\d(:\d\d)?(\s+[^\s]+)?\s+\d\d\d\d\s*" + r"[^\s]*\s*" + "$") + _regexp = None + + def _strict_isrealfromline(self, line): + if not self._regexp: + import re + self._regexp = re.compile(self._fromlinepattern) + return self._regexp.match(line) + + def _portable_isrealfromline(self, line): + return True + + _isrealfromline = _strict_isrealfromline + + +class PortableUnixMailbox(UnixMailbox): + _isrealfromline = UnixMailbox._portable_isrealfromline + + +class MmdfMailbox(_Mailbox): + + def _search_start(self): + while 1: + line = self.fp.readline() + if not line: + raise EOFError + if line[:5] == '\001\001\001\001\n': + return + + def _search_end(self): + while 1: + pos = self.fp.tell() + line = self.fp.readline() + if not line: + return + if line == '\001\001\001\001\n': + self.fp.seek(pos) + return + + +class MHMailbox: + + def __init__(self, dirname, factory=rfc822.Message): + import re + pat = re.compile('^[1-9][0-9]*$') + self.dirname = dirname + # the three following lines could be combined into: + # list = map(long, filter(pat.match, os.listdir(self.dirname))) + list = os.listdir(self.dirname) + list = filter(pat.match, list) + list = map(long, list) + list.sort() + # This only works in Python 1.6 or later; + # before that str() added 'L': + self.boxes = map(str, list) + self.boxes.reverse() + self.factory = factory + + def __iter__(self): + return iter(self.next, None) + + def next(self): + if not self.boxes: + return None + fn = self.boxes.pop() + fp = open(os.path.join(self.dirname, fn)) + msg = self.factory(fp) + try: + msg._mh_msgno = fn + except (AttributeError, TypeError): + pass + return msg + + +class BabylMailbox(_Mailbox): + + def _search_start(self): + while 1: + line = self.fp.readline() + if not line: + raise EOFError + if line == '*** EOOH ***\n': + return + + def _search_end(self): + while 1: + pos = self.fp.tell() + line = self.fp.readline() + if not line: + return + if line == '\037\014\n' or line == '\037': + self.fp.seek(pos) + return + +## End: classes from the original module (for backward compatibility). + + +class Error(Exception): + """Raised for module-specific errors.""" + +class NoSuchMailboxError(Error): + """The specified mailbox does not exist and won't be created.""" + +class NotEmptyError(Error): + """The specified mailbox is not empty and deletion was requested.""" + +class ExternalClashError(Error): + """Another process caused an action to fail.""" + +class FormatError(Error): + """A file appears to have an invalid format.""" diff --git a/PythonHome/Lib/mailbox.pyc b/PythonHome/Lib/mailbox.pyc deleted file mode 100644 index 299bd3d7c5ec81cbf2ca84a1164b4079f9501825..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73406 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 diff --git a/PythonHome/Lib/mailcap.py b/PythonHome/Lib/mailcap.py new file mode 100644 index 0000000000..04077ba0db --- /dev/null +++ b/PythonHome/Lib/mailcap.py @@ -0,0 +1,255 @@ +"""Mailcap file handling. See RFC 1524.""" + +import os + +__all__ = ["getcaps","findmatch"] + +# Part 1: top-level interface. + +def getcaps(): + """Return a dictionary containing the mailcap database. + + The dictionary maps a MIME type (in all lowercase, e.g. 'text/plain') + to a list of dictionaries corresponding to mailcap entries. The list + collects all the entries for that MIME type from all available mailcap + files. Each dictionary contains key-value pairs for that MIME type, + where the viewing command is stored with the key "view". + + """ + caps = {} + for mailcap in listmailcapfiles(): + try: + fp = open(mailcap, 'r') + except IOError: + continue + with fp: + morecaps = readmailcapfile(fp) + for key, value in morecaps.iteritems(): + if not key in caps: + caps[key] = value + else: + caps[key] = caps[key] + value + return caps + +def listmailcapfiles(): + """Return a list of all mailcap files found on the system.""" + # XXX Actually, this is Unix-specific + if 'MAILCAPS' in os.environ: + str = os.environ['MAILCAPS'] + mailcaps = str.split(':') + else: + if 'HOME' in os.environ: + home = os.environ['HOME'] + else: + # Don't bother with getpwuid() + home = '.' # Last resort + mailcaps = [home + '/.mailcap', '/etc/mailcap', + '/usr/etc/mailcap', '/usr/local/etc/mailcap'] + return mailcaps + + +# Part 2: the parser. + +def readmailcapfile(fp): + """Read a mailcap file and return a dictionary keyed by MIME type. + + Each MIME type is mapped to an entry consisting of a list of + dictionaries; the list will contain more than one such dictionary + if a given MIME type appears more than once in the mailcap file. + Each dictionary contains key-value pairs for that MIME type, where + the viewing command is stored with the key "view". + """ + caps = {} + while 1: + line = fp.readline() + if not line: break + # Ignore comments and blank lines + if line[0] == '#' or line.strip() == '': + continue + nextline = line + # Join continuation lines + while nextline[-2:] == '\\\n': + nextline = fp.readline() + if not nextline: nextline = '\n' + line = line[:-2] + nextline + # Parse the line + key, fields = parseline(line) + if not (key and fields): + continue + # Normalize the key + types = key.split('/') + for j in range(len(types)): + types[j] = types[j].strip() + key = '/'.join(types).lower() + # Update the database + if key in caps: + caps[key].append(fields) + else: + caps[key] = [fields] + return caps + +def parseline(line): + """Parse one entry in a mailcap file and return a dictionary. + + The viewing command is stored as the value with the key "view", + and the rest of the fields produce key-value pairs in the dict. + """ + fields = [] + i, n = 0, len(line) + while i < n: + field, i = parsefield(line, i, n) + fields.append(field) + i = i+1 # Skip semicolon + if len(fields) < 2: + return None, None + key, view, rest = fields[0], fields[1], fields[2:] + fields = {'view': view} + for field in rest: + i = field.find('=') + if i < 0: + fkey = field + fvalue = "" + else: + fkey = field[:i].strip() + fvalue = field[i+1:].strip() + if fkey in fields: + # Ignore it + pass + else: + fields[fkey] = fvalue + return key, fields + +def parsefield(line, i, n): + """Separate one key-value pair in a mailcap entry.""" + start = i + while i < n: + c = line[i] + if c == ';': + break + elif c == '\\': + i = i+2 + else: + i = i+1 + return line[start:i].strip(), i + + +# Part 3: using the database. + +def findmatch(caps, MIMEtype, key='view', filename="/dev/null", plist=[]): + """Find a match for a mailcap entry. + + Return a tuple containing the command line, and the mailcap entry + used; (None, None) if no match is found. This may invoke the + 'test' command of several matching entries before deciding which + entry to use. + + """ + entries = lookup(caps, MIMEtype, key) + # XXX This code should somehow check for the needsterminal flag. + for e in entries: + if 'test' in e: + test = subst(e['test'], filename, plist) + if test and os.system(test) != 0: + continue + command = subst(e[key], MIMEtype, filename, plist) + return command, e + return None, None + +def lookup(caps, MIMEtype, key=None): + entries = [] + if MIMEtype in caps: + entries = entries + caps[MIMEtype] + MIMEtypes = MIMEtype.split('/') + MIMEtype = MIMEtypes[0] + '/*' + if MIMEtype in caps: + entries = entries + caps[MIMEtype] + if key is not None: + entries = filter(lambda e, key=key: key in e, entries) + return entries + +def subst(field, MIMEtype, filename, plist=[]): + # XXX Actually, this is Unix-specific + res = '' + i, n = 0, len(field) + while i < n: + c = field[i]; i = i+1 + if c != '%': + if c == '\\': + c = field[i:i+1]; i = i+1 + res = res + c + else: + c = field[i]; i = i+1 + if c == '%': + res = res + c + elif c == 's': + res = res + filename + elif c == 't': + res = res + MIMEtype + elif c == '{': + start = i + while i < n and field[i] != '}': + i = i+1 + name = field[start:i] + i = i+1 + res = res + findparam(name, plist) + # XXX To do: + # %n == number of parts if type is multipart/* + # %F == list of alternating type and filename for parts + else: + res = res + '%' + c + return res + +def findparam(name, plist): + name = name.lower() + '=' + n = len(name) + for p in plist: + if p[:n].lower() == name: + return p[n:] + return '' + + +# Part 4: test program. + +def test(): + import sys + caps = getcaps() + if not sys.argv[1:]: + show(caps) + return + for i in range(1, len(sys.argv), 2): + args = sys.argv[i:i+2] + if len(args) < 2: + print "usage: mailcap [MIMEtype file] ..." + return + MIMEtype = args[0] + file = args[1] + command, e = findmatch(caps, MIMEtype, 'view', file) + if not command: + print "No viewer found for", type + else: + print "Executing:", command + sts = os.system(command) + if sts: + print "Exit status:", sts + +def show(caps): + print "Mailcap files:" + for fn in listmailcapfiles(): print "\t" + fn + print + if not caps: caps = getcaps() + print "Mailcap entries:" + print + ckeys = caps.keys() + ckeys.sort() + for type in ckeys: + print type + entries = caps[type] + for e in entries: + keys = e.keys() + keys.sort() + for k in keys: + print " %-15s" % k, e[k] + print + +if __name__ == '__main__': + test() diff --git a/PythonHome/Lib/mailcap.pyc b/PythonHome/Lib/mailcap.pyc deleted file mode 100644 index b5576b502558c32481d83fba0689715f5c066177..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6883 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') +_markedsectionclose = re.compile(r']\s*]\s*>') + +# An analysis of the MS-Word extensions is available at +# http://www.planetpublish.com/xmlarena/xap/Thursday/WordtoXML.pdf + +_msmarkedsectionclose = re.compile(r']\s*>') + +del re + + +class ParserBase: + """Parser base class which provides some common support methods used + by the SGML/HTML and XHTML parsers.""" + + def __init__(self): + if self.__class__ is ParserBase: + raise RuntimeError( + "markupbase.ParserBase must be subclassed") + + def error(self, message): + raise NotImplementedError( + "subclasses of ParserBase must override error()") + + def reset(self): + self.lineno = 1 + self.offset = 0 + + def getpos(self): + """Return current line number and offset.""" + return self.lineno, self.offset + + # Internal -- update line number and offset. This should be + # called for each piece of data exactly once, in order -- in other + # words the concatenation of all the input strings to this + # function should be exactly the entire input. + def updatepos(self, i, j): + if i >= j: + return j + rawdata = self.rawdata + nlines = rawdata.count("\n", i, j) + if nlines: + self.lineno = self.lineno + nlines + pos = rawdata.rindex("\n", i, j) # Should not fail + self.offset = j-(pos+1) + else: + self.offset = self.offset + j-i + return j + + _decl_otherchars = '' + + # Internal -- parse declaration (for use by subclasses). + def parse_declaration(self, i): + # This is some sort of declaration; in "HTML as + # deployed," this should only be the document type + # declaration (""). + # ISO 8879:1986, however, has more complex + # declaration syntax for elements in , including: + # --comment-- + # [marked section] + # name in the following list: ENTITY, DOCTYPE, ELEMENT, + # ATTLIST, NOTATION, SHORTREF, USEMAP, + # LINKTYPE, LINK, IDLINK, USELINK, SYSTEM + rawdata = self.rawdata + j = i + 2 + assert rawdata[i:j] == "": + # the empty comment + return j + 1 + if rawdata[j:j+1] in ("-", ""): + # Start of comment followed by buffer boundary, + # or just a buffer boundary. + return -1 + # A simple, practical version could look like: ((name|stringlit) S*) + '>' + n = len(rawdata) + if rawdata[j:j+2] == '--': #comment + # Locate --.*-- as the body of the comment + return self.parse_comment(i) + elif rawdata[j] == '[': #marked section + # Locate [statusWord [...arbitrary SGML...]] as the body of the marked section + # Where statusWord is one of TEMP, CDATA, IGNORE, INCLUDE, RCDATA + # Note that this is extended by Microsoft Office "Save as Web" function + # to include [if...] and [endif]. + return self.parse_marked_section(i) + else: #all other declaration elements + decltype, j = self._scan_name(j, i) + if j < 0: + return j + if decltype == "doctype": + self._decl_otherchars = '' + while j < n: + c = rawdata[j] + if c == ">": + # end of declaration syntax + data = rawdata[i+2:j] + if decltype == "doctype": + self.handle_decl(data) + else: + # According to the HTML5 specs sections "8.2.4.44 Bogus + # comment state" and "8.2.4.45 Markup declaration open + # state", a comment token should be emitted. + # Calling unknown_decl provides more flexibility though. + self.unknown_decl(data) + return j + 1 + if c in "\"'": + m = _declstringlit_match(rawdata, j) + if not m: + return -1 # incomplete + j = m.end() + elif c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ": + name, j = self._scan_name(j, i) + elif c in self._decl_otherchars: + j = j + 1 + elif c == "[": + # this could be handled in a separate doctype parser + if decltype == "doctype": + j = self._parse_doctype_subset(j + 1, i) + elif decltype in ("attlist", "linktype", "link", "element"): + # must tolerate []'d groups in a content model in an element declaration + # also in data attribute specifications of attlist declaration + # also link type declaration subsets in linktype declarations + # also link attribute specification lists in link declarations + self.error("unsupported '[' char in %s declaration" % decltype) + else: + self.error("unexpected '[' char in declaration") + else: + self.error( + "unexpected %r char in declaration" % rawdata[j]) + if j < 0: + return j + return -1 # incomplete + + # Internal -- parse a marked section + # Override this to handle MS-word extension syntax content + def parse_marked_section(self, i, report=1): + rawdata= self.rawdata + assert rawdata[i:i+3] == ' ending + match= _markedsectionclose.search(rawdata, i+3) + elif sectName in ("if", "else", "endif"): + # look for MS Office ]> ending + match= _msmarkedsectionclose.search(rawdata, i+3) + else: + self.error('unknown status keyword %r in marked section' % rawdata[i+3:j]) + if not match: + return -1 + if report: + j = match.start(0) + self.unknown_decl(rawdata[i+3: j]) + return match.end(0) + + # Internal -- parse comment, return length or -1 if not terminated + def parse_comment(self, i, report=1): + rawdata = self.rawdata + if rawdata[i:i+4] != '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¹@DMq1^^1b9&mn;+OfdoQj9xcDbh?TG%FdXZ`S7T+uNs&@h1h!yo z4huhF&kSifBXW?cAy8c}Q$@OC^ecoG&I`I?_0?LC#6p_cdffKN;1#h0wh5#H1@XF3 zpb7vu{sRmSz2B*AYI8`puaDhJKEX*IdD1A7V1GPw12OIZq-#{k7wkgIi3X53lQq>| zI4`6Tl7#n<(L5pDO_Ac+MEjKt%j{lBsB|T=+oFs;l`JBKM7(vjSI_V5HLkvzrYZ;} zE8yM)v2tajh7V`<`TIO{WmP6aRl*5lwT{gP@ZNK99;RaV9)u1Zi~?7GteaKUwYVL5 z&z_G}7GDle>$*g(r78dykF%##;wmlX3EOJvsBp=^LpPJ3J*v$R%wHTvX8`I=u4L>F z;Nnv0#Zb}>jf1MeS_$xkcALattC(3-X6fvlT1G*OeN6V3Mj@goh<`yT>|y;F1^oS; zb}cT?)=hyDaC(K%tOuNReIZBObXvqV{3PrtDKG5?=@P|Pyk925qp%^8s1#nK0Ed<# zT4*D|Em(n)9c%f?4+J!IrdTRR5?Q~giCrQ}$)`wvgk5OJ1MVA;ZmH0z&Vi1bW-83% zq-oI;=?J^>s5hj+SrZQv;hR`hwr4t<`MO6ywFeOKu^0dgIbNdGM}EKQ^__WbACe)N zUKki=cXM_QaxH40GR6c&ea9M@aRsmNR|mLhc|&Z34O?niy}G45y0Rjq@3=t&CX>pHZh;ef zCNVArANFIja!2)Ro1_9X2=mM}e+W}xJCz)h zw*VGG*mu5+{KnREwQV3SUu{RWpcI%rc(YM%`HPA@IOjVY2qu7D(mh4UFgI-MdnE2@ z$L$E0iI4_heZ--q$%Cu%DR7E!BMgT=^KMC4bQxNOJNx4+J$G_M^;3ll7;;pof{M$ z_h+e|2tI%~gvD@FKo6FTdvfF54R@D+4+OtniWGMFN8sXjuhhp9B7EANJ8O;rJ`bkb=wm>ZXs z)LA1S6Cw%8nT+*)5mm&A7PHdYfaX6u17y?pI7k`=sC*8`YEn?>$PZ^We9+yPe!*>& zbkPFR%&Dyni@&JBioyhi^5u+1PDQ_jA+e!_@z^8Xkl^Ln z79YH{lzZzu2wWV(jhqJGg`J@;)xnAZ*8>|19|V-QT^n)V z;$R92I0-leQ-N}S%I*yaY4lt3`vJjYbsL#aA@Ihf4k#o@pc0GF)5=t^a+4XRnq)i)Q zN3_s1Q-lke5>;H&zqv>O)ycb8?T0&iAOY17yx^Ze5(%@})YPlZRef@)@x0O;kEaX? z1c-ZF#WGvv9oJt=M)q%Sat#i&R1UZc5;g)OJ{l{?8yE=4Q>ZuTUP7cHBiWHx9S~x- z&)$kUTbr^z2oaS10~g+5F_J2w|6Xe2I9e2iyOCMwZ>1CABXV9?s%0H^3h&h`Z|4Rf z-<74Z_0#>|nO(h1rB2%7L{bH+Lt~2dOPN;Px%0AAF%eZJ(1vJ~75cOZeW7%K9wDLk3ssn$P&;a0XN|<{=)@}I z&&q5F510qc@rH)r8#Q1iuJ!EM!X&s~34+nuPlNpfYJNj`BTki1Krq}d-wWt89ua~^0HYMN65 zC1m16F?^N;*a?|ODIzO0kD>-H7U60BA{#kH%zab|`XCK!j$asc5u zT8;$e8+*fw8K99;R6jV9&&hQeO)Fb8F0;6o0Vc@bKq>^>i25aA41{fD!qHTSDNA&-*c6amS zAH2b}IN^46<*_Z}P-_NRn6Dv5qM-~zx>PSn7>(EM#Z}3ah5L?8wUxP2oUFW1l|$DF zoq_zi+#rVFupYLt=)pSOPDo`ii)Y_^$3s=s=aihKfR36*GvIfPcD>kcsN11+9BADHVEJ$eCLy zkL0s{A7>1mJp=+mU)2^dOJn<7uJ%YWzsC+@P;iEq+;kRaRigj1ONww^RSPXysQgqX z#};P_MLHdr{FS@{fFPYkp>J3Ky#~;5U{bsES}j&=g|HuwLLt7qROd0IFeA8J+O@q> zZQMX%8coxJfsTU96sqxsRRbAz&)uz+#iAw$%e%?3fUQCnU7b!}UA*4vmAZ;TVeioz zSgF;$J>5DI@dJcXL=J$GaMmRi9S)%_=J(lMd3_}y+)@F|%@67M7 zc{CDCYR$ynfpEDlIwy_Tvq-R0A%nT?5+WkU&;xoqZkJ2brziJwT0O`OFfh;DMNIgX7IdZbIA6Y$Y-P=+p@rStdTJG!hlkG|v#>vA7k5#81=` zi6a!h6(AuDGDJ{h!`_wej(Bh~Nt%Fy&y4*M<37Uq)h6#BbFLUv;Nt4ow=Zxk+cAEP)>rAOnfkwTq)vP>hITBkBR&x?(sGhnRhnvpjYu!D zg|-2%yM|WJ&y1ROCL)>bhO?#o6pJIYi2;}OG3 zDlp$HyU|Y(+hdae0BQh2ZIBW{!LM=EP2e+DxzsfPhd13{7avbVIIl&W96;FXRNkKT z^KAB$8!yk!Zm8_#{i%>F6E?(MF~@B7pR?|k9i@RNm&t@8ZsDSl zGy=I)g^O%4aD}7%jx+sIL50NNMv+?eGtdTWw_=B@$SNp7gXE1%#YoX8y2Ys+wPDj! z9Kyx1^HCxxJAPILP_-G6k1v}6+9cCZ(~K8Vm3A~;NewHy4j3U3FdYaaX(27srFB;E zdR94FIQi%Xf=+k5$a?Z{#@yso5u+m}`PjF7#P|uzzo6H{LB15rZZwh*gmv0$2 zZ)ZgA>O;i(tMFUt-EN-gb(h-ZzT2R(ksjB}DrFp}g>9som8`a#k)5{?fN-XhSL!N# zZ3x3)_9-+YmfHZ_em1e|W~8|91q?Z?b-KBnc; z=1WJZ;@*oopojfgF)LCJ$G&h~Ej8M=B_YdW(~oGRcSuYs0@dW!W)p7^+Ujqiy^$is zZ;#J>5b)O&;2lsBbeet1*^PDpM`V`W!X|VOiF{8=WjM;%^JzzPDvW#59IJ2aTG~*iJ0`!*u17D@;QY3? zaM=FygPr@od+;@43BGC(etQ(XW<|-EYLSm{CKn;F9K~^<4KVLN$70jHPQO#tr-=>H z*=B4N|1D=*blTH-gn*2q76C;iF3Cv;Ku4;NBDj zSDJS)Be;ScSY*SjMwo184U()ImSruc_IJ9R`gZej>eoMcIrXAUtG1jET~EEt1y(_l zll6SlN==}fPFLoHD9us9ZRVzf1{#%8u866ZJM7ejv|~kM6W4McjkH!~l@=Z(DXI&E z!jEV>scvmAwlrp#tuj$_Rx~kLclm-}E#}0uv7gGJ*RCOnvRDR=uuZ_~G+I5N*)j*6 zQ3t5CI(~+cwpjfB;qT`k-@W_Si^cplPC7@9UR?UR>Wy3_65`JzGYL$l=~{%-{3r=t z2Lxp~Ob9OJM~~`xaCHp)!rb=Z2@=di*Xcq?o19232`;0l zBoy5~FS7kA81qUL&7mQ!H$9@n8<8+~*B>q2LabUSXPefzHBOsKhn7nv_z?OJPw0Vd zORCvEmEIdg`SjmIIj7!Ak-~j1SYvSwg)O27!RgINEQD$Mw}Nc8M5DbWyL10WMyLgg zmgX9&fa2XYb8wL(|NY1}ISK2GhkyH;ron{Sod64oqDrF#aQ&^7)knNcE}w+z)xP>w z`YSS;CFUmLO`N4*9D^rrcV-XjD;b(`Bu&gz0cf;Dg@2U!APfRviuRy5_-EcTyqv|& zFwOVD3K*J;w`P{ndZ~i}y6^+J^~+Ay;Vf)6#b9Cdz`P}b^>J036SOg{pyC>s2J39r ze@MXM6n?pNy4Nf1A`yFk-KrN40o`e{UTx9_eG?+XO?8&OgI;e(pp(<)bqD=7ka5);tc{qY2JPjEuFzhutm+#o<(Z>$uz zy16)dek2}kmIDTiD?F&@@O|LvOqm;9Lm#~?Dz;YQ85Jmc#c%i7H_m2N3mP?__EkY1 zZpm5FM~)(U1Uv((@#1$&;i3i^g1T?h(UaQ7y**)7QcUa<@wocrHP#18SfBBzKe8Iu zQopD zR5+xATb~67VC#tVZ}|VJA{Jdl?F#MWRHXlc&2mgC12M&Rk>uao`&+WgU)UQ=*;uH9 zGgyIs`ugbI(J8Ve6sWf9@c2#U*deO1csbL$_M(D`iW;=CAO@ihg}{9#dk6!^h zFBduq&t|KjE*R1t%e`*wip1CToi92fxre8aOpVOpyZR8sRi6;b9LuOrwK2dDUBK#x zY=W(i_6Z;a#BKcQCLvin)UYqHmEFP=%lVRczpJxqAt7gr+nXua?dR=`-Rp3TZoG}E zy6C}!Ai6lx5u;F{^(gVqH^MNxuA4tY7*~j_GsLrJL`lYNIbZpFwDOth@^NqMdHbBG zz!vCVMZV%WCaziEqEIdDeQH|~k(4!#ytwmViVKK1%y;TuXbFVk%C2VAE-6nT2|#7k z3iG?xr%3=YO<@=jUUgWKf(AV`5rstF$-s#n4m&V)F#STVSV>Pf8b+8!`;fEqh$z*J zqHFU>cN2P75RKqoZ6#PfaTkRKpo10pVpO66Xs>Y(AyP{xo{4_v(Cohu1#nv)(NEsl zw0u1jv^4-!$Gi?V-~bZn<91wF`zV}_w-=JJSUb?T5fw4HOy)IQ43<~)O_49RdRAq! z?LA;s_9a`wyV`$H`*`dFDXU2kPqk+VPel|kN29Id-rnb*Aqeg;z!w*n?~k<(@No=i`L9ACJRc&2VkD`R<62VV@m zfDLO9tp;`_lfwySH?GE>E<%kfl!B1;$`jro+7{QQx=hQu^Z;y#BH6}1vO98jkxf!R5?Y8${!dy&^9L)ovYiQ9T8fHRrU<&W;J(B7x zpgLnlnlH97Wtm2>@sC)-*{?O9;0sEJY%7>K_+vKcJ;i@Ke4i6&h_yK)I*hZg69}vg z+~QV~i6Jz|u?dz6yMWdeSS!ty2}xem=wONP$t!e2VT(Pq1)Y&W7*6-?B&`UI7zHWH zV}PRCkuSPo()gmf0F162b9Lb|q-yzImf^r2^T(2UpiH7qJF2SP{Hym?`!fWLLKo z+a6slyL_-MiQwOOYivl$n0aa3UytiyXQ~ZtW)Zt{Y^vd-C~On*HO2?x-?X%bd<~G| zZ@_;lcp*RVZqiK^g*=UjhN^zhL+DDI5YQAq)g2(FF+yJD{9Epi!z3eQsxWh9HBiue z$P1BV+6jVI5p#)w32&?lEAaN^z)geor6F>(7)mrL#!11^A$DS+WL!D4C;K>^46)xY z|A`1(B4=v(Aa{87(R5WPMU^)Bmh6d?8KOaHN)sp101c-+p7;XlYz|pVRUUY_8%5F7 z+82$HQY6}RFB(YFV{RqT?1prIk$I$;!GSCq5Dx&X$Xh0e)K||(YL*;HnphTQdfKQDyh*z-m#u6hV0tJ^ThX+mYZV zlFDbdeiU-m!Uo*-j9r;v$=r@-=e;@&9UT(mEyHZVhDTCvgXI5%j1lfNP_)eXiVF=FiG51PEHlM1bCppS#;hXWM~&45>qC}7#wij zn9`^l1!;(QQ!}T?(wlO!1{X^VG@uDCssQE5 zbA${uB>+uU5%5)+r4lja>Z(JF2GKXc{T?96`q83qe%vXCp%R2Gg}&NgGD8p* z37<6>a#x^^N3ADz{aCGwnt8~^op2wslVoEw2)qs9<4Ym$k ztJnw3HH9^dmHcvR{)ga~FLZmEB5Kv)U-DZ>{b=XTz4_xbs3-oZgo&yL!3@uujN)Lm z$YrwKWjD>Yn`r6EPihqfr1u|WypX1CYCnUJiQYp^f|(MBRYbUASM@6x>fv#!IboE7 z4mAU+f9b7$?GQ7ot+F;a{+yXrO^WDFdbJ$c7y>xD_Xmdn046Pus1yq1m-0rGVeyKU zZK#S$g~pI85Xv_#{aYU9;%FhLVDiNu5JSOtu@AV4SQy?VrHRTDk$&-o9OYl>uG^D+ zBG+q~VbsqbZbhA>QrSVQc;(BV4> z+}5LdKWd#)nn7iS1|dbDn?Ul`U%mfI)oP=7z5)?7D)(R>sr|N5aO&<|$r%Gf3)(1# zl8zg~Kl&jnLX9}8S#4$ul5E3;{j|<%Lb7^g3~Y}dUo&>Lmk5qyi&qo+MrXbVz4`JX zhLcWZiHK0clP&madhx53)~-qb(pKPKoVicwlgRRm1KhIyI;MiK;dnf~At$DQOmY{$ z>5f1x_Xz;s`vKkreXAH2G84(+!%Q*T10dF$iCX5+dqVvRgjvUH4`AE?{O-a)-+-&p zzQIlZmm)nPD%T*qRy2URigWv^*C9N{_$i!Uf$#wUSvX~CbetREE8wjl9O$L#CKF zI`bmvPpLLt!7bXH;LegK?O)#T3zy5IZ-qZDw2XUIK$3C^9nl47eUp+20 z_o%k@(FfVlM_(V9$F3Q?hSi??ptpF{Q9h?u_V%ISkJ6ZKDO?q7`?vy0V%tJA`U~?9%Kp)5XFG()s>rLtkx06 z%cJ9q+sN*+r7Bk>*~D-bWR4(A0%xI*BGV&#l+&B?oV3bTf>oZ9)RA=>+?#=`{bL>B z5;gH&tbAYXT~^I_Tvb`OoWV=8=IAt|r9KkM>xxJq*4=smD1-plueT6yt&6gCHkMxx zHD9-q^u`r5wd3|-dOVoo4qf|1yUa;523@m^e-}a`P>&)}V=D(eV6LGGF>4>LufkhZ zUd1Ep4trIm)v&1~c4l8^+4m@9^vI- z-Qpwr_mZ?ESGxZ3>X*;1o|N~n39fwg&6y674f9ehY8&G0=>YjLQL2}{Kj`Yh z6vVpbXE<>>$1w7{v)H#PtjbLAz&%rERvo{P_*|NB@fuP*I?(IGP7}KQ zRg~Y|j=vW1*ROvafB!Q63Jgl4WI7$3`4e2V$X7o7G@kwZ^Z5He#9#j<{`!%Ca0p*P zP(C=~mO=pWnv6QJ@eoa*qIUkPIX6=)M60twi+7HIhAUn}NXpmwaC3$GUB+d*L5W>e zCGe`fjh}Qmb+=4`56oJUG?M8rciPtq3~Re%NXw{$ug{(h#H!cJLJS(@8%hpVZy11~ zd`)u5VaYOG8WaStF}7Dqw}eYYX#x}sCcP4btj9Z>mW2g?QTw6DdkZHb?av)ME#q6U zW-W~fg9)dsvUF%$yo|O}K>_V3r?=JC2Wx2(2?+|ai0 zhm!&0z#=YIX&l!CaCiBFq%_R>o`z~D-!6PXJryU}X>?e#28~8=k~9WkGZNM8Qoo3$ z6AIc}b{6v*=_t2`d3mB2Zyfb)K_Ul{iM1XdLZRTrO zK4FQKO|TfloYM*XqjF z$@|PXq98Memb}54tgdPg!yI;aCKuUDdTi|En=T)WfNka@BrvDOT9;u=B}nv0&1^g( z3+oI5o{h2(JM$+WJ$3M=RNF*5)+j3q^7ceQMk$o5kQ!P{0*G zUT4f7T_>QAeo8qIgAK>uZ;c>nU1 zx~n1ere=T7qfnQN-A|dc*!_0?y~w|RU4Pdi`0ITVpEi7cV65eVS8yQp4J16$W~f=7Iw&n7axoSrs*1se#!WpCXy?}XOtcWn1Wp7|ES6t~q zXo{cGftEY1QFP4Jhsx6b`>$e$!5guuXeG~;Rx7=IH z9-g)u!eLD`|DV0OM8ATi+9$m`i-1S7Lb9+tE8F{ zsdDxu{k#-+LnO>I7++e%Sulu=;%HEGGw1=3zY=Aqsbwld2CjutGFZ0^}97K^dc#(tyuV+WrRxQ{#y{p}7|C7pw#? zR;dGd2gXn3LsWj9F=PiTj5B#eq?8SG(gH~yH{(bEx;}EAuDNn>URozZ(7?C5 zh=d9^x6@VgIJ1-QriVrIZq=diOq81^UUoQq>b- z%Pcm|)K%cXGDmr+#+hMusG|r6`$ielYq%y6DGO^^Gvz0SG|y~w#d3lu;HDZrTtIDT z#dgHDmJ#&z$}X9mtt!Z;2PV_6KFJ^%pkkfgv-u)oQwxtiq9WgI3>Gg!d2;@Fo&Wio zdCX)>h#}&ptax}KzNe|ykdl%CiU)~~ehbjqEl}Y9Gz1YMWRUFhnE9`@wcm@>%dne) z`&Vdy?8V3+tfERKw1q4Cw6;O9F}xI$3kn~-wz(kH<2spaVB=M?hu+n2uBEz5vt`7v zJ_?kO?u^<3hDj8wn*ozbSgevjA47J4EK?Nr@(d|{E@LD_Pn)pVoMoqpi*VvTnIn=> zDv@UhgI-do))O~7wqbxfwHb{8DN!g92a&5ZiBWih7=Uz1Ka!<`u`#QKnek@)XN;&w zWF8HNB#H?=-H3DKE;&j|TNJ|_1zZzl(Mq-{h_bCq@hTXh%P=_N&D*sYuw+O?O#y+# z$21nSs^hq8iV-H;p{;EJqZ&KSS-fa!<3%fvl+JF+aF$cSnxW!HcG0k;Rx)FUpf@S$ z1=lQPXkH@J=ZeQE7ZHkLN^MF*ov5>B2&UdVb#Hpo#a{R|Oy^AupP29owh0cO$yJ6U zww5TfP0~kNh4ecW$4iJ1?ObAPap+NDjSPWO5fkz#cKPt{2a^MVL^l>@38N01VBFr_ z*PLIutpfc%`0CiXod+jr$=nR@U>wPQLf9ETYysAz%{>UfY-0OG6ca74Fubz3XrI~( zQAwUh>AReDyZWu^oza)pl8shja%|P^SdPNBVW5Nr)?J}QVx{Fr`03vrXLpy@qBg=C zf*}Kuvk7-<{f3#OfmVvt3`)FU+phvrtd!7OxVKPZ^T$5g`AdG9eXo$<;}$1yPGp-M)K%{%LiLl<3I*5Z(a(6IN( zdM}o0+UX!__M7;~*^>vJ8DGFnShd*0r zb&lb-6)%R~Z;qXSG>F3$Yjs6uOevf}(MRXQ(Xrk4Z`^Z;H(V1~$ZwEGmr;2mE^)Up z?bMb=lPSzSHZzsN`Sn-FXV38s4cslhEVVk7%dx^JAx^y-CjySR)T~LW1l5(2yZVT zY0Mn)cv4uK$k8nnCKyVfo;?%!W{ef=y*qd&lOg`)AQV(hL)t?nQsPj`L(#kD`cu}8 z78s5KR@Ib;=^lc)`aqC}6I;85^)F^--aIeG>{@;OuHNbKtI0d80C+1DZFBSp#95J!;r;ESox>fqT=q3%iV!+_ zk;SrDfcqSKzG`fDAS+*;Hd~x7Y(nEw-OGicn0g?xSTga& z3=>Fg=)qLSrK2-BC?#}GNJ4d~qJSv%r5;rPH(*w3rj@oiH!(ZtlARElcvJh?UrC`)^b2Kv|BXVRPo_N z*=ZD!u{I=~E0blUwVR9LHVe_NR)2ugNfR{1H`RPxa^dZ3UP=L$@AGgFWuG3`N;wb} zW5Z+Ya|9*&=^GbqGqFsM@j-a%-IJrIuJp6FnPm_h2~v|jfrVkbiUM_jI(+vU5+Rt_ zyqNx~HluwHI0!b?N@zV8z9jNKR;b@16P^2$%%HutL>@J5(9&B4M`}0RDpYIaSalZ<_Ki)ri{$l^${I?n;p5E~5 zU)Qg^wtaBdL$^2l-ADfJudk)wl~Bh&hkns^ia43D&)6Wm*)JXWlm=(n00Fm4HI)#rCWVwG ziF&PTtDZe0ne=+_1?`n{{x`p})X@2g=IWs7@MO?239vGFt?j)b5Bw9ULa~c{8r`OZ zC&|XwXtW~O(f-iQpqLPtrTKI!SljwKF{i4Qm-|P@YACGeQ&{Ivnx-1&NAJsa?BsEG z&JNdV=bwEh?7rR(7T=}Fyf`0cW7C6t{WB9l7-?^me&FtqfRu`~m-8FU%|F~#2Os@V zS24h{nbOf+37xGo;cD-J!i~t!@bu+rToqNSO9DJ&b3z?~ZD~1~UX_`}@F1#{4IEKM zd2^1EOW1)g@rO9Q7zP@z?f>zN#GYy6`FqLg^j`oWltu&>wW<0AO}iqt`bKFJ*_XZv zcW+*^U4B}d)1TL;_D0_~wis0P?zOUV8>mw54b(wTr3hpcB7ABH!VO#@LrGzZ_Dd*F zms8a1EDg*ejv>qv^Pvw!tYS43dz)-x0+Qf`yd?}q0nF~j?I;~vv58;v!*EYhiaiAU zd~J>egd?#Tx|ILw4~-&`Vp|#}1{?t^F58;ElLoUk0Njr+u#%W1Untg!p&x9N(9;`a zKAQ`aalTlKwRu#{tgN6J@OSU5zqS#$wE+?d4}7V|_{tRsXj2Ajekc;I&^y~VV=IRL z{`vf2+Ji+;>fcjjs%2gct9}hs$k;KL9Ee8(g9pQ8n`hA*8smDBn9gDYX&8A}%KXo1 zyAvjBt|edPiu6%jT*VaJ$*u1EVp5AMbO42?+}MYHP(yVDm(!!fMn^3RVchndLyfr_dDv%SYcKx}( zPR;ayD27m=zR%&rG6&g}M_tL@YEA#! zw238SrKL3_ZOR^`-_Pb*qHt~SHFJh$X_!`m9}7FNxX+zFZ2OAdp%`i?6a z3M$n;D>Zj({?5e3)j|=P#ak!mae48Ed=^sTL{<~6wv0HZ9A@OZsR1HNQ(q!W1j^nX zM|3jNCFgh@R1czns795o^KF&dz>97E`|ioDU}%hbt}?%H3_@Cv%cGGTzEA_Kw=LDrBYYDPDQEc`ZCSN$Fq6{49=Ia7_$ zqxI$~HGY~eYLJevuQ0N1TFp|@jhUC<^qyZYEW8(4ol>OrPs14%(8En)rQV1jJqKl(3y4)$0J~JMa zON=B-iW((bz`Ta}9gJI7+|{A9)ynCQg0VNU!N*fJh*+p+?KV-M)R8*4vgE|Z;r?ee; zoewAcE3i|7m7lM`QKkfROkXf+r2*CSwUSIqGWm ziKAiCqcP+{)fBNJ_f5%gz~0`MSc;4$(VS1( z`F&Tdj~F~X(_f3p!rMo55}lEtB*6Ry}I7r;@K z29bsst){=ar4co=An)UV*qD1cr^Ogg-Tezg5j93uikRMkEgMonY!2@>@te>im!-hb z<8GijEG8+G2b3Lf!=whP3T@g4)|pZ0_La;;OH2Vy!PVbUZ$&P64ZVGk*bc%j_`=YC zm|j8%HnI9xsT77CM8~Y4U-13CuJL3E`uS9KDI>m&kL_K4(zgSMj$I2<`-t4Xh9)Jj za^+e`7dgYA^_;RErTw?D) z!o*)#M+L4s_eIF2ce#rYK24FjnPDp8B0S*$Mi4-L(NTW~>dLlIcZ`Bb=8 zJbw7D%=)Bn7K?aTvHsIa$Tqc3?YikH&O=bwQj;s z`v@YN<|Z`9jYFV!L!C6BM8^g>)a*BINg%@Kz8zso#~;#b%-RR+cqfLUQRqvxw{-GD z%=E))T;;6k30|k{mr>veCEXO=I;74Eoz{TB)oY#<3<6Aq5M0m4C}PlT;2+VQv-60u zdk)jZ@893h4&8|22GfgwbowZE-EMzGzwyQvx|5POM^L6VdTUo(aOuv8 zcj>+Lk=W`V@BGu&PHfrs-Cso+z>Q50etg5*t!kUam)>FuHhtjs@q0LvgC~r_A}ilV z1gBy%RiX!s6XH;$QBI1qE74PhlAAdOLB_L5Gj@t2ZdNG{YUeOo&v^&a!0zBtQ}( zUf4K*M5;M=j_{2y9sUIV0>1Q@@MrSx|If^-dd@izscva@)`)HqIOln)va<3$v$FD_ zG2FY}ko{D316`6t&x0tN+THyTFTv3CT0Pa|pS$svg% zi>+yE)#(_OiQ@>CK1U_i>EYJ<25HW0>|*qFl?rUb5CxOr+%4)r38?$?LTscvjsW5> zS-?Ye$}6`9r2X@Pzt7o4PPCga(z}0S{QF%n9rmx`)&~D`Vcv1l9|7I5+_v+J`Ga@A zUPDAJ+G@~;r7W#uI@-@qNA@<>uO^5>6mK<6t^pTK;nYsoOYHHQwUpiW^RI$iC6AT@ z<3&!E2O*-xo*Y8uQHQxpZjOWm_O*!hEDX11!4fqN1pYP3hznKRH#Eq@ za?&|t>b5?L>cWJ48Dxh+q~Zh)#gqhg>Vp7@f}#_Is7oCaaKM z(g7HL-P}o(haW$FBS`J+egFOU1Q1--zQcU&mCZ-Tr{Djuvl*|BPuNnqvyNVG?A(|p zJH)Zet4@a3iBN|!DRX)rvg#g%Gf|t8e1#pO5h8WllZDzp8qPc?-YJC@tQYRq&DGX4 z8bOmGpfKSh5zWgXwPH)#pTbI1sq`ZmemAcDwE(JD*;L46@{#Cnw6U)=*yfi2RszI< zFw}unrF~X`Li<)O_UI#gXR%|w%`Bv*3lpu=aN|S{+yQ`(**P?;2&6k;3_DxTj8n_j%H=2t z@729=tm!G2ll@Y`rmU*^=MOXCKC3Y2;!IAY@!@#H<-xb~7SCGXN$0+^BK`I5qN7RX zhY(Vu(|GpNly$To_%ETY@5B55B9-;oPY{2qw;$N@|1Z*SS+=c8KQ?b7AEA4M;^oqB zA^oxS0BMfk<4P3&T~!h*B)2m0W$ETz3YAKGTfry;#&eps;)&E++J$o6|8~tX z3OKZu&rA$o8j`3MK(48JCv6F{hMwM5W=36#(J3)?8V5ZB78YbTMwEu`Hbz60JiDgQ z81Q4CS5)v!%P=Ia*J_tp8wMrA&jNvpQM){mh^bGiAnS}-zR(cOg&4zN;D>1Z5iepb zUb0c|mf#Wwf2tj*8$(=QbHP|++ele6HiZOm(@QqHq56~lBaNxm6@YTM(3iG$3Q%I{$5Py z*(k-9(MD>>T@r)619DwQnbm%yOi3#Y2ah6@3*W%mL|eQl;B@E}&jRm{0|J=}k*#f% z9FQ}yW0)^aZPfV|qNbulc4ep(xqju!jm@3d_021r5;0-6D=G6}^ExMNHue7-o22Zr zk8sFA;j&qi3M&b6Z30dJU8m0vIgdMfb8Bb+&2Mk~=C?N+0KfU|dI)X^gqsP%J;^*t zN<%4_$BC+pHsAq>YYSlN9<{UFwd(kdgY!Ep2hTZW5WEY;$Ej9WS_ zZ$o|D&_OGN9jz0(adsPp2H30$tTmXsvy-WQ6F4KfCLR(T*B)xD{51FVVY{J?!}Nx% z9$^nfKf-s19!h)*nH@ZM%L3=erNtEqsMezgir@@bfE&pOdADhX~P7#VBsLF zPK|HZ0=p5#?jvBxLIv|I?~aN{{&4aKN(ttVpZwwM+0h@){&14}WQd$+PXUu#y{VT< z%=kt9@$5(}>Vph0gfJOhdn8ol>BY-lZw!1NpqBSAz|n9(!G9C1O_Kyu7`jGkU&Zm? z!Ki|AiJK}@8Y$~CF}op{LVGDaUJ|siiYY?UR|^?=HW-|U|G^n$MD!;G`&v)zS#&Xy zR7&<&I2HDL0n_@iwA)-(5#@Ffuv(v`OiO!rD7Oof850$8F%;Wv$1uckTx6^IIzble zf9im z^>&GphVnndQkI#Lk~jD$EN3BQo$-91=YN9XtYIz*qOxBqe z;ig-9q-sAAq-&NFiUWd%5-AQ76%8aWW2h}J)+4&wYlfAzpzI?~Me!)jw=d{7MkAVb zum>ScJk5b?86K|jiF*D;7|koj*wF!bgfqGJnrnES*PcmdYbmt0vSq89CJsRnsKewR zI-2ZZ;h)pfhp?vfsZ2A~(7Ij*9@h}^0Z^wXZ?~s8c5q|R_jOuNHne0t)ivh^h_2RQ z8;106)nG0W;*pme+L%AY<)LZDV=M=?)oQ_mul{ahr?wU#_)%5S%grwj<{#;md-G57 zl~2@LSt$7G*@k7}ZTITfb9)_0YpjgE$gKa7nTH+VOPwMvljp*;;^Ao61ZZ}T!+nr| z9^yv}0q;HEO_wX5isrlOoRK<*;3^d}TW1>&ZeRV+dslz>`t7aF_Ul{!VZ$nYcum9i zpJ={9^ye1;-?0z1b?vPO*S_A#Ec5*B1gWO&?=Jl|zJLAJ*E=TLEjLNjlk4A)=3Vji zu=bYc-`ZHeojV(j3-DrW9{cUhTh!+5#E!`h`}3He16&-YI6v5;0Ql$ty8&B=_WI(@ z6}$G*syG>C12;#yKr9{>rdGTr0Wr*^453AXl+@_-q^!^g!vxu29^32~16VHaQ;79R z+*M+eOm2-ACduWcnLr{!R`=bO+ah_9nduwvsp5;-{*h`=kvf9M+^9IhvjdN68}{kJ z5!Ds#(z3FpF&^z@MW`XqQ)2s2d91^n2-an|c6_QNrE0b=(K!tY7mlzm8f3Ya>s(g^fUF*hV60Z4d5O;cb8Q%b;X?i6?jTj3UM?j4Y_%t(_u`9Ib3 zdYq@%M}6O)W*XIZQDYHUSYAn2TuaA*Bcijr+o6$VpS7p$_M6^ESc_}~w!K7GahglP zo@kCw&kTv6^NTb5^NC6}wmBplx^0Q5Ur%#-y&!I6CtC^ktdpE5R;&TdwN>jD0&4Hl ziCg~oN_#M<1Vz?U-#dJnOwbubkXWVCX;-HMPU*KJ>0;d5%F z;YB1SUql}QbZ_%Gp`4MhXU*)WykKWKT+etWD#=BDxhp9sdgSczkcJr zjM!NP$?b76T%j`%QIgw4n4ZmKH!JQgZ}F#khZBsk|!c#>r~h zZ$@)B-$+pxUSWx{2{3tdQ^iVE2RoV3ncQ`uO{G6Xlv)LHchK7wqbM_{J>U5BVq?Db zsf`&6xdwjr`aIZqvcps7{i&{SGYyICF3^}TUCS^^ivsRs*vdxu2dK`J}J<*{W z8%={8*7BE%gmg)YdTXRFsby2*;ARZH6~narN2BDdJRQ8Qc*ms`K$n;QtR%H4rGNls zF7=jTA(E2FydGf=%5B>N@{_n$h`lI;g zVGQw6ygNduF|>${&5f{b0z#@KkGK8dtNG@}=IU2`XaUrg7r?|&n+(<$USsj8URnCl z_#4cy{JcN4bdt^0p)$0?3dFA&Oy-ww-@9}7ZU^SKv)LB} zKo>fzf+MY-4MLQCYWv4H{c*jl4iEt#7CHiGA79j7x9k$d3VV>MG$oRavu>0}WkIYK zR|b0!I@;QSIlj=W7-`Xkb;4+h&jX*^Qg^UzvNN~2OOwP!Ic3pEOwcvOC4;(mUNFVN z(Mn3>p83)aK~eC+_VhlVl?P&Y24Ud>A%+HiMF==5RlG6vm9bVR}Ew9p|f47%61aoM{NOe z)^wrJTar8owC`p)QUDOQyGK$v@`{A%vmpnLTDG!Go*}nW?Fm}F;>bpQhMg7h?b7@_ z4@t)@_9TdsJqa5Y%SaI`Xm<0AjR0S?K-&D0U!exU5dtObkUXEaeYU6bRg&d+HX?3$ zw7o}!FMONH!fstywDElviJ9t@q;T2oGR5#=0N|p-@|Av-qb&TfuR&^i&1{Gd7^3Wm zf;ipm)(@(0l00FydCFGp{X2xAkfev4mDAep-uq&9{o4EQzRwhHAf?Vc5(}uk<%KBJ zQGK3V9D}bzWNNQCzv@(uIYO^ed$S(N)E4ltC@S__-h%np9rx+Xq z)pZ(j9U*Xn05oaO@^<kpOdn9U1$q!kQX+tc1Bv zv=Tio+SY;_bHU8SEvRl2mtjK2g^R?s57kqP58~cCgZ=O&G6Iz83dK9D^FAxnEq+|X z_5Wa8 ztF6<=&`XWBnPyp?(69?FRAwc{RW5#zp(_=i2|iYM%nf@^=A@}KNJKp z_$#`@WG9-^Ep68NL4hV0=O} zR6jrCzU(c-5q1^536JJmAAS7k5)6Xi7lGs9C2)vJd?az}qkBuR{338XUJnN`p5w=A zM!NOMCre=bGWehmNbPpuJoZH;DFMf)|2%Mf{wMV>`=^5DRS$!@O%x4<^gT5$QOFmt z7UZvxL90Knnq{!RM|hr0?|iFl1x0Fv-~QguNb59G8KHTVKExfGU>=eXoo66)>&};L zi+>R~bVu0mQ*it(b#Ol@+lg8y8?F;@zaQc;|)laNvWi2;vtXs>CH&}}Xy>val$XdSZdm^kAef*v% zp<__@Db3pY{ryH9ex~sIGxE#n>FEf`3QoDR9$Jkk<~9#+n?7z{c~6l2jBvbo`t(QP z=mfg`^eI4S_W9PkKPMbBr7{%pyUqy-oDsTKt2LDUhzklQ)GJu2DhD-n3dRmPvH1(S z1M0>i4(lDNJ*&b63P@q-y3b+t*u)-QGD&e8Zs0Q!aVl2ohItP=co1hIxdI?sXSBy$ z(@LY<1?`+|+0#RkkkDtUFQ!h8Dv+c3-%}2P{Qc;&zkdry8Koc5i~+VifxEO0!Y=7n z0k;~n5ma$dSFUJ^jR7}mtgTV-L)8~ld6SzgEdub(NXHp^9!9*v8bMsu3POI6o4C1g z)VoUD`49(cr(5~*hkW~wj~I$7hS$$9##Iu+-0x`*@ruI7C|^;xp1+{F+yQAjVF5yH zi=1fcO9GGTQLOb?O3G!5w7EH<;!`|~ONTeJ*drO09vT%VyqcSjhonK;c9jlY7aU87 zixSekb*eY23zwkmQG-7GI%vU0Vsb>IvKSX9ukn@$sE{BHy`S!yl5}x`He5uSC6P zgDg9&$9reGf{LLwriyQ)qK~danD0HLMnkP)6q&HUs>A9%VYvqBE_>oe!;`DE`BSph z>Dhm9rEQBlyvE%o(OaqPAq_|5qxFXXha1x7E+?(0QCcj_`U`Mydi+W*`9Ra;eIhg#h`L2CPvD&Ub~nG z<3`+A_r8OYoIo-qCs`6+1h;hM2$7x^v7E7Fz2HL(d_}W{eWFb5UZJ*7?qL$T;?Rd9 zVeqX-s+BB_R3Ya!0_G7>Xi6%l-0u5+X2~r2s;ASuD}7T1z~_>#j(l5KBA&t6(YPU# zC|kwLg!oB-NI@)O@k@xF!J9twPS~~YCJO~cgm$%gE*)pH5E~cOI{S?{%kd@zA@6>R z1XRd0gU%wyjPNP|<_K>D1^b~WMQJYn6F(4%(x3XF5^6=(h`UJHNV6bvFgu7| zuwRIj=;_>cW#Gh;LP5g_+}AK7K#+F)!^O30@82*#>SET;kIp-kI2t)~^V8e+?|weN z_u1`FKb?R2@%{TBe>wk1hX=m=`1c=wdGF)dy)Qn!`@661@sXCg?(xqzcY17yC9GlG znd_n-9XJfwmixh+7L@9N3NM3+WZzU!$u5xDZK>T*4>}XmP`?(>E*uzig|!jnBXdOI z?jPZ)o!R-nZMo^i;(z$pN=nmqfXfk_rdUcz>l$BmHLI_QhSJ3d`NteiSwgq4L`4+0 zVke=Z3)S=@l5|Sqtr@>m-OyIQ=Z%h{55Hx!%vg`pD49q{P88V7`No3{B%8vrs#*TV z=PowBrbzNWyju^s80$c$j;vaAn2_MnT{+xA96*s`Morxf)~k^$F%#O*27PibCknr& zbLCa6(7kv(d=CbqMo!aks^vwD6}Bz{RWXN3Ne!& zWe!LQqXk=_AuM3_s$y3%I*+kT%2FrC$~*;Hu8lc3RQfix5u)^)|?D87C%py-I zLC8(gz~*6rrD5oV3oUgnGRDj@p%R8kRx<&wM%G#=FmKWLSL?;FrVL8#^5VhO>zw&% z)G5^YB!AK<0uK*dmXvVQt*`*27xH1x6hM~V0FB8&(tznsY{7L!rJ=hPPEgyHuIC!y zGKP~*+*3lD!aEwkY`KSrw6e>-RZu0z1U9tcKv{T9EP2~yoFqv9Q$vPQ&QphE2Z?FT zd?SkL-C@}tKZz75)~!vE)JZ5G zot|ZCZhkVx>L-IZk7X6mSFjoTt9 zXeLvkMU_bjnE^W()DZ>|;x(ObqWK2X{Sf#Ci8&lwn`%70mLYAZB%?KEhK2a z`36?ds`COl(5?^R&&iE)I_BUU93DuP@$fT8dC--GB zK#@|&2n;_Bg<@7|G0?M};l?C!n08G-?5m6<%3I?B_(b*5N$dw#D2=luX_b7iAgYQA z-YqUMBi}8TE<`h0?v}Avz;wDskew=C9Fy^1{T|Cr7`w_Lu#aqeONKK6K0Op&;`SE$wLGjo1`12K8`SON;S7f4p;gTc%+?a3NqAKhH$*2dWKU*6C z-NyXEpcEf$ZR{;vfOci$Elv~YKK8G_?&G}m_UcFvHV%*!!({H>Hl6Lk226(4JHq70 z+7hCQ?R8ME8D=)S6HyEqk9C6U#tsJ?@4Aqd5Cx6M@(c4t1jDXCG)#y1+1a5S+gp`? zB&?9Y{vl2nZkf(W?G#~5UYI?N>(z+FQ5+ya4jALeZ7|eT5KPS_5rYU)fpZ+jK+x-l{hxW-386Sc&O*US!HsPTf>tbC?UtLsNJ8KK89 zCic!Eb}Eayzt%?=1*>l#+E;<1dIQmm*NTxW2^jCq0?q(mq9pqJ3k$sGc27JlDXMxZ z!cxixzG_JlBPVVx&0Fb0Sv0bN9Qn&(S%@y@PG)7;Poz(4aXC~viTboA zly!!E**_4}WdRR|dt#OA7m?~FogAs-vH>RALQ2(lfyJS`LSF~X5(WLUUd zyPsj~cKYgDz-Gf|LA`-TqyC?7rB(RGc@jL)rN zbje+Bcx`PB{*<#ruuOd|%;XwoYcAG~74&Xjja9&3!Os?8_&vg5Bm~K^$;MIU8V3*! zI<+93CJUTP)@mDE!Jt^>oCd5S#d9CUa-=hj8k8Af^^#9r)x=_S=&4u}q{zSy@ergd z1W&lDF=?#36Ap9hUg9URt7zAtQA3wBrlNv~{lOETJQN>Sa zx;JG^)S^;4TA9SL^5GcmOglkTF_lG9g=__!#juM+)1>KhIc!9CpBjp1Qz@-kQ_6TD zGBLTswTLe15{chFLPQV`vJ@YqxK_7i18y00uXy?F3i?wGZC3Vx`;p5g?wIS$( z;eA`p%LBA0SrD;C5Ds?6w>aST=s*Fh@l79VjE@ThALwf3$@dkvs4SU1%cqC9U#QHN z+Z<$C0{1!Hk}EBvIN=lEkn=#e%7ocPaa>b~PGtflcEh)VTe|PM7jq6LLI$0$Noc@y*e zW3Df^JT2<W*}JOr zwf>C7cB3~TRC4OB>YSU&s$GyqgvXG~yxRR+^19r>%hOo-z^N5}m@UMD!rL7klm#0??B+ zryQMF$q}JbB$+YL*m|??ym7-9X9paOqJa!_VHv1w&a7=>$7;+#mN+5}Bf@j?W?R@V z9%L!JlSCvqNH^I9M?&!hQ3RMo;tB!8LcMFkfWaLG0o46Na%*bH6;bADPw;qadR;ww zW##Vn>+ejiea~gBJeH34yEo)9;xg$UO~VxWmCx-CH8Biv5EW2;H|7`+igpK~rr4%a zDHf6Y7b-FQkQy&AK?utwuyHfqcq?`P%fXcxa@^qIQ0Eboe+0xwhl+1py#;_=~w54vH9- zkyGMb5TmhN(++p!c|C`s`>qTNETkX;sQArPr1?Hib9=`{W@+*HrV7lpSY{88LwfR&HTRJY22ep^+$hTcDtYa73KAK0- z|GCR3?#DgQWPXU5>zyEqLnHKEo=;v8Bh9!DKCmz6A`iov+yky6eMFxe zIvRp$n?Sxj-ZoQ)p8@{h{Lzlwyx|IZ&j+`*t?2KY#m(zE6Lzrk(2?K8zR4i1P46%;`Q-MqpCunq5foo{l6+<>%AK#?Ek+Kux zfI;$Uk5&E%gLz3nIvCQs62rojx*e4WR^SJ`)AxB(0d;y@KH};f)mG_gtp<|{sekeWyF@{{ zo{ADjIhb$!ofDT2`i_oG|3xt=xP{CSD7hw|XE%V>t^hHFCVL7I6Hz-mluoSgpcW02 zf*KUGJgm*Lm*C9CNaJf$R7*aT&#o~lu~6i#5UAC#sP_y@S`N4iHz7(W)3t_D()1ir zf2lTxj3A4fh0e)^%wY?T7}FfUm7?rsXm9SG#%0V$(E zggj~qn&@3*1BC|ooGaA@LcSRVcBHvghmyh>Owa?`ipEML5roX=j*RdT{iTLMN{P`FZ_4{Z z5;EKl>5B`FXXAU<>GZCT@PQcw|1bh04IGRCjjKWF?NDHbJ=Qn%t_mvHtk_nbzwcN{ zgReEj?!Dti1Yo7OrE`I!8Tr|wB^-K%Qc!uRRR|%i8Q(LB6deDLz*gvM@LuBtm^@7R zHkhf8^L0L72DA1rl^0E~&}3I{Tz~gh@BaGc`|ti*6R8PUAEABstFrt3PMTqyw^Yf7 zWF9e1vfbJL)D_LKhLelBzp*X;y#dv#EPe6fWBo>Z$KVjL8PaFPc)7*bS2y#d4M zw66r0T$-$GN4|PR;hhH?pmh1_4E;*U!1Y)*1U_SxIEtaWYO#}eU0 zWQeQ!Fqu8q1xjbs``;kc7$hw7P)fxdgBc@|zj;GWyiGSedP zPY1*g+w>z;3lWgl&%1APv%56ufOY?V>$}4XZ$MkPSFRGZY@63F8LxwRx&dSb^ z*D}tRWRrb^*eA!-`zXcMC0fkSO>nTS(3^^RiCMFA&^deA-ySwKPL}A1fh;Zr`Oy*E z3+n}M;9RLAjis?RowggX$Nbl=pS-&?s7nPOhOrB@+kRyI!!ZByR%qhE0HBAWig`@L z_hkrJkjxP+xcL;E``d5ueDLQKQqP z7-3(`!-K#8MstN}5hbZNf!&p2@pk+^><0&ejV)DzJHWIdwCgXai4tp50NeK72a9o5 zUR5$FW0ncoHUcZKO9YXK;06)qWoG9N9n8=uwm(DQK#P}(wZwojr$^rj1&uYjxMNR* zc#2raS&@^ZNL0Psg{OR7ExMzzN-2505Syzloe1-N+BzVOA$F3Ei9 zYqg=8(iq{{P3Q$vT_cs~w59F$46c)E)3?`vp$!`r60-UD@C7oU%=_e@SYxwdaut#> z?v03_fs{{tBp+vr2h%dPyW1{b9>{K)bC%pT5a-GBO~?V(ZERU8oMH#ay1K|pbV4-;XGhMYrJ0a#D|v;;dW31f;WO>t9U(~}5$x1y zutOxPov!m=IYgK+dexbekbHBF*H}02R2HW-yj06UwdxGF{A!MJ*(ytDe~{ZOvUQdK zbSu07OiZ1Fq<*BJ!7U?N(+9m1>OnpS^mYFtgCV_A`E3BSybsn6+i;<8zM2$9}CG2`$fISW=2RI}Dr$>{G5mue5=;_k3YS9Dj%f@9yqBIBYjfG}NJc;ep22 z3P0(Dpr5|=?O3HQ?Hp@Vu&u+p{cM}}iQ$-O1OzHvxm(ZH zc(-3{YZd4=#1NJL^AG2T^S9?G+hh#A(|q__;WO%a#RVghUnG(>hVX1zGi)z|j@~^n zlCk*@Xd`anmh!ELNMlKr9|b7;{eY7e%8v-= z5jFSd(R2rDtbIzd9z`sces6-sl4D$Tj#0pmi&m*l%y6F>dR2dfA#5kE;4UkRdF`If z*upv=Xpm9D_f7?)0mcQ&+vRK zNN`MAId>~)3(m6n`Brv=*HLX*kiehlV2ss>8^rzSY4kDbjdp~N7*C4kWbftyqr>HJvtQ*nR6HBvtq3k+-mVQo0Q|ysw zCg2HQHh{Llmw5=2&RN9^{8k^tX2s6@3ksL8GWVWS{7BSGNog56*tZT-5$=e7iSir& zLlX#j=(CRobBxSgheA`VNLJKGy&nYRal4PO^1ak(Lu>JKJ(UBm<7+dM)?i9GK+_{# z_o^KQ)?xO5F$MSe+f?F$-Z#Nr=Gb8Mu3$%A93Imq(XWo_nV_|L7Qmwu1auO$hP-$Y zJ*=e>wR4ea!P*j>-*+%FoXrr(jmL*i@QhsaBa>7|e9sS$DT_e7PCANEk{Y?D0E8n0 zDK?T+8}N*z14b~TmY z#m_gxw>~E!95o8j>Ly_5v+Yqx@FJMa6AS%tZJ$CBf$`7Chs7|^&B4)Qf)r>yn`tNm z^$iG!kl-%vi9m^rtgP7{A;C{q&9?kSpO6wL$df+5`yt#01RoyEQwo4I4l*pK9xOL^ zm^}9Nv#b(twtC`q<@0hiQBmY);7cl_9Q>ecgAMDZCsH@Z7!Qt`?9$$Eseo3eQ|^n{ zC`;$t4o5AuQwSp6-CeG-fQ+}|MhgxTRrO!y-q;I303?HjM2fNy(HWYNLOS&sDoeJO zZ5yE5iJywdI)yRbs7OSD9)0gpLg#))ktrbbQTnzJ#gpFyWvrv_r40w_KE~pY7h2Xs zOj9ncf!?{!MMvFL>;Up|)v{96G6NOigb_i_1ByxdFi^FiY0Ol9^fj^K^=@O!f}7ty zJJa#UpmF|t+xDJ~p(+ZO@zikYZyeW{kOpt{F|^T5?ogh{JbtZ=Q|t!Xe)~Sb+fJmp zy2C;0K1gk%gLDLANgQ9CaF+e4cu03-2zn2Tzz}wH-C0-bLWH>%qSp&}6__jD;IIi|H=Hh%_7L4s8FFLl zo%!EpPYVqL68#c_NUS0Ui4Y+^MyPe+xb1gg7GBQqk49J<0ZO(*eJXfyE){uvjCq2< zh^QJLn$1YN#ucXoJSlY`-cP@-IGL`*1D7O<;r3Bsjyq;bu}4Gi(dNwT~J z=mSfp2W1(u)KATlRm7qZDz*3sR7+wlULK=|RbA1)3E}$*+$KZ6Zm!P!iUNtbM~)t3 ze#9|FO$_VCJoc@nXVq7NGN2|3h|##5BfR3%hwP1ZAX3de-J((IQLQ^nbT_h+xQs|o zBylBmh_A`$tbPkR<;?mt2uGfE$Q_<@LQDob^v0COO>IOu9YoRg((H1-39T&8RaAN+ zs)Zo0BZ4UR*lyi(P>wEG_bD)i)k~-?x>STYYx=12s@gbt&}Iun!B+0+&UoR*-<#I>0{C zkC{xPu*5q|bu&aK?;zR`V%U;{(G$C1ZVG1lU2Rmxe1V0bCQSAE?Kwep_Z&mps|d!V zgJ!Xi(&%wTf@C8{=FCR#UU7!IR$)Qg=SM>GDfNCn6D+hLc+nv zFmE`^XerSyPr&G81|99pLE`KhS08zMvE)@mIb_LsbKc615!Yj4u(QVm%xv>04q=H@ z$B5?=6fCmn>891H9Q=GI0r`9)%gvD}fNUjnnPe}qo@4w)!rhz_@?E%an5pS{!(+oK z90PU|0WMRUoRCo`(<;Ge*x>v*rufSsUdA8k(3W*>p;Me~uBr-TtAzdC-9M4F`KOle zgPbDYKRu$@#-_COkbA|kWw}J;$80r4!uB5?D=M4m=2lo4!Isvx8*q9~~H}?WBRmW?dz? zWhS@tH7t88b1YCZ3!16cs_w?QBAVQ<$IxAqr_5Zy7`i0)eS#Q0{<@W0oF287D z`J4KC`fi6&?S1x7AAR!;BtHJUvdS7T%R`8zIzlC==KnxVu&G;rC5*b}L2qf$>5#87 zo^7LHHxCG?_ND!-U-k6U_ORx}1aB2~5Zda`^xcASx?i=6`uFm0>Z$1yQ#|VE!!jaQ z@Ti9-u)YS5dVYe)>6%v8EWC_Azx1lZ+nugER_&u8;T6cFCUkEJXW%Yd^$7X+`>QS( zzsCUUQC5?ao?O4`>8H~XM15NzksC2eHugdp-Shf|q$rg5h2*Jx~XRG{2a>+hH6>8GnD}>q_D(nW=!p<@C=_ zA90NdIY`Q#OSo{V&q~Yb-^;(Lr>0L#b)mL!veB%nYlT>O7E2{{YuT@pW(?Xl+RyiZ zd?W8}-9hB*@i>LN*7KLITK6uJDxEA`7Ey{a#9F3?WXaMZiDOq@#g9^W4%!!<6rN79 zP6DWABBG;WpUYM~#f4_BpRQeHLr=Qbq>!AxTNM6t;xQTfvr|$n$rF7iIjc@(%xow>DqqTBT0fqU^yU2B$y^p}Ml8?K`Wrj%s@Tj%YZ_aGRZci)trOC+ zZ=3(H_U-p?*;J0w(W@>pUU2e+ltP*R<#@@~9wv>6Him z^5DsZZr*DvBQJY?wZ#b7REI8j3kWNi$4EpLGltuM+L>>E-a_j}W<=RmqCUOUHia4Z zFXS{h2n{%YvFdXJcHwdbF?y*5d}~lwSSUoD)3NoCG7#qL(Xe8NUIBrk+xx6=lAD~6M#wVI6a5|{+Sj^o-v>a`qY@I6~etk&uQriPV1&fy2M2&!3*MDfu6KP%bybbF? zFc!`&P9jyI{S=)wEi+P3f|-wrnDtl#@3RA(MJ(%y$d8r~GUT?@XIx=^q^h(4O?E+i zv(j?#M&wf&sYi!XI_;@omj=Qb*^%7R#A8J;b4za!ma_`N zokh_xYVzdc{lQMzuoClZGJ7jG|Hea3YI3+Qi*CCYHDFx z5?-%1v`nDRQKSkQ3oIk{XFyzI$=LG=2op|}2~^OVkYC4@T3QSW{Aj=+=1bQCMsmq| zafw1kjn>BvV3&~4w8MmLmncHa?(~@%BRD)k}WKw8Y~-zgDtvR-<2stEw#?BMkA5(?6Goe0_K#tsYV zYxqg)hZJ;qDKfq7N1~#LWF9LBOCH>DZ3Mk#dR$`6SK@hMnk@~GH)QPY-bouQF%vp8 zBR8@a2Db}t%~1xP#bZ~cQV^i8v(Zj2ZG)$|VzOXWIS3E$Jm!Af0DwxaLqZ`W@T5yb zKw3X9^2`g)Lyl$NZ=@t^GbaKnb}9iVJ4Q&}NN!3WZG&8(d$xhuQJeTI0B5j#QYeSP z*=^e-abk9?lZdsD)EmQ^8!}^!ufxORtvgrzOdTH#7cOBC0BcCB(e5-@;M4K!ruq)y z#2Z7)LV-=#DnF}%YPU-rLS$l>dgf3J-LUAbs|bkBT^Jpsf=VE}HRc&R(gx{gB|G+& zfz-~pK!Y9%wQJl5c6|6lfDWkvXvET%rq$3s##a+RdW11^ z0K|ok?#W%m3>a$w&FNjR*Kw*o1$w)drqyxOF=QlM;Y9a#408Nv<P5yPhtbaU47cW9?It`dA+AS7@;VBcW7vCd%!=j zazG5t*P=&17Q8DAGq~b!@o2@51cA1l&2BEQV?~s;3ABVj{3DJ!UKil=64rO$y*ETT@$*QSCL?M~le=W|YSQSQ({GgDX)HQDF{b#z@ffnJ_G}_2vCT~k3;mJmeC}!k{OPu_I@Wf%?e4}Je zUfS1`jT1cV_79Ad{vz>o`Kb-zr5WZ0G# z!I<(z;W2<-LL+c_EBm`5tz3!b3|m-sb{UPig}NYCW&jCl9-G|$_(8+Oi>(G|x|y6o zc#2s}mOUC-%OPt+j1RN0&s-Ad)#R_H`!K9UT2=HNpRAabz4RDv7fkV7H$GK;e7h#si4&WQbLui?}ol4bg8GYe$kS@ ztOUJ&yT#tx=&`rP7oam0>ZjtCk8U4J8F#Dl?mKa%iO;;)bxveltXD6973(dIv}&CZ(c<3LDP9kr#`^(6AO-9^2qID<7$=NvB+?IU)t$ zohpd|6A`64eIATGjDYfdc5uM?&0yq&Agy;?HB^1LK?=bR?^S1^z~kT3q#`f7_3Z`{ zZaDbGPiYd1_sclx$capLw_7of*F7{fo7YveYd@wYW*EZi2s4gIm)fVJEvxS%RAkpw z!*u9u&(b=YBi+hBVj&No#9Mg8j9@=Q?}{?plnn);oaAI;9uW$Z)p954M#7DFP3i}E z<}xbK4EVd03&5zUUVZk55pWJa@CeH%pMwqz?R@_wi_C#CRLE&a4K5wpPr;DE|nvqpX-M%0u0D(T3zZ{u0B-{~lymDD5gx zFl5(am>#zEVyEYi?pU=CkN6nO?Syhk1DRfm?L+IW(Lfx7_Mm+yJB!tpy|I31_ov@U z&JT=0-5L))o#qjWv3$dVI>>=5Uq@CSEPNL)~ zic3w9bl?g4qRviK*iQ4QsjH1)1r8%^-xwHu-U1yR6XqgYT_R}weJ@9IhxF@D=GB{W z#U?jw_B%q|V(XI#$cjRyZib082a(Dpi}v)YGbLB(r||gv>iOx_v%@D(aba6gmXGFZ z-M-M!-Ouvd@oG|gXY82_(;i{#okNq-SZhZhwzLE zEwC4Vlx1=i6KiQE7>{j*rv03Xr-OAoFZ+r%zjZ!_mgtsgnH> z=%h-r@*9r!G>&ZSSba~c3KXETX7bLG-s*yj%g(LW&St9xx|W$p}PGT zCaerT4GXbp4Qbbg!m1tA7xDHGv<#b3$Vi)U4H|}sVjE-hgklWgDURF#glm|hg_Lgn zP#ZB0X1lSJ__H22BCA zMnQ=80UTIC{fQ34L|QS7szfA4@d!1)O6>`Dttvp)S}-xVsBNO*G{{d@auW?_FxDu! zM*Z_G@w*%f>l!Lg!dES;WUgkcST#SQA|?> z5?V>`zeZIm#`_u-rctzvS|BQAqOvqX(7{A8Mm$MzR}awFpsYYT_{zL1yo<-bq*!7= zW7y^Y8pE;5Y{eQ8Mx#JfP92K-R01Fse8&_#~B7gy|PJ zJ&U{_FJgSD--`c~xM}TXG`ZX2IU_OX)51l>HCD80v9Ba-nD-DO8;3@w2?&aecy z!dN=MV_dT?u*3giU9~f6lgkbo#?mSU{9%Qx(f9=s*ILIq6FMvnF;>wG6Ry0{8+UJUu`Nep&*Ni ziKyuqZ`#o0HHL=@Get~b;}haLso)$eO2yT>VL{sXfYb_QBxtS|Qh)}>cP*$zNpR2^ zl^0yGuqKBo>T-4ljlq+Po#*wmO#pxNc)xvCtiZF!l-UZ%u@-{O$3dZqVZkIIT%A*u z_e>KeZs`dE0aa|Gi@JTKrfupLa?%)KR=H2+eby9s5gXHSd1rBsFB*+q@=p>hI76&W z@3x1?(dknqa4I5=^oPU-T&FwTx>WORa{dq#W5-$Ac z?;?ojMbqaBpTG;wCCTMBw4>7g*VwV;+^3m)KbJS&ga`|&*-x-AaZ}3q`0olc5W*J>q=Qv z_6_{|1%1YK3L=@x>l5{;>wK_p`efd^Isj0_S+Zi8#k&2V(!$-~ z2r_E#LO^-cGuu5!>x|~|$y05ev(gggSPDiB>^=p%O;1Krzr!{(t5^A2ZZbG!1ofSO z3bNKW%W}jD6BXG2%!OYWO4K6WH9^_d!^~MQl@3zWX65iG2So{GVzo^9*~Q7#>MZ>g z_p5RL)e^FuKWH5iLaMd4cA`0cB(-wk%EUH2bLVmC7Ks&|nhs54pD_DR|MOn^BkD+>csk^h?#V^~<`=R?}dLe#617bX=bi9SWYPA1^N zADo;v%0?yXxPm?%G7X-CWV|pm8R7^>WAEV->Z{wjL8wM?h^e#XG9T4& zkB|1A6fNjDqwn&hz!O-Yt^{Mu%=iU|8ilz5z$OOoOT}@=%jx%`Pd!if2~Z(jk($Ww zTgv79xAaKP#?3n~uDu(}Q(+jX%yE+xFNjFl?(TN6zLpTTAm6y7Y&-V<| zIuZK8G8DglGbpy{+o;Q8e+-HSLO$D6DQpRJ$oy+BZqO`O!ai1AD;X^YzTD%eY8GHO zlz(#JYv~?S3Z?7m_789sDABgRNA;-*RHu3M?Kj_K4NQ)|fB2m*&D-S=jY+5`>L%^x{_ zG%c4F0|k3<<5pJwwHMbls?>h`;Yr*f!$PTbQ&-p0Ll%~uKWwUoeb})5g;%~7MWS(~ z&AG`WYMaa;x^;zF+5iz58!X3W_-K1ep+wXzgqEsZL4K~%yMlmiVqE+&^#D>;U@MHg zBd52G(OYMYu~O`qPt+H&JfwVl@>$nFX+=Y5$YS1~gawBh&eV-sfr-BSp>8Wz`|$Mq zoQpPwk)-Y(yAMlFt?`B(j25t2PhZuDHh5uK!xAGbSzBXF!*nQpLGGIfNP@Ct|HLS1 z`Ufa}PiiImOf|!$t22;gp06Dw+fL^wkeF&YGI|p? zP(Ux??28+7iDkAWBp}z!o6U6wYfAVu!5K&zbGaFl$jn5*i&A_!jJyQ_plCd{R@Vp^pYUM`q|N7}Xt z>|B$-AEdH~xk7+&H5eP-3z04%?~GH&Oy-7!uF3PN@jZe%E>188v(;Wo0|?LZmEd?; zer66H^?97Q+Bf%W2|xr{oONSI*<&BNt@TJSC#|%#6~Jp@W5JL*8M6K2AQ4r_{=gnj z98*?Dh2q{}wrUP317kda__%LnDHhC5Z{KGWx>;+a*yQbguE*D`*f<3dgf2tV#nSSjqXT z*v__!E;^~X<7OfkJ)BXF)yjkj;4POqHjVg#lC^wjE)6t{aw{nCu)JlP4h- z+r=K9<-QT z1TKSC)opwo#CDIk@v_xE`OFTuO$)SLHwbk5R#fku%(o#vj$k4S{Atb`j2*cJ zAsYUNj`5^<`jq=wxZ4%C#1{6FB*CRt{ z9h5-Q6&`$iW&Z5ekve z|IP;1CE|fh@Y(BbJrf;&9#*sF9HgryP$Qd zLaTDV2x#?%f_1D( zLY^~>y68Z59gtMljt82Dx0{?rbg%v?GyA=v0)jz+QjLs43tL; zbK$Nm(b*(P)MX$;QZ1kMhC^C8d7~um>&gp=r)5dg`O}(#usmDBFac3>_VN>JkE(@| ziJY|)(m|?q9_^hZ=~jT!>^epir<$Z=q2WKg)c4!C5;i# zkrg_^gv^Z@D{lQ|JeW&aB?y!^2fITi_;=VY=mBwbAJq27T`eOP&rQ~&3R(G5>UfbP zN4Syc8k0ofRq0R#`_ASYUtzyqt#Et{sA8;j*tB5Fjmp(jGN_KU6Oq(vVw}}|I{!C+ z^;du8QiH|+{onl6U(G(rgv(;KT|bnr4A1O^{Nh6$VHmX7*MtY|Ho&Lm8Fa42zY%*z4AKwL;$Tz+nVtW;+P{KkvH0J2*vQXNw36rdHS$~`816`- zRt(3XHg@&j+3fawJCkSVzz|may_omw=7zo>J$n<6vVxq}(yCoBTHl%^*geqF?>%!g zM>U$_Fm>OUB>=XQBGkSu$U!J|<&=EPw?2`&1>e@5ssIzKSI*9RK0{H`00h#BcpQlv z{i4ms#@EHjSa;?Oow6+Dukbx*-8~lp*;$k(>3UUSNeu)lJlc(CG(S+#36r9wks^x^ zn7`jUx&Zf;q@GD^cRXrkE+D*87){4pyC%SatIer42bd(W=IM25L?{`?9H|2{3Kt*) z3QUi);ktEC&uBb>mTBjV4W~x_U zhhBTp@QgbU4_@Ai{RLyXCpwBDA$Z*~EOJ(`FFT7!oc?L^TM{#yx90C&`|Dp{nQbn< zJv}(v*WcG~{OX?=gvWVG-`<+Xvse5bf9110WtT3r3qXi6#X(ASHJu+iF#f9twzjvQ zk>q*u)@%OAn~KMS*_JtH0WrCkBk2*+5)y&miS!mLv{rKJWpinX#F4N~%8I6BA^22t=KKon%!+7H5Vj(>j zv2O7~5Sd(s5az+aOrTY)9XxypsUmj~Wf50H6a=9_l=?2m(I#LL^ra!!Jixm6=FrBm7ZERU*nQvf5 z^4ksl_LQIkzu!dQwaCkFfBRcT`p{!-@z#gD!z&;1f}j8J=381SKYH>ZPyT6>#}KeQ zxXF|J#zGZa4R8{8^LjFyY}C_HNQt#kcK$csIn`gdUK?zBJ?$j72n11_a{-P=1$}a8;!~) zDCc71fMw#O3114zYvCM>i;I z`cZPVw`0|^i<;l60+rmYbnzXlOX(IX$KuN&2GPmRgN8LD@~V$!Ijo85aH_us_#Ttq zxqGk_q6`UM57|)E%+qzUHg$0lqzT5b=)`s|S2xe6|J0T!|02;SlKAfQS#kDs8Ye4J zjVqrPN;7g%L5(R5RPRZsWOaaMUL+hO1uJj{Bd4Dt!y$t)Fne6+#x*FF?0 zhkkJBb^uP*@}i!)6eIQqacD(Uw5~#cVc$?0+y1^7eT@Zn}me5L?c7HNXhgc$W0+T89u5;+d zkXs^c4RX)hBAXzjU9)zEY2rm18;$R!0YL{FcR6w2BLvS9gnm_H8Vd3m57M1S+a}0& zZ1y9hrZ#Dln^6oy;^E+rk(n@|MXhP;{WqaLgk+SC*3!j$6}nFOWK%R`hrXN6Z5M=5 za#RUYUtX#>+-_#HE~l7GJ8&v;3jkPfzTTHSXbLaJyOnYurNLXyS*GysI}ucyc-zil zVIbs9`>W(k+QPU<>!2_3RljbnwxgglNhrY%ZHdZ+&S4kr6pB@Vq_v+kxbcVN` zrd;8qT4zLPC7d;|M7|rLu#8yNNs=4sp~O{<5LW^aj4-(ENNroJ6;|Ri0)imOQbV_R z#quOW^p|8xe>7*9ikbj1KI<=o2;51;1^BUfa8hleUB*K9HCe^P6fs`a97*89a8rqr zex>4n4AOLY9d;Vr)sl{uPclw2XQRNg>1oTL6(@+8Q5O*hh`NB?T{#_mswh!>@!?z_ z?eEm8>h1lVKo}2u-i$BMV<#5!^zb?HHQm`7ey~)J5Lsw$)S~#SzNiTRDcI7roKqmi z=Q<#LSg$9JmB#uV^YF;2A3UBwzK!l8zL8)k>j~z=12*RTruhfD?Z|kr^&KS*Z+Wz> zXHcKHmA?v4`MJhia=QoYWP z56Y}(pvTnS37uLxV$E8;_8YyM!#7@BvG3CY(d$7jKN)d)4YFLuPy+Ercq&5uuL4cQ zJU0PRQZ+lQ`!AiQ*3%P0lqQxd#@wJm*AUcevBc^6%j_Z9FARB^(Q|fS zBNbCd$~KHPxM>l3wc@z9J@t1YZ)C!V`6{Y8wGi@4yELsv~ zv{J(0?hBb%2x~>0tHCAP638wT+x&>+nn^y754&>fiNp@s^f*YV%Abi4YPJ7;Ks2`; z4Hc>?DkOVL@&3J|C-f3Oe;V~h%T|7Z#jI|&)UN80q8OkG7k;fp$sB2={@EmAf20vb z>^r+jY{SM+!Wi3a>tip-M|9rEWhAinA!D`QYX>fM2%<^J)&r~4Zt;KBdx3RihZQ7R zgZSSGy&M`od}EKXUGyzyunO%DUSI%a3{jFjRp{=rZ?e0a@W>R1V}-42-d?Eu!Jn+K zKRRo#w78X)%Dq9;GL&0Nmnc{4;E16O`r>&}Q6eh~!wB^1)B)_sIBSCUDo<0`k{+;A z_Uq)u=g_55nI>fPdRqca=Gy*FuAGD~0qGp$AsOcnZ;ZCU+Q=qXX5W@q3j+w0idTu7 zrn#9Mb`5SMscd;N#>#qwZA(uqYpK_Z-#<@HeRp^O;oBHmnNt3*zSlNSv5(aEOLLB6 zPR*}eyeU>YEAzt5R!^3dXjlDGQ1#9- zC^^+%4$!3=_M_OFY*xe1Uk+5yl@r$Y)&*{7AFls#eNeLa5H=-cod%!=37m(cXX{xX z*19D_D1{v!Pjb>1_;%YP7>euNS7{w(0pF=Ulw?zMOE$E#b&hMA!c`j>&2k;7Y3DY& z^qfVT7V`NbSWitdK-DRBc8Kof15niOy0xwcTWNu%oBZ{Nv{mm!2Ba-aub7?dTJ|e0 zjjBY#@xk#!GA#1zCBBIsUHT49ta6Z`r<0oV~69Qb#PZFLyC?+u=!3)^5~yG)}SBJdOLB>S-d z$5K5QYmwOOp$&~Og>4euNY(B@LA-c$;IM%sVn&Wes0A=|ASg&c6gyo|1|=AlZHRD$ z-hZQrL@XXL7gM+ceFY^nNKd1iFR+zf7nhLQum`Ua77g*{L5cY^95Fcef4OIGw|?T% z-?d*WYa|f+hEC5wamF$+ho9<2JD1)4XPu(;sDi_KquE76GT_DNX1J#G$W4?x13+ZU z#Dhr`8>_RRBFQ|87Pkg%GbWMuiz9MR5_HLAT9%1V+h`Wlp-SN!*TKh#oT=THgec}L+G)=y4QjBzpMvs@$#6+C0FmV;<#4~ zAgA+Y|87lESlJeI>|f3rrNbf?9^w@9)7JI0UNB=U?~w*s0{3=Hf6B(y+Zn#|Mqe!U zo*YDBfQnSO{|sUz>G`M4gC|cGS)j7uNE?r3;R@#^Pfzl9?q)gW*Y~bnbM1Dt<7SQy4Y9*D;v?t=Tw0ZT=|CAaEQ0u)D2EA5)C?>^ALQcGUOW$y)jQ^s3 z=Wjc0TTefyp}_gpi9vYp+PjvJF^ho}JtkD*IwXO@m1!F>gOKbvuytJxs-UnW&BDVz z2z*g06X@ZW!kT^+n!cXA85734RPa#8!~eizR8<6Y-l42`vp^_AQV^%j=N&DJuVx^G zo9Ior+T7ze1z`Jfc}WJlEop>oDy(W+WAon^?X(w-i=(~$P1DGq5<~wqJO6L1MmV-0R`N(Ad)3a@N!U6Ku`?VIz#Xr%0mC_f%r(#{ z-1m?w=1y%TnI;9$NjA-d8(km*=A+o8RU721klsgis-Q*_IkiI_Gn-i=rl`=dt}3&d zkBMY*!2MIH~}=T+PbT*j&BR)0kRf4&q2|1oJbk7C&xS77_JISmVyB$ z5UOT!Y*!vo=c$Y;f7g{#?Y{APyLO?&Dl16i#uz)ZJIGmm#_KwARVQ6{W|NJQf4_ufw0w<660MmESS6_Y#<+|*f0&H^xgJ}JRRwqZ|8*! z+gC!tssRZoo#B14s3=8nMQDK(RIu=nE1tb0;NFQJcrkg-uk zNm_bNORNsxjl4|TrM9yW4GIh6YBxh%roh9;N%e9ZsBVc4lsuE0oV%NaGqb#N5XGP^ ziW0ku?EuzYi8yVfxw1a6qsnn`aGo1VsL}O8dje%suQ+m>$~6J(v0; z_id7~IUKtR6S>iQB3AdqLK#JsG~!ZeQ2-Ki3{WUlog^2xJcFev0-;kK3RpnzioNa3 zZgXCk_WePH8d=-ipw@tmiXbrxmu$)qyWHL7RjzR4pl;zdYI764-t2JMkQg2~S+);< zW%ly)0(%Dy$TLM;aHk$87m)#s%hA)#i6DzR6Xi_2JE!zvWlYsUb4z=RTJy6~EGmY* z(@ls+JAvdKZUW&ND!$x2##jT(s6wa&+T2?l=6~4IM?~ND^WPyWlr*4CuFla*B2iNR&J%Xp(a9JkUxV+4Id< z!)9A*tu2M_kFIg$r5H>fufa$jBfF0bs54boMbu4T@ti$+N+L>z)tb{}T~miHUcC3O zrK$6($2>5Wfi~6bmab}Lgh{j6^A>};$kfsK1z{v9nrJ8KyT8$#+sF1;A@z7ox_4WT zP!1Im*oL{b9in1i_I0|8w-87e;SWzq1KDew2cUh@76*gWXu57nM-cir5bl`kf?TQK z+u%`C;0ulvfk0qb6|lQ3e4R>Qse8}hREy%aUWNG@;Ia4Wh=Fd8vSBs3Y_~9GJILi1 zW?Cytetde0b0Sv620=r`;Vn2Z-vbM@SJ44{8nzz2<)n>Iy_}wG&$OWpka55T=Of(4 zBaX4vj`fW})~nW(&TwtlRGTReLM_dEQwfxcJ;C%VhU02dH}UqmEjfIgmpD=9IQS*j zcugipEHi8i!?83{I7$(5n#Fc{pTL)9A0h7hpSxHmd~nYs@{krYC7SfsaF6EZ-sabc znCl7-6XM|@OHi9M_VLah8_8VO(0&BjYXKUvXLUS=`V*%JlsJGa69*G8Tlg$!jcvw6 zVo^~x9<*Zo|&PCk}arN-zt>0=p zm7$8u2qW*RrX@N&4jQB5R}D#MwGGA507i1!Zu6as#o0UVe)kTy0KOAI>tZ0Bl5j_Pj|CNb@|TfI;XIb!U{*6xdaRyNj?E@B0ry#mnWk;tAYdKV4!>B z2)UQMH+bs|0{rYA2Ze}3<6I)r=r0n4sYPdx82dHRbVnUF4((%lQJ^Wje+{sIMMKPH z9~B=K$9WU$ket^i085rOGGL6x!dZp)k=b}Mj*wUKzI+-s5me`?rXbe95Gn;lGpo6I zs9fZ=5J0dYI1(B6CCIskdGmZ$VF$KX6~`xzl8Adrp^-{bh>)d!k-nC^KBU(?C6DN0 zad=E)Jv?JnUkIn*t}vZ=z`CoGcPvAX_u@*bf3rVA=$Beoi{ya9n9@O*;xD$fucUD1 zzE*6tE+U>T2`9XkBoj?d9z=fFVkg1W+JgH1_%Low0TU?qy%(N1{6V_;%F8-`;9-#k!5IHU&6xhtbfU8eAO-=>wu z%Fo&lr%z2Dd3*M1{zYvTPF()Hnty38zy4nH@2mOe(zo%=tJ&M@N+H&MIDK&Ph@gQ3 zwE^lvTtE7-rxg)NmaSk+=!8f3c{SgQ26!|8*QM`}^Qb8TT-R33?PH?lRW`U@77==y~hwV1y>mr>V#UYUrO1Y+!y1mQMh z&!XNRc4~sE!s6Nw>&rE}5GbZM%>0DQWcVkj=aqO!H-Fc;DK{?(a1vyoxiLU9+5cMA zt3kpe9oGF!-uqeUX7S(<3u%~>MICO_;c?&rHN-f40@GZJ=UCLuVNq+bx%R`?qgbsK zM|fUkd&gwPsHQ|_iN_FG`Y|+H?*>3WH*VrP`*25*79HYUuYTfw$)8mxD&;$r3b+WB5sD&;|;e!1N13gMG9F4JP4} z9|MNX9DaV*om!{|=D~}t7qwfjP+V#Nl)6099>Yzxe7*$D^W5aU zpLtQfQEFV&IXTUvp{%a2$Y#q5G!x+di!Z7NdSq5%IJ(d#yD4;=7EAUnH$v*(C|xIZ zhX0&CDF$;`jq*a`1+>5svC&6rQ~jI(9Sq?M@p3pU*@;~{tMZSGU=G!ma!;aJRv0H( zC60jR8{w1Y6SFX1DsbWqZL=RMcb2qgW7{s29-r9Ys-Ap8Dk++madd&qJ$G^*(pF%h z=*XRB=gYbZ^Yw^;)&&I_xHd$&6kSpb*9IV#==JP&ndX?5&i z4PhH8g&?PB^c@I^M2LkUFCONoDgssP@T4485VpX5bPDI8n^dSHDYi3Qq`POqv1`Q& zDuRy2z#O>yD7<3l2rwQVyreZx44}qjOK+>YN8)fcyRlQ<)uaM3HxP}=dSaz=i44mT z)eL1@@!?j4b$x$0B#s4qZVCj|lK6A|!54Im@&6}fABzXqzTU}-hiF@~^x93mlmCfIkbh8~MER_z zeovm7QLP3EnjdWQ0g-{VSdu483h=kUh^BzDR0(De3 z?>%kfufApnZ^rR?tV0BYtV0%ia`1#mkb3GXL=ftekK;720tXT4#1~I2YUE&Kg-XL% z!V5VBjSiu-PreOmu-rI2Cp|4<|A>Gf)bHb6=AGT$t71~2{akeqW=}!}?@Cm|NYN8J zT!v-imX|UMSRs;uc?G8oq`V(ERwiT80l%F4aQ>SQ=g;Q9nFFju8uN_U(HKu$@#%(M z?jxDjp}G(&rW4B@-v+8|{|!Pk!fw`a)GMqv=ZY=pPfs6>ch^oZ0SdHtzxrGJY6p9a zxM(M0&H$(Hy#Y?AhW84F1=E1!RSdI)7v#GRA&HZ1T>&+s`A7G0xkeS7urt#^1r zxZs#NKoc{jP=VNRl45k@Mx3ImB5-&3HZS;u6Cb^OLlY=SfB5!I&m~ohG&#iyrLZF! z<@q>85<6S@=qXZ*G?>+0w0~&VVu~jmGFl>oOKCvsxQq;v#iR|^ZZK<Oh0Ncj4xK&O z-6e?$b-cer2gWdWA?=e}+uLRl%#sQwXnCqtO_4xaNd&^0N_$O9+u-snwyTL0 z;I7u0gu%#N(=XHN`0(Vad&6OmaLWAfhX`0Zxjo#Qo}%6Fk>Y~%Dkf6Q$KM|+NCKTj zHI~}WKZH=ZRMy@;N%zA?T25VNi!G>(lgtYt&h=gQr7$J~@V60?Mv*Y3 zL8f@fZBG8whWWykOsd!{i+TVebOa*1UTo*0EypP%h~i)M7_ zI^wgLwkFjlqeCy-a){>gDrg~)KaCQN5M*nPvg_8bAy2m5!P0snOJHnALIg~@V6 z?~ye7rqh}A1Xo>s!T_<~kYc4CGXb`A%!>rg0aa5rw4?@^TzJT7Dn1DOL%>D@p#UT!`dk zO%b4`*AO|Dgm|_l4_MFLx93E3NW-B=B9W}pB$bEQQ6iaFX)7gJlnlR;>6;;ecpvE) zcbJP~sQdtV1tA1AQxVz`>7n)^v>8P9KWnWHRP)gqP`ykgrZuW^2`#FPxM&H?+cs_IMDLGiI*8cT$Z5pGW57ePK9Y;K>rnZlw8MtoYV8Pwx+~!y7IHZhs zMKWjpfEzlPNLd*IZF!`!R; z^*&BPb1C6pL&^cbT1ve+rPNEXQ-YPRFTqhdck5Y3Hq+0^FZ&C*uqYy`HeURwE*f*% zlC_QMIepWLe0nJvI!HrClM)L7A8erhQvIb{E?J^EpHz8i*pCii+Dt>QdBZ)HB2Iai zFbu(){{ZNAC%E9^s5BSGg^ZAg=#UeO+qBQZTZ#Pxp2$J8mI`MjY z^YZYcD`6j*YFx-AySJJW6DQ+<*qD1UzjkHLQ`g@&6pltwh@EcKwF`b2I+??&i+Gl#UAX7!dNqqxJ92{QKs+?HtPMM|=1GYw!Gf<4le_ zzd7V`cLN-7f9H>2z=J`Gk_HlGtrOYnK$cf~Le|=aq_vZ*7UGB;QH)3qZ-%s_%_i?7 zc`^6S0_5}kR&_r;zeGxwwDy5CtR-ijr@Okkx~jTCM`2$3Pc7k@`VPa_WQs8d^wmJbojwMzTt>4A6!XZpz5(3QZA6wXR{rK| zLR=@_bVtw_^_oyGoY=B4r74)G0wp>&$RTF$WBR_8(SXL3JlA<^?5Zko5!aO$mnK8C znOQH6I#R(Ll$}g;Rq}-5Zn!g_k7z>M0?|6}I3U1eQ?wQlMMu&VSg!Zszwo!FvaesS z3#aR08#KN6OT{?FwSed%=ngLirb5001U@DPn2-2XjBIY5C_BaS_E0_dl;R5-#{4XM8wKrx{iXd|+$G14>l&k{^!~iM&*Y)P>qfrJUSUxwyS3h4 z1QEh70<%$C!u{)emu4>9WlRg{(%%H~-eVn(YGq_?^x7k7L8pg$I;#s!gJ*HdrP3~{)^ zO&oJ=I9gPvjzN&|Y?4))BW;jPa$y-sP|c_;$(y2z7DY>Dth9UIumM}lygQCzcGcY- zk*s&Ow`B}##%#@D+NKh~e|NbxjOpax)pae|0)O#gxw&l(K27z?6tVJ#p z`U0%r>ZmNUz5QF=y7N}famu16olONqzzGCyVNf7zpp;Y$G_#g85)JSTMje(at(|}> zbR>?$SbB^|%;NzTH9C)=>@gcU(!oewawG!lFj&Dbv2sB4oHXh{38;HF6Pp$Q5P!%5 zC@(@Oj~@&CT_Ooj-VuDi3#LQ=HQKcW9}DxglfD6T+j8s9Py65g^t&pogH?!#s*K^0?jI|WK@BOcW)Q*EW!+1H)&EeJY z?E6uhx$Bvp#l9A?{0MVeO9vk;#$haPaiJ(4p-Lk}j)c_b*&PhJt-Ig8ZY;;+Fb`Ng z!=&ZweRB_kzkJtqVO@ZEISp4NoU!k-7ONOBYcK)zLDhGp=YH~oORKK;*g|J z$XV;@I=(f(77cEMsbQ#&9;HZAjk<|RG(gTB=_6ra=F5=UDftfmi55p^I7%A&Js3SZ z>FX7jRTWd|g5VZBCjw#4dD2+yI~AjGcCv8Ek3AHt%zfnPRVJs$Yp}LHqoQKCo zGO!Cy3-@%rCpVEKs|_-^RnPB`S;CB$YnZY*MF1A;YnC9*qJ=If1MS4FRvE0)9rg!` z>I0#RR%en3)AN{(1S$N-Uav-saJ|Nh6tQ%^MsIpVCG3QXYwe?KPV8^yp`*R1R0PFU z3J11Hj+8qV-Hm(i*~%b}{=#HwMb|)e6cKqRCGxB+ya|Em!srB5OpSE1A4<}MPAcXz zK76_#nR|AS)f&*SPGphMc|6+f;?F3FVK<+&YkplHB+5gJ7Y&zh1gS53FJHdIfG|}2 z$AJ0jE9*OlRm7Tks~C{*}}p~zg>v7(Np(H15qtb|c2 zhSryUcSzmv@Ql}I*;L46=5^6st7EIyP&N}<0a#%mHiRJ#=s~RdFc|j)iXx6PO4aI8 z-gy?hSvM1>c{ALg8wY7QqnDV&9bA6ivnH<4p?TgX%cz?{;J$C$y0ytHDuKIvxZgZ)TjYM?%yCT&o($c?6jyVny;1x&^nYuaK@EHO(FZ&_w(85~l}^`7x;Cx@~x&=B7RF4%d4+&7g#JHn{f2l@E={_*#z0p{0X^u4nz2=r~V zzaXfOc2uRGG{=#nmCDHCS*?d8bZni~{>I7k(+pEr1SW=e6eZ_)mG@mr!i&0$OGsms zYj6oL@0h`ogUu0>E6Gg35pQsb@PtrF&VCH6Ddt#RFr8q@dm)k|&`TxqDj$dyDZlCEv`HNw4V<9NO}tE2We zU^T@$l(GBk*RNdJS|7x&uU}agiwV_Os>rwN*Vm~atN(AUJxv!YZ8x;BpSPh9*-9HLcXu8r>|4m} zz+Vdy1w6oB-V|Y% zP_=<}U~Vp4ZefU}fp$5R4OVjltTvY|jkn8{R+PWJ#Z;IroY$Vgtbit@G-l7LJU`N@ zpEJ@~#FQ(=tm3R;Rv1y)xwOn8?p9^N>HUT28XIa1B0kZ|i3UgwQ0+^pOcfKV#KfEq zZCm#eOR9!xBGt8nc(UGPO!XtUig;1={%uR`^ydXbYCOKwj{3f|=$FG|S@37wSF5f5 z)l1dV0g|+u`n9xb?KcztJxQ4kR2X)w_?=Q=miQ%SJdh!F%r<*rAis9%Zv4hu4)U&kb^!P}&U%>bPxn5o`ofb8c0@14J! znl`RU&ex@(NXi_Ht3=FfOxC`=ef1xQSHJ)6^2U1o_0r$2S)@0w#RTQwgW=)RU6o?K z#s3E;hmC8ORCgi0%>By=Qkk~Ax$xii{p+{B8<=c2D6t<;E`L87mGA^#H*2qc{*ATe z+c{V>Q{%NmPO&G)%2{i36gU$tC@YkZLbI$tyHMBO!gme>x(PO5ICz<;`XgIyV_;o(tn3 zMkR7@P*})Hg_v?}(M2V5`nGN=;)~fzxrr{hR|(0S?IZW~rn2k-(G|7gXwjvy$oZBP zriQ5Ct7x^Xya{8Shil-hlH{tH!^(9_;m>J0^UgFrREFEmOQ}z1Gh{L)M`;9lXEE0} zB-P4BqZGXp zjdd&O1XrdGl^ou%!ESGN&`7h-V8W^sM{n7Jrb=M+&8-yN%!L6Lj>V!Khh8;wICkwj zEnKN`Psp}8qCT7E^m>7~lAUxVu4f&|WxpNKTwV19M>?^0d5N3W0i)z0 z=njY=u}D=g2H62)g0$t9ztf%3a&Q`23KNoWM|LeE+$Tnwvltm4G`W0bLsq?ULOCsA z?{L#cj#MBtLRqUb1)Io@?QMUO6<qTGP9X3XR& z_@rD&VHpkf20V4rJ=F=^%sPH&`SHDSnj<=BCag)gF5#!i+Z-9B$KluB6D8GHX=?be zmOr0f?Ml*A+lUL8mhA*uhH-5%b%IE{Wbr6!l$@2P;F%Y84o)$II6}1}s3;g>OEO2LdET^d=BGU^ys1DEk?q)^5QZnO z4T#C@o6B3*Z{EDp|Lr$lesTLj|L%j^cOKpQ>VE&L`=9sk-n;wg|A4~|599~$Q%mvO zc*y5lFwr#LfQMhl1hX%^10GWObzTU}55{ze!eroSI=j37Ds$=sn~8~QpMFXz+U*Co ze|7K9)qD4UeeX{H*Z01-_o)AmpFj8tJd`3E9Kywt4Ra+oW=jUwSG8|tYf32%@0pw= z;91Q)YnAkx>v7AnbK61mCFP_~OP<}+1Gi0g2tNnNl{b{~g7rxnM)CgkXpd4rj#5^U z$v;M+L;&&;RG|<=j^`I#e-xY%Z}fkXH+=LYYV3%}b1a)0JBHBJ&5LEh(gI$XYFt2_6H&*~$tl4q9n+EgbQ)uE1tE-kn_+Uu7SercjZ^Di%%&-~uBFFiN1j(wDo&o+ zOc-iz|4y%5Oj$67mI{V&IJZAeN`WCcWjRd6xpBSd8WjsvpkG(RfTgEEDVK6BaBkzR zJgNPeQUjx*iwZp=o91DF_F5>rmNuo5TQTO4NtD<@q?amy$Rh;z5tSpdYe2wHo${OC zW$w4K2-$MFU68@>-~G zL2)l&|K0ct=1--?M=S(i#81|x8x)PKzB-icL2C`G3b^ne>Cc(~JcSm2lXW^sV(L?k zJz~2!8>~t$IH?M}i0uvfaH9t{f=rrH#U@gp>)iM%L2S{lbiy`NIZ9O@(7S~%3fA4} z5ccd~xW_xqyrJX{4Gj{+$Qdp~-d#YG zn55?#d?gnjV#cXahk75w{lXeVDFr|7aNIjot|Z(q~&#D6v`bv82$65`T@X?-B# z*w`JPTuL>A?Ta&@8PPFfge3?{?0_1Lwh}uU<~#^`19mh-$p6*&X+U*hvoE7`PS$y( zgGoV>sO)DmR3<9n!{3#JsR&jpEJ?t(r<##UC!WFyG(gZrG!+cyVFBSI74FbYUCod> zG)IwIG=FBwV4O6y98lgFcY%(Z@M1~JrZVX6KB_zEqLn@t54!uI)|-(IFsasvnmF_o zpRmb*R}!F7a6&V1-=Vw@!Bk`rv^eUo|74@cpi9z|r~RL71XsOu?Z$3&28tf2gLQ=P z<6dX4`scOs=Gv|PTBPC8bZ;$Q=d-PU>1A@B#=UlJYi2l?-LgGFmmK5*OIHJoa(d~U z?c5XR`E%H4ab@L!s~@zsb5h@%Ov_OWEp1uWNsAK7Q+8qZPpV{}v}v zWojWU$g4q}^@C#LS{ojKWy0En_P8&GYG%_oWT>CnjuJm0&M|;0F60mTnJwJ?K6eXt zc&)|2{MtEZF79yb>L;SfdT$MtXJKg{6xOSYu!;f1zQOW*i5~7Mtb&g>RI_VB8RB3b z-CE0L%W>ly;bdQ=*H9fV!7jPx(0fc$RXU_QQFiEA*!6)5$D08gCE|E0IlXqob-Fsr)cRGDp-22@mP1l-;{hE~^bAQf$`G&u` z_fo*@2DyqR`VZqA$qYbmreYd7<1jTn9A>HNz2TCxvi~Om<#-Xw@s4^ED~)G5vbQca_vg9wv+lj5 z%U6rIe2&UoY=;{)-e4u)1IlcP^x<&%_h&%a8S@+T8TaL%j{&8sM8 zfPDQnen?X<8vPQ~0%dk$`f#}X{OzDzg4&M(<+IgL7TOFvuG(;&@ehv6yMGc;?yZKh z;P4y8&sKt*Ay-i}xU3Di=GyiAQ0N&|xlp;x4qfW_)t^cmk$Ta6rXkDEtm@_2s_90N z7IqwzSsJ%ZdB6U*9kOF|@0VYGaZX&;V^fi$qpzO}TwYDtqo&112{?HehVp7{#WLqw zjxt1rngk7n5xY_K+a2$I_n7o{v*~K3+=`hO{_TeOa4dMzE<6lu8*v}Oz$ITtYTjvB z&5S-=G?R@>ZloY0sy*pG6sb?&1xow>*9I1pC>;^Z z5|(ybHElWW-a3O5bp)C2s~Bme)Cqd}z(mw`(vrby)*?k@1hy&}eoGj&Z8y3W%g93; zBKx_DNmd5xQv5^~gR6=gz?>M>+V#7x%ONO=&qSZ383DG>UmB#$)}bujGU?`EM z2l6+_o*=NeGvcW^&msiAwN+nj*RNS8q|k{XTVWo8fItFlae!000IWAJ`1#bmUSgV+ zd-{(K7r2mCuOT27pAy%rN&< ze)`=>D;}R7;8|i0muS;UpJp!3Iae%G7qxkaWRM$!3TH$$yZ(m85-6STq9`b#=r2P= zHZsCULWS4X@FX$}iz>_|dH&WQYh1q(QqnOM3sMdtdsI(dP&W9dL(aX{XD%%)=|4&t zVb|kKiXUc>3D6a%F}TxGs#X{U&fy7I&t^8#5$m}Z6yttA#iyWrprwAKko`bc?=CIbL_PKcE(y zjjRm4H#;D?md)|@_&vXJSIXuj!>D5UdK5Yxz!$XH(iLc`K#}758@bD2j&_;S^U3xiRmuTqnb!ax30|Vpsn`H)n?1sEd|X6)!vei(*d*oxw4_A# zmM)KE+!F2K>I3`Zi6e)ikQ`Y(ZrOu2OUGBRa;4`&XNpPa9O)5OrzqaiQAQiJyit9- zXN@7U*ZWf0#j(}3#SSADXbT{c?-3D^0Z2fiqd@u>VW1T5Ee(!DNoIw5x?nO!8}z^8 z><}h2M-{!W`^qtf3sVL2rE}<*73b-t;-+xaRDp>nXzJ4uH_X7=F;p%!B&)i!SxX4f zQ{Hl=|5s^?^T+~Ri~KUj5u>beIEf*7oyTlENY;^5vekO&Z_4Z7|!A1`E&bS z!N_a0Zkot`9w3mXG2>xfYNwmi-JeR}zH<1O_GanN5B&!beUavtFUeNP6szszMq|40G!!sl1G;RoC`B8l67uji{gpS4%6R% z*yyFkBe@QnOMzSs`>K;rPtBPRtad#GMUoiN58N-uJ5d%=G@A`l9)7os9}{-NO^5rX zRP%#5a1+g0*1!uaKmw2pd-_GX_2{>Epc&~v2<3K%e@x8OU5&-gEiZ2nsR|yr|AA?} zKDQe7Ro^tPCauKOHB8Cr?(x*BF+K{PDP5IoU-}BU`AkFasMyLqjQ@zp^aIVL|EGCR zpCg;j`1zs#?W>uyv-td~F+L7v$o9gz&^5Pj;DZCd2{RICU?x2f&3pX%abS1l!lj@C zSmuj%S9}@?D?b*sJv92&cwhBRUE>eISD=qoavcDc|9l+GMBzboTiWOU|3rzk%D*dS zrrfT%KAosrt(8iv#)6t%O<&0D8qP)U;sj#Pftk?K+pf+(I%X86xv@_x&JHKB%vpNh zzh$*;_V|LCG)m87=1ie{<^yL*?djlnOl{u%W-mJ+TG-X@SxV>6u~%8p^BX_Fo~G*V zHGh5{E|#Zhxe^-y=aVa_TYI;9&)6RV0>|LFVlz>2q zhu_^h;6d^oRwMYV_ z`M3VCt4>x%QJ=?3S(Gue@z<9&{^rug^=lDjqW6WFMC*4gW2|HAsGRw;>X8pk@2z7* znx_+rYg(QKcE-)2!RsCqEmR{Khjj}(GFerp#GUz0*w9xRA{E|EVmOIgih@%(yB(Go z3`$)$8Bl9jcGxgfnM2k}9#^${8AfPsDjz2X{jhNSoR91(N&BEiDYZ7r+%gjP`#9~x z9>e3*H+(i4QmuL9cy_1#;~OF1kw9ga$A|#(1pfL!)hzKg$aazWdU8D0n^_uoY{h>t zBr!%ep5HF?Xi3wDtSqjutAoe+8)WZt0t)vCgZaH}$>uAvBp%b}o0XR>pdT&P9W)Qt zjp4Fltk{gy?g^urSb%U5X{3?KVih`fl!0w(!kiY0Ozth-A%Yq~7shaJv<4yjhXl?7 zU1_>TsSc8l6*J6s$j7i^Ec;HDT8HUD`8CH!Wy)0#t^pl4!tT-f3A+>6D2~d6)tO7K z@*WvYQVrYU~FPWkq>l!I=;Xu2h%hHGyY-A4nSabcC3 zmQ$C-w`m%SQ#!fKJY3mW3|9EBJ}5S>{=j%($~thk{E3xWu)+#usKU+ z*TR@Ia~+iNp%dO6kSu2>7JpbhJWB^C2Gt+rGD}{YRy=KPY#LHZKR(!(cWa zVzeg3hIqtG>GbhpwPTTNsy96Dy<NgQ{sNtF3$3drYVH8rRPgaw;St6N9jPmk>cINuBIY$hbvMuZn&ZHgIYkhxO9)jXuDDEy!3~ch`}_YY0q+F#0^Y?joJ$ih+sI8#NbBdbO5?PvI}0?-0w zAk~iJE`MVV&^#-d^!#*8C@r@366_0G&o-E)CV+`Isy3FLuU0QvxpZP!2x0=?xIt~! zAa;@msr0VAchuh-9jR$wNS(l(&hcgijV+U+Dlh^3hTbGA9qD)i_NN1g@5#yd2|H@83Q5HJ<#_7TXyNMgbfm&Wk1`*JOHjdZ0ms)FM6*Hbrj@1#Ldx z*o#9UL*3lGlL&G}I=$oa1F$AlTfeori9Q2i zN?gfn34oE-uek`@5{z1KsWZST<=8zWm0QAMY`>h!@30Q;i8!c_BqQh-s+V#|4?>N$ z@a83Ne1l%UHMjwF?V@PF3do+3=t`u=kSeA%EV)xcp(fisrG^8iKb*PC+f?kkm$r6S z8n>ctsGU$Gag41?MU?Eqr79-HxLPa8SD<9jJNfUQeDaB1op|7<|MRat`DB%QcysB` zg?kuoeBmC}xr(0)_i(|){C_Xp!}Ay^f6GGTi%F@raN!c78m4}+a~nz?Wf zcc zxQ8#?!#gB@$(K3fV83t=6O>2;2sxK7+{41cg?qTyyKoOHK|(9LYUTRMp9IqO$gP?Bga|Rn_O44B*~UxAEeKWTg{~cY3}-9rS27xkGR% z!c5TY32{tf9H&pz2(5qX)@KA<$>sh-f9>j8`ItX0w}1R=`6Kew0{}wx2&~(nbj2y* zT@lfSU;g#}=zwN#a?eN9VB{~Wm;;F~R7BtDl@KR5`6C`H!(G;J#|O(sYu@exqzH_O zS^;z8{Hw;H(imCSz5;7`@sVxeC7mJscu|1U>n$kgV}O{ePlUZNv7q zA+ch#Of&m!(|6!V8+i@oI|Dz+XvlG~pDZSMC}PA%GR5*0Dsrt{0!)Q|sO! zP7nKJdUAMT0$uapYpUr*{Q&RR+O0M6gNOokoXM`F}5AAY;Y*%V$d@fCBh9o@6XG&H19LTGcxPx7zMy;tQGwzw0ZHSV#TOH z;Kc%fE8*~^2aK3a<6vfKMB&q@g!XJbkfG z^GglP&bpq2eh-AOz}}t;&O9CNywG{kra1(OM>@18F`GuF|M5RMVg~*e0V`-3^VCRX z7u>H@frMLwo5@c&5OZTx@&=lhlOcFFD22KeDMdZ#G2rUWUI{TSJb{2MMQ*}YUeTy? zctl+e+6<_@7}2LL^sxCm-cz(&p1(W!@NeSbsp^oKmf;fPmkM`P{SQw3$>cR`W-x$! zeBSd9YANs}UvVl`1?1QzI#hDP)u`xcHaw;oi%zMlhd7|{h<2TdKZg9k1cytDX^$g+ zuEmFr!`@iC()@X8vpae9Wj`lj)9qXT+qL0zjVNUzrcZoCwW|#(gWMLjKp!|zc1?q> zMd0TMi8GvLR*V4MOmc_}@n$4s z*!YDnMO1zwDwli~W3;ab%K3KcixeF}dvV{^awBZn+0ur(nUl##A&Dx=Afi;Wx=$Cn zTN!S@uvtw&WrQ<_ESnoz6PFYd=#G3EC{$yK|0w2EqRf!0!^#XUn-VoK3S~zkL{|sp zG{k2aBKqD?nJB{hwBfNL$vShGFvk)87&ufgBV0Fo6*2S)Rn)|M^=ipPo*i9*g8_*a zkYp7MEed2&6U)_>;Qz<{Pl-F^AhY#Zt}31s(IubftIVfZK@}ZcEfR$Z!o7k!Ex_^2 zxdKVh!U`BiHT$G#Db(>wkb)yCwH^wr?2OEb70lfw6BV_@EM<0cvQUjXEqMrQHQS}- zX7{GU!wES?F)FwFpp(QKl&s?e-gjvh2JH#uMXib0Pi;tAjZDItujc&Ef>oMz>VQ~Y z#~G*tO3L!~gwS)fCaU$k+Tne=q_8Z1SEY5NstBQy(;Z*aCQ3pEeFq&CZVx*US5E@! z*ikFRAO~RMoSOo@e_BVPNBl$yWl$+;98rsnCqdUN#&|iFsH3)U<~xcKf7v@4lT9(d z4u{*rbu|oW3WA2`R2&WQ7vaVwNcV-(Ulc0MxB`aL1jNctQPZK{iJiOSnc&Ee z0z|rNp*qp^-TH<1f_Jh}Y*#D~ISdC9!-6ap zk`HN&MSwdrtNR9HWx2xqm^HwVYV^Fy1uo41pxRoS0Zr z+AAp-vBa|BeksMp(=nAgIWbyseXm-A2fc4pk{3z8y}bko=_X|gWh0fw^Gq~7eMWUf zYj;p|B)0fKHjlwwYeVS8xuGA965W}l>Qdg%C%(+4)9l(~OMn(~LM~gL79kH?;k}y_ z5H*VmY)UN|a}_ASvl3%mEiQlcy1y2KuE7$KfPn3t2Ld_5$&`ZTXlx)p*KSM^kKws2!oak&sM$jIm^>l6AK{4TmioqgQSkLFxET}l1 z_}uIq5MkWrVOc$|Dmhe;3J&D(x?gGt&n(hb4=a;-R6+M$)Ebhf4l;wu$Zs}o#7zs^ zD%9t-q$1zn{0CVg8zU1HD)OGqn2SPrYxV9)VOcGfD>hUC^$jA~7kBBR&rVe`;K>u6 zUix!Rl+#(IqqQST16XkgZgZ#{IHYVUx7|=VP{$FcD+Ke_&6^g?51ky=|H3Jjh$U-s zDV1eU9Ftn+`>9G+LM`1Q>rrmDU{16Hc^nQ9&6rgu*z(kO#)x>dV3gqB?+^Q*AEBVC z66>2`5xatbFn5r3?NeDn0!={!B*yztBGvT-}*&@Y^TdKhwYD&%xs__n$sKe!V;1d9ph^89t6j2gk3S aQTB_d7W+#Ku%Ar-oqu|N_TTprevline dance. + thisline = EMPTYSTRING.join(outline) + while len(thisline) > MAXLINESIZE: + # Don't forget to include the soft line break `=' sign in the + # length calculation! + write(thisline[:MAXLINESIZE-1], lineEnd='=\n') + thisline = thisline[MAXLINESIZE-1:] + # Write out the current line + prevline = thisline + # Write out the last line, without a trailing newline + if prevline is not None: + write(prevline, lineEnd=stripped) + +def encodestring(s, quotetabs = 0, header = 0): + if b2a_qp is not None: + return b2a_qp(s, quotetabs = quotetabs, header = header) + from cStringIO import StringIO + infp = StringIO(s) + outfp = StringIO() + encode(infp, outfp, quotetabs, header) + return outfp.getvalue() + + + +def decode(input, output, header = 0): + """Read 'input', apply quoted-printable decoding, and write to 'output'. + 'input' and 'output' are files with readline() and write() methods. + If 'header' is true, decode underscore as space (per RFC 1522).""" + + if a2b_qp is not None: + data = input.read() + odata = a2b_qp(data, header = header) + output.write(odata) + return + + new = '' + while 1: + line = input.readline() + if not line: break + i, n = 0, len(line) + if n > 0 and line[n-1] == '\n': + partial = 0; n = n-1 + # Strip trailing whitespace + while n > 0 and line[n-1] in " \t\r": + n = n-1 + else: + partial = 1 + while i < n: + c = line[i] + if c == '_' and header: + new = new + ' '; i = i+1 + elif c != ESCAPE: + new = new + c; i = i+1 + elif i+1 == n and not partial: + partial = 1; break + elif i+1 < n and line[i+1] == ESCAPE: + new = new + ESCAPE; i = i+2 + elif i+2 < n and ishex(line[i+1]) and ishex(line[i+2]): + new = new + chr(unhex(line[i+1:i+3])); i = i+3 + else: # Bad escape sequence -- leave it in + new = new + c; i = i+1 + if not partial: + output.write(new + '\n') + new = '' + if new: + output.write(new) + +def decodestring(s, header = 0): + if a2b_qp is not None: + return a2b_qp(s, header = header) + from cStringIO import StringIO + infp = StringIO(s) + outfp = StringIO() + decode(infp, outfp, header = header) + return outfp.getvalue() + + + +# Other helper functions +def ishex(c): + """Return true if the character 'c' is a hexadecimal digit.""" + return '0' <= c <= '9' or 'a' <= c <= 'f' or 'A' <= c <= 'F' + +def unhex(s): + """Get the integer value of a hexadecimal number.""" + bits = 0 + for c in s: + if '0' <= c <= '9': + i = ord('0') + elif 'a' <= c <= 'f': + i = ord('a')-10 + elif 'A' <= c <= 'F': + i = ord('A')-10 + else: + break + bits = bits*16 + (ord(c) - i) + return bits + + + +def main(): + import sys + import getopt + try: + opts, args = getopt.getopt(sys.argv[1:], 'td') + except getopt.error, msg: + sys.stdout = sys.stderr + print msg + print "usage: quopri [-t | -d] [file] ..." + print "-t: quote tabs" + print "-d: decode; default encode" + sys.exit(2) + deco = 0 + tabs = 0 + for o, a in opts: + if o == '-t': tabs = 1 + if o == '-d': deco = 1 + if tabs and deco: + sys.stdout = sys.stderr + print "-t and -d are mutually exclusive" + sys.exit(2) + if not args: args = ['-'] + sts = 0 + for file in args: + if file == '-': + fp = sys.stdin + else: + try: + fp = open(file) + except IOError, msg: + sys.stderr.write("%s: can't open (%s)\n" % (file, msg)) + sts = 1 + continue + if deco: + decode(fp, sys.stdout) + else: + encode(fp, sys.stdout, tabs) + if fp is not sys.stdin: + fp.close() + if sts: + sys.exit(sts) + + + +if __name__ == '__main__': + main() diff --git a/PythonHome/Lib/quopri.pyc b/PythonHome/Lib/quopri.pyc index 8d0f48c9746552c9e602699e36814d373a0658bf..a76d56faad4a7163078548c37be6aab2d675fa95 100644 GIT binary patch delta 646 zcmexr^xAa8Ek;I`&9@onF&bJkFfgQA#iVDJWRxbwgy&c2c?J9X1qC?A_?MOxl$OM} zq$ZW7#{^WCWaQ_0&9@onG4e|?Ffce<#ROEAWaQ@=nNMEDd=_17^9q(8W=7V@rW|)L zq?|Y%G0fP!g)0q1aI!a#F(dotdLC{T3`2GccwnkG5i(|Eo}3|sVdvyhVRc59&2xnl bFg59kS~Ie3&Jtb4jA4nZq&lYhxl(=rs5wdV diff --git a/PythonHome/Lib/random.py b/PythonHome/Lib/random.py new file mode 100644 index 0000000000..3f96a3770b --- /dev/null +++ b/PythonHome/Lib/random.py @@ -0,0 +1,910 @@ +"""Random variable generators. + + integers + -------- + uniform within range + + sequences + --------- + pick random element + pick random sample + generate random permutation + + distributions on the real line: + ------------------------------ + uniform + triangular + normal (Gaussian) + lognormal + negative exponential + gamma + beta + pareto + Weibull + + distributions on the circle (angles 0 to 2pi) + --------------------------------------------- + circular uniform + von Mises + +General notes on the underlying Mersenne Twister core generator: + +* The period is 2**19937-1. +* It is one of the most extensively tested generators in existence. +* Without a direct way to compute N steps forward, the semantics of + jumpahead(n) are weakened to simply jump to another distant state and rely + on the large period to avoid overlapping sequences. +* The random() method is implemented in C, executes in a single Python step, + and is, therefore, threadsafe. + +""" + +from __future__ import division +from warnings import warn as _warn +from types import MethodType as _MethodType, BuiltinMethodType as _BuiltinMethodType +from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil +from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin +from os import urandom as _urandom +from binascii import hexlify as _hexlify +import hashlib as _hashlib + +__all__ = ["Random","seed","random","uniform","randint","choice","sample", + "randrange","shuffle","normalvariate","lognormvariate", + "expovariate","vonmisesvariate","gammavariate","triangular", + "gauss","betavariate","paretovariate","weibullvariate", + "getstate","setstate","jumpahead", "WichmannHill", "getrandbits", + "SystemRandom"] + +NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0) +TWOPI = 2.0*_pi +LOG4 = _log(4.0) +SG_MAGICCONST = 1.0 + _log(4.5) +BPF = 53 # Number of bits in a float +RECIP_BPF = 2**-BPF + + +# Translated by Guido van Rossum from C source provided by +# Adrian Baddeley. Adapted by Raymond Hettinger for use with +# the Mersenne Twister and os.urandom() core generators. + +import _random + +class Random(_random.Random): + """Random number generator base class used by bound module functions. + + Used to instantiate instances of Random to get generators that don't + share state. Especially useful for multi-threaded programs, creating + a different instance of Random for each thread, and using the jumpahead() + method to ensure that the generated sequences seen by each thread don't + overlap. + + Class Random can also be subclassed if you want to use a different basic + generator of your own devising: in that case, override the following + methods: random(), seed(), getstate(), setstate() and jumpahead(). + Optionally, implement a getrandbits() method so that randrange() can cover + arbitrarily large ranges. + + """ + + VERSION = 3 # used by getstate/setstate + + def __init__(self, x=None): + """Initialize an instance. + + Optional argument x controls seeding, as for Random.seed(). + """ + + self.seed(x) + self.gauss_next = None + + def seed(self, a=None): + """Initialize internal state from hashable object. + + None or no argument seeds from current time or from an operating + system specific randomness source if available. + + If a is not None or an int or long, hash(a) is used instead. + """ + + if a is None: + try: + # Seed with enough bytes to span the 19937 bit + # state space for the Mersenne Twister + a = long(_hexlify(_urandom(2500)), 16) + except NotImplementedError: + import time + a = long(time.time() * 256) # use fractional seconds + + super(Random, self).seed(a) + self.gauss_next = None + + def getstate(self): + """Return internal state; can be passed to setstate() later.""" + return self.VERSION, super(Random, self).getstate(), self.gauss_next + + def setstate(self, state): + """Restore internal state from object returned by getstate().""" + version = state[0] + if version == 3: + version, internalstate, self.gauss_next = state + super(Random, self).setstate(internalstate) + elif version == 2: + version, internalstate, self.gauss_next = state + # In version 2, the state was saved as signed ints, which causes + # inconsistencies between 32/64-bit systems. The state is + # really unsigned 32-bit ints, so we convert negative ints from + # version 2 to positive longs for version 3. + try: + internalstate = tuple( long(x) % (2**32) for x in internalstate ) + except ValueError, e: + raise TypeError, e + super(Random, self).setstate(internalstate) + else: + raise ValueError("state with version %s passed to " + "Random.setstate() of version %s" % + (version, self.VERSION)) + + def jumpahead(self, n): + """Change the internal state to one that is likely far away + from the current state. This method will not be in Py3.x, + so it is better to simply reseed. + """ + # The super.jumpahead() method uses shuffling to change state, + # so it needs a large and "interesting" n to work with. Here, + # we use hashing to create a large n for the shuffle. + s = repr(n) + repr(self.getstate()) + n = int(_hashlib.new('sha512', s).hexdigest(), 16) + super(Random, self).jumpahead(n) + +## ---- Methods below this point do not need to be overridden when +## ---- subclassing for the purpose of using a different core generator. + +## -------------------- pickle support ------------------- + + def __getstate__(self): # for pickle + return self.getstate() + + def __setstate__(self, state): # for pickle + self.setstate(state) + + def __reduce__(self): + return self.__class__, (), self.getstate() + +## -------------------- integer methods ------------------- + + def randrange(self, start, stop=None, step=1, _int=int, _maxwidth=1L< 0: + if istart >= _maxwidth: + return self._randbelow(istart) + return _int(self.random() * istart) + raise ValueError, "empty range for randrange()" + + # stop argument supplied. + istop = _int(stop) + if istop != stop: + raise ValueError, "non-integer stop for randrange()" + width = istop - istart + if step == 1 and width > 0: + # Note that + # int(istart + self.random()*width) + # instead would be incorrect. For example, consider istart + # = -2 and istop = 0. Then the guts would be in + # -2.0 to 0.0 exclusive on both ends (ignoring that random() + # might return 0.0), and because int() truncates toward 0, the + # final result would be -1 or 0 (instead of -2 or -1). + # istart + int(self.random()*width) + # would also be incorrect, for a subtler reason: the RHS + # can return a long, and then randrange() would also return + # a long, but we're supposed to return an int (for backward + # compatibility). + + if width >= _maxwidth: + return _int(istart + self._randbelow(width)) + return _int(istart + _int(self.random()*width)) + if step == 1: + raise ValueError, "empty range for randrange() (%d,%d, %d)" % (istart, istop, width) + + # Non-unit step argument supplied. + istep = _int(step) + if istep != step: + raise ValueError, "non-integer step for randrange()" + if istep > 0: + n = (width + istep - 1) // istep + elif istep < 0: + n = (width + istep + 1) // istep + else: + raise ValueError, "zero step for randrange()" + + if n <= 0: + raise ValueError, "empty range for randrange()" + + if n >= _maxwidth: + return istart + istep*self._randbelow(n) + return istart + istep*_int(self.random() * n) + + def randint(self, a, b): + """Return random integer in range [a, b], including both end points. + """ + + return self.randrange(a, b+1) + + def _randbelow(self, n, _log=_log, _int=int, _maxwidth=1L< n-1 > 2**(k-2) + r = getrandbits(k) + while r >= n: + r = getrandbits(k) + return r + if n >= _maxwidth: + _warn("Underlying random() generator does not supply \n" + "enough bits to choose from a population range this large") + return _int(self.random() * n) + +## -------------------- sequence methods ------------------- + + def choice(self, seq): + """Choose a random element from a non-empty sequence.""" + return seq[int(self.random() * len(seq))] # raises IndexError if seq is empty + + def shuffle(self, x, random=None): + """x, random=random.random -> shuffle list x in place; return None. + + Optional arg random is a 0-argument function returning a random + float in [0.0, 1.0); by default, the standard random.random. + + """ + + if random is None: + random = self.random + _int = int + for i in reversed(xrange(1, len(x))): + # pick an element in x[:i+1] with which to exchange x[i] + j = _int(random() * (i+1)) + x[i], x[j] = x[j], x[i] + + def sample(self, population, k): + """Chooses k unique random elements from a population sequence. + + Returns a new list containing elements from the population while + leaving the original population unchanged. The resulting list is + in selection order so that all sub-slices will also be valid random + samples. This allows raffle winners (the sample) to be partitioned + into grand prize and second place winners (the subslices). + + Members of the population need not be hashable or unique. If the + population contains repeats, then each occurrence is a possible + selection in the sample. + + To choose a sample in a range of integers, use xrange as an argument. + This is especially fast and space efficient for sampling from a + large population: sample(xrange(10000000), 60) + """ + + # Sampling without replacement entails tracking either potential + # selections (the pool) in a list or previous selections in a set. + + # When the number of selections is small compared to the + # population, then tracking selections is efficient, requiring + # only a small set and an occasional reselection. For + # a larger number of selections, the pool tracking method is + # preferred since the list takes less space than the + # set and it doesn't suffer from frequent reselections. + + n = len(population) + if not 0 <= k <= n: + raise ValueError("sample larger than population") + random = self.random + _int = int + result = [None] * k + setsize = 21 # size of a small set minus size of an empty list + if k > 5: + setsize += 4 ** _ceil(_log(k * 3, 4)) # table size for big sets + if n <= setsize or hasattr(population, "keys"): + # An n-length list is smaller than a k-length set, or this is a + # mapping type so the other algorithm wouldn't work. + pool = list(population) + for i in xrange(k): # invariant: non-selected at [0,n-i) + j = _int(random() * (n-i)) + result[i] = pool[j] + pool[j] = pool[n-i-1] # move non-selected item into vacancy + else: + try: + selected = set() + selected_add = selected.add + for i in xrange(k): + j = _int(random() * n) + while j in selected: + j = _int(random() * n) + selected_add(j) + result[i] = population[j] + except (TypeError, KeyError): # handle (at least) sets + if isinstance(population, list): + raise + return self.sample(tuple(population), k) + return result + +## -------------------- real-valued distributions ------------------- + +## -------------------- uniform distribution ------------------- + + def uniform(self, a, b): + "Get a random number in the range [a, b) or [a, b] depending on rounding." + return a + (b-a) * self.random() + +## -------------------- triangular -------------------- + + def triangular(self, low=0.0, high=1.0, mode=None): + """Triangular distribution. + + Continuous distribution bounded by given lower and upper limits, + and having a given mode value in-between. + + http://en.wikipedia.org/wiki/Triangular_distribution + + """ + u = self.random() + try: + c = 0.5 if mode is None else (mode - low) / (high - low) + except ZeroDivisionError: + return low + if u > c: + u = 1.0 - u + c = 1.0 - c + low, high = high, low + return low + (high - low) * (u * c) ** 0.5 + +## -------------------- normal distribution -------------------- + + def normalvariate(self, mu, sigma): + """Normal distribution. + + mu is the mean, and sigma is the standard deviation. + + """ + # mu = mean, sigma = standard deviation + + # Uses Kinderman and Monahan method. Reference: Kinderman, + # A.J. and Monahan, J.F., "Computer generation of random + # variables using the ratio of uniform deviates", ACM Trans + # Math Software, 3, (1977), pp257-260. + + random = self.random + while 1: + u1 = random() + u2 = 1.0 - random() + z = NV_MAGICCONST*(u1-0.5)/u2 + zz = z*z/4.0 + if zz <= -_log(u2): + break + return mu + z*sigma + +## -------------------- lognormal distribution -------------------- + + def lognormvariate(self, mu, sigma): + """Log normal distribution. + + If you take the natural logarithm of this distribution, you'll get a + normal distribution with mean mu and standard deviation sigma. + mu can have any value, and sigma must be greater than zero. + + """ + return _exp(self.normalvariate(mu, sigma)) + +## -------------------- exponential distribution -------------------- + + def expovariate(self, lambd): + """Exponential distribution. + + lambd is 1.0 divided by the desired mean. It should be + nonzero. (The parameter would be called "lambda", but that is + a reserved word in Python.) Returned values range from 0 to + positive infinity if lambd is positive, and from negative + infinity to 0 if lambd is negative. + + """ + # lambd: rate lambd = 1/mean + # ('lambda' is a Python reserved word) + + # we use 1-random() instead of random() to preclude the + # possibility of taking the log of zero. + return -_log(1.0 - self.random())/lambd + +## -------------------- von Mises distribution -------------------- + + def vonmisesvariate(self, mu, kappa): + """Circular data distribution. + + mu is the mean angle, expressed in radians between 0 and 2*pi, and + kappa is the concentration parameter, which must be greater than or + equal to zero. If kappa is equal to zero, this distribution reduces + to a uniform random angle over the range 0 to 2*pi. + + """ + # mu: mean angle (in radians between 0 and 2*pi) + # kappa: concentration parameter kappa (>= 0) + # if kappa = 0 generate uniform random angle + + # Based upon an algorithm published in: Fisher, N.I., + # "Statistical Analysis of Circular Data", Cambridge + # University Press, 1993. + + # Thanks to Magnus Kessler for a correction to the + # implementation of step 4. + + random = self.random + if kappa <= 1e-6: + return TWOPI * random() + + s = 0.5 / kappa + r = s + _sqrt(1.0 + s * s) + + while 1: + u1 = random() + z = _cos(_pi * u1) + + d = z / (r + z) + u2 = random() + if u2 < 1.0 - d * d or u2 <= (1.0 - d) * _exp(d): + break + + q = 1.0 / r + f = (q + z) / (1.0 + q * z) + u3 = random() + if u3 > 0.5: + theta = (mu + _acos(f)) % TWOPI + else: + theta = (mu - _acos(f)) % TWOPI + + return theta + +## -------------------- gamma distribution -------------------- + + def gammavariate(self, alpha, beta): + """Gamma distribution. Not the gamma function! + + Conditions on the parameters are alpha > 0 and beta > 0. + + The probability distribution function is: + + x ** (alpha - 1) * math.exp(-x / beta) + pdf(x) = -------------------------------------- + math.gamma(alpha) * beta ** alpha + + """ + + # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2 + + # Warning: a few older sources define the gamma distribution in terms + # of alpha > -1.0 + if alpha <= 0.0 or beta <= 0.0: + raise ValueError, 'gammavariate: alpha and beta must be > 0.0' + + random = self.random + if alpha > 1.0: + + # Uses R.C.H. Cheng, "The generation of Gamma + # variables with non-integral shape parameters", + # Applied Statistics, (1977), 26, No. 1, p71-74 + + ainv = _sqrt(2.0 * alpha - 1.0) + bbb = alpha - LOG4 + ccc = alpha + ainv + + while 1: + u1 = random() + if not 1e-7 < u1 < .9999999: + continue + u2 = 1.0 - random() + v = _log(u1/(1.0-u1))/ainv + x = alpha*_exp(v) + z = u1*u1*u2 + r = bbb+ccc*v-x + if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z): + return x * beta + + elif alpha == 1.0: + # expovariate(1) + u = random() + while u <= 1e-7: + u = random() + return -_log(u) * beta + + else: # alpha is between 0 and 1 (exclusive) + + # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle + + while 1: + u = random() + b = (_e + alpha)/_e + p = b*u + if p <= 1.0: + x = p ** (1.0/alpha) + else: + x = -_log((b-p)/alpha) + u1 = random() + if p > 1.0: + if u1 <= x ** (alpha - 1.0): + break + elif u1 <= _exp(-x): + break + return x * beta + +## -------------------- Gauss (faster alternative) -------------------- + + def gauss(self, mu, sigma): + """Gaussian distribution. + + mu is the mean, and sigma is the standard deviation. This is + slightly faster than the normalvariate() function. + + Not thread-safe without a lock around calls. + + """ + + # When x and y are two variables from [0, 1), uniformly + # distributed, then + # + # cos(2*pi*x)*sqrt(-2*log(1-y)) + # sin(2*pi*x)*sqrt(-2*log(1-y)) + # + # are two *independent* variables with normal distribution + # (mu = 0, sigma = 1). + # (Lambert Meertens) + # (corrected version; bug discovered by Mike Miller, fixed by LM) + + # Multithreading note: When two threads call this function + # simultaneously, it is possible that they will receive the + # same return value. The window is very small though. To + # avoid this, you have to use a lock around all calls. (I + # didn't want to slow this down in the serial case by using a + # lock here.) + + random = self.random + z = self.gauss_next + self.gauss_next = None + if z is None: + x2pi = random() * TWOPI + g2rad = _sqrt(-2.0 * _log(1.0 - random())) + z = _cos(x2pi) * g2rad + self.gauss_next = _sin(x2pi) * g2rad + + return mu + z*sigma + +## -------------------- beta -------------------- +## See +## http://mail.python.org/pipermail/python-bugs-list/2001-January/003752.html +## for Ivan Frohne's insightful analysis of why the original implementation: +## +## def betavariate(self, alpha, beta): +## # Discrete Event Simulation in C, pp 87-88. +## +## y = self.expovariate(alpha) +## z = self.expovariate(1.0/beta) +## return z/(y+z) +## +## was dead wrong, and how it probably got that way. + + def betavariate(self, alpha, beta): + """Beta distribution. + + Conditions on the parameters are alpha > 0 and beta > 0. + Returned values range between 0 and 1. + + """ + + # This version due to Janne Sinkkonen, and matches all the std + # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution"). + y = self.gammavariate(alpha, 1.) + if y == 0: + return 0.0 + else: + return y / (y + self.gammavariate(beta, 1.)) + +## -------------------- Pareto -------------------- + + def paretovariate(self, alpha): + """Pareto distribution. alpha is the shape parameter.""" + # Jain, pg. 495 + + u = 1.0 - self.random() + return 1.0 / pow(u, 1.0/alpha) + +## -------------------- Weibull -------------------- + + def weibullvariate(self, alpha, beta): + """Weibull distribution. + + alpha is the scale parameter and beta is the shape parameter. + + """ + # Jain, pg. 499; bug fix courtesy Bill Arms + + u = 1.0 - self.random() + return alpha * pow(-_log(u), 1.0/beta) + +## -------------------- Wichmann-Hill ------------------- + +class WichmannHill(Random): + + VERSION = 1 # used by getstate/setstate + + def seed(self, a=None): + """Initialize internal state from hashable object. + + None or no argument seeds from current time or from an operating + system specific randomness source if available. + + If a is not None or an int or long, hash(a) is used instead. + + If a is an int or long, a is used directly. Distinct values between + 0 and 27814431486575L inclusive are guaranteed to yield distinct + internal states (this guarantee is specific to the default + Wichmann-Hill generator). + """ + + if a is None: + try: + a = long(_hexlify(_urandom(16)), 16) + except NotImplementedError: + import time + a = long(time.time() * 256) # use fractional seconds + + if not isinstance(a, (int, long)): + a = hash(a) + + a, x = divmod(a, 30268) + a, y = divmod(a, 30306) + a, z = divmod(a, 30322) + self._seed = int(x)+1, int(y)+1, int(z)+1 + + self.gauss_next = None + + def random(self): + """Get the next random number in the range [0.0, 1.0).""" + + # Wichman-Hill random number generator. + # + # Wichmann, B. A. & Hill, I. D. (1982) + # Algorithm AS 183: + # An efficient and portable pseudo-random number generator + # Applied Statistics 31 (1982) 188-190 + # + # see also: + # Correction to Algorithm AS 183 + # Applied Statistics 33 (1984) 123 + # + # McLeod, A. I. (1985) + # A remark on Algorithm AS 183 + # Applied Statistics 34 (1985),198-200 + + # This part is thread-unsafe: + # BEGIN CRITICAL SECTION + x, y, z = self._seed + x = (171 * x) % 30269 + y = (172 * y) % 30307 + z = (170 * z) % 30323 + self._seed = x, y, z + # END CRITICAL SECTION + + # Note: on a platform using IEEE-754 double arithmetic, this can + # never return 0.0 (asserted by Tim; proof too long for a comment). + return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0 + + def getstate(self): + """Return internal state; can be passed to setstate() later.""" + return self.VERSION, self._seed, self.gauss_next + + def setstate(self, state): + """Restore internal state from object returned by getstate().""" + version = state[0] + if version == 1: + version, self._seed, self.gauss_next = state + else: + raise ValueError("state with version %s passed to " + "Random.setstate() of version %s" % + (version, self.VERSION)) + + def jumpahead(self, n): + """Act as if n calls to random() were made, but quickly. + + n is an int, greater than or equal to 0. + + Example use: If you have 2 threads and know that each will + consume no more than a million random numbers, create two Random + objects r1 and r2, then do + r2.setstate(r1.getstate()) + r2.jumpahead(1000000) + Then r1 and r2 will use guaranteed-disjoint segments of the full + period. + """ + + if not n >= 0: + raise ValueError("n must be >= 0") + x, y, z = self._seed + x = int(x * pow(171, n, 30269)) % 30269 + y = int(y * pow(172, n, 30307)) % 30307 + z = int(z * pow(170, n, 30323)) % 30323 + self._seed = x, y, z + + def __whseed(self, x=0, y=0, z=0): + """Set the Wichmann-Hill seed from (x, y, z). + + These must be integers in the range [0, 256). + """ + + if not type(x) == type(y) == type(z) == int: + raise TypeError('seeds must be integers') + if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256): + raise ValueError('seeds must be in range(0, 256)') + if 0 == x == y == z: + # Initialize from current time + import time + t = long(time.time() * 256) + t = int((t&0xffffff) ^ (t>>24)) + t, x = divmod(t, 256) + t, y = divmod(t, 256) + t, z = divmod(t, 256) + # Zero is a poor seed, so substitute 1 + self._seed = (x or 1, y or 1, z or 1) + + self.gauss_next = None + + def whseed(self, a=None): + """Seed from hashable object's hash code. + + None or no argument seeds from current time. It is not guaranteed + that objects with distinct hash codes lead to distinct internal + states. + + This is obsolete, provided for compatibility with the seed routine + used prior to Python 2.1. Use the .seed() method instead. + """ + + if a is None: + self.__whseed() + return + a = hash(a) + a, x = divmod(a, 256) + a, y = divmod(a, 256) + a, z = divmod(a, 256) + x = (x + a) % 256 or 1 + y = (y + a) % 256 or 1 + z = (z + a) % 256 or 1 + self.__whseed(x, y, z) + +## --------------- Operating System Random Source ------------------ + +class SystemRandom(Random): + """Alternate random number generator using sources provided + by the operating system (such as /dev/urandom on Unix or + CryptGenRandom on Windows). + + Not available on all systems (see os.urandom() for details). + """ + + def random(self): + """Get the next random number in the range [0.0, 1.0).""" + return (long(_hexlify(_urandom(7)), 16) >> 3) * RECIP_BPF + + def getrandbits(self, k): + """getrandbits(k) -> x. Generates a long int with k random bits.""" + if k <= 0: + raise ValueError('number of bits must be greater than zero') + if k != int(k): + raise TypeError('number of bits should be an integer') + bytes = (k + 7) // 8 # bits / 8 and rounded up + x = long(_hexlify(_urandom(bytes)), 16) + return x >> (bytes * 8 - k) # trim excess bits + + def _stub(self, *args, **kwds): + "Stub method. Not used for a system random number generator." + return None + seed = jumpahead = _stub + + def _notimplemented(self, *args, **kwds): + "Method should not be called for a system random number generator." + raise NotImplementedError('System entropy source does not have state.') + getstate = setstate = _notimplemented + +## -------------------- test program -------------------- + +def _test_generator(n, func, args): + import time + print n, 'times', func.__name__ + total = 0.0 + sqsum = 0.0 + smallest = 1e10 + largest = -1e10 + t0 = time.time() + for i in range(n): + x = func(*args) + total += x + sqsum = sqsum + x*x + smallest = min(x, smallest) + largest = max(x, largest) + t1 = time.time() + print round(t1-t0, 3), 'sec,', + avg = total/n + stddev = _sqrt(sqsum/n - avg*avg) + print 'avg %g, stddev %g, min %g, max %g' % \ + (avg, stddev, smallest, largest) + + +def _test(N=2000): + _test_generator(N, random, ()) + _test_generator(N, normalvariate, (0.0, 1.0)) + _test_generator(N, lognormvariate, (0.0, 1.0)) + _test_generator(N, vonmisesvariate, (0.0, 1.0)) + _test_generator(N, gammavariate, (0.01, 1.0)) + _test_generator(N, gammavariate, (0.1, 1.0)) + _test_generator(N, gammavariate, (0.1, 2.0)) + _test_generator(N, gammavariate, (0.5, 1.0)) + _test_generator(N, gammavariate, (0.9, 1.0)) + _test_generator(N, gammavariate, (1.0, 1.0)) + _test_generator(N, gammavariate, (2.0, 1.0)) + _test_generator(N, gammavariate, (20.0, 1.0)) + _test_generator(N, gammavariate, (200.0, 1.0)) + _test_generator(N, gauss, (0.0, 1.0)) + _test_generator(N, betavariate, (3.0, 3.0)) + _test_generator(N, triangular, (0.0, 1.0, 1.0/3.0)) + +# Create one instance, seeded from current time, and export its methods +# as module-level functions. The functions share state across all uses +#(both in the user's code and in the Python libraries), but that's fine +# for most programs and is easier for the casual user than making them +# instantiate their own Random() instance. + +_inst = Random() +seed = _inst.seed +random = _inst.random +uniform = _inst.uniform +triangular = _inst.triangular +randint = _inst.randint +choice = _inst.choice +randrange = _inst.randrange +sample = _inst.sample +shuffle = _inst.shuffle +normalvariate = _inst.normalvariate +lognormvariate = _inst.lognormvariate +expovariate = _inst.expovariate +vonmisesvariate = _inst.vonmisesvariate +gammavariate = _inst.gammavariate +gauss = _inst.gauss +betavariate = _inst.betavariate +paretovariate = _inst.paretovariate +weibullvariate = _inst.weibullvariate +getstate = _inst.getstate +setstate = _inst.setstate +jumpahead = _inst.jumpahead +getrandbits = _inst.getrandbits + +if __name__ == '__main__': + _test() diff --git a/PythonHome/Lib/random.pyc b/PythonHome/Lib/random.pyc index 9e61c7df180cd1a97b73338924861788c91d0c1e..874c2acb7699932061e13e070ccf1df97299f775 100644 GIT binary patch delta 2408 zcmeA?#<>3?GhE%JV^vsfs(xjO1{0cp@A)~md-vhbj3>8GO}%+En&$*y5`M~WjM(RncuSNKs%M?`pHQ!2NiCS;nG!# zKgn_FCS^lLj?GV$li5hOb8?v0U($7LPSQ3YBUm;s)SX6#2RFOvPb5d%GlMteXnSZB zz)X6OOm;By2Bw!Dv&rP7Q9bKKa>8?-Z2}oSoXl%~jdTxg{$wvqhGm;Y9OcN-=IAtu zoPd1fmQ03ilS4cXkP#xvo?c{Fwz293-KH@DIx?V?ClCEoWaa15V;c+>p Wkcd7E*SJm~L3(kbq(GWLu|e=mu|gaTdl< zxVghc4pZ>D>m*FeXL%)KsGO|la{%3*$%#V3n~i+UF%>t83U6NPCxq$c4}lgyFKY%J z!tfm^5l_|+H33SegigYgR*z^!w}1292u%!yo6Vz_VLFH}b`QGl$-iUYVu(q`SE7q; ZJ{%v2X^U%8A%^cZKTnm!Pzm%`9{|_4488yW diff --git a/PythonHome/Lib/re.py b/PythonHome/Lib/re.py new file mode 100644 index 0000000000..9b01f3e228 --- /dev/null +++ b/PythonHome/Lib/re.py @@ -0,0 +1,327 @@ +# +# Secret Labs' Regular Expression Engine +# +# re-compatible interface for the sre matching engine +# +# Copyright (c) 1998-2001 by Secret Labs AB. All rights reserved. +# +# This version of the SRE library can be redistributed under CNRI's +# Python 1.6 license. For any other use, please contact Secret Labs +# AB (info@pythonware.com). +# +# Portions of this engine have been developed in cooperation with +# CNRI. Hewlett-Packard provided funding for 1.6 integration and +# other compatibility work. +# + +r"""Support for regular expressions (RE). + +This module provides regular expression matching operations similar to +those found in Perl. It supports both 8-bit and Unicode strings; both +the pattern and the strings being processed can contain null bytes and +characters outside the US ASCII range. + +Regular expressions can contain both special and ordinary characters. +Most ordinary characters, like "A", "a", or "0", are the simplest +regular expressions; they simply match themselves. You can +concatenate ordinary characters, so last matches the string 'last'. + +The special characters are: + "." Matches any character except a newline. + "^" Matches the start of the string. + "$" Matches the end of the string or just before the newline at + the end of the string. + "*" Matches 0 or more (greedy) repetitions of the preceding RE. + Greedy means that it will match as many repetitions as possible. + "+" Matches 1 or more (greedy) repetitions of the preceding RE. + "?" Matches 0 or 1 (greedy) of the preceding RE. + *?,+?,?? Non-greedy versions of the previous three special characters. + {m,n} Matches from m to n repetitions of the preceding RE. + {m,n}? Non-greedy version of the above. + "\\" Either escapes special characters or signals a special sequence. + [] Indicates a set of characters. + A "^" as the first character indicates a complementing set. + "|" A|B, creates an RE that will match either A or B. + (...) Matches the RE inside the parentheses. + The contents can be retrieved or matched later in the string. + (?iLmsux) Set the I, L, M, S, U, or X flag for the RE (see below). + (?:...) Non-grouping version of regular parentheses. + (?P...) The substring matched by the group is accessible by name. + (?P=name) Matches the text matched earlier by the group named name. + (?#...) A comment; ignored. + (?=...) Matches if ... matches next, but doesn't consume the string. + (?!...) Matches if ... doesn't match next. + (?<=...) Matches if preceded by ... (must be fixed length). + (?= 0x02020000: + __all__.append("finditer") + def finditer(pattern, string, flags=0): + """Return an iterator over all non-overlapping matches in the + string. For each match, the iterator returns a match object. + + Empty matches are included in the result.""" + return _compile(pattern, flags).finditer(string) + +def compile(pattern, flags=0): + "Compile a regular expression pattern, returning a pattern object." + return _compile(pattern, flags) + +def purge(): + "Clear the regular expression cache" + _cache.clear() + _cache_repl.clear() + +def template(pattern, flags=0): + "Compile a template pattern, returning a pattern object" + return _compile(pattern, flags|T) + +_alphanum = frozenset( + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") + +def escape(pattern): + "Escape all non-alphanumeric characters in pattern." + s = list(pattern) + alphanum = _alphanum + for i, c in enumerate(pattern): + if c not in alphanum: + if c == "\000": + s[i] = "\\000" + else: + s[i] = "\\" + c + return pattern[:0].join(s) + +# -------------------------------------------------------------------- +# internals + +_cache = {} +_cache_repl = {} + +_pattern_type = type(sre_compile.compile("", 0)) + +_MAXCACHE = 100 + +def _compile(*key): + # internal: compile pattern + pattern, flags = key + bypass_cache = flags & DEBUG + if not bypass_cache: + cachekey = (type(key[0]),) + key + p = _cache.get(cachekey) + if p is not None: + return p + if isinstance(pattern, _pattern_type): + if flags: + raise ValueError('Cannot process flags argument with a compiled pattern') + return pattern + if not sre_compile.isstring(pattern): + raise TypeError, "first argument must be string or compiled pattern" + try: + p = sre_compile.compile(pattern, flags) + except error, v: + raise error, v # invalid expression + if not bypass_cache: + if len(_cache) >= _MAXCACHE: + _cache.clear() + _cache[cachekey] = p + return p + +def _compile_repl(*key): + # internal: compile replacement pattern + p = _cache_repl.get(key) + if p is not None: + return p + repl, pattern = key + try: + p = sre_parse.parse_template(repl, pattern) + except error, v: + raise error, v # invalid expression + if len(_cache_repl) >= _MAXCACHE: + _cache_repl.clear() + _cache_repl[key] = p + return p + +def _expand(pattern, match, template): + # internal: match.expand implementation hook + template = sre_parse.parse_template(template, pattern) + return sre_parse.expand_template(template, match) + +def _subx(pattern, template): + # internal: pattern.sub/subn implementation helper + template = _compile_repl(template, pattern) + if not template[0] and len(template[1]) == 1: + # literal replacement + return template[1][0] + def filter(match, template=template): + return sre_parse.expand_template(template, match) + return filter + +# register myself for pickling + +import copy_reg + +def _pickle(p): + return _compile, (p.pattern, p.flags) + +copy_reg.pickle(_pattern_type, _pickle, _compile) + +# -------------------------------------------------------------------- +# experimental stuff (see python-dev discussions for details) + +class Scanner: + def __init__(self, lexicon, flags=0): + from sre_constants import BRANCH, SUBPATTERN + self.lexicon = lexicon + # combine phrases into a compound pattern + p = [] + s = sre_parse.Pattern() + s.flags = flags + for phrase, action in lexicon: + p.append(sre_parse.SubPattern(s, [ + (SUBPATTERN, (len(p)+1, sre_parse.parse(phrase, flags))), + ])) + s.groups = len(p)+1 + p = sre_parse.SubPattern(s, [(BRANCH, (None, p))]) + self.scanner = sre_compile.compile(p) + def scan(self, string): + result = [] + append = result.append + match = self.scanner.scanner(string).match + i = 0 + while 1: + m = match() + if not m: + break + j = m.end() + if i == j: + break + action = self.lexicon[m.lastindex-1][1] + if hasattr(action, '__call__'): + self.match = m + action = action(self, m.group()) + if action is not None: + append(action) + i = j + return result, string[i:] diff --git a/PythonHome/Lib/re.pyc b/PythonHome/Lib/re.pyc index 631953dea1a74152abbcfdb2cf45459ea5ba024b..b2d643d31609c5da23a513fb43bc947c0ff939e3 100644 GIT binary patch delta 1158 zcmeyGx<7k^gt(zO0|SGrRZMzjNk(Z>On82Uo>#EHUr>N^jDKlKL1{^hOKMVSdQ3oN zNk)F2M}BVVWOeaRr0d$OA@Pxs9BopWOk`+VAj3qCZ5w6V$kFB|?@Wfa$uktzknXj~ z!HVn2&?Ts}mULa4&nhh=!(*G9R1T06X@TnTWY{)&zs6qDy*9a9Q-_gd@(xXM^tNdE pkzwOQttQfSZ7$MICnqdl=$;`bED!6~lHo>w19>vsIJwrS0suU8mEZsX delta 444 zcmdm={WW!iggCz_0|SGzRZKu-Nk)F2k@;j#@lWVtn{y;SGGYk!No6u&2x`bOVXBOl zYr_;2QgFr)oZP0k2HnWX$x7=n#GIAaqKj=-R9S{$;N~By2QVG^QX?Ki<>X4Oz34_x zPS@69WS%@l8&jr9#}7j_qiz$r*yb&|>6rHW7@Wbh-_xiTL-%(hc?{i?-AyY1e}8-M diff --git a/PythonHome/Lib/repr.py b/PythonHome/Lib/repr.py new file mode 100644 index 0000000000..3c26cc39a2 --- /dev/null +++ b/PythonHome/Lib/repr.py @@ -0,0 +1,132 @@ +"""Redo the builtin repr() (representation) but with limits on most sizes.""" + +__all__ = ["Repr","repr"] + +import __builtin__ +from itertools import islice + +class Repr: + + def __init__(self): + self.maxlevel = 6 + self.maxtuple = 6 + self.maxlist = 6 + self.maxarray = 5 + self.maxdict = 4 + self.maxset = 6 + self.maxfrozenset = 6 + self.maxdeque = 6 + self.maxstring = 30 + self.maxlong = 40 + self.maxother = 20 + + def repr(self, x): + return self.repr1(x, self.maxlevel) + + def repr1(self, x, level): + typename = type(x).__name__ + if ' ' in typename: + parts = typename.split() + typename = '_'.join(parts) + if hasattr(self, 'repr_' + typename): + return getattr(self, 'repr_' + typename)(x, level) + else: + s = __builtin__.repr(x) + if len(s) > self.maxother: + i = max(0, (self.maxother-3)//2) + j = max(0, self.maxother-3-i) + s = s[:i] + '...' + s[len(s)-j:] + return s + + def _repr_iterable(self, x, level, left, right, maxiter, trail=''): + n = len(x) + if level <= 0 and n: + s = '...' + else: + newlevel = level - 1 + repr1 = self.repr1 + pieces = [repr1(elem, newlevel) for elem in islice(x, maxiter)] + if n > maxiter: pieces.append('...') + s = ', '.join(pieces) + if n == 1 and trail: right = trail + right + return '%s%s%s' % (left, s, right) + + def repr_tuple(self, x, level): + return self._repr_iterable(x, level, '(', ')', self.maxtuple, ',') + + def repr_list(self, x, level): + return self._repr_iterable(x, level, '[', ']', self.maxlist) + + def repr_array(self, x, level): + header = "array('%s', [" % x.typecode + return self._repr_iterable(x, level, header, '])', self.maxarray) + + def repr_set(self, x, level): + x = _possibly_sorted(x) + return self._repr_iterable(x, level, 'set([', '])', self.maxset) + + def repr_frozenset(self, x, level): + x = _possibly_sorted(x) + return self._repr_iterable(x, level, 'frozenset([', '])', + self.maxfrozenset) + + def repr_deque(self, x, level): + return self._repr_iterable(x, level, 'deque([', '])', self.maxdeque) + + def repr_dict(self, x, level): + n = len(x) + if n == 0: return '{}' + if level <= 0: return '{...}' + newlevel = level - 1 + repr1 = self.repr1 + pieces = [] + for key in islice(_possibly_sorted(x), self.maxdict): + keyrepr = repr1(key, newlevel) + valrepr = repr1(x[key], newlevel) + pieces.append('%s: %s' % (keyrepr, valrepr)) + if n > self.maxdict: pieces.append('...') + s = ', '.join(pieces) + return '{%s}' % (s,) + + def repr_str(self, x, level): + s = __builtin__.repr(x[:self.maxstring]) + if len(s) > self.maxstring: + i = max(0, (self.maxstring-3)//2) + j = max(0, self.maxstring-3-i) + s = __builtin__.repr(x[:i] + x[len(x)-j:]) + s = s[:i] + '...' + s[len(s)-j:] + return s + + def repr_long(self, x, level): + s = __builtin__.repr(x) # XXX Hope this isn't too slow... + if len(s) > self.maxlong: + i = max(0, (self.maxlong-3)//2) + j = max(0, self.maxlong-3-i) + s = s[:i] + '...' + s[len(s)-j:] + return s + + def repr_instance(self, x, level): + try: + s = __builtin__.repr(x) + # Bugs in x.__repr__() can cause arbitrary + # exceptions -- then make up something + except Exception: + return '<%s instance at %x>' % (x.__class__.__name__, id(x)) + if len(s) > self.maxstring: + i = max(0, (self.maxstring-3)//2) + j = max(0, self.maxstring-3-i) + s = s[:i] + '...' + s[len(s)-j:] + return s + + +def _possibly_sorted(x): + # Since not all sequences of items can be sorted and comparison + # functions may raise arbitrary exceptions, return an unsorted + # sequence in that case. + try: + return sorted(x) + except Exception: + return list(x) + +aRepr = Repr() +repr = aRepr.repr diff --git a/PythonHome/Lib/repr.pyc b/PythonHome/Lib/repr.pyc deleted file mode 100644 index 5b903597762515c81198d4e90f524b8d393a8ace..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5130 zcmb_gUvC^&6+bik&+Dx1G^Vym0~x4R8Pi}1BoHm3gtmY{l^+$Yp z?oDeaULoW@z$ZZh3BCXi{T#gU$TJ@Re!p{PXI#4GBr|z7 zNGo%F484QL{23&LhOj|YXV~W{1B-oS>ZSFcdqUG1I@l}?hH0g-Fl|An+LE-DS(Ic^ znQM|G(HN0}u_mXukRWLcRNiF)A*v>8xmKGgADJZ29BN}Y(r6$5?U2=w)J3i{TR zfxd1E$~p$hItI$tRR+p7l!3BMWuUAeGA-=2ovFtfU^6;4`z}dH@-2|?8i-v0IqV8EKvd$CU^d1|=?XEI}F6aAv-AI~O|Y+yAe5HhK?9VfqAjGv_=4wOqL>653aB~&PA zi)^$vTOuEWFU7`yPvHVhWlfszQdLo6mcVU&^nUjEBcft!a;%@laW=|q953>NHA;K! zOMV9o0iPNk4aF)L#9;`k9vyme>cee}*LFxzOSf^aA4U91$D(CUQ0C|=)gnr)<1t)F zya5-Wm9$H@{|^|ed!KrOy{8B|^r*=}Q;Ijq41FHBDKOy65O}ByBq27!hZ=ffD_#e`H@sEvroZC7 z>fOZe>mKlcq`^Z+&8We76A6nEsLMGAyW7i9D&ovO*kw5`xaycY#2 z$0DsD-iW#{?>%}|rq|?TQBFYH9QxRoC%>0zhl@doi1?$NbO<^u45WAnCEzgxLOO~f zKnVEO&h^_;#lm<3{PRP||w$l*_6fA=zGn2ilsXN=Sop6C|b_KJ6&_ z$N6z=#)VB2XU_s=UOFWFNJE01?t?E)=*&_5bxdHouDXXW8xk@8PI1EGr4{EvRmH3I z-@}L|9?@K^HTo+6-tZV}hcj20Nz3WVpue=P6;gEB-%-yqeFU9U6^DP}WsVc=2mlWz z=34|wZ(c0!GL`6i9Tmb=d+i8NAyDX#K4hIhIdq)@@rI6r1>={qYLD`uL#Q>V6D%n$ z`F1&kii18wn`);0w(R<{#@g}ZV|l<@pzE==d@+-3R<#8;3bd~Jj*5lm8|7)&W7%M+ z%d$ZaJf9j`{u~X$)YT87t!v&2x@J~a)Kw@cJX_DZW~z$#&H z{eWX{kZ3XbAvo@~$*W(O zK}@yDLt9rZUzY$8pW_2v;_Y>}8^eofvP)AEBYV6`S}^|X`Q*$uWn}U*K;nbmi;;|Q*ZGK_Kmo#0x553305^+nyu@sU9CJ; z0rKwc}kzi&FeTJdgioV4=np2hh_*0*^9Z^gci>Ex`lewba3XWt&#k zJMB6*0JIr!&&^zPaKmA;TK2qyd7!opFN62GCdfv{_D6#>=-Z%s^mc~f%kC!h%^a(G zvHkVYAf50Z9Qqc=gS>AHE*!j)!gef^xE!Rw{w6TZ9$2%;Oz9j0<_3s(HE*@Hgv>Du zRjAoZbzyCZk;{Pe!iBl16bbidSpOE~F~hJ{72#bB~t^suTQI%9GxM(FX8@ zA_qK$#1ro~Zt4R7b#{ekDc9Dl?0I;m-6a9dq+av&rZ?C961CZLJi}v{K%`#tmeH)a zFNgt6`*EC%2e_58n#6HG&*4?(F$IENJ;vkQ=siZ=ptVP@BmIcwg2v93Q0}58+K%3H WQG1(TXa;Ng9lzsU_g4$J&ig-34<>d1 diff --git a/PythonHome/Lib/rexec.py b/PythonHome/Lib/rexec.py new file mode 100644 index 0000000000..74461512dd --- /dev/null +++ b/PythonHome/Lib/rexec.py @@ -0,0 +1,588 @@ +"""Restricted execution facilities. + +The class RExec exports methods r_exec(), r_eval(), r_execfile(), and +r_import(), which correspond roughly to the built-in operations +exec, eval(), execfile() and import, but executing the code in an +environment that only exposes those built-in operations that are +deemed safe. To this end, a modest collection of 'fake' modules is +created which mimics the standard modules by the same names. It is a +policy decision which built-in modules and operations are made +available; this module provides a reasonable default, but derived +classes can change the policies e.g. by overriding or extending class +variables like ok_builtin_modules or methods like make_sys(). + +XXX To do: +- r_open should allow writing tmp dir +- r_exec etc. with explicit globals/locals? (Use rexec("exec ... in ...")?) + +""" +from warnings import warnpy3k +warnpy3k("the rexec module has been removed in Python 3.0", stacklevel=2) +del warnpy3k + + +import sys +import __builtin__ +import os +import ihooks +import imp + +__all__ = ["RExec"] + +class FileBase: + + ok_file_methods = ('fileno', 'flush', 'isatty', 'read', 'readline', + 'readlines', 'seek', 'tell', 'write', 'writelines', 'xreadlines', + '__iter__') + + +class FileWrapper(FileBase): + + # XXX This is just like a Bastion -- should use that! + + def __init__(self, f): + for m in self.ok_file_methods: + if not hasattr(self, m) and hasattr(f, m): + setattr(self, m, getattr(f, m)) + + def close(self): + self.flush() + + +TEMPLATE = """ +def %s(self, *args): + return getattr(self.mod, self.name).%s(*args) +""" + +class FileDelegate(FileBase): + + def __init__(self, mod, name): + self.mod = mod + self.name = name + + for m in FileBase.ok_file_methods + ('close',): + exec TEMPLATE % (m, m) + + +class RHooks(ihooks.Hooks): + + def __init__(self, *args): + # Hacks to support both old and new interfaces: + # old interface was RHooks(rexec[, verbose]) + # new interface is RHooks([verbose]) + verbose = 0 + rexec = None + if args and type(args[-1]) == type(0): + verbose = args[-1] + args = args[:-1] + if args and hasattr(args[0], '__class__'): + rexec = args[0] + args = args[1:] + if args: + raise TypeError, "too many arguments" + ihooks.Hooks.__init__(self, verbose) + self.rexec = rexec + + def set_rexec(self, rexec): + # Called by RExec instance to complete initialization + self.rexec = rexec + + def get_suffixes(self): + return self.rexec.get_suffixes() + + def is_builtin(self, name): + return self.rexec.is_builtin(name) + + def init_builtin(self, name): + m = __import__(name) + return self.rexec.copy_except(m, ()) + + def init_frozen(self, name): raise SystemError, "don't use this" + def load_source(self, *args): raise SystemError, "don't use this" + def load_compiled(self, *args): raise SystemError, "don't use this" + def load_package(self, *args): raise SystemError, "don't use this" + + def load_dynamic(self, name, filename, file): + return self.rexec.load_dynamic(name, filename, file) + + def add_module(self, name): + return self.rexec.add_module(name) + + def modules_dict(self): + return self.rexec.modules + + def default_path(self): + return self.rexec.modules['sys'].path + + +# XXX Backwards compatibility +RModuleLoader = ihooks.FancyModuleLoader +RModuleImporter = ihooks.ModuleImporter + + +class RExec(ihooks._Verbose): + """Basic restricted execution framework. + + Code executed in this restricted environment will only have access to + modules and functions that are deemed safe; you can subclass RExec to + add or remove capabilities as desired. + + The RExec class can prevent code from performing unsafe operations like + reading or writing disk files, or using TCP/IP sockets. However, it does + not protect against code using extremely large amounts of memory or + processor time. + + """ + + ok_path = tuple(sys.path) # That's a policy decision + + ok_builtin_modules = ('audioop', 'array', 'binascii', + 'cmath', 'errno', 'imageop', + 'marshal', 'math', 'md5', 'operator', + 'parser', 'select', + 'sha', '_sre', 'strop', 'struct', 'time', + '_weakref') + + ok_posix_names = ('error', 'fstat', 'listdir', 'lstat', 'readlink', + 'stat', 'times', 'uname', 'getpid', 'getppid', + 'getcwd', 'getuid', 'getgid', 'geteuid', 'getegid') + + ok_sys_names = ('byteorder', 'copyright', 'exit', 'getdefaultencoding', + 'getrefcount', 'hexversion', 'maxint', 'maxunicode', + 'platform', 'ps1', 'ps2', 'version', 'version_info') + + nok_builtin_names = ('open', 'file', 'reload', '__import__') + + ok_file_types = (imp.C_EXTENSION, imp.PY_SOURCE) + + def __init__(self, hooks = None, verbose = 0): + """Returns an instance of the RExec class. + + The hooks parameter is an instance of the RHooks class or a subclass + of it. If it is omitted or None, the default RHooks class is + instantiated. + + Whenever the RExec module searches for a module (even a built-in one) + or reads a module's code, it doesn't actually go out to the file + system itself. Rather, it calls methods of an RHooks instance that + was passed to or created by its constructor. (Actually, the RExec + object doesn't make these calls --- they are made by a module loader + object that's part of the RExec object. This allows another level of + flexibility, which can be useful when changing the mechanics of + import within the restricted environment.) + + By providing an alternate RHooks object, we can control the file + system accesses made to import a module, without changing the + actual algorithm that controls the order in which those accesses are + made. For instance, we could substitute an RHooks object that + passes all filesystem requests to a file server elsewhere, via some + RPC mechanism such as ILU. Grail's applet loader uses this to support + importing applets from a URL for a directory. + + If the verbose parameter is true, additional debugging output may be + sent to standard output. + + """ + + raise RuntimeError, "This code is not secure in Python 2.2 and later" + + ihooks._Verbose.__init__(self, verbose) + # XXX There's a circular reference here: + self.hooks = hooks or RHooks(verbose) + self.hooks.set_rexec(self) + self.modules = {} + self.ok_dynamic_modules = self.ok_builtin_modules + list = [] + for mname in self.ok_builtin_modules: + if mname in sys.builtin_module_names: + list.append(mname) + self.ok_builtin_modules = tuple(list) + self.set_trusted_path() + self.make_builtin() + self.make_initial_modules() + # make_sys must be last because it adds the already created + # modules to its builtin_module_names + self.make_sys() + self.loader = RModuleLoader(self.hooks, verbose) + self.importer = RModuleImporter(self.loader, verbose) + + def set_trusted_path(self): + # Set the path from which dynamic modules may be loaded. + # Those dynamic modules must also occur in ok_builtin_modules + self.trusted_path = filter(os.path.isabs, sys.path) + + def load_dynamic(self, name, filename, file): + if name not in self.ok_dynamic_modules: + raise ImportError, "untrusted dynamic module: %s" % name + if name in sys.modules: + src = sys.modules[name] + else: + src = imp.load_dynamic(name, filename, file) + dst = self.copy_except(src, []) + return dst + + def make_initial_modules(self): + self.make_main() + self.make_osname() + + # Helpers for RHooks + + def get_suffixes(self): + return [item # (suff, mode, type) + for item in imp.get_suffixes() + if item[2] in self.ok_file_types] + + def is_builtin(self, mname): + return mname in self.ok_builtin_modules + + # The make_* methods create specific built-in modules + + def make_builtin(self): + m = self.copy_except(__builtin__, self.nok_builtin_names) + m.__import__ = self.r_import + m.reload = self.r_reload + m.open = m.file = self.r_open + + def make_main(self): + self.add_module('__main__') + + def make_osname(self): + osname = os.name + src = __import__(osname) + dst = self.copy_only(src, self.ok_posix_names) + dst.environ = e = {} + for key, value in os.environ.items(): + e[key] = value + + def make_sys(self): + m = self.copy_only(sys, self.ok_sys_names) + m.modules = self.modules + m.argv = ['RESTRICTED'] + m.path = map(None, self.ok_path) + m.exc_info = self.r_exc_info + m = self.modules['sys'] + l = self.modules.keys() + list(self.ok_builtin_modules) + l.sort() + m.builtin_module_names = tuple(l) + + # The copy_* methods copy existing modules with some changes + + def copy_except(self, src, exceptions): + dst = self.copy_none(src) + for name in dir(src): + setattr(dst, name, getattr(src, name)) + for name in exceptions: + try: + delattr(dst, name) + except AttributeError: + pass + return dst + + def copy_only(self, src, names): + dst = self.copy_none(src) + for name in names: + try: + value = getattr(src, name) + except AttributeError: + continue + setattr(dst, name, value) + return dst + + def copy_none(self, src): + m = self.add_module(src.__name__) + m.__doc__ = src.__doc__ + return m + + # Add a module -- return an existing module or create one + + def add_module(self, mname): + m = self.modules.get(mname) + if m is None: + self.modules[mname] = m = self.hooks.new_module(mname) + m.__builtins__ = self.modules['__builtin__'] + return m + + # The r* methods are public interfaces + + def r_exec(self, code): + """Execute code within a restricted environment. + + The code parameter must either be a string containing one or more + lines of Python code, or a compiled code object, which will be + executed in the restricted environment's __main__ module. + + """ + m = self.add_module('__main__') + exec code in m.__dict__ + + def r_eval(self, code): + """Evaluate code within a restricted environment. + + The code parameter must either be a string containing a Python + expression, or a compiled code object, which will be evaluated in + the restricted environment's __main__ module. The value of the + expression or code object will be returned. + + """ + m = self.add_module('__main__') + return eval(code, m.__dict__) + + def r_execfile(self, file): + """Execute the Python code in the file in the restricted + environment's __main__ module. + + """ + m = self.add_module('__main__') + execfile(file, m.__dict__) + + def r_import(self, mname, globals={}, locals={}, fromlist=[]): + """Import a module, raising an ImportError exception if the module + is considered unsafe. + + This method is implicitly called by code executing in the + restricted environment. Overriding this method in a subclass is + used to change the policies enforced by a restricted environment. + + """ + return self.importer.import_module(mname, globals, locals, fromlist) + + def r_reload(self, m): + """Reload the module object, re-parsing and re-initializing it. + + This method is implicitly called by code executing in the + restricted environment. Overriding this method in a subclass is + used to change the policies enforced by a restricted environment. + + """ + return self.importer.reload(m) + + def r_unload(self, m): + """Unload the module. + + Removes it from the restricted environment's sys.modules dictionary. + + This method is implicitly called by code executing in the + restricted environment. Overriding this method in a subclass is + used to change the policies enforced by a restricted environment. + + """ + return self.importer.unload(m) + + # The s_* methods are similar but also swap std{in,out,err} + + def make_delegate_files(self): + s = self.modules['sys'] + self.delegate_stdin = FileDelegate(s, 'stdin') + self.delegate_stdout = FileDelegate(s, 'stdout') + self.delegate_stderr = FileDelegate(s, 'stderr') + self.restricted_stdin = FileWrapper(sys.stdin) + self.restricted_stdout = FileWrapper(sys.stdout) + self.restricted_stderr = FileWrapper(sys.stderr) + + def set_files(self): + if not hasattr(self, 'save_stdin'): + self.save_files() + if not hasattr(self, 'delegate_stdin'): + self.make_delegate_files() + s = self.modules['sys'] + s.stdin = self.restricted_stdin + s.stdout = self.restricted_stdout + s.stderr = self.restricted_stderr + sys.stdin = self.delegate_stdin + sys.stdout = self.delegate_stdout + sys.stderr = self.delegate_stderr + + def reset_files(self): + self.restore_files() + s = self.modules['sys'] + self.restricted_stdin = s.stdin + self.restricted_stdout = s.stdout + self.restricted_stderr = s.stderr + + + def save_files(self): + self.save_stdin = sys.stdin + self.save_stdout = sys.stdout + self.save_stderr = sys.stderr + + def restore_files(self): + sys.stdin = self.save_stdin + sys.stdout = self.save_stdout + sys.stderr = self.save_stderr + + def s_apply(self, func, args=(), kw={}): + self.save_files() + try: + self.set_files() + r = func(*args, **kw) + finally: + self.restore_files() + return r + + def s_exec(self, *args): + """Execute code within a restricted environment. + + Similar to the r_exec() method, but the code will be granted access + to restricted versions of the standard I/O streams sys.stdin, + sys.stderr, and sys.stdout. + + The code parameter must either be a string containing one or more + lines of Python code, or a compiled code object, which will be + executed in the restricted environment's __main__ module. + + """ + return self.s_apply(self.r_exec, args) + + def s_eval(self, *args): + """Evaluate code within a restricted environment. + + Similar to the r_eval() method, but the code will be granted access + to restricted versions of the standard I/O streams sys.stdin, + sys.stderr, and sys.stdout. + + The code parameter must either be a string containing a Python + expression, or a compiled code object, which will be evaluated in + the restricted environment's __main__ module. The value of the + expression or code object will be returned. + + """ + return self.s_apply(self.r_eval, args) + + def s_execfile(self, *args): + """Execute the Python code in the file in the restricted + environment's __main__ module. + + Similar to the r_execfile() method, but the code will be granted + access to restricted versions of the standard I/O streams sys.stdin, + sys.stderr, and sys.stdout. + + """ + return self.s_apply(self.r_execfile, args) + + def s_import(self, *args): + """Import a module, raising an ImportError exception if the module + is considered unsafe. + + This method is implicitly called by code executing in the + restricted environment. Overriding this method in a subclass is + used to change the policies enforced by a restricted environment. + + Similar to the r_import() method, but has access to restricted + versions of the standard I/O streams sys.stdin, sys.stderr, and + sys.stdout. + + """ + return self.s_apply(self.r_import, args) + + def s_reload(self, *args): + """Reload the module object, re-parsing and re-initializing it. + + This method is implicitly called by code executing in the + restricted environment. Overriding this method in a subclass is + used to change the policies enforced by a restricted environment. + + Similar to the r_reload() method, but has access to restricted + versions of the standard I/O streams sys.stdin, sys.stderr, and + sys.stdout. + + """ + return self.s_apply(self.r_reload, args) + + def s_unload(self, *args): + """Unload the module. + + Removes it from the restricted environment's sys.modules dictionary. + + This method is implicitly called by code executing in the + restricted environment. Overriding this method in a subclass is + used to change the policies enforced by a restricted environment. + + Similar to the r_unload() method, but has access to restricted + versions of the standard I/O streams sys.stdin, sys.stderr, and + sys.stdout. + + """ + return self.s_apply(self.r_unload, args) + + # Restricted open(...) + + def r_open(self, file, mode='r', buf=-1): + """Method called when open() is called in the restricted environment. + + The arguments are identical to those of the open() function, and a + file object (or a class instance compatible with file objects) + should be returned. RExec's default behaviour is allow opening + any file for reading, but forbidding any attempt to write a file. + + This method is implicitly called by code executing in the + restricted environment. Overriding this method in a subclass is + used to change the policies enforced by a restricted environment. + + """ + mode = str(mode) + if mode not in ('r', 'rb'): + raise IOError, "can't open files for writing in restricted mode" + return open(file, mode, buf) + + # Restricted version of sys.exc_info() + + def r_exc_info(self): + ty, va, tr = sys.exc_info() + tr = None + return ty, va, tr + + +def test(): + import getopt, traceback + opts, args = getopt.getopt(sys.argv[1:], 'vt:') + verbose = 0 + trusted = [] + for o, a in opts: + if o == '-v': + verbose = verbose+1 + if o == '-t': + trusted.append(a) + r = RExec(verbose=verbose) + if trusted: + r.ok_builtin_modules = r.ok_builtin_modules + tuple(trusted) + if args: + r.modules['sys'].argv = args + r.modules['sys'].path.insert(0, os.path.dirname(args[0])) + else: + r.modules['sys'].path.insert(0, "") + fp = sys.stdin + if args and args[0] != '-': + try: + fp = open(args[0]) + except IOError, msg: + print "%s: can't open file %r" % (sys.argv[0], args[0]) + return 1 + if fp.isatty(): + try: + import readline + except ImportError: + pass + import code + class RestrictedConsole(code.InteractiveConsole): + def runcode(self, co): + self.locals['__builtins__'] = r.modules['__builtin__'] + r.s_apply(code.InteractiveConsole.runcode, (self, co)) + try: + RestrictedConsole(r.modules['__main__'].__dict__).interact() + except SystemExit, n: + return n + else: + text = fp.read() + fp.close() + c = compile(text, fp.name, 'exec') + try: + r.s_exec(c) + except SystemExit, n: + return n + except: + traceback.print_exc() + return 1 + + +if __name__ == '__main__': + sys.exit(test()) diff --git a/PythonHome/Lib/rexec.pyc b/PythonHome/Lib/rexec.pyc deleted file mode 100644 index 9f5b71ea0b074b060495cc47f538742b2482f606..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23253 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 + +import time + +from warnings import warnpy3k +warnpy3k("in 3.x, rfc822 has been removed in favor of the email package", + stacklevel=2) + +__all__ = ["Message","AddressList","parsedate","parsedate_tz","mktime_tz"] + +_blanklines = ('\r\n', '\n') # Optimization for islast() + + +class Message: + """Represents a single RFC 2822-compliant message.""" + + def __init__(self, fp, seekable = 1): + """Initialize the class instance and read the headers.""" + if seekable == 1: + # Exercise tell() to make sure it works + # (and then assume seek() works, too) + try: + fp.tell() + except (AttributeError, IOError): + seekable = 0 + self.fp = fp + self.seekable = seekable + self.startofheaders = None + self.startofbody = None + # + if self.seekable: + try: + self.startofheaders = self.fp.tell() + except IOError: + self.seekable = 0 + # + self.readheaders() + # + if self.seekable: + try: + self.startofbody = self.fp.tell() + except IOError: + self.seekable = 0 + + def rewindbody(self): + """Rewind the file to the start of the body (if seekable).""" + if not self.seekable: + raise IOError, "unseekable file" + self.fp.seek(self.startofbody) + + def readheaders(self): + """Read header lines. + + Read header lines up to the entirely blank line that terminates them. + The (normally blank) line that ends the headers is skipped, but not + included in the returned list. If a non-header line ends the headers, + (which is an error), an attempt is made to backspace over it; it is + never included in the returned list. + + The variable self.status is set to the empty string if all went well, + otherwise it is an error message. The variable self.headers is a + completely uninterpreted list of lines contained in the header (so + printing them will reproduce the header exactly as it appears in the + file). + """ + self.dict = {} + self.unixfrom = '' + self.headers = lst = [] + self.status = '' + headerseen = "" + firstline = 1 + startofline = unread = tell = None + if hasattr(self.fp, 'unread'): + unread = self.fp.unread + elif self.seekable: + tell = self.fp.tell + while 1: + if tell: + try: + startofline = tell() + except IOError: + startofline = tell = None + self.seekable = 0 + line = self.fp.readline() + if not line: + self.status = 'EOF in headers' + break + # Skip unix From name time lines + if firstline and line.startswith('From '): + self.unixfrom = self.unixfrom + line + continue + firstline = 0 + if headerseen and line[0] in ' \t': + # It's a continuation line. + lst.append(line) + x = (self.dict[headerseen] + "\n " + line.strip()) + self.dict[headerseen] = x.strip() + continue + elif self.iscomment(line): + # It's a comment. Ignore it. + continue + elif self.islast(line): + # Note! No pushback here! The delimiter line gets eaten. + break + headerseen = self.isheader(line) + if headerseen: + # It's a legal header line, save it. + lst.append(line) + self.dict[headerseen] = line[len(headerseen)+1:].strip() + continue + else: + # It's not a header line; throw it back and stop here. + if not self.dict: + self.status = 'No headers' + else: + self.status = 'Non-header line where header expected' + # Try to undo the read. + if unread: + unread(line) + elif tell: + self.fp.seek(startofline) + else: + self.status = self.status + '; bad seek' + break + + def isheader(self, line): + """Determine whether a given line is a legal header. + + This method should return the header name, suitably canonicalized. + You may override this method in order to use Message parsing on tagged + data in RFC 2822-like formats with special header formats. + """ + i = line.find(':') + if i > 0: + return line[:i].lower() + return None + + def islast(self, line): + """Determine whether a line is a legal end of RFC 2822 headers. + + You may override this method if your application wants to bend the + rules, e.g. to strip trailing whitespace, or to recognize MH template + separators ('--------'). For convenience (e.g. for code reading from + sockets) a line consisting of \\r\\n also matches. + """ + return line in _blanklines + + def iscomment(self, line): + """Determine whether a line should be skipped entirely. + + You may override this method in order to use Message parsing on tagged + data in RFC 2822-like formats that support embedded comments or + free-text data. + """ + return False + + def getallmatchingheaders(self, name): + """Find all header lines matching a given header name. + + Look through the list of headers and find all lines matching a given + header name (and their continuation lines). A list of the lines is + returned, without interpretation. If the header does not occur, an + empty list is returned. If the header occurs multiple times, all + occurrences are returned. Case is not important in the header name. + """ + name = name.lower() + ':' + n = len(name) + lst = [] + hit = 0 + for line in self.headers: + if line[:n].lower() == name: + hit = 1 + elif not line[:1].isspace(): + hit = 0 + if hit: + lst.append(line) + return lst + + def getfirstmatchingheader(self, name): + """Get the first header line matching name. + + This is similar to getallmatchingheaders, but it returns only the + first matching header (and its continuation lines). + """ + name = name.lower() + ':' + n = len(name) + lst = [] + hit = 0 + for line in self.headers: + if hit: + if not line[:1].isspace(): + break + elif line[:n].lower() == name: + hit = 1 + if hit: + lst.append(line) + return lst + + def getrawheader(self, name): + """A higher-level interface to getfirstmatchingheader(). + + Return a string containing the literal text of the header but with the + keyword stripped. All leading, trailing and embedded whitespace is + kept in the string, however. Return None if the header does not + occur. + """ + + lst = self.getfirstmatchingheader(name) + if not lst: + return None + lst[0] = lst[0][len(name) + 1:] + return ''.join(lst) + + def getheader(self, name, default=None): + """Get the header value for a name. + + This is the normal interface: it returns a stripped version of the + header value for a given header name, or None if it doesn't exist. + This uses the dictionary version which finds the *last* such header. + """ + return self.dict.get(name.lower(), default) + get = getheader + + def getheaders(self, name): + """Get all values for a header. + + This returns a list of values for headers given more than once; each + value in the result list is stripped in the same way as the result of + getheader(). If the header is not given, return an empty list. + """ + result = [] + current = '' + have_header = 0 + for s in self.getallmatchingheaders(name): + if s[0].isspace(): + if current: + current = "%s\n %s" % (current, s.strip()) + else: + current = s.strip() + else: + if have_header: + result.append(current) + current = s[s.find(":") + 1:].strip() + have_header = 1 + if have_header: + result.append(current) + return result + + def getaddr(self, name): + """Get a single address from a header, as a tuple. + + An example return value: + ('Guido van Rossum', 'guido@cwi.nl') + """ + # New, by Ben Escoto + alist = self.getaddrlist(name) + if alist: + return alist[0] + else: + return (None, None) + + def getaddrlist(self, name): + """Get a list of addresses from a header. + + Retrieves a list of addresses from a header, where each address is a + tuple as returned by getaddr(). Scans all named headers, so it works + properly with multiple To: or Cc: headers for example. + """ + raw = [] + for h in self.getallmatchingheaders(name): + if h[0] in ' \t': + raw.append(h) + else: + if raw: + raw.append(', ') + i = h.find(':') + if i > 0: + addr = h[i+1:] + raw.append(addr) + alladdrs = ''.join(raw) + a = AddressList(alladdrs) + return a.addresslist + + def getdate(self, name): + """Retrieve a date field from a header. + + Retrieves a date field from the named header, returning a tuple + compatible with time.mktime(). + """ + try: + data = self[name] + except KeyError: + return None + return parsedate(data) + + def getdate_tz(self, name): + """Retrieve a date field from a header as a 10-tuple. + + The first 9 elements make up a tuple compatible with time.mktime(), + and the 10th is the offset of the poster's time zone from GMT/UTC. + """ + try: + data = self[name] + except KeyError: + return None + return parsedate_tz(data) + + + # Access as a dictionary (only finds *last* header of each type): + + def __len__(self): + """Get the number of headers in a message.""" + return len(self.dict) + + def __getitem__(self, name): + """Get a specific header, as from a dictionary.""" + return self.dict[name.lower()] + + def __setitem__(self, name, value): + """Set the value of a header. + + Note: This is not a perfect inversion of __getitem__, because any + changed headers get stuck at the end of the raw-headers list rather + than where the altered header was. + """ + del self[name] # Won't fail if it doesn't exist + self.dict[name.lower()] = value + text = name + ": " + value + for line in text.split("\n"): + self.headers.append(line + "\n") + + def __delitem__(self, name): + """Delete all occurrences of a specific header, if it is present.""" + name = name.lower() + if not name in self.dict: + return + del self.dict[name] + name = name + ':' + n = len(name) + lst = [] + hit = 0 + for i in range(len(self.headers)): + line = self.headers[i] + if line[:n].lower() == name: + hit = 1 + elif not line[:1].isspace(): + hit = 0 + if hit: + lst.append(i) + for i in reversed(lst): + del self.headers[i] + + def setdefault(self, name, default=""): + lowername = name.lower() + if lowername in self.dict: + return self.dict[lowername] + else: + text = name + ": " + default + for line in text.split("\n"): + self.headers.append(line + "\n") + self.dict[lowername] = default + return default + + def has_key(self, name): + """Determine whether a message contains the named header.""" + return name.lower() in self.dict + + def __contains__(self, name): + """Determine whether a message contains the named header.""" + return name.lower() in self.dict + + def __iter__(self): + return iter(self.dict) + + def keys(self): + """Get all of a message's header field names.""" + return self.dict.keys() + + def values(self): + """Get all of a message's header field values.""" + return self.dict.values() + + def items(self): + """Get all of a message's headers. + + Returns a list of name, value tuples. + """ + return self.dict.items() + + def __str__(self): + return ''.join(self.headers) + + +# Utility functions +# ----------------- + +# XXX Should fix unquote() and quote() to be really conformant. +# XXX The inverses of the parse functions may also be useful. + + +def unquote(s): + """Remove quotes from a string.""" + if len(s) > 1: + if s.startswith('"') and s.endswith('"'): + return s[1:-1].replace('\\\\', '\\').replace('\\"', '"') + if s.startswith('<') and s.endswith('>'): + return s[1:-1] + return s + + +def quote(s): + """Add quotes around a string.""" + return s.replace('\\', '\\\\').replace('"', '\\"') + + +def parseaddr(address): + """Parse an address into a (realname, mailaddr) tuple.""" + a = AddressList(address) + lst = a.addresslist + if not lst: + return (None, None) + return lst[0] + + +class AddrlistClass: + """Address parser class by Ben Escoto. + + To understand what this class does, it helps to have a copy of + RFC 2822 in front of you. + + http://www.faqs.org/rfcs/rfc2822.html + + Note: this class interface is deprecated and may be removed in the future. + Use rfc822.AddressList instead. + """ + + def __init__(self, field): + """Initialize a new instance. + + `field' is an unparsed address header field, containing one or more + addresses. + """ + self.specials = '()<>@,:;.\"[]' + self.pos = 0 + self.LWS = ' \t' + self.CR = '\r\n' + self.atomends = self.specials + self.LWS + self.CR + # Note that RFC 2822 now specifies `.' as obs-phrase, meaning that it + # is obsolete syntax. RFC 2822 requires that we recognize obsolete + # syntax, so allow dots in phrases. + self.phraseends = self.atomends.replace('.', '') + self.field = field + self.commentlist = [] + + def gotonext(self): + """Parse up to the start of the next address.""" + while self.pos < len(self.field): + if self.field[self.pos] in self.LWS + '\n\r': + self.pos = self.pos + 1 + elif self.field[self.pos] == '(': + self.commentlist.append(self.getcomment()) + else: break + + def getaddrlist(self): + """Parse all addresses. + + Returns a list containing all of the addresses. + """ + result = [] + ad = self.getaddress() + while ad: + result += ad + ad = self.getaddress() + return result + + def getaddress(self): + """Parse the next address.""" + self.commentlist = [] + self.gotonext() + + oldpos = self.pos + oldcl = self.commentlist + plist = self.getphraselist() + + self.gotonext() + returnlist = [] + + if self.pos >= len(self.field): + # Bad email address technically, no domain. + if plist: + returnlist = [(' '.join(self.commentlist), plist[0])] + + elif self.field[self.pos] in '.@': + # email address is just an addrspec + # this isn't very efficient since we start over + self.pos = oldpos + self.commentlist = oldcl + addrspec = self.getaddrspec() + returnlist = [(' '.join(self.commentlist), addrspec)] + + elif self.field[self.pos] == ':': + # address is a group + returnlist = [] + + fieldlen = len(self.field) + self.pos += 1 + while self.pos < len(self.field): + self.gotonext() + if self.pos < fieldlen and self.field[self.pos] == ';': + self.pos += 1 + break + returnlist = returnlist + self.getaddress() + + elif self.field[self.pos] == '<': + # Address is a phrase then a route addr + routeaddr = self.getrouteaddr() + + if self.commentlist: + returnlist = [(' '.join(plist) + ' (' + \ + ' '.join(self.commentlist) + ')', routeaddr)] + else: returnlist = [(' '.join(plist), routeaddr)] + + else: + if plist: + returnlist = [(' '.join(self.commentlist), plist[0])] + elif self.field[self.pos] in self.specials: + self.pos += 1 + + self.gotonext() + if self.pos < len(self.field) and self.field[self.pos] == ',': + self.pos += 1 + return returnlist + + def getrouteaddr(self): + """Parse a route address (Return-path value). + + This method just skips all the route stuff and returns the addrspec. + """ + if self.field[self.pos] != '<': + return + + expectroute = 0 + self.pos += 1 + self.gotonext() + adlist = "" + while self.pos < len(self.field): + if expectroute: + self.getdomain() + expectroute = 0 + elif self.field[self.pos] == '>': + self.pos += 1 + break + elif self.field[self.pos] == '@': + self.pos += 1 + expectroute = 1 + elif self.field[self.pos] == ':': + self.pos += 1 + else: + adlist = self.getaddrspec() + self.pos += 1 + break + self.gotonext() + + return adlist + + def getaddrspec(self): + """Parse an RFC 2822 addr-spec.""" + aslist = [] + + self.gotonext() + while self.pos < len(self.field): + if self.field[self.pos] == '.': + aslist.append('.') + self.pos += 1 + elif self.field[self.pos] == '"': + aslist.append('"%s"' % self.getquote()) + elif self.field[self.pos] in self.atomends: + break + else: aslist.append(self.getatom()) + self.gotonext() + + if self.pos >= len(self.field) or self.field[self.pos] != '@': + return ''.join(aslist) + + aslist.append('@') + self.pos += 1 + self.gotonext() + return ''.join(aslist) + self.getdomain() + + def getdomain(self): + """Get the complete domain name from an address.""" + sdlist = [] + while self.pos < len(self.field): + if self.field[self.pos] in self.LWS: + self.pos += 1 + elif self.field[self.pos] == '(': + self.commentlist.append(self.getcomment()) + elif self.field[self.pos] == '[': + sdlist.append(self.getdomainliteral()) + elif self.field[self.pos] == '.': + self.pos += 1 + sdlist.append('.') + elif self.field[self.pos] in self.atomends: + break + else: sdlist.append(self.getatom()) + return ''.join(sdlist) + + def getdelimited(self, beginchar, endchars, allowcomments = 1): + """Parse a header fragment delimited by special characters. + + `beginchar' is the start character for the fragment. If self is not + looking at an instance of `beginchar' then getdelimited returns the + empty string. + + `endchars' is a sequence of allowable end-delimiting characters. + Parsing stops when one of these is encountered. + + If `allowcomments' is non-zero, embedded RFC 2822 comments are allowed + within the parsed fragment. + """ + if self.field[self.pos] != beginchar: + return '' + + slist = [''] + quote = 0 + self.pos += 1 + while self.pos < len(self.field): + if quote == 1: + slist.append(self.field[self.pos]) + quote = 0 + elif self.field[self.pos] in endchars: + self.pos += 1 + break + elif allowcomments and self.field[self.pos] == '(': + slist.append(self.getcomment()) + continue # have already advanced pos from getcomment + elif self.field[self.pos] == '\\': + quote = 1 + else: + slist.append(self.field[self.pos]) + self.pos += 1 + + return ''.join(slist) + + def getquote(self): + """Get a quote-delimited fragment from self's field.""" + return self.getdelimited('"', '"\r', 0) + + def getcomment(self): + """Get a parenthesis-delimited fragment from self's field.""" + return self.getdelimited('(', ')\r', 1) + + def getdomainliteral(self): + """Parse an RFC 2822 domain-literal.""" + return '[%s]' % self.getdelimited('[', ']\r', 0) + + def getatom(self, atomends=None): + """Parse an RFC 2822 atom. + + Optional atomends specifies a different set of end token delimiters + (the default is to use self.atomends). This is used e.g. in + getphraselist() since phrase endings must not include the `.' (which + is legal in phrases).""" + atomlist = [''] + if atomends is None: + atomends = self.atomends + + while self.pos < len(self.field): + if self.field[self.pos] in atomends: + break + else: atomlist.append(self.field[self.pos]) + self.pos += 1 + + return ''.join(atomlist) + + def getphraselist(self): + """Parse a sequence of RFC 2822 phrases. + + A phrase is a sequence of words, which are in turn either RFC 2822 + atoms or quoted-strings. Phrases are canonicalized by squeezing all + runs of continuous whitespace into one space. + """ + plist = [] + + while self.pos < len(self.field): + if self.field[self.pos] in self.LWS: + self.pos += 1 + elif self.field[self.pos] == '"': + plist.append(self.getquote()) + elif self.field[self.pos] == '(': + self.commentlist.append(self.getcomment()) + elif self.field[self.pos] in self.phraseends: + break + else: + plist.append(self.getatom(self.phraseends)) + + return plist + +class AddressList(AddrlistClass): + """An AddressList encapsulates a list of parsed RFC 2822 addresses.""" + def __init__(self, field): + AddrlistClass.__init__(self, field) + if field: + self.addresslist = self.getaddrlist() + else: + self.addresslist = [] + + def __len__(self): + return len(self.addresslist) + + def __str__(self): + return ", ".join(map(dump_address_pair, self.addresslist)) + + def __add__(self, other): + # Set union + newaddr = AddressList(None) + newaddr.addresslist = self.addresslist[:] + for x in other.addresslist: + if not x in self.addresslist: + newaddr.addresslist.append(x) + return newaddr + + def __iadd__(self, other): + # Set union, in-place + for x in other.addresslist: + if not x in self.addresslist: + self.addresslist.append(x) + return self + + def __sub__(self, other): + # Set difference + newaddr = AddressList(None) + for x in self.addresslist: + if not x in other.addresslist: + newaddr.addresslist.append(x) + return newaddr + + def __isub__(self, other): + # Set difference, in-place + for x in other.addresslist: + if x in self.addresslist: + self.addresslist.remove(x) + return self + + def __getitem__(self, index): + # Make indexing, slices, and 'in' work + return self.addresslist[index] + +def dump_address_pair(pair): + """Dump a (name, address) pair in a canonicalized form.""" + if pair[0]: + return '"' + pair[0] + '" <' + pair[1] + '>' + else: + return pair[1] + +# Parse a date field + +_monthnames = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', + 'aug', 'sep', 'oct', 'nov', 'dec', + 'january', 'february', 'march', 'april', 'may', 'june', 'july', + 'august', 'september', 'october', 'november', 'december'] +_daynames = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'] + +# The timezone table does not include the military time zones defined +# in RFC822, other than Z. According to RFC1123, the description in +# RFC822 gets the signs wrong, so we can't rely on any such time +# zones. RFC1123 recommends that numeric timezone indicators be used +# instead of timezone names. + +_timezones = {'UT':0, 'UTC':0, 'GMT':0, 'Z':0, + 'AST': -400, 'ADT': -300, # Atlantic (used in Canada) + 'EST': -500, 'EDT': -400, # Eastern + 'CST': -600, 'CDT': -500, # Central + 'MST': -700, 'MDT': -600, # Mountain + 'PST': -800, 'PDT': -700 # Pacific + } + + +def parsedate_tz(data): + """Convert a date string to a time tuple. + + Accounts for military timezones. + """ + if not data: + return None + data = data.split() + if data[0][-1] in (',', '.') or data[0].lower() in _daynames: + # There's a dayname here. Skip it + del data[0] + else: + # no space after the "weekday,"? + i = data[0].rfind(',') + if i >= 0: + data[0] = data[0][i+1:] + if len(data) == 3: # RFC 850 date, deprecated + stuff = data[0].split('-') + if len(stuff) == 3: + data = stuff + data[1:] + if len(data) == 4: + s = data[3] + i = s.find('+') + if i > 0: + data[3:] = [s[:i], s[i+1:]] + else: + data.append('') # Dummy tz + if len(data) < 5: + return None + data = data[:5] + [dd, mm, yy, tm, tz] = data + mm = mm.lower() + if not mm in _monthnames: + dd, mm = mm, dd.lower() + if not mm in _monthnames: + return None + mm = _monthnames.index(mm)+1 + if mm > 12: mm = mm - 12 + if dd[-1] == ',': + dd = dd[:-1] + i = yy.find(':') + if i > 0: + yy, tm = tm, yy + if yy[-1] == ',': + yy = yy[:-1] + if not yy[0].isdigit(): + yy, tz = tz, yy + if tm[-1] == ',': + tm = tm[:-1] + tm = tm.split(':') + if len(tm) == 2: + [thh, tmm] = tm + tss = '0' + elif len(tm) == 3: + [thh, tmm, tss] = tm + else: + return None + try: + yy = int(yy) + dd = int(dd) + thh = int(thh) + tmm = int(tmm) + tss = int(tss) + except ValueError: + return None + tzoffset = None + tz = tz.upper() + if tz in _timezones: + tzoffset = _timezones[tz] + else: + try: + tzoffset = int(tz) + except ValueError: + pass + # Convert a timezone offset into seconds ; -0500 -> -18000 + if tzoffset: + if tzoffset < 0: + tzsign = -1 + tzoffset = -tzoffset + else: + tzsign = 1 + tzoffset = tzsign * ( (tzoffset//100)*3600 + (tzoffset % 100)*60) + return (yy, mm, dd, thh, tmm, tss, 0, 1, 0, tzoffset) + + +def parsedate(data): + """Convert a time string to a time tuple.""" + t = parsedate_tz(data) + if t is None: + return t + return t[:9] + + +def mktime_tz(data): + """Turn a 10-tuple as returned by parsedate_tz() into a UTC timestamp.""" + if data[9] is None: + # No zone info, so localtime is better assumption than GMT + return time.mktime(data[:8] + (-1,)) + else: + t = time.mktime(data[:8] + (0,)) + return t - data[9] - time.timezone + +def formatdate(timeval=None): + """Returns time format preferred for Internet standards. + + Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 + + According to RFC 1123, day and month names must always be in + English. If not for that, this code could use strftime(). It + can't because strftime() honors the locale and could generated + non-English names. + """ + if timeval is None: + timeval = time.time() + timeval = time.gmtime(timeval) + return "%s, %02d %s %04d %02d:%02d:%02d GMT" % ( + ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")[timeval[6]], + timeval[2], + ("Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")[timeval[1]-1], + timeval[0], timeval[3], timeval[4], timeval[5]) + + +# When used as script, run a small test program. +# The first command line argument must be a filename containing one +# message in RFC-822 format. + +if __name__ == '__main__': + import sys, os + file = os.path.join(os.environ['HOME'], 'Mail/inbox/1') + if sys.argv[1:]: file = sys.argv[1] + f = open(file, 'r') + m = Message(f) + print 'From:', m.getaddr('from') + print 'To:', m.getaddrlist('to') + print 'Subject:', m.getheader('subject') + print 'Date:', m.getheader('date') + date = m.getdate_tz('date') + tz = date[-1] + date = time.localtime(mktime_tz(date)) + if date: + print 'ParsedDate:', time.asctime(date), + hhmmss = tz + hhmm, ss = divmod(hhmmss, 60) + hh, mm = divmod(hhmm, 60) + print "%+03d%02d" % (hh, mm), + if ss: print ".%02d" % ss, + print + else: + print 'ParsedDate:', None + m.rewindbody() + n = 0 + while f.readline(): + n += 1 + print 'Lines:', n + print '-'*70 + print 'len =', len(m) + if 'Date' in m: print 'Date =', m['Date'] + if 'X-Nonsense' in m: pass + print 'keys =', m.keys() + print 'values =', m.values() + print 'items =', m.items() diff --git a/PythonHome/Lib/rfc822.pyc b/PythonHome/Lib/rfc822.pyc index f957ddc1ec2b4f2f9fbcd2e52f47b414c7343da0..b41fbd54346ff29c6860777393e30d68bcb9cdb7 100644 GIT binary patch delta 3353 zcmbW%+be@{7zgmZb1V_PxLM96iOn36(~M2l%8aEsyoh;ij&s;@%#FBEgr9b$$cRwr zNl9(j!UZneDwK;QMY&OO_z&LiAMojUp5OERJ+q(O*PQ$~kyn?u=lte?oPq# z99J4GwWfNrPN;RehTJYeFLt`^f_cK_a1I)r10rSf3Jze_*pE09#9VLYkaU zYDCy;@*C1*AT0`E;pxzm=rT@`*}^hcfF_wgFP?l^RY=7cxdPOSW)x6=0h=j*0A#h z5D8F0-N@1XJD=~}TR=UpeHu_oM=zju9dFVV?eyGoTm+5v`9c7#8`cByBF~5cVXvdB Qz$Kxjv2*0ZStk#F03W5H_W%F@ delta 1313 zcmey}%GCUgaf6&Nza#?#gR@mkKxIirex8x}W`AL6MhwB(BA?kX1ounpFkuMF$UVl? zZlDl>DY#SdJ*M`XDtwrN66%;1O}-c>wz*q#KBl?R+7mI2kkyOERJl@rKBme_qXbNq zTqcbef|K`{u0Z$xUU=*cQ} z+cCs0#tBcBx6i;3_ZJqMe9pcfL%h#n0ftz-<7o`BXs2QfvHwnAFvL_`;u)DYx40-_ zdf~e3J`Cl@+@7F|ZNBY(ff+;aj(0GIiJKFAMKA;>FZDA7y5PDW7DH|Xt-^@*$(uui z8JQQehhfNUwumsm5S%-Me zDHAXRC*Mk&kD+^2dJ$$o_+}QOE1dj3a}I{so~&yaVxZJ~BYPf(I4BwI&Dn|}{@+P# z^3L3a7~&xH3-i)2#4Yl(FvKqBzeg9_{JG#FBO}-5qeXjJG2}K^xL|mCvqqH%rr^Tr SNf@!UIi-FVX5jiatpNbP4THe| diff --git a/PythonHome/Lib/rlcompleter.py b/PythonHome/Lib/rlcompleter.py new file mode 100644 index 0000000000..6e4bd12ad3 --- /dev/null +++ b/PythonHome/Lib/rlcompleter.py @@ -0,0 +1,166 @@ +"""Word completion for GNU readline. + +The completer completes keywords, built-ins and globals in a selectable +namespace (which defaults to __main__); when completing NAME.NAME..., it +evaluates (!) the expression up to the last dot and completes its attributes. + +It's very cool to do "import sys" type "sys.", hit the completion key (twice), +and see the list of names defined by the sys module! + +Tip: to use the tab key as the completion key, call + + readline.parse_and_bind("tab: complete") + +Notes: + +- Exceptions raised by the completer function are *ignored* (and generally cause + the completion to fail). This is a feature -- since readline sets the tty + device in raw (or cbreak) mode, printing a traceback wouldn't work well + without some complicated hoopla to save, reset and restore the tty state. + +- 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 *not* evaluated. + +- GNU readline is also used by the built-in functions input() and +raw_input(), and thus these also benefit/suffer from the completer +features. Clearly an interactive application can benefit by +specifying its own completer function and using raw_input() for all +its input. + +- When the original stdin is not a tty device, GNU readline is never + used, and this module (and the readline module) are silently inactive. + +""" + +import __builtin__ +import __main__ + +__all__ = ["Completer"] + +class Completer: + def __init__(self, namespace = None): + """Create a new completer for the command line. + + Completer([namespace]) -> completer instance. + + If unspecified, the default namespace where completions are performed + is __main__ (technically, __main__.__dict__). Namespaces should be + given as dictionaries. + + Completer instances should be used as the completion mechanism of + readline via the set_completer() call: + + readline.set_completer(Completer(my_namespace).complete) + """ + + if namespace and not isinstance(namespace, dict): + raise TypeError,'namespace must be a dictionary' + + # Don't bind to namespace quite yet, but flag whether the user wants a + # specific namespace or to use __main__.__dict__. This will allow us + # to bind to __main__.__dict__ at completion time, not now. + if namespace is None: + self.use_main_ns = 1 + else: + self.use_main_ns = 0 + self.namespace = namespace + + def complete(self, text, state): + """Return the next possible completion for 'text'. + + This is called successively with state == 0, 1, 2, ... until it + returns None. The completion should begin with 'text'. + + """ + if self.use_main_ns: + self.namespace = __main__.__dict__ + + if state == 0: + if "." in text: + self.matches = self.attr_matches(text) + else: + self.matches = self.global_matches(text) + try: + return self.matches[state] + except IndexError: + return None + + def _callable_postfix(self, val, word): + if hasattr(val, '__call__'): + word = word + "(" + return word + + def global_matches(self, text): + """Compute matches when text is a simple name. + + Return a list of all keywords, built-in functions and names currently + defined in self.namespace that match. + + """ + import keyword + matches = [] + n = len(text) + for word in keyword.kwlist: + if word[:n] == text: + matches.append(word) + for nspace in [__builtin__.__dict__, self.namespace]: + for word, val in nspace.items(): + if word[:n] == text and word != "__builtins__": + matches.append(self._callable_postfix(val, word)) + return matches + + def attr_matches(self, text): + """Compute matches when text contains a dot. + + Assuming the text is of the form NAME.NAME....[NAME], and is + evaluable in self.namespace, it will be evaluated and its attributes + (as revealed by dir()) are used as possible completions. (For class + instances, class members are also considered.) + + WARNING: this can still invoke arbitrary C code, if an object + with a __getattr__ hook is evaluated. + + """ + import re + m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text) + if not m: + return [] + expr, attr = m.group(1, 3) + try: + thisobject = eval(expr, self.namespace) + except Exception: + return [] + + # get the content of the object, except __builtins__ + words = dir(thisobject) + if "__builtins__" in words: + words.remove("__builtins__") + + if hasattr(thisobject, '__class__'): + words.append('__class__') + words.extend(get_class_members(thisobject.__class__)) + matches = [] + n = len(attr) + for word in words: + if word[:n] == attr and hasattr(thisobject, word): + val = getattr(thisobject, word) + word = self._callable_postfix(val, "%s.%s" % (expr, word)) + matches.append(word) + return matches + +def get_class_members(klass): + ret = dir(klass) + if hasattr(klass,'__bases__'): + for base in klass.__bases__: + ret = ret + get_class_members(base) + return ret + +try: + import readline +except ImportError: + pass +else: + readline.set_completer(Completer().complete) diff --git a/PythonHome/Lib/rlcompleter.pyc b/PythonHome/Lib/rlcompleter.pyc deleted file mode 100644 index faf237e76f9dab44656e3ff983f9bb2cb5dd211e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5858 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 400 and self.errcode < 500: + self.allow_all = True + elif self.errcode == 200 and lines: + self.parse(lines) + + def _add_entry(self, entry): + if "*" in entry.useragents: + # the default entry is considered last + if self.default_entry is None: + # the first default entry wins + self.default_entry = entry + else: + self.entries.append(entry) + + def parse(self, lines): + """parse the input lines from a robots.txt file. + We allow that a user-agent: line is not preceded by + one or more blank lines.""" + # states: + # 0: start state + # 1: saw user-agent line + # 2: saw an allow or disallow line + state = 0 + linenumber = 0 + entry = Entry() + + self.modified() + for line in lines: + linenumber += 1 + if not line: + if state == 1: + entry = Entry() + state = 0 + elif state == 2: + self._add_entry(entry) + entry = Entry() + state = 0 + # remove optional comment and strip line + i = line.find('#') + if i >= 0: + line = line[:i] + line = line.strip() + if not line: + continue + line = line.split(':', 1) + if len(line) == 2: + line[0] = line[0].strip().lower() + line[1] = urllib.unquote(line[1].strip()) + if line[0] == "user-agent": + if state == 2: + self._add_entry(entry) + entry = Entry() + entry.useragents.append(line[1]) + state = 1 + elif line[0] == "disallow": + if state != 0: + entry.rulelines.append(RuleLine(line[1], False)) + state = 2 + elif line[0] == "allow": + if state != 0: + entry.rulelines.append(RuleLine(line[1], True)) + state = 2 + if state == 2: + self._add_entry(entry) + + + def can_fetch(self, useragent, url): + """using the parsed robots.txt decide if useragent can fetch url""" + if self.disallow_all: + return False + if self.allow_all: + return True + + # Until the robots.txt file has been read or found not + # to exist, we must assume that no url is allowable. + # This prevents false positives when a user erronenously + # calls can_fetch() before calling read(). + if not self.last_checked: + return False + + # search for given user agent matches + # the first match counts + parsed_url = urlparse.urlparse(urllib.unquote(url)) + url = urlparse.urlunparse(('', '', parsed_url.path, + parsed_url.params, parsed_url.query, parsed_url.fragment)) + url = urllib.quote(url) + if not url: + url = "/" + for entry in self.entries: + if entry.applies_to(useragent): + return entry.allowance(url) + # try the default entry last + if self.default_entry: + return self.default_entry.allowance(url) + # agent not found ==> access granted + return True + + + def __str__(self): + return ''.join([str(entry) + "\n" for entry in self.entries]) + + +class RuleLine: + """A rule line is a single "Allow:" (allowance==True) or "Disallow:" + (allowance==False) followed by a path.""" + def __init__(self, path, allowance): + if path == '' and not allowance: + # an empty value means allow all + allowance = True + path = urlparse.urlunparse(urlparse.urlparse(path)) + self.path = urllib.quote(path) + self.allowance = allowance + + def applies_to(self, filename): + return self.path == "*" or filename.startswith(self.path) + + def __str__(self): + return (self.allowance and "Allow" or "Disallow") + ": " + self.path + + +class Entry: + """An entry has one or more user-agents and zero or more rulelines""" + def __init__(self): + self.useragents = [] + self.rulelines = [] + + def __str__(self): + ret = [] + for agent in self.useragents: + ret.extend(["User-agent: ", agent, "\n"]) + for line in self.rulelines: + ret.extend([str(line), "\n"]) + return ''.join(ret) + + def applies_to(self, useragent): + """check if this entry applies to the specified agent""" + # split the name token and make it lower case + useragent = useragent.split("/")[0].lower() + for agent in self.useragents: + if agent == '*': + # we have the catch-all agent + return True + agent = agent.lower() + if agent in useragent: + return True + return False + + def allowance(self, filename): + """Preconditions: + - our agent applies to this entry + - filename is URL decoded""" + for line in self.rulelines: + if line.applies_to(filename): + return line.allowance + return True + +class URLopener(urllib.FancyURLopener): + def __init__(self, *args): + urllib.FancyURLopener.__init__(self, *args) + self.errcode = 200 + + def prompt_user_passwd(self, host, realm): + ## If robots.txt file is accessible only with a password, + ## we act as if the file wasn't there. + return None, None + + def http_error_default(self, url, fp, errcode, errmsg, headers): + self.errcode = errcode + return urllib.FancyURLopener.http_error_default(self, url, fp, errcode, + errmsg, headers) diff --git a/PythonHome/Lib/robotparser.pyc b/PythonHome/Lib/robotparser.pyc deleted file mode 100644 index d61e9a5b35049ef98b44dd90c8df5eec7e651bd5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7600 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 diff --git a/PythonHome/Lib/runpy.py b/PythonHome/Lib/runpy.py new file mode 100644 index 0000000000..c4d7cc26a2 --- /dev/null +++ b/PythonHome/Lib/runpy.py @@ -0,0 +1,278 @@ +"""runpy.py - locating and running Python code using the module namespace + +Provides support for locating and running Python scripts using the Python +module namespace instead of the native filesystem. + +This allows Python code to play nicely with non-filesystem based PEP 302 +importers when locating support scripts as well as when importing modules. +""" +# Written by Nick Coghlan +# to implement PEP 338 (Executing Modules as Scripts) + +import sys +import imp +from pkgutil import read_code +try: + from imp import get_loader +except ImportError: + from pkgutil import get_loader + +__all__ = [ + "run_module", "run_path", +] + +class _TempModule(object): + """Temporarily replace a module in sys.modules with an empty namespace""" + def __init__(self, mod_name): + self.mod_name = mod_name + self.module = imp.new_module(mod_name) + self._saved_module = [] + + def __enter__(self): + mod_name = self.mod_name + try: + self._saved_module.append(sys.modules[mod_name]) + except KeyError: + pass + sys.modules[mod_name] = self.module + return self + + def __exit__(self, *args): + if self._saved_module: + sys.modules[self.mod_name] = self._saved_module[0] + else: + del sys.modules[self.mod_name] + self._saved_module = [] + +class _ModifiedArgv0(object): + def __init__(self, value): + self.value = value + self._saved_value = self._sentinel = object() + + def __enter__(self): + if self._saved_value is not self._sentinel: + raise RuntimeError("Already preserving saved value") + self._saved_value = sys.argv[0] + sys.argv[0] = self.value + + def __exit__(self, *args): + self.value = self._sentinel + sys.argv[0] = self._saved_value + +def _run_code(code, run_globals, init_globals=None, + mod_name=None, mod_fname=None, + mod_loader=None, pkg_name=None): + """Helper to run code in nominated namespace""" + if init_globals is not None: + run_globals.update(init_globals) + run_globals.update(__name__ = mod_name, + __file__ = mod_fname, + __loader__ = mod_loader, + __package__ = pkg_name) + exec code in run_globals + return run_globals + +def _run_module_code(code, init_globals=None, + mod_name=None, mod_fname=None, + mod_loader=None, pkg_name=None): + """Helper to run code in new namespace with sys modified""" + with _TempModule(mod_name) as temp_module, _ModifiedArgv0(mod_fname): + mod_globals = temp_module.module.__dict__ + _run_code(code, mod_globals, init_globals, + mod_name, mod_fname, mod_loader, pkg_name) + # Copy the globals of the temporary module, as they + # may be cleared when the temporary module goes away + return mod_globals.copy() + + +# This helper is needed due to a missing component in the PEP 302 +# loader protocol (specifically, "get_filename" is non-standard) +# Since we can't introduce new features in maintenance releases, +# support was added to zipimporter under the name '_get_filename' +def _get_filename(loader, mod_name): + for attr in ("get_filename", "_get_filename"): + meth = getattr(loader, attr, None) + if meth is not None: + return meth(mod_name) + return None + +# Helper to get the loader, code and filename for a module +def _get_module_details(mod_name): + loader = get_loader(mod_name) + if loader is None: + raise ImportError("No module named %s" % mod_name) + if loader.is_package(mod_name): + if mod_name == "__main__" or mod_name.endswith(".__main__"): + raise ImportError("Cannot use package as __main__ module") + try: + pkg_main_name = mod_name + ".__main__" + return _get_module_details(pkg_main_name) + except ImportError, e: + raise ImportError(("%s; %r is a package and cannot " + + "be directly executed") %(e, mod_name)) + code = loader.get_code(mod_name) + if code is None: + raise ImportError("No code object available for %s" % mod_name) + filename = _get_filename(loader, mod_name) + return mod_name, loader, code, filename + + +def _get_main_module_details(): + # Helper that gives a nicer error message when attempting to + # execute a zipfile or directory by invoking __main__.py + main_name = "__main__" + try: + return _get_module_details(main_name) + except ImportError as exc: + if main_name in str(exc): + raise ImportError("can't find %r module in %r" % + (main_name, sys.path[0])) + raise + +# This function is the actual implementation of the -m switch and direct +# execution of zipfiles and directories and is deliberately kept private. +# This avoids a repeat of the situation where run_module() no longer met the +# needs of mainmodule.c, but couldn't be changed because it was public +def _run_module_as_main(mod_name, alter_argv=True): + """Runs the designated module in the __main__ namespace + + Note that the executed module will have full access to the + __main__ namespace. If this is not desirable, the run_module() + function should be used to run the module code in a fresh namespace. + + At the very least, these variables in __main__ will be overwritten: + __name__ + __file__ + __loader__ + __package__ + """ + try: + if alter_argv or mod_name != "__main__": # i.e. -m switch + mod_name, loader, code, fname = _get_module_details(mod_name) + else: # i.e. directory or zipfile execution + mod_name, loader, code, fname = _get_main_module_details() + except ImportError as exc: + msg = "%s: %s" % (sys.executable, str(exc)) + sys.exit(msg) + pkg_name = mod_name.rpartition('.')[0] + main_globals = sys.modules["__main__"].__dict__ + if alter_argv: + sys.argv[0] = fname + return _run_code(code, main_globals, None, + "__main__", fname, loader, pkg_name) + +def run_module(mod_name, init_globals=None, + run_name=None, alter_sys=False): + """Execute a module's code without importing it + + Returns the resulting top level namespace dictionary + """ + mod_name, loader, code, fname = _get_module_details(mod_name) + if run_name is None: + run_name = mod_name + pkg_name = mod_name.rpartition('.')[0] + if alter_sys: + return _run_module_code(code, init_globals, run_name, + fname, loader, pkg_name) + else: + # Leave the sys module alone + return _run_code(code, {}, init_globals, run_name, + fname, loader, pkg_name) + + +# XXX (ncoghlan): Perhaps expose the C API function +# as imp.get_importer instead of reimplementing it in Python? +def _get_importer(path_name): + """Python version of PyImport_GetImporter C API function""" + cache = sys.path_importer_cache + try: + importer = cache[path_name] + except KeyError: + # Not yet cached. Flag as using the + # standard machinery until we finish + # checking the hooks + cache[path_name] = None + for hook in sys.path_hooks: + try: + importer = hook(path_name) + break + except ImportError: + pass + else: + # The following check looks a bit odd. The trick is that + # NullImporter raises ImportError if the supplied path is a + # *valid* directory entry (and hence able to be handled + # by the standard import machinery) + try: + importer = imp.NullImporter(path_name) + except ImportError: + return None + cache[path_name] = importer + return importer + +def _get_code_from_file(fname): + # Check for a compiled file first + with open(fname, "rb") as f: + code = read_code(f) + if code is None: + # That didn't work, so try it as normal source code + with open(fname, "rU") as f: + code = compile(f.read(), fname, 'exec') + return code + +def run_path(path_name, init_globals=None, run_name=None): + """Execute code located at the specified filesystem location + + Returns the resulting top level namespace dictionary + + The file path may refer directly to a Python script (i.e. + one that could be directly executed with execfile) or else + it may refer to a zipfile or directory containing a top + level __main__.py script. + """ + if run_name is None: + run_name = "" + importer = _get_importer(path_name) + if isinstance(importer, imp.NullImporter): + # Not a valid sys.path entry, so run the code directly + # execfile() doesn't help as we want to allow compiled files + code = _get_code_from_file(path_name) + return _run_module_code(code, init_globals, run_name, path_name) + else: + # Importer is defined for path, so add it to + # the start of sys.path + sys.path.insert(0, path_name) + try: + # Here's where things are a little different from the run_module + # case. There, we only had to replace the module in sys while the + # code was running and doing so was somewhat optional. Here, we + # have no choice and we have to remove it even while we read the + # code. If we don't do this, a __loader__ attribute in the + # existing __main__ module may prevent location of the new module. + main_name = "__main__" + saved_main = sys.modules[main_name] + del sys.modules[main_name] + try: + mod_name, loader, code, fname = _get_main_module_details() + finally: + sys.modules[main_name] = saved_main + pkg_name = "" + with _TempModule(run_name) as temp_module, \ + _ModifiedArgv0(path_name): + mod_globals = temp_module.module.__dict__ + return _run_code(code, mod_globals, init_globals, + run_name, fname, loader, pkg_name).copy() + finally: + try: + sys.path.remove(path_name) + except ValueError: + pass + + +if __name__ == "__main__": + # Run the module specified as the next command line argument + if len(sys.argv) < 2: + print >> sys.stderr, "No module specified for execution" + else: + del sys.argv[0] # Make the requested module sys.argv[0] + _run_module_as_main(sys.argv[0]) diff --git a/PythonHome/Lib/runpy.pyc b/PythonHome/Lib/runpy.pyc deleted file mode 100644 index a66ac7ff9b7174221795d183948bc82a1c47ed80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8308 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 X7wXQ$OzT3cJ@N8r?UXZFYdik~WeB_8 diff --git a/PythonHome/Lib/sched.py b/PythonHome/Lib/sched.py new file mode 100644 index 0000000000..47646a1008 --- /dev/null +++ b/PythonHome/Lib/sched.py @@ -0,0 +1,134 @@ +"""A generally useful event scheduler class. + +Each instance of this class manages its own queue. +No multi-threading is implied; you are supposed to hack that +yourself, or use a single instance per application. + +Each instance is parametrized with two functions, one that is +supposed to return the current time, one that is supposed to +implement a delay. You can implement real-time scheduling by +substituting time and sleep from built-in module time, or you can +implement simulated time by writing your own functions. This can +also be used to integrate scheduling with STDWIN events; the delay +function is allowed to modify the queue. Time can be expressed as +integers or floating point numbers, as long as it is consistent. + +Events are specified by tuples (time, priority, action, argument). +As in UNIX, lower priority numbers mean higher priority; in this +way the queue can be maintained as a priority queue. Execution of the +event means calling the action function, passing it the argument +sequence in "argument" (remember that in Python, multiple function +arguments are be packed in a sequence). +The action function may be an instance method so it +has another way to reference private data (besides global variables). +""" + +# XXX The timefunc and delayfunc should have been defined as methods +# XXX so you can define new kinds of schedulers using subclassing +# XXX instead of having to define a module or class just to hold +# XXX the global state of your particular time and delay functions. + +import heapq +from collections import namedtuple + +__all__ = ["scheduler"] + +Event = namedtuple('Event', 'time, priority, action, argument') + +class scheduler: + def __init__(self, timefunc, delayfunc): + """Initialize a new instance, passing the time and delay + functions""" + self._queue = [] + self.timefunc = timefunc + self.delayfunc = delayfunc + + def enterabs(self, time, priority, action, argument): + """Enter a new event in the queue at an absolute time. + + Returns an ID for the event which can be used to remove it, + if necessary. + + """ + event = Event(time, priority, action, argument) + heapq.heappush(self._queue, event) + return event # The ID + + def enter(self, delay, priority, action, argument): + """A variant that specifies the time as a relative time. + + This is actually the more commonly used interface. + + """ + time = self.timefunc() + delay + return self.enterabs(time, priority, action, argument) + + def cancel(self, event): + """Remove an event from the queue. + + This must be presented the ID as returned by enter(). + If the event is not in the queue, this raises ValueError. + + """ + self._queue.remove(event) + heapq.heapify(self._queue) + + def empty(self): + """Check whether the queue is empty.""" + return not self._queue + + def run(self): + """Execute events until the queue is empty. + + When there is a positive delay until the first event, the + delay function is called and the event is left in the queue; + otherwise, the event is removed from the queue and executed + (its action function is called, passing it the argument). If + the delay function returns prematurely, it is simply + restarted. + + It is legal for both the delay function and the action + function to modify the queue or to raise an exception; + exceptions are not caught but the scheduler's state remains + well-defined so run() may be called again. + + A questionable hack is added to allow other threads to run: + just after an event is executed, a delay of 0 is executed, to + avoid monopolizing the CPU when other threads are also + runnable. + + """ + # localize variable access to minimize overhead + # and to improve thread safety + q = self._queue + delayfunc = self.delayfunc + timefunc = self.timefunc + pop = heapq.heappop + while q: + time, priority, action, argument = checked_event = q[0] + now = timefunc() + if now < time: + delayfunc(time - now) + else: + event = pop(q) + # Verify that the event was not removed or altered + # by another thread after we last looked at q[0]. + if event is checked_event: + action(*argument) + delayfunc(0) # Let other threads run + else: + heapq.heappush(q, event) + + @property + def queue(self): + """An ordered list of upcoming events. + + Events are named tuples with fields for: + time, priority, action, arguments + + """ + # Use heapq to sort the queue rather than using 'sorted(self._queue)'. + # With heapq, two events scheduled at the same time will show in + # the actual order they would be retrieved. + events = self._queue[:] + return map(heapq.heappop, [events]*len(events)) diff --git a/PythonHome/Lib/sched.pyc b/PythonHome/Lib/sched.pyc deleted file mode 100644 index b3f9ece42cc01c3388520af40c18ae0263afdb5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4859 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])'. + """ + return self._repr() + + # __str__ is the same as __repr__ + __str__ = __repr__ + + def _repr(self, sorted=False): + elements = self._data.keys() + if sorted: + elements.sort() + return '%s(%r)' % (self.__class__.__name__, elements) + + def __iter__(self): + """Return an iterator over the elements or a set. + + This is the keys iterator for the underlying dict. + """ + return self._data.iterkeys() + + # Three-way comparison is not supported. However, because __eq__ is + # tried before __cmp__, if Set x == Set y, x.__eq__(y) returns True and + # then cmp(x, y) returns 0 (Python doesn't actually call __cmp__ in this + # case). + + def __cmp__(self, other): + raise TypeError, "can't compare sets using cmp()" + + # Equality comparisons using the underlying dicts. Mixed-type comparisons + # are allowed here, where Set == z for non-Set z always returns False, + # and Set != z always True. This allows expressions like "x in y" to + # give the expected result when y is a sequence of mixed types, not + # raising a pointless TypeError just because y contains a Set, or x is + # a Set and y contain's a non-set ("in" invokes only __eq__). + # Subtle: it would be nicer if __eq__ and __ne__ could return + # NotImplemented instead of True or False. Then the other comparand + # would get a chance to determine the result, and if the other comparand + # also returned NotImplemented then it would fall back to object address + # comparison (which would always return False for __eq__ and always + # True for __ne__). However, that doesn't work, because this type + # *also* implements __cmp__: if, e.g., __eq__ returns NotImplemented, + # Python tries __cmp__ next, and the __cmp__ here then raises TypeError. + + def __eq__(self, other): + if isinstance(other, BaseSet): + return self._data == other._data + else: + return False + + def __ne__(self, other): + if isinstance(other, BaseSet): + return self._data != other._data + else: + return True + + # Copying operations + + def copy(self): + """Return a shallow copy of a set.""" + result = self.__class__() + result._data.update(self._data) + return result + + __copy__ = copy # For the copy module + + def __deepcopy__(self, memo): + """Return a deep copy of a set; used by copy module.""" + # This pre-creates the result and inserts it in the memo + # early, in case the deep copy recurses into another reference + # to this same set. A set can't be an element of itself, but + # it can certainly contain an object that has a reference to + # itself. + from copy import deepcopy + result = self.__class__() + memo[id(self)] = result + data = result._data + value = True + for elt in self: + data[deepcopy(elt, memo)] = value + return result + + # Standard set operations: union, intersection, both differences. + # Each has an operator version (e.g. __or__, invoked with |) and a + # method version (e.g. union). + # Subtle: Each pair requires distinct code so that the outcome is + # correct when the type of other isn't suitable. For example, if + # we did "union = __or__" instead, then Set().union(3) would return + # NotImplemented instead of raising TypeError (albeit that *why* it + # raises TypeError as-is is also a bit subtle). + + def __or__(self, other): + """Return the union of two sets as a new set. + + (I.e. all elements that are in either set.) + """ + if not isinstance(other, BaseSet): + return NotImplemented + return self.union(other) + + def union(self, other): + """Return the union of two sets as a new set. + + (I.e. all elements that are in either set.) + """ + result = self.__class__(self) + result._update(other) + return result + + def __and__(self, other): + """Return the intersection of two sets as a new set. + + (I.e. all elements that are in both sets.) + """ + if not isinstance(other, BaseSet): + return NotImplemented + return self.intersection(other) + + def intersection(self, other): + """Return the intersection of two sets as a new set. + + (I.e. all elements that are in both sets.) + """ + if not isinstance(other, BaseSet): + other = Set(other) + if len(self) <= len(other): + little, big = self, other + else: + little, big = other, self + common = ifilter(big._data.__contains__, little) + return self.__class__(common) + + def __xor__(self, other): + """Return the symmetric difference of two sets as a new set. + + (I.e. all elements that are in exactly one of the sets.) + """ + if not isinstance(other, BaseSet): + return NotImplemented + return self.symmetric_difference(other) + + def symmetric_difference(self, other): + """Return the symmetric difference of two sets as a new set. + + (I.e. all elements that are in exactly one of the sets.) + """ + result = self.__class__() + data = result._data + value = True + selfdata = self._data + try: + otherdata = other._data + except AttributeError: + otherdata = Set(other)._data + for elt in ifilterfalse(otherdata.__contains__, selfdata): + data[elt] = value + for elt in ifilterfalse(selfdata.__contains__, otherdata): + data[elt] = value + return result + + def __sub__(self, other): + """Return the difference of two sets as a new Set. + + (I.e. all elements that are in this set and not in the other.) + """ + if not isinstance(other, BaseSet): + return NotImplemented + return self.difference(other) + + def difference(self, other): + """Return the difference of two sets as a new Set. + + (I.e. all elements that are in this set and not in the other.) + """ + result = self.__class__() + data = result._data + try: + otherdata = other._data + except AttributeError: + otherdata = Set(other)._data + value = True + for elt in ifilterfalse(otherdata.__contains__, self): + data[elt] = value + return result + + # Membership test + + def __contains__(self, element): + """Report whether an element is a member of a set. + + (Called in response to the expression `element in self'.) + """ + try: + return element in self._data + except TypeError: + transform = getattr(element, "__as_temporarily_immutable__", None) + if transform is None: + raise # re-raise the TypeError exception we caught + return transform() in self._data + + # Subset and superset test + + def issubset(self, other): + """Report whether another set contains this set.""" + self._binary_sanity_check(other) + if len(self) > len(other): # Fast check for obvious cases + return False + for elt in ifilterfalse(other._data.__contains__, self): + return False + return True + + def issuperset(self, other): + """Report whether this set contains another set.""" + self._binary_sanity_check(other) + if len(self) < len(other): # Fast check for obvious cases + return False + for elt in ifilterfalse(self._data.__contains__, other): + return False + return True + + # Inequality comparisons using the is-subset relation. + __le__ = issubset + __ge__ = issuperset + + def __lt__(self, other): + self._binary_sanity_check(other) + return len(self) < len(other) and self.issubset(other) + + def __gt__(self, other): + self._binary_sanity_check(other) + return len(self) > len(other) and self.issuperset(other) + + # We inherit object.__hash__, so we must deny this explicitly + __hash__ = None + + # Assorted helpers + + def _binary_sanity_check(self, other): + # Check that the other argument to a binary operation is also + # a set, raising a TypeError otherwise. + if not isinstance(other, BaseSet): + raise TypeError, "Binary operation only permitted between sets" + + def _compute_hash(self): + # Calculate hash code for a set by xor'ing the hash codes of + # the elements. This ensures that the hash code does not depend + # on the order in which elements are added to the set. This is + # not called __hash__ because a BaseSet should not be hashable; + # only an ImmutableSet is hashable. + result = 0 + for elt in self: + result ^= hash(elt) + return result + + def _update(self, iterable): + # The main loop for update() and the subclass __init__() methods. + data = self._data + + # Use the fast update() method when a dictionary is available. + if isinstance(iterable, BaseSet): + data.update(iterable._data) + return + + value = True + + if type(iterable) in (list, tuple, xrange): + # Optimized: we know that __iter__() and next() can't + # raise TypeError, so we can move 'try:' out of the loop. + it = iter(iterable) + while True: + try: + for element in it: + data[element] = value + return + except TypeError: + transform = getattr(element, "__as_immutable__", None) + if transform is None: + raise # re-raise the TypeError exception we caught + data[transform()] = value + else: + # Safe: only catch TypeError where intended + for element in iterable: + try: + data[element] = value + except TypeError: + transform = getattr(element, "__as_immutable__", None) + if transform is None: + raise # re-raise the TypeError exception we caught + data[transform()] = value + + +class ImmutableSet(BaseSet): + """Immutable set class.""" + + __slots__ = ['_hashcode'] + + # BaseSet + hashing + + def __init__(self, iterable=None): + """Construct an immutable set from an optional iterable.""" + self._hashcode = None + self._data = {} + if iterable is not None: + self._update(iterable) + + def __hash__(self): + if self._hashcode is None: + self._hashcode = self._compute_hash() + return self._hashcode + + def __getstate__(self): + return self._data, self._hashcode + + def __setstate__(self, state): + self._data, self._hashcode = state + +class Set(BaseSet): + """ Mutable set class.""" + + __slots__ = [] + + # BaseSet + operations requiring mutability; no hashing + + def __init__(self, iterable=None): + """Construct a set from an optional iterable.""" + self._data = {} + if iterable is not None: + self._update(iterable) + + def __getstate__(self): + # getstate's results are ignored if it is not + return self._data, + + def __setstate__(self, data): + self._data, = data + + # In-place union, intersection, differences. + # Subtle: The xyz_update() functions deliberately return None, + # as do all mutating operations on built-in container types. + # The __xyz__ spellings have to return self, though. + + def __ior__(self, other): + """Update a set with the union of itself and another.""" + self._binary_sanity_check(other) + self._data.update(other._data) + return self + + def union_update(self, other): + """Update a set with the union of itself and another.""" + self._update(other) + + def __iand__(self, other): + """Update a set with the intersection of itself and another.""" + self._binary_sanity_check(other) + self._data = (self & other)._data + return self + + def intersection_update(self, other): + """Update a set with the intersection of itself and another.""" + if isinstance(other, BaseSet): + self &= other + else: + self._data = (self.intersection(other))._data + + def __ixor__(self, other): + """Update a set with the symmetric difference of itself and another.""" + self._binary_sanity_check(other) + self.symmetric_difference_update(other) + return self + + def symmetric_difference_update(self, other): + """Update a set with the symmetric difference of itself and another.""" + data = self._data + value = True + if not isinstance(other, BaseSet): + other = Set(other) + if self is other: + self.clear() + for elt in other: + if elt in data: + del data[elt] + else: + data[elt] = value + + def __isub__(self, other): + """Remove all elements of another set from this set.""" + self._binary_sanity_check(other) + self.difference_update(other) + return self + + def difference_update(self, other): + """Remove all elements of another set from this set.""" + data = self._data + if not isinstance(other, BaseSet): + other = Set(other) + if self is other: + self.clear() + for elt in ifilter(data.__contains__, other): + del data[elt] + + # Python dict-like mass mutations: update, clear + + def update(self, iterable): + """Add all values from an iterable (such as a list or file).""" + self._update(iterable) + + def clear(self): + """Remove all elements from this set.""" + self._data.clear() + + # Single-element mutations: add, remove, discard + + def add(self, element): + """Add an element to a set. + + This has no effect if the element is already present. + """ + try: + self._data[element] = True + except TypeError: + transform = getattr(element, "__as_immutable__", None) + if transform is None: + raise # re-raise the TypeError exception we caught + self._data[transform()] = True + + def remove(self, element): + """Remove an element from a set; it must be a member. + + If the element is not a member, raise a KeyError. + """ + try: + del self._data[element] + except TypeError: + transform = getattr(element, "__as_temporarily_immutable__", None) + if transform is None: + raise # re-raise the TypeError exception we caught + del self._data[transform()] + + def discard(self, element): + """Remove an element from a set if it is a member. + + If the element is not a member, do nothing. + """ + try: + self.remove(element) + except KeyError: + pass + + def pop(self): + """Remove and return an arbitrary set element.""" + return self._data.popitem()[0] + + def __as_immutable__(self): + # Return a copy of self as an immutable set + return ImmutableSet(self) + + def __as_temporarily_immutable__(self): + # Return self wrapped in a temporarily immutable set + return _TemporarilyImmutableSet(self) + + +class _TemporarilyImmutableSet(BaseSet): + # Wrap a mutable set as if it was temporarily immutable. + # This only supplies hashing and equality comparisons. + + def __init__(self, set): + self._set = set + self._data = set._data # Needed by ImmutableSet.__eq__() + + def __hash__(self): + return self._set._compute_hash() diff --git a/PythonHome/Lib/sets.pyc b/PythonHome/Lib/sets.pyc deleted file mode 100644 index c378c2549fb9aed8c60173aefc0a3073dcdb41b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16055 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 WnZ{=CX=}W4_802ivlq_(;C}%Or;]*|' + '/([a-zA-Z][^<>]*)?|' + '![^<>]*)?') + +entityref = re.compile('&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]') +charref = re.compile('&#([0-9]+)[^0-9]') + +starttagopen = re.compile('<[>a-zA-Z]') +shorttagopen = re.compile('<[a-zA-Z][-.a-zA-Z0-9]*/') +shorttag = re.compile('<([a-zA-Z][-.a-zA-Z0-9]*)/([^/]*)/') +piclose = re.compile('>') +endbracket = re.compile('[<>]') +tagfind = re.compile('[a-zA-Z][-_.a-zA-Z0-9]*') +attrfind = re.compile( + r'\s*([a-zA-Z_][-:.a-zA-Z_0-9]*)(\s*=\s*' + r'(\'[^\']*\'|"[^"]*"|[][\-a-zA-Z0-9./,:;+*%?!&$\(\)_#=~\'"@]*))?') + + +class SGMLParseError(RuntimeError): + """Exception raised for all parse errors.""" + pass + + +# SGML parser base class -- find tags and call handler functions. +# Usage: p = SGMLParser(); p.feed(data); ...; p.close(). +# The dtd is defined by deriving a class which defines methods +# with special names to handle tags: start_foo and end_foo to handle +# and , respectively, or do_foo to handle by itself. +# (Tags are converted to lower case for this purpose.) The data +# between tags is passed to the parser by calling self.handle_data() +# with some data as argument (the data may be split up in arbitrary +# chunks). Entity references are passed by calling +# self.handle_entityref() with the entity reference as argument. + +class SGMLParser(markupbase.ParserBase): + # Definition of entities -- derived classes may override + entity_or_charref = re.compile('&(?:' + '([a-zA-Z][-.a-zA-Z0-9]*)|#([0-9]+)' + ')(;?)') + + def __init__(self, verbose=0): + """Initialize and reset this instance.""" + self.verbose = verbose + self.reset() + + def reset(self): + """Reset this instance. Loses all unprocessed data.""" + self.__starttag_text = None + self.rawdata = '' + self.stack = [] + self.lasttag = '???' + self.nomoretags = 0 + self.literal = 0 + markupbase.ParserBase.reset(self) + + def setnomoretags(self): + """Enter literal mode (CDATA) till EOF. + + Intended for derived classes only. + """ + self.nomoretags = self.literal = 1 + + def setliteral(self, *args): + """Enter literal mode (CDATA). + + Intended for derived classes only. + """ + self.literal = 1 + + def feed(self, data): + """Feed some data to the parser. + + Call this as often as you want, with as little or as much text + as you want (may include '\n'). (This just saves the text, + all the processing is done by goahead().) + """ + + self.rawdata = self.rawdata + data + self.goahead(0) + + def close(self): + """Handle the remaining data.""" + self.goahead(1) + + def error(self, message): + raise SGMLParseError(message) + + # Internal -- handle data as far as reasonable. May leave state + # and data to be processed by a subsequent call. If 'end' is + # true, force handling all data as if followed by EOF marker. + def goahead(self, end): + rawdata = self.rawdata + i = 0 + n = len(rawdata) + while i < n: + if self.nomoretags: + self.handle_data(rawdata[i:n]) + i = n + break + match = interesting.search(rawdata, i) + if match: j = match.start() + else: j = n + if i < j: + self.handle_data(rawdata[i:j]) + i = j + if i == n: break + if rawdata[i] == '<': + if starttagopen.match(rawdata, i): + if self.literal: + self.handle_data(rawdata[i]) + i = i+1 + continue + k = self.parse_starttag(i) + if k < 0: break + i = k + continue + if rawdata.startswith(" (i + 1): + self.handle_data("<") + i = i+1 + else: + # incomplete + break + continue + if rawdata.startswith("2Z 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 o#^uy{#VkYz((|PAwC$^XW1i7IcUvG', 'eval', + dont_inherit=True) + +_cache = weakref.WeakValueDictionary() + +def compile(marker): + """Return compiled marker as a function accepting an environment dict.""" + try: + return _cache[marker] + except KeyError: + pass + if not marker.strip(): + def marker_fn(environment=None, override=None): + """""" + return True + else: + compiled_marker = compile_marker(parse_marker(marker)) + def marker_fn(environment=None, override=None): + """override updates environment""" + if override is None: + override = {} + if environment is None: + environment = default_environment() + environment.update(override) + return eval(compiled_marker, environment) + marker_fn.__doc__ = marker + _cache[marker] = marker_fn + return _cache[marker] + +def interpret(marker, environment=None): + return compile(marker)(environment) diff --git a/PythonHome/Lib/site-packages/_markerlib/markers.pyc b/PythonHome/Lib/site-packages/_markerlib/markers.pyc deleted file mode 100644 index 50e4b1bde103cf3b42a3c382def380b91e781750..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4894 zcmbtXZFAek5nh1Q3u(!+Wxd)?0(I(&?$}K0G)|h4-S|cJC{<|>=!sm$3I-yMGAIb3 zaYxCTQD!=ErZ0b>pV}YL5B&-KNB!0xkUYBwQdH_Ma!BI1*jwD~?epC3q4dA$>d)yv z%{CREar}RdOaI#;iilch9g19vO0-*|7UVKTW0bhmg3`*+mj-f~T2Na37`4U*@;J4| zNlj2|l8)v?IZjEL_AAt?kh7J3NM%)}y(;DZAjff3iMr<~nxH+G^1o9wN#DVl3cdO# zeM^)&^gNy`RH55ZRc@vzI!E3@G)1?$Z<@O2DVnC}JiURlGqfCCK#v{zBBV0g zyulJ@?ahqbT*6I7q&bX?70lD^)bF?>3`HF*X z$jkPxJI{U5BG10|YQ@2CD_WA3K)p=LrS2ki5Yx-7#Grp{Em3quES4#{D#B$_y(h{E1|fQ%zH_Mc9?Q+z2MpVP0oz7uRNl*#@t&?f^*;K|$DT?L;yg?DRcgHb zFyB+Tu2-w;&!768|!n z=7s5zmvubzGSlj_YSqK1cZ9n%IKTvPmU?%*)oZ$bO|N>_yqZ4J^`aw)(@yr)ueNV^ z|EK)*_Vv+`I{hRW8E(Y9u6s#rYS%H0Jdo*n8tyC1SxBPg2YN|pI$6GtuF+dNP0=^- z3^oJvfvQ$GG_c$c+b`pkCmLE7svlbx(TMkZiQ?FY#s+2h+*=KbQ9`eiE9GgE$La13 zFNyb*w|c97d-aBw<=*OHoPKm`wQ4Q_^+H z=u=!43fC|c_nObPUINA>)@Hb(bLhCwhW|pNkfV^!NOF`*oNCL`j!BCO0L_H7NZ*hv z)InuH_Qp^0GPhIIap{v2?X>irmv%E0y$JeTRH8+MaRK!D)}a&+ zq9US@Oz`SpgJ+wyG6vK)(X6Msj}$*#o|mP`5m<<%6{p$@lO#J-k(XwX(sfy01Lb0% zj?=f7m}|OvP5ZpnWE*^4v^8#5>~Nq zXGxHCI$9aS$c5S%4tWFqJj=sWbADI3kpBQ<8-d5?jV(Ka{eD+?{AG;t2$yEZ$(?n^ z@x5ZUMlclC|EVdf&a!8yKy=exC9EuT>k>iBNQ5=QXrtb zL>;Jvi!4-mywf+z3)^j_fdP|3Qelnb>o1~_r8ZCmZ5+a+ufPoiJCYtAL!#FSBeO^HK)e0E%?vXI|u~rAlT2M zeu7*7A`I-}c$p7S(L$VTxa!=`vgAomira8-{|b-CfNW-AB#UjD+@E7DLv=5WBqC38 z`CES_e~&Gx9-DQ!#rcV&wxK1A8yZX(#iljegc%1PYCK;^8>!I5{~0Uf5K04U5k+B zkbZHiFgQjrt)At5WzSB$fyB|M@bsOR%!n6r6hl3S#_kbk#x9u& z$;fc<^`FojO%O)sf;!A%hLz^^2D!4hzHWo8(81vcQ^i_3?lWQ7Oe6X0dp-! zz>dEm24eFUlGhQJ{w$U-K+Xz~r@$$R@tXZxE=mU@Fg&ryVKXYi>xHNqUZ`~cm4U`5S=5`xeTVb=UdJoa#ucNU<l9VbwlV!j z7^aI$@)EgIPQ{tRciL%40g{XmwDE3a6T$D*k(6*rko*$U^EqVxeQx-WBXvIrqO2VR z*6+`_i>I+WN$}pl?HL{A=f390I5Uu25+}=OXUntB{A9(co}8?hNz7q6?OSRC9t)D? zo;~~dJm`p*9O8G~?>~5-PK{qG{6C;6LV{Bj3ZE2ow#c+_d+>rHbqp^>VtlB= zyRdx%Z5pMPXa2^*RmxLtW$6cd Cv_Y=` diff --git a/PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/PKG-INFO b/PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/PKG-INFO new file mode 100644 index 0000000000..c9fbab8f8a --- /dev/null +++ b/PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/PKG-INFO @@ -0,0 +1,20 @@ +Metadata-Version: 1.1 +Name: beautifulsoup4 +Version: 4.3.2 +Summary: UNKNOWN +Home-page: http://www.crummy.com/software/BeautifulSoup/bs4/ +Author: Leonard Richardson +Author-email: leonardr@segfault.org +License: MIT +Download-URL: http://www.crummy.com/software/BeautifulSoup/bs4/download/ +Description: Beautiful Soup sits atop an HTML or XML parser, providing Pythonic idioms for iterating, searching, and modifying the parse tree. +Platform: UNKNOWN +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Topic :: Text Processing :: Markup :: HTML +Classifier: Topic :: Text Processing :: Markup :: XML +Classifier: Topic :: Text Processing :: Markup :: SGML +Classifier: Topic :: Software Development :: Libraries :: Python Modules diff --git a/PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/SOURCES.txt b/PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/SOURCES.txt new file mode 100644 index 0000000000..d5fbda3bf9 --- /dev/null +++ b/PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/SOURCES.txt @@ -0,0 +1,22 @@ +README.txt +beautifulsoup4.egg-info/PKG-INFO +beautifulsoup4.egg-info/SOURCES.txt +beautifulsoup4.egg-info/dependency_links.txt +beautifulsoup4.egg-info/top_level.txt +bs4/__init__.py +bs4/dammit.py +bs4/diagnose.py +bs4/element.py +bs4/testing.py +bs4/builder/__init__.py +bs4/builder/_html5lib.py +bs4/builder/_htmlparser.py +bs4/builder/_lxml.py +bs4/tests/__init__.py +bs4/tests/test_builder_registry.py +bs4/tests/test_docs.py +bs4/tests/test_html5lib.py +bs4/tests/test_htmlparser.py +bs4/tests/test_lxml.py +bs4/tests/test_soup.py +bs4/tests/test_tree.py \ No newline at end of file diff --git a/PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/dependency_links.txt b/PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/dependency_links.txt new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/installed-files.txt b/PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/installed-files.txt new file mode 100644 index 0000000000..1c4d344b9e --- /dev/null +++ b/PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/installed-files.txt @@ -0,0 +1,39 @@ +..\bs4\dammit.py +..\bs4\diagnose.py +..\bs4\element.py +..\bs4\testing.py +..\bs4\__init__.py +..\bs4\builder\_html5lib.py +..\bs4\builder\_htmlparser.py +..\bs4\builder\_lxml.py +..\bs4\builder\__init__.py +..\bs4\tests\test_builder_registry.py +..\bs4\tests\test_docs.py +..\bs4\tests\test_html5lib.py +..\bs4\tests\test_htmlparser.py +..\bs4\tests\test_lxml.py +..\bs4\tests\test_soup.py +..\bs4\tests\test_tree.py +..\bs4\tests\__init__.py +..\bs4\dammit.pyc +..\bs4\diagnose.pyc +..\bs4\element.pyc +..\bs4\testing.pyc +..\bs4\__init__.pyc +..\bs4\builder\_html5lib.pyc +..\bs4\builder\_htmlparser.pyc +..\bs4\builder\_lxml.pyc +..\bs4\builder\__init__.pyc +..\bs4\tests\test_builder_registry.pyc +..\bs4\tests\test_docs.pyc +..\bs4\tests\test_html5lib.pyc +..\bs4\tests\test_htmlparser.pyc +..\bs4\tests\test_lxml.pyc +..\bs4\tests\test_soup.pyc +..\bs4\tests\test_tree.pyc +..\bs4\tests\__init__.pyc +.\ +dependency_links.txt +PKG-INFO +SOURCES.txt +top_level.txt diff --git a/PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/top_level.txt b/PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/top_level.txt new file mode 100644 index 0000000000..13154420d4 --- /dev/null +++ b/PythonHome/Lib/site-packages/beautifulsoup4-4.3.2-py2.7.egg-info/top_level.txt @@ -0,0 +1 @@ +bs4 diff --git a/PythonHome/Lib/site-packages/bs4/__init__.py b/PythonHome/Lib/site-packages/bs4/__init__.py new file mode 100644 index 0000000000..7ba34269af --- /dev/null +++ b/PythonHome/Lib/site-packages/bs4/__init__.py @@ -0,0 +1,406 @@ +"""Beautiful Soup +Elixir and Tonic +"The Screen-Scraper's Friend" +http://www.crummy.com/software/BeautifulSoup/ + +Beautiful Soup uses a pluggable XML or HTML parser to parse a +(possibly invalid) document into a tree representation. Beautiful Soup +provides provides methods and Pythonic idioms that make it easy to +navigate, search, and modify the parse tree. + +Beautiful Soup works with Python 2.6 and up. It works better if lxml +and/or html5lib is installed. + +For more than you ever wanted to know about Beautiful Soup, see the +documentation: +http://www.crummy.com/software/BeautifulSoup/bs4/doc/ +""" + +__author__ = "Leonard Richardson (leonardr@segfault.org)" +__version__ = "4.3.2" +__copyright__ = "Copyright (c) 2004-2013 Leonard Richardson" +__license__ = "MIT" + +__all__ = ['BeautifulSoup'] + +import os +import re +import warnings + +from .builder import builder_registry, ParserRejectedMarkup +from .dammit import UnicodeDammit +from .element import ( + CData, + Comment, + DEFAULT_OUTPUT_ENCODING, + Declaration, + Doctype, + NavigableString, + PageElement, + ProcessingInstruction, + ResultSet, + SoupStrainer, + Tag, + ) + +# The very first thing we do is give a useful error if someone is +# running this code under Python 3 without converting it. +syntax_error = u'You are trying to run the Python 2 version of Beautiful Soup under Python 3. This will not work. You need to convert the code, either by installing it (`python setup.py install`) or by running 2to3 (`2to3 -w bs4`).' + +class BeautifulSoup(Tag): + """ + This class defines the basic interface called by the tree builders. + + These methods will be called by the parser: + reset() + feed(markup) + + The tree builder may call these methods from its feed() implementation: + handle_starttag(name, attrs) # See note about return value + handle_endtag(name) + handle_data(data) # Appends to the current data node + endData(containerClass=NavigableString) # Ends the current data node + + No matter how complicated the underlying parser is, you should be + able to build a tree using 'start tag' events, 'end tag' events, + 'data' events, and "done with data" events. + + If you encounter an empty-element tag (aka a self-closing tag, + like HTML's
tag), call handle_starttag and then + handle_endtag. + """ + ROOT_TAG_NAME = u'[document]' + + # If the end-user gives no indication which tree builder they + # want, look for one with these features. + DEFAULT_BUILDER_FEATURES = ['html', 'fast'] + + ASCII_SPACES = '\x20\x0a\x09\x0c\x0d' + + def __init__(self, markup="", features=None, builder=None, + parse_only=None, from_encoding=None, **kwargs): + """The Soup object is initialized as the 'root tag', and the + provided markup (which can be a string or a file-like object) + is fed into the underlying parser.""" + + if 'convertEntities' in kwargs: + warnings.warn( + "BS4 does not respect the convertEntities argument to the " + "BeautifulSoup constructor. Entities are always converted " + "to Unicode characters.") + + if 'markupMassage' in kwargs: + del kwargs['markupMassage'] + warnings.warn( + "BS4 does not respect the markupMassage argument to the " + "BeautifulSoup constructor. The tree builder is responsible " + "for any necessary markup massage.") + + if 'smartQuotesTo' in kwargs: + del kwargs['smartQuotesTo'] + warnings.warn( + "BS4 does not respect the smartQuotesTo argument to the " + "BeautifulSoup constructor. Smart quotes are always converted " + "to Unicode characters.") + + if 'selfClosingTags' in kwargs: + del kwargs['selfClosingTags'] + warnings.warn( + "BS4 does not respect the selfClosingTags argument to the " + "BeautifulSoup constructor. The tree builder is responsible " + "for understanding self-closing tags.") + + if 'isHTML' in kwargs: + del kwargs['isHTML'] + warnings.warn( + "BS4 does not respect the isHTML argument to the " + "BeautifulSoup constructor. You can pass in features='html' " + "or features='xml' to get a builder capable of handling " + "one or the other.") + + def deprecated_argument(old_name, new_name): + if old_name in kwargs: + warnings.warn( + 'The "%s" argument to the BeautifulSoup constructor ' + 'has been renamed to "%s."' % (old_name, new_name)) + value = kwargs[old_name] + del kwargs[old_name] + return value + return None + + parse_only = parse_only or deprecated_argument( + "parseOnlyThese", "parse_only") + + from_encoding = from_encoding or deprecated_argument( + "fromEncoding", "from_encoding") + + if len(kwargs) > 0: + arg = kwargs.keys().pop() + raise TypeError( + "__init__() got an unexpected keyword argument '%s'" % arg) + + if builder is None: + if isinstance(features, basestring): + features = [features] + if features is None or len(features) == 0: + features = self.DEFAULT_BUILDER_FEATURES + builder_class = builder_registry.lookup(*features) + if builder_class is None: + raise FeatureNotFound( + "Couldn't find a tree builder with the features you " + "requested: %s. Do you need to install a parser library?" + % ",".join(features)) + builder = builder_class() + self.builder = builder + self.is_xml = builder.is_xml + self.builder.soup = self + + self.parse_only = parse_only + + if hasattr(markup, 'read'): # It's a file-type object. + markup = markup.read() + elif len(markup) <= 256: + # Print out warnings for a couple beginner problems + # involving passing non-markup to Beautiful Soup. + # Beautiful Soup will still parse the input as markup, + # just in case that's what the user really wants. + if (isinstance(markup, unicode) + and not os.path.supports_unicode_filenames): + possible_filename = markup.encode("utf8") + else: + possible_filename = markup + is_file = False + try: + is_file = os.path.exists(possible_filename) + except Exception, e: + # This is almost certainly a problem involving + # characters not valid in filenames on this + # system. Just let it go. + pass + if is_file: + warnings.warn( + '"%s" looks like a filename, not markup. You should probably open this file and pass the filehandle into Beautiful Soup.' % markup) + if markup[:5] == "http:" or markup[:6] == "https:": + # TODO: This is ugly but I couldn't get it to work in + # Python 3 otherwise. + if ((isinstance(markup, bytes) and not b' ' in markup) + or (isinstance(markup, unicode) and not u' ' in markup)): + warnings.warn( + '"%s" looks like a URL. Beautiful Soup is not an HTTP client. You should probably use an HTTP client to get the document behind the URL, and feed that document to Beautiful Soup.' % markup) + + for (self.markup, self.original_encoding, self.declared_html_encoding, + self.contains_replacement_characters) in ( + self.builder.prepare_markup(markup, from_encoding)): + self.reset() + try: + self._feed() + break + except ParserRejectedMarkup: + pass + + # Clear out the markup and remove the builder's circular + # reference to this object. + self.markup = None + self.builder.soup = None + + def _feed(self): + # Convert the document to Unicode. + self.builder.reset() + + self.builder.feed(self.markup) + # Close out any unfinished strings and close all the open tags. + self.endData() + while self.currentTag.name != self.ROOT_TAG_NAME: + self.popTag() + + def reset(self): + Tag.__init__(self, self, self.builder, self.ROOT_TAG_NAME) + self.hidden = 1 + self.builder.reset() + self.current_data = [] + self.currentTag = None + self.tagStack = [] + self.preserve_whitespace_tag_stack = [] + self.pushTag(self) + + def new_tag(self, name, namespace=None, nsprefix=None, **attrs): + """Create a new tag associated with this soup.""" + return Tag(None, self.builder, name, namespace, nsprefix, attrs) + + def new_string(self, s, subclass=NavigableString): + """Create a new NavigableString associated with this soup.""" + navigable = subclass(s) + navigable.setup() + return navigable + + def insert_before(self, successor): + raise NotImplementedError("BeautifulSoup objects don't support insert_before().") + + def insert_after(self, successor): + raise NotImplementedError("BeautifulSoup objects don't support insert_after().") + + def popTag(self): + tag = self.tagStack.pop() + if self.preserve_whitespace_tag_stack and tag == self.preserve_whitespace_tag_stack[-1]: + self.preserve_whitespace_tag_stack.pop() + #print "Pop", tag.name + if self.tagStack: + self.currentTag = self.tagStack[-1] + return self.currentTag + + def pushTag(self, tag): + #print "Push", tag.name + if self.currentTag: + self.currentTag.contents.append(tag) + self.tagStack.append(tag) + self.currentTag = self.tagStack[-1] + if tag.name in self.builder.preserve_whitespace_tags: + self.preserve_whitespace_tag_stack.append(tag) + + def endData(self, containerClass=NavigableString): + if self.current_data: + current_data = u''.join(self.current_data) + # If whitespace is not preserved, and this string contains + # nothing but ASCII spaces, replace it with a single space + # or newline. + if not self.preserve_whitespace_tag_stack: + strippable = True + for i in current_data: + if i not in self.ASCII_SPACES: + strippable = False + break + if strippable: + if '\n' in current_data: + current_data = '\n' + else: + current_data = ' ' + + # Reset the data collector. + self.current_data = [] + + # Should we add this string to the tree at all? + if self.parse_only and len(self.tagStack) <= 1 and \ + (not self.parse_only.text or \ + not self.parse_only.search(current_data)): + return + + o = containerClass(current_data) + self.object_was_parsed(o) + + def object_was_parsed(self, o, parent=None, most_recent_element=None): + """Add an object to the parse tree.""" + parent = parent or self.currentTag + most_recent_element = most_recent_element or self._most_recent_element + o.setup(parent, most_recent_element) + + if most_recent_element is not None: + most_recent_element.next_element = o + self._most_recent_element = o + parent.contents.append(o) + + def _popToTag(self, name, nsprefix=None, inclusivePop=True): + """Pops the tag stack up to and including the most recent + instance of the given tag. If inclusivePop is false, pops the tag + stack up to but *not* including the most recent instqance of + the given tag.""" + #print "Popping to %s" % name + if name == self.ROOT_TAG_NAME: + # The BeautifulSoup object itself can never be popped. + return + + most_recently_popped = None + + stack_size = len(self.tagStack) + for i in range(stack_size - 1, 0, -1): + t = self.tagStack[i] + if (name == t.name and nsprefix == t.prefix): + if inclusivePop: + most_recently_popped = self.popTag() + break + most_recently_popped = self.popTag() + + return most_recently_popped + + def handle_starttag(self, name, namespace, nsprefix, attrs): + """Push a start tag on to the stack. + + If this method returns None, the tag was rejected by the + SoupStrainer. You should proceed as if the tag had not occured + in the document. For instance, if this was a self-closing tag, + don't call handle_endtag. + """ + + # print "Start tag %s: %s" % (name, attrs) + self.endData() + + if (self.parse_only and len(self.tagStack) <= 1 + and (self.parse_only.text + or not self.parse_only.search_tag(name, attrs))): + return None + + tag = Tag(self, self.builder, name, namespace, nsprefix, attrs, + self.currentTag, self._most_recent_element) + if tag is None: + return tag + if self._most_recent_element: + self._most_recent_element.next_element = tag + self._most_recent_element = tag + self.pushTag(tag) + return tag + + def handle_endtag(self, name, nsprefix=None): + #print "End tag: " + name + self.endData() + self._popToTag(name, nsprefix) + + def handle_data(self, data): + self.current_data.append(data) + + def decode(self, pretty_print=False, + eventual_encoding=DEFAULT_OUTPUT_ENCODING, + formatter="minimal"): + """Returns a string or Unicode representation of this document. + To get Unicode, pass None for encoding.""" + + if self.is_xml: + # Print the XML declaration + encoding_part = '' + if eventual_encoding != None: + encoding_part = ' encoding="%s"' % eventual_encoding + prefix = u'\n' % encoding_part + else: + prefix = u'' + if not pretty_print: + indent_level = None + else: + indent_level = 0 + return prefix + super(BeautifulSoup, self).decode( + indent_level, eventual_encoding, formatter) + +# Alias to make it easier to type import: 'from bs4 import _soup' +_s = BeautifulSoup +_soup = BeautifulSoup + +class BeautifulStoneSoup(BeautifulSoup): + """Deprecated interface to an XML parser.""" + + def __init__(self, *args, **kwargs): + kwargs['features'] = 'xml' + warnings.warn( + 'The BeautifulStoneSoup class is deprecated. Instead of using ' + 'it, pass features="xml" into the BeautifulSoup constructor.') + super(BeautifulStoneSoup, self).__init__(*args, **kwargs) + + +class StopParsing(Exception): + pass + +class FeatureNotFound(ValueError): + pass + + +#By default, act as an HTML pretty-printer. +if __name__ == '__main__': + import sys + soup = BeautifulSoup(sys.stdin) + print soup.prettify() diff --git a/PythonHome/Lib/site-packages/bs4/__init__.pyc b/PythonHome/Lib/site-packages/bs4/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ec20aa419c4c02bde68c720576478bd7aec0351f GIT binary patch literal 14358 zcmd5@O>7)TcCMZwhnyiP>X(u%S#Hxm968d+mc7}9*Rm~M_Y!LKbU#v&n7@B)Q}gU{661r^ya@c&| ztM1{CY-4qx5lUU`u6|wh>eZ|7{Zz5|`BbI*+27ZjD*Gwo_nWxP2aZyqQVo=jYB(w^ zs767BMb#*(a6~mmR5+^Icr~iRk_yLEr=%LVvG-%DF_zzttH!tr@xQD(W!0^yMn!ce zRAWLptgWcdr0Pzo#*}@YP@O}nJFObis(V;94y*1F)i|QMM^)pf>K;>#W2$>xHIA$9 z3Dr2Ex-+UVqq-+mY(ydlN(km8&Q4=eqY)E*hux+*-X^wUy%Y*;(1^fM|vt~LrPx#wi#e^xb~WwZKO zwf>y?7-D)}>F3q@965OF?H;5$rs~xbl=N~zscSkIq)}_oaqID*Us>!#TT$W$z0h5W zdr`A8yRxR;dNa|wcM-pWzE0+hdp(JCFPyEcrD^}wOP4k`H*3vg(Cu#5nsN7%iCgJr zkmyUp#@Y6zN@e&gow);}jT^ZA&Y;~6Ry*2#_ts4}PTaRw@Vg%*Mkj6>+dDU?RQs_p z(Q0Sgjd~vjohUr-hH-Py)x8uoAPn3Te7cG5C)%JkNTaw{bNBXI=_m1rQHY+0H(i~s z#UWV1sF$~KkAb^U7{y)VrfWg!c7qM=Myaa zc01qbM5}IOFlLhmosJIC$925x#)&4sJ$E}ExcWnUy&3dU9a4xJy?E0NR^vgsPaYft zKhu?5m?E}UA8&3~%`2Di{iTX|0h)DF$Gsp4T`y{`;kSu1FrP2Gb%wymezGox<Fo-o;(&UV0Mu3yasU-nqHr-@dc5d}qa9T$;bVaAWDMl%Fl= zW+zBQs`A}J+)TIoI-SP5CDA14emza1UR&swgSKAmXla}4bUBHe8k*m0-@uF~gC^BF zE#r-+4Fp+-rcC0AgGVz#)YFNGXC-J4{sk}IgF0Y2LLax$2(=*@^h8gsw!4>ID2qX> zZrs|Z9`2wAx#gPra?M>?gX(QYosQd!t*+KwcF@yS(VB4&jiu5&<#)l=P<1r1%5^Im zOD3?Isvq=au|WY-sD6L={)6*G0nmfZ9*Hlf@yj5WUl%uBDBB0;YfX$yeo82>;WGb$ zLc?+ZQBlHX0R3Py#CWt}MPNB#KVUZS|KzU!CH2Xun2j-FtF;-tDd#k0^$9+&C_O=| z@d=upRN;gWPbt7Xi4SE!59UxYERVH|qB7D#!qd+_^6BE$nC?ij<^j(607^E_5tN)5M&2 zpKPMH6S+3X}=RSVQYZm_()b` zN0xDBAR}`@@ZPM&gHGtKT8_k=f@hiB+%OJ^A?}=r&c)#8Xe4?m8khtBduoK0IgWCN zh~{xNjCUNat04Og$J; z{eMyq;0yz+rqss;^>9Qz7*+j$lS;tVv{a6&w7@38E?m!z5tW>B@VH*2!?=!NptW(D zK48^@aWw2f?fEcZ#cMzgZ{7}WPo2GGw(a-39quA zKp8m?&__9=Oe<=Af&@QBmu2+;@N3)unFIR<$7044TJ#T*x%Fwq zdnwt?A>|*YR9JaLrAO5RjQF^4{67xv*N;g%7+XOYb%fCqYQs^

hl&dJCZR7Qm_a2VPLcyo@S?J($n8vnOKu1Hr1!=QcIHI*J6m=6^-N2q zRU^46=7WVbT(~_Lzve>=Y*e{t2?Q==JufI2{}nH^JwQ6xJTtHdu`HwjCX4)nWB}6~ zIR9=fHzfe?Jd4RARuUEI7eEl0K*!nIWW82nV%9#dnvh?r zH0Mk8sY`yCE7u_D^;N^RRIVWIR%TZX%!SHqvkQPCnH@;0-nu~e1l7UP)DW3ZeFKFe zl=^ypMr%z>n?_wb8FhcW+$=(7nrU;q^2_V$+zIM2YaPNlcA%ff>`t{Oa8Ks)#pGo6 zm@-5UvJnMBjZA~f)JW&8j=j0CnLSJ`)okcB8+!)&hBgmu9Jp@gHO%FD@?$#ziU~`M z5h^wo^0OMyf{eY2J7%^M@F8=3oLEiel&(fy3-qaA>Aai%&ZuGiCx9L0*Z3CJM4PvQ z?`u^Ds1o|pqBRCqC0J#!XkCGyQ3~{@Me7I_2h*81QxI%Piyegk3W9BEF;@V5B%Rrj zN+0R^>rbzuwb+?T17_;GQfbhU-Klh)BYRS5$dSFNwAm51{j{*fjQ@sI`e-VBER{Z< zN>@_p)l~Y1RQg1kqwhDS@=fVHyYHJV;BGFIK4~?;2VLO)RC>sf2U6)_M;=V2M;v)5l^%8E z;Z%C3BafugV~#wUN{>78&QyBBk;mNlyWIHWj*mG0gyZja{9UPZ*o8+@={=6TJC&Yv zy~#I^oE%RC>yh;d&!p0rBhRMN^Nu{1N~atdOQrWY@_Z^~j+{!RaYx>lN~ayk zQt5?MdcWHoPo)Vbo_6AkP9*mwC%!+G&NwoWN*{3K#Z)@$$V;ho&XF^z^g%~HkV=z| zoK2+EX=yEgy0md?=+?d(xSyR4Tj7w9{u@X2$V3$4jX+?*e56 z5l3cI>AWLzsdT}S`Bbi?(t^vMPo+gCUPz^?BMYfib7V1?3(nUvVsZ@7lDU}+I zTuh~=BlT2TcBGL?FFVpqrAv-1r_zceFQ?L~BbQR?!;Y+^($_h%no6%Y^5Imv?8w)p z($_okiUjsgLz%3->L`&;mFqLLg^o^Y3q?k23$^+&bOv*sbO|jlpqc6HQ1Y?1;Ye}y#^)yw%?)EbmkN{WBmsnF@u zbqOYNh2f}c{jCxxEc*S<%>^Ry&gwm_CWmsm+J1lD+-A$O))nMgTdV{@VZq=69<+=w z#h@n(M1UEavw#QGUcGEc!yB;N6WJFVg^Mp2(D>%?*#>+f2Xc;n==?SfKuV2}zOR@1 zV(Ie*iFwQW z-hm&3u$CGXHCqC`_14rZrdI|9DsKaBOPA^V?dcWJ0j9aD-Gw{S_5|;QYr-$# zls9Mxp_cZi$_DGCccP3&Nq#f`!2NDbkCJ;HUbZ(qDk!$=!wXyWVU~|x-kh2+y4%u) z4XOV7Jt(hV*(}Yqm}&E_gj#_<(k)Uymv{E=beWl_^}Aa@xW^H6*b<}3xUU`Cm(Iic z?sWb^jo$gB!uj?)^?s)|A4umPRIU1-?|lW8)>YYg(mPz^A=jwxNO>xXS>73`dC~zV zJsdBL=AyHYbSFi(AMH-M*A?H{ophg*9_vmTcGBbBNe7+uM0e65C%vmX>3%1TbSJ^^ zEdm%e(bb1s>fPO?9(K~0M4b-kmh!q!Zmq?{?Bt-ARX?^mKR9dz^H#JLyR$y|+8*h?Ab_PCDwOXSGv3$T$TLpLx|5!D(s(36KYn6k zD4K(8jPOvO-U!l)lAM-GS*tC7^>eQKLU(gxPP#swe}8xC^G==UPCDhJ7oDUQSr#wF zQUtNiq*sO{OO5c)c|@BmHIZw^Q}Y}}dJ0PYpgMs}HG(*G8H(IZH;|m58@#T!P~W?$ z^r8yny+#IlX>DQNikhRlIzm;8?7Xryp<}*+DjT|z_XN?2o**&NF<_n`Zge?%iTLz7 zc{3hZ=N*g%>8#bo%iGc`+tLsam_*8ATtvzSh{MTQ$LFGrd1oVLRUA3*ybFRwi#{); z%kUk*xu_Z@+0}Fze!-;F(kt6lu)sg(msD$#koZN%35nNTyAkDRr>W;w>&xjf#B4`8 z|FTP6aw%~s3W^&kGP&Z%Rmq+E&Lept5gD|8*W3@`~!dVnyTN zK+cjb>yc*bf83v^K;NA*M3Or4_4#w*;^2UuKhk>6vFf94UHxN7Inn=^JNWUuqya+y zm3IDWI{#`a&FaOMccxc%rut6}5T5^rRAL@TWWc+m!Igyd;Q>TrQuIC&pE7&;g3Es* zS|s%(){IsW4fB)c<)3mtKCLEg==n@K|BZ&iH>T!i)A`Ri{<+j7{hJ(jc>bH+EUzCw zAoau;kV)wnb~f$xkvz*Q2j`oM3s!|KRI1A>)~9y*xwn!xqpFE;K@4X=8@U zzdSuvkMdKMYBo-a0gB2Qdx;7(SC?|T4(fU*VB0{%AxBS3Q>7J0sC?+agCWW25C<7(Tk(Y}Ts74;;3gYUH8A)(%oZ%X2Z9NG+9Bvy&Q~ovAHq zVRn)OB+Kk?ugZv4z+}|No#N5+WtR5Z^uVfSZEkL%JS_C5%Yi~Om~Q9F`9Qn`$r2qI zdA2;;Jj||!xe{F%$+WZ%SA;J)z)R(YVXdy=1r==pyq#Kig~KL*BO}v{zgh+NhHJBH z0c}(Ts-4v)lG$22%=z!c?O%JYBC{Vjc1JsN^i!G&(u9PzZp`n8`(>QVO~O zfm*QjcNOz$ZDFBRNaM%hVKFzW%(Cu>r)vvQd%9Lza5L=`<$I;OV59QkvWZc7Wl3*T zV<(L#W+Pa~hK*1S`>|9WB)jtaK(+GZGtZ{%ULJ$LOih;;OyV2|Qt@P|k1wvi!&T#UmAefp=tP2_lN}T`HGa${g2h)|Oleh8wOe%?sGN%JoSn zXzf?3@^&egDl<*<2m94vq(u3ir#w||z5q^*&f$_xd#LWb=B`@MhuDbaXO|vF_}Q zyt<_D5+Gb?YH4Xb2C3J;wcy0%O_JUg!DG;p)DNz?C4M9*a_jUyMAr%qom zFZ7C?RO?a95QVF`Z{lbkwz*kTq$W5SzD(j|c@@2>%a-9c2RoaT9AOkND{Gl`)s^63 ztrRt(b(|Z44B?>QlTd@`shPxNo36WzNPXT5A+R6KBJxCa*@=~EK9vRrN}@cy-CSNl zUCS9oo+3gjRxzpNm#2yFnDS4ynMIzX1(CChNk{>J64B2yMe(EBnq+k{PY9Ng7gu^P zjmb6X>U_=})@F#lw;9LUEVUIZVr{xc(qbNKbG*{cJ|@LJy2cj_Bp;d?NS?Wm#>B}d zrx-DQ2$PlBuK5yZ;S`hNACuxAM&@>kG0_-5kHK^jccKLW*NEtKDzhe_?c@lYf#H;0 zn`~T~5xbbo*@YLilSP}_sakY+(@f%MhaQ;e4DYv98NvN(1c3`)1KG)^o<40W`%7LV z)H1ycM0VL{kDoa0$kFFdKkY)NpFd?<;B^fwnx<+jae>sUkw}QaL8yc+@vO;I&ye2) z{y-3CWyi>33+zQ?Iz)q$5Kxb?y1Y0^pPVj~ZDglaTpN?6ay@&$9z;%IDK#(6Sj&)a zXr@=1awex2YBLuEmU`2#T9XLH^%4-^re20#UXz+l=)IzPm0DAaL_-tH z&>mq;^;nv(lkpm=EUIM~DqSR&1ESNOz&UntetO5-H&aTHV1^R^iH?KRL9uol@A$ zB{*c?tY$y2z%16|5)%d)1;k*YV$G7tCcG_l=UE&fePzF;%G!@)Ur{in;G+bRg09tc zZ|{V!r+ni{$;E}OxXf+u*;UwH7{EbpEC25xzK!2dVQbG;!tKf=|cJxd400HmCz?*TgabD!V1OnCvp15GPf~(A|-H9*%(WD(kDR; z(l;r+Rga9mRz`m-LvK4EydTT#P$SeH8F{*e^}{D5r9JPhzwm9O{haSet}1y_8&)+J z1$p$aHCzo_thw>61fODnED|GXnE+F*Ntxr%yh65{1v`^J6DYK4sO0>BRw>OmFT(6kaLSw%yIHdc$@d3uE=3^3+4*SBOFXu}a&giw+`uF+;i2We&Y0_{2D6+&=(d1>xjhyaUnib z$IOc+Y!wx?DNhg^*3bAvbrh>Ie)Tx_H{^)Fri|_0;}aK~?J_l$iAM72eo^LU7IAnN zHXfq~;J27xu_XcNw8wH4-@sD2SgGQ1%XVLBxu^twTASLCFrzK6)KXc^W-n^s5}99!ykkzbuX`rX%Z`7ad3VeR>DRJ61pbaR$6hHP z%hzje^v(q5>g(y{K*#1h^vsC-X?8p_cM}oV`D131&ozV}Cn@&34QoZAqq5AFs1qKP zUm<4Ms#Knx;zU#nvX(|nx!5~&Ia^+&e0Efo`Uxa~ND^JosIy<9BG&O_vX5t&MKx;`qB4IpYACNfAy7a%F-%gDzhmcau$!%&)c4_1 zaA8xb|71FK@h2016YZk%cJ6*Nz9+BqW^*UJHpI$qDgX%e1*qVOFqm79_TVM52e%Rd zhn#_Acv1eW{RaRAjuKmSHW1GaajNPcwZ_7LZH{Za+A50G6YoU&0z<66)G9|WTG$j7 zaJ=ZGxaWfLm)EvJ(`p5CT~v;?@z)@=T|0bW@bPJ<$nyi34VCu=d!CNG+Y0*FJ{7fdM73xwcUO{WdZs3=74~+x*kBE$foRWqAuEfou63^q z&t!dCF}>7i$q1%t$Pk<|LV;)Ay|{|R%1s+MY$1w@ zi2T~2jy%KmH%>_AmcB40w$hBU*;z_@e`~o`$Q!z-E{RIg6R(+EkdYw!d#dnd0^=;| zrqjmoGd?jAk5ZpRE>@kXm88(MT_7O57WdfBFCNtNOp58=f@@ZnR64b5LwPh0~VU@Hl1NGH30xshmV5#rsdD+0q4$mOXZW61Rle zn{-e^b8R9aUWzx+#Uf&cU2U&0?7!7%MLT`DYl0pd(@1wKA}4M|BqL|3NITK7zHDv3^)`jg~pw@2-+ogEb2}voGwij+F6nlnxZYbSjD8I%9g1|6v zWM61MBp{nWASr65!$%0uNpQ@vqmYQXLx}E6bsXKmq>%5-g!YhavCT7wBuqZySWL3W z_?Xv-^%ORtTBHfU7!(p0!dCj+t5r;qAdI#?9=HqhXV{xs7gWDjhe@?4>6$!b|r|Mbs z7HTJ|JJ}gu=iT#P*UtFjtMu%y!}YsgbIv(;NC9iwuIsKn zp=1PM#)r2bAzJ~-zI5|8^L;QPx~XOFZt|vVoo8>Vi zlI>wphPel3dVF;AmpQSlMt`7ZQJw7XFAAHe9Q4hY7&| z;SMxqyU`8z65CwZgm@~=*&g%*8w-Z?sLuGmu1l8rlIE_B{U)EW09x1&TY!43%o$_F zmd+Z%As;>5*kN&EUk_-lBLt8MXbQJP;H?SPz?@(~oIwZgV-p%;2E`yAS~Wd|i=5^L z=VA%*Fu_wS9V3}&`>@3VO-z$0TYW?abDagAdy_W%WQ6?c(*99=4F`Fw_ zxn`kR4kgVzMKaE_t&grWsC5%B&(9eKb5mlFJi#(>`-8L`IN0V);YyQzO=W~fAwqe> zqsI)rdd@A?t<0@bHad6>ioA2w+M~X0Q!T4fb|FA+XUDRovooPkP(7`efE<*fb@X4k z;VEDqI5S_yfGHP-wG?z27-#?FEZ!#N5sp<^=RzrqlK}nw!{6Tp#_|pUMQEcOFRUBF$#D;s{*HI z7OcqY=JWzbT=7 zqGZFEI6>C*-x>KyVwpBOb7z*Zu6g@G>OZPJ>%FO?^}hDLdZ#ds30f{i(Ni&jaNp{> zpvk+`x6{=x(dy$@byeNev!x!FX{j2CD4Qr$orXSHpv^+pB;>n^CB{1AG z9i)%F+h>S{;rM-ujVMEJ>tc(KD2?AWFOt7P*%6IED^C*c5Jm@6ceN}I;Bl-H3G|?w zMHYn=pXG%0An!lJ@gAu#ad8>?fI*IxGL;I9un?Obhy&{diHq4`xKI-@BI-#Y!tQ7} zy;$9*{RMhaB}a2eOS$2$OS;i=YgU^06Uvy`atAMt%fF*|VydzrnL>T%<{mi;WCBYl z*@OpO0?b`JdWl*WC^dWbF(s*3zS9h&!XK#KA1Sy;OL$&|g#DMw(=DGIO}cz?u9_38 z)h^Aiu4`I;fVM_8Ex|%|K)rS%I&Ur9jI`nD5pw9~>5;}lFyqgn1Hd(1c2~x7_wG^I zc)L`M8bfwL#76COkZ4^U{T`~0siPWwY8egIbnYH9uIgNu5u7etoNcb%onLTqUj1Nf}U*j(lXy-+s86z{SM$`Bm0vwas?{OK~%jKfI)w#onOZ!X|NoT@z0~(eGPAnjq zbgodEm@ik0Q$=|(9(_&bvjFuSMwVa=j{}?&MUg93L`Qpr!e3ocGZ`A#pt=ATPlM+siwV4W=fl^UUmg*rFEVbKe_qOY% zD667nK(UGC-UntHlI)crivvhG!^E|f|2vfT96^8>_Vpz5A@+4Lt=^hG73%?d`6)yD zQ+VVgtc$R%iHj%UWY`7ZWXHYRKM9LsI@>tpGdJ89R)aHG?Py^|(emuxo&NWBL2wpm)YKdZzmgEFys?M1!4 z3(?T5;7tMCwMeX1(prx+Z=yb`h4ZS?)U}XZoc1wgd|Ux*@f!M^{T%h@)lae7)Gs$H z?rqz&ZU!hF=E!sCABK-v=k;gK27jIxAk?&$c^4%X7L4+JdaZAPMvO-~^d&F~2w14hM6mBZDUNU04e2Rgz$<%b5jXkia{Yhk@WPV;_(XM2TmST6u8ASJx;ecF@WE=}s(I-$ zt>*hoI5!a11ocpWNPXE;(W(M#C$YiZM=~{Ov?GE^k9K4U%$A-I7>~rO(8$0_KF$}o65pF5Kd=NWkHqpxCR6pnG^G&oQ7D*Ua>EqVAqL3eUq33)z zZsQ2g$94A1f|^w6lFp{MK2s;D^Gk0B5dj-$hY|Eh(+$z`eYcFLy>OtUWe?pq%B7z# z%Q9dIBkrdymgS1?eeMg@M%<9C3!^zh-H>a}{)R+Qocnome&uc)3qBypF36JnT`Xi- z=Z-0|vSb|h&K~c7rBvs#hbZQxF~$F}$ z#58HPoXmzTT$Ho1jJ`b1dDGu=Hmfqd1dENib*-NtqR#hf{X9%0;c&PQIc*SA1Fq@0 zGx|omBi@b#cWYq-t4sbdeMm}nPVe#h68&gXuZL3SPPAjT$9rwWx*XlSrzqi zx+0PVE`j!OJygCvY+93DJkmj8jLQK8TXx`EnRP$$*9&?7tBO5PO+R@AX9$!9UAXGri~ZW$IAdL7`W0&ZhQ=gF ztx+H;VU%BkUdyOd3iB2>omj^uGdXdPC|GdtUv9#OPZ(uM_LeR;@*?Ksh1o${z%bYXva7OV_@$pmmC{l-*3=lZMf(2|HIWr~DY*h@u*N8(cOwoE8o^aiW^ycjq9 z5yR02Ul;5)YdmS?>E-;&(F5eJpwHgtxHhH+1ZY?d7iF2-7hI?eCCz zQkXW8Z(SX1A*1!ZXiG;7WU)G)-l#1SVbyXeCzE7~!hy&byElaEou{2S+&qj>}y3ugD26 zO3z3f`V8+Jo%ZzcX5^aH>_1WPt<6aGZ>akF8h20-`7;b^E(Buz1P)W+%S1F1P>R(F ziPS@jeMshplsxPbtlTaP%j>K8FB>WYh0VRgZBwiIH<9ZO}EH<911I$h!T4myq`|8tSsQ zHGIMXNQYOHZ}bS4!AqoN6TsC>Vs`H6935k&&Se{wsO5q?YkAIxh5e}0{rRI%BSeC$ z5<}(FRZ%4)u~Tv^_US*YN&S)n2yV~L=`1*3mx zOJZLjH3t{+-J|U}1={3P(i^+z?(!f-OA^Uj2m3?o z`{o>4pYYG<}%wf8xha(Gkf@EiuBcn=wqHdB_iN>d;|mAmQS&aImc{5hS59hQ0B@m6yCw&u1pXpu30UmU5~M5845+6FDzcAL^nSms>G z%dZPVuBWL0+%p}R-7QQpyW(j3J~jzE&=72F`7P`1>dh#>#=in3UmsV55}we)N|)R1 zv2*uY*G6VbR~D+zI;iCuu~{fw98UaAR8Y_g4`b41@{3dB~l08sk{+Rd-FGOu?D(swTNMDoH6!)whphs zNH*b?ZG6Sq1QJPgx#)60XOnfdn+q3z%Y=xOp7c)gR(@7@8u2Qr^yG>8!@kd%WrFuE z8ywyr#~<&~t5@Ktnk_VGdOHk5z5p<;%yS&A1O^70ll)Uu>;Zc1NkxCmA(E{ZVN>)qi-utlVyp~_v@B4c!Z zuaCHA&Nr>{m6~>$!`pl%iEDmz%A4yN8*p5m*$Jjf`?24^W|3bc7hH9YjGS@)2GK6L z=O6R<)`a)$pHTHBK~q3Ty#v6=aM5EMF0xRx$sQ7jU}T%lzR-;#h=7(X@gQ!>Mm2%@ z>3y~z#HPjsYmew1>LB?;d^60#3KvKhpc@c0)-+9+Z;EKCVQ3NbkkyM-&g!Xs zXg^rf_R^lm=s|-p<5tH;pd9(+NU7a5IXVI;=L^1Hrvo&2efWfol=Cpn;?qhKLi=ow z&xm;KdVPCokNGQaajk_G9<1%i!UEi_KBdaz{_0&rH`jT+dNIT@&9tIkQ1CSY^mYQD z{%U=mp&+e7FLJBa zXBPSF3I92Gb1gtN&bvP(?2sE_LZ!Z$J8n3d;#H-6&uyVRr-)s3^smb@lb=NBvmWvj zOdnGtOTL6VuNHs2v|PmJB_AeB0IP^*KqJtOzi2~95l5I0%loETgbvz7qM52JmW`%r zP)l%!8vZwv2=DE6izi&~B@pGd2GJAn0WOr;#`;M;7x zk}mG!n5{?x*7->jI4b5TSc(;Zh~S^%rPqOqIB9+x9x$A7x9uw48Lq0@5yjOi+!AaW zuDf?TE}NNe^>|}%&FsU%n@4CRv^xJxkH00V5Kl0?u685adz_6-d&{RR<7G{;-82$@qG1BoTDoV7LwJw~?`WUl#~0;eGQ?i;GyQ z5Xo!?E(8oFsvlzQ@F@`1&JS`vM#7Pz(*QaxTL+ent zu8H8L2Hu0Y0xgBgasPrA*p~`b?pIlXbC9+>o%e@5u4u#cP5D<*`7%d{lzhxX!?@Al zTv_eVjdq< zt&jPtgF$m28&Kn;JHC(afd?OY_>o87`Pk$4A2~XD?D&bNo<8~BXI$t~^A=D#8rL#b z%ab-Ea|5TpGs)=^6C9DHlblv4hPqxv#)iZfs&caPJvGtWtm}?i_w_ZAZqgIb8_-;M^YXyIx$3Ifgp>p4>$8S^cD=PAD6*DiE1nnLH^+g}M ziq3?Ue4ldfpzu|ky6bkq_Jw@Gszp^o>(oz7S6FHayv4202G`aeI*&)Dg!O4YUMtst zhC$}?%L~YksHiqYdAHL`oT&_8VBp1!U zk#Z)&8c*x@W}?H`46|X8T{X<}rMUbQtCl|t8&Cx+xMZaijUO|hWH2}ZP=a@Ug>)mL zIh$cLTeYQwV-f4;c2XVqs?jc-_#wec?@xt*vpO7Vt^X$U`yT|6p%FRb8hD$;gURlT zE!(K~CB4tg4Q0EbB*9M|80FWH)0XI^fFl*6;&2(WJJ?PA5fMg(hM|s9??IHW-l>E- z><4PdBL{RSHLg&P);37uFQlb;B`UNVkeau(r}0e|*m2sT9Mln>vm1^kE=iFv1DV6N z%tB^M5d9FEG=?y2^6^?vMljyD;cWd&E1wJp^2wb`ly)7n8DV0NX>Paa{g4f)kdpz^-NWNK|Kr9^#WD2 zjYvDY-_FFhr%LaO?`FCaCPT6x8q~4uq*^e*W*4T`=i$@C`+upcTY6dRXP`*0*A0|F zpR4;M9ugNM=z80?2%Go@tC#qyi!rC=Q7g4r zbWYvOzCxAglUg!uTo)4m3Dtg6y%W}^*q|z^);vSnF-4!4p>9<1`@TTfLD+TctFrH> z^?%lWeZk_47m`SgD4P2)-R^@X+@PT|XH8ji{f7}js9~ZAW!;Nt4%$e^N|MR%4SU%t z=*lr05YYjm8Knw;F)sRn!;;43&$)yiVV*}D_@RX@gE>N#v4W&Qq~!Z*hNada-Hc~Gn30swxAU0kdT46wSQf6s7d%20%Bm8)KXhf?9cR}3gp`@kllR|ue?wDC&> zWIAxnuA{i&w=SS#X59zC`rL1c~Oxs=fU(lV)2z zI;wR&`t`z$czwO(2s20V3CE3hJhE=(@BKt8F$`+Cv`C@w6H+s+iEcT1lVmM&+%}-M zj>Rnk0!na{KNU^V1jdoGXNej53%cw)drps%5ADw-spT!o2fKOsp9m7IML5KC=&In{ zZAg7YWJaW=a|+C8wHnGKp9c_B z)rIR*{nyWc+3f1Kd*xFlXzfTF@+P_@A>h}Ne znU~=pr1k%x*f9lKBH5o)@LLLuswWh)^PV8SepzTQXffEw4Bk$4Z8daDq@1C3%0zC3 z@{-rBUH-j}{HFbNr8OS{me*}J{SY#Hqt&+2H~bj}kNdSw0r8RM^^fGg@S0mR5`K&% z=M;Lm5=Qyiu(0xwXR_7NW9M$q{j0><%`NJv9pU|KJ894Df%M636EM`AG6nz zE{MGd}!?fDE zgYmBmU^lCR02U-R3<&) z*-v%3tTe1#e2W}G7X1g*UAoQunl)>xMZ(?1_fvqA*7TC;f(2Xw-K;)A*t+5y+a{_v zqEe6Bbw*m#OJOD!gnbdPBl>8rE%!j}+lB}B65uP6kc42w+>aVtFs(w0p{w9QZjD9o z<886qK$2ns*}yeIk$Pq_Y0nE0-IecA#kfTA*tu`b9Z=+!ZY7U8u_>*fN9WeJ4XKD- zLIU>J^5)#h*(2$sBB?)|P+F(%oPOtNHv1DxwZvvyc8|roal+VTY3;#NR=xkv_Xq z`I@l!_R#_9{IdN7CI)j0wP`*j=K_34hiG<(3VeuKVWyWuM|LX+km=~2UzdrjgwKaH z(w|nwys8~1=k}aX#eL`x=0H_nCy{dDvW#7e63{l70p~T5xR}09u|_` zr&_3NZ#7fUVJZEu`(5>&5ZQdU^V{OzAUQKs^tP7DfzH|@fQ!Iir#tzSx{0xLA8p^o zwweQ1I}BXVY$&p&yJP3}ckP0~J%m9Edmt=G$Hua7@rlIWgy$D1pmy3s7-x~rC}w9G zL()+C+XB^2g08KWGhF1NYW#w7iCi0MutKwUp5nS)^jIuxuJHr;E=^ zBwG1*(i0pz_b+qrt;YYM>|7wahz+vez#g!{4CjghtJQZu;CqEjRsHYUVXBaBy*!}i zP{D>Pm)^}uHH>-C5GW7srKBKmu^O@A_4-mhBrTeF%(MeqGH98NVys&qZ<9Wlcd~jB z*%$yOG71hI@rFJ!}Pga6Xe=E-Z9^ zm-ehp=aY#Q+4;u8iNHdsSCGhIETgZgmV5DE6_evi_@aGTjfjJ4A4)@$wdwOFKu7s} zW_hamey*C@O1ADy^^JPd{-|!)$V@)H6ZV_D8ryI3W@S+n%yNUhS7gBqud{!muG!=$ zu($`^&3lv@V7TFFEz-Glt!+{07X-b>sGK%vZMW8Uc!tJjls4lIv&|$?x~Z*J+socH z$X)EYZHq=adp(_K)Ot285TmuiMcXClo0-1Wxel9|m4Dn4TT20>abyoNoxZw0(V#?KK1QxVXDM|(BQ^_R8UfUYHEuD@)`xETdS*0=H5#`^NNA6Q9&7EhKq1x#EEuqf zwZ^T$HE#d=!Tfz%iosZ_G)8zZx--tKl|JdDvq!h?F=2q9{>L?@e%{3WRm{w`9#d$I zNpR3Fh`B2)dCKl5vQ3C{F~G zxJcpj^T(byZj7JKPL4fgniga6rd30;Z>YY~#1%*{$F~%uL{W+saHDH$B&_P()w8a- zyq>C+hK_%6e|;5CbDdWIjt(padUq9e_s(bn1P9@gVet%+)dxE>3luc7z{2Yg5J)PH zrD&v;ZnyjX&J&ikfy|2~Z43>XwKo|Vv0w5K?v2Tgn1PzW@ zqyVC|Gtxlipc>fhiI%nf^fQyEj~tyidF=Gld{h0zkr$pl9Xf2i#N+asbpk9Tdkn|F%3xF(B(^Jp?c`&=b8N=kr+r@%YVfSQu;&g28X2bXC1N7-P)*qptv&Z zJ__RRyn=UmB!yp?68JG+t`MAw%z37%ID|{b%-9VJlwbj_)6c7U|WI@?&El->J z2^kH{WdRc+HzgXO(5nM@0v!>K-qhF2#VoZ$S}sJYJzR}ke^MC~ooq|>6g7p^98B4q zLT+EWIAsz^7NVXDfN7yYQWwT-new-?!-#KG;0lb^S5UKmOsVWQ6&zFW8w#Ei#Dx;E zoPL*>ncti$W?x(9!pi~Y1mQm3WJE`5PcUYjfOR;ZM z;1zKYecH!9{YA^o;uMK$*?iTMtkSW(^= zi}H6^l^2*j()?~zFF2oLDRJb|RJG}E(CCiA_y|pH7O{YDFU4or`N9*vY;kC8eO~B4 z!F&F`7Uz43NcAiK7~SUC$9G6Euk>u=GZS1)%EuG>IKklKmYg`=he)p5KXjE+9K*bc zudEK@q&9^6S^l*eNhKP`D8I(jz(F`2eo;igoo=JN@k+??;p_bcf>*rCUookJd7!+D zg&tLDkwoL2K5P#_8xE6{hei8FgVgXSAhj$ zJ=HI@3f$t9zFtAW;LnLt^;4}9x4OjLy@GMku(?g|@K9!2g>HADMz6+uhq46;R>is3 zG<@;1T`k?&Zpnjae73i_-=fBLop##IJCK)*#B6e<5i-KWSOAL)(>`slnK@NJ=M?#(7U5k^ai($&ep)f%|CM)mA;+8 z-Lw-bAJy4KmhU~CtJUOaPjwwxuQ!|O_~i6*WkHI{ZVkhvE^3a$wPI#!X`zE`mLJihh$%H?KxavF2$1>PAf%^OEbQ+WK@BjZoEyTmC5i(lG4F~Y^Bt?}(fXrqCM zHlH_>y|48e4QE>470X#>Xj!boMfWm|UF*W6+}we>Sl8MNUlUZ%B&qpE@Q^0Oq~4gR z`ulp?shM{gaPjKw1@)JM+<2HhI@#num?IJ9;@fji^bq0S9-n;_~*_OgkFH$HfUmb+l5C7hR#JLA)GTzL;sF!=T_F%#8MZvrQ2Y`*(*m`zzWTFrC zvz#>4f<<~kiAu?eXs#l@&)_LUG9B=ql8Yv+R5Zj4BlOQRObL#Du zw3wH+(&b(@BLOVc^VINlBNl+MF4j%JTQUd^^Of}}Dpadd1(iN40Bc04C#>s7dFVI@ zSi1B4`fb^&a#h;Fo1d7-rl|0ZdWROU%$i$6e3H1QP8fh+BoffOg0ydgd+g-dm#!>I zMe1B2x{3QkY@Pqe!vDXzUEY;%sn%Nn>;{ycinhpu@ ze@@dO3{0$reXJQSEN6Ax&I&SaubG-3qSzZw&C9Qyn(6gS4P#>}Vovtvf=xVo@55Zb z@f?|{ubm?)3F zZ5Do#SA6H|&BE@^Ec8>Ry+9D_-*^@tT{8=SajzH2Eo*0j9R$E^Bm1Giba4D?OqZTL zpa=>EZMfr((DYpeM}tfKyjF0n3srxLhX0CyqzMtK-VCa8IRdb^8oCXfA0*)oQM9=R zI0npz)&d5oG@jDZm-fl>Y!O&VCNJgBa+s;!?1$b|)P97_kLAzKbj=POF%fwK(5l;^ zaW&b!;|^=1tj7NT1Ij;5cYZ`rmY~xi2w3U73Em7tHN@ph(T4ah^YBIxS2~h1I|}G5 zTas`>d03J0m1R+Bv{j<27N?J$oAT)i2!SrVVNoM}KP93^gz8s9?L;3Q z7XQ31?G$zorJZ|JYaplTo6^WdCibZ}r0H!;?^1moaUn>YT7K&TCz7DNk#HwNfLe%cG+3=gpoz(a6QDsSWezCG+__v8oXvGnahYqAGT z#~w8CDj{FMLjC=D=^>J^;^?kGA~tBVmCv=`zGwP$ZEjA-!9fnw!_)q@4NpZRBTm0o zEo)0el*`9^22c71oT4pxMW0){#Mg|uoXoX3=RJken>#(cc`QD5uyGsJ263=ymY*n2 z={>q|ZffDu)M}&n7#m7|oZZLGZ72%ns#j;Kn|B2d`F~W$TEKb5#C$t8 z>h&M?`dRA#15KB9tO-%3xA!)b%s9*S;*6>eikDr-ZFEnWzWxE@tP4o9#Ut@vu6k%?O!^DSZ5OC9Tm8Ccq46lM9xGqMe@T}U z+D8aUDx{fJ2dj|1n`|i3~+!h*E@x`0{9s%Wc5?K9RvL@ z6A`@N2@nG!<_~AROA7mM{gjP%gm#vIKCqs&Cz3TUl282fo5kq4+_w}k9<1kZI%l!)lpIujK}n;mR@ zqnO>+Om9ZXWW9vi6mUlGzlP8-PgLl6>&zz+?#pWBSF__2k)MF=+;R(SVX< zXfqM8a6bcjDkz7>XjmjLo|z7w&DWjJ!ploy3xQQY8L3ROdYetu`K=tUz3trEs}SK0 z&LmX`hu7y3$yuLQJnT8@>ES`8D265HrG8S`ZQiC{rO|*Iq!9fqFs)>O}_92W~01 zGrWn^RDdgNJwX6WfbnpPZEBYtUsjZi#`!!J!McV>AJP`K`MImt0K5}dFA_bRHj;Jr zGC^B|8d!hoWl!%xB$?UYrC|xRKmby512G;F=bQn81@%U}urS#wK_!qW$4-xJ?Ddze z`gYs9183~QY@9KE*vi{M5{)fXYJz77cn=GsRAXIGl2&oApcL}O0Mo9km^K#p%8=-V zerP1d z1VZg8x=N~yT|tyi$?hdXIvfORRw4DlIpq4lUtijr>))(AFwwRhKX~}KKOlqV)fi&Q z@`$Einx61G5*Y8yVx{$P6ghl&?7(FzWOph! zMc`Y^@^6?NJXNkEgidi(C_Ak@ZC6`)pmwdU&*sfJ{{`jm>dJqCzIL+TuWTDvO1hY7 z`rygu^9yma39_;m6}+V2JLsuz2ermK|BPg&V_<7u|J?FIvoek{e7SLSs-B%yRqtCq zrr2W&{#b$UR`?~weo?`%DtKJ4cvgXyTLyZk>rd{MCvDt1l*mv5zPQNgkT zDL=9=DflZ2en7$ZDEM9l->2Y*75r5NKd0d575svNA5rk53jUgcA5-w-3jVr+A5!qk z3Vubwcj;}vtJwD`_WcU}jUKdjSFDRxn^*+6y?Nsc$mEp6tHz}s$mDzt$>_)|IR`7RJO~+~C zY>&_TJfX)C1@_^Vk~IH|5;7_go3}R;BP393OoB-iv6Sl>7}xtR-oN> z_O})MtO7~Kp=uPf4~?Rzede94R%~a9J9Z7~^Ksg2=%7b66N`aRM*@V*96%f|UQ6fvwJA&W^uZg+r}2h%Wf zSwRR%*dkuYUGEWFBpmy+6mrQPF(^bA#d_04%=L&Xp*bvzC3T9xw{FlA|L%;UrzkGx z2I|Wn+Po;&Y2ONNTVWU~s~Dhq30UZQ7#-S5Y3l}N=GO%VakL`>!%iAZNGF@&Ev;}@ z&xS(w8A{A3Q~&kzJIb%|E`oAOXOPwSU?vd@bBgq)vhVv;$j%zh+n-+TO=s9*54dDM z6vB>gGlF&NH>y@2B>*r$nw@)aaw$q+-AXcNM_GC4p8z(;mQ|mC?j$%zgYk zW=3O)1vZR(h#c3vWd_0a^u-1m5HPjCg=Nq}B+A6$e&8M(T_ot|+V#l;I#eQiBl~FK zmB2D)@5w+Z<~89wsecZ?JNqdASohT0{<8ZGQRnlNFc59z50S|7viu{vpk&kXAcfZj zr7r>y=CC6m>kEwA5O4Yl){xrQ%<3-gqxHXtFvj#sJo3pI7v$s4e85x&ApJBdgSX?k zULQ);F{2lbQ>@+l4IrFUxgL~wU=z;O_WfXgsxr8?do~n_0>*RU9Xmq^gtn-9S6uoN z&@jNhT~PZDK||e%EyOG__qAEOfKo^c*_sCf-xel|lqbiI9UnW5EK9RTo;z-Fak)Bp1d*6C#kFTOzUkPvA&Rl4q zo(nH`T{|M@eYL+H$Y$CMXsU9%>Hx45C%%DGG5tv8v2Ok%FU$Utg6~xD1qI)w;4c#d zR@|xXoKj%9(F6K^75Soq?@^%f`F))ZI`-!CZ_2HY=6ct#aTEM^P(Beu1MN8%ig}eB zCZY*3%Y)2l<{>srBTj$*kP?qYN+=cXb?Y94ckrJ_63w=Zu9+4?g~ozy1#kWapyfr9 z{RItX-G>Eq7yqjoN52|I($TdV=71jvDjtqH`dqwI&v|ll_Z@#f-pPkz!O0nChJKg= zw*fH3I|2XfCmkG*(2i=%D$$V<@yOx$$m!w34cWX#M)bkIVev^)b~^F96Z#Th{K12-H;uV zH~fLA;SZlXJ8c96;#PlH=#{t^@V^2YG6f>6DiJ$ePo1xIa*VICmg|9B_fw{`G_GM) zNZIfOVH5u*?{3ddpS^T%SEqW(aHnn}5|mI~vkJ5wF-wgOs=O%^pNa4(ywLalI7s$3 z`uJV#J_BJIvR!AiSzj1F%Ei7HyfQ{H3)O22!wvBj=VfBcU zPoDFKGgPEntE#yurFtLuU{|pqgp%idSS=nuLn$9%TMszhCqC(`mrWZBeo(LtBH8r; zIH8YGf`1!8PY?urAa;;Cky4NwK;Bv(&dD7Q`qqS;j49mudbP+Oe!Z}JP!Xu>8BstB zqX!ZP-N2VBzf_&Lk5J^-5wM;^pRb;TuoPEG535%qHZA=Sy0TnH)Hr-N4#@lrNMMbL zWg@g^FNem(lcMqBUA4T#M@#&LtdLNTlWg^YSEdZ03pFl96fi;wYMATo*}IvHbpd`0 zwfs>;Zn6n=){hJF;bavbzuktj;WqGjx4vUQX&l0E51kBpAo1bAA-!5;FS|r6Yf}bQQ0nMR*qsT!*>QDZuVU76Jw(iei2DaPl94^EocAeE?_&bAx3;b{`vJu) z(R@ZRaq{dZ6cZ`PJg+~e$2-;P9)gyVPyh0j&qnj$yu!C80U7ioIpgAm`2Q2=_FwsU zYM-lch#MQ%{*T6`7d;A^k=+N_w)O4)U#a!~-$Qe;S=X=j_UwKTg$KrG&N%g=%@|Pn Hw!;4hneAH- diff --git a/PythonHome/Lib/idlelib/FileList.py b/PythonHome/Lib/idlelib/FileList.py new file mode 100644 index 0000000000..8318ff17b2 --- /dev/null +++ b/PythonHome/Lib/idlelib/FileList.py @@ -0,0 +1,124 @@ +import os +from Tkinter import * +import tkMessageBox + + +class FileList: + + # N.B. this import overridden in PyShellFileList. + from idlelib.EditorWindow import EditorWindow + + def __init__(self, root): + self.root = root + self.dict = {} + self.inversedict = {} + self.vars = {} # For EditorWindow.getrawvar (shared Tcl variables) + + def open(self, filename, action=None): + assert filename + filename = self.canonize(filename) + if os.path.isdir(filename): + # This can happen when bad filename is passed on command line: + tkMessageBox.showerror( + "File Error", + "%r is a directory." % (filename,), + master=self.root) + return None + key = os.path.normcase(filename) + if key in self.dict: + edit = self.dict[key] + edit.top.wakeup() + return edit + if action: + # Don't create window, perform 'action', e.g. open in same window + return action(filename) + else: + return self.EditorWindow(self, filename, key) + + def gotofileline(self, filename, lineno=None): + edit = self.open(filename) + if edit is not None and lineno is not None: + edit.gotoline(lineno) + + def new(self, filename=None): + return self.EditorWindow(self, filename) + + def close_all_callback(self, *args, **kwds): + for edit in self.inversedict.keys(): + reply = edit.close() + if reply == "cancel": + break + return "break" + + def unregister_maybe_terminate(self, edit): + try: + key = self.inversedict[edit] + except KeyError: + print "Don't know this EditorWindow object. (close)" + return + if key: + del self.dict[key] + del self.inversedict[edit] + if not self.inversedict: + self.root.quit() + + def filename_changed_edit(self, edit): + edit.saved_change_hook() + try: + key = self.inversedict[edit] + except KeyError: + print "Don't know this EditorWindow object. (rename)" + return + filename = edit.io.filename + if not filename: + if key: + del self.dict[key] + self.inversedict[edit] = None + return + filename = self.canonize(filename) + newkey = os.path.normcase(filename) + if newkey == key: + return + if newkey in self.dict: + conflict = self.dict[newkey] + self.inversedict[conflict] = None + tkMessageBox.showerror( + "Name Conflict", + "You now have multiple edit windows open for %r" % (filename,), + master=self.root) + self.dict[newkey] = edit + self.inversedict[edit] = newkey + if key: + try: + del self.dict[key] + except KeyError: + pass + + def canonize(self, filename): + if not os.path.isabs(filename): + try: + pwd = os.getcwd() + except os.error: + pass + else: + filename = os.path.join(pwd, filename) + return os.path.normpath(filename) + + +def _test(): + from idlelib.EditorWindow import fixwordbreaks + import sys + root = Tk() + fixwordbreaks(root) + root.withdraw() + flist = FileList(root) + if sys.argv[1:]: + for filename in sys.argv[1:]: + flist.open(filename) + else: + flist.new() + if flist.inversedict: + root.mainloop() + +if __name__ == '__main__': + _test() diff --git a/PythonHome/Lib/idlelib/FileList.pyc b/PythonHome/Lib/idlelib/FileList.pyc deleted file mode 100644 index 760958ffce258445b54aebd4170af16c91f0406e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3783 zcma)9U2i1C6}{E-VbAP%*Si>4B2ZdL3$sM)2tfi$%qp-;5(yaCo|U{rqdRJV_doY)R6T??o;}zC1#|#m-SvY)g{1j6EqH zi*0h+WU6r3--hz^fA|~p4aAboTO~*TnojJesVi3oc^Lc%Uzeh>P;8cFc`|JXHZ+M> z@0fIH(Dz1;+Cmv-L56*hVHMx@?0duO2`n*Qt*}n!Xq+Nor8W8OG-9Ho|h^lXz0#F&TZ(_`>s=1M@*Pw+WpqtOJ;e<=!{-3fkAk)`V@TyY zT!TK=TsCCLT{Nl#*M$cRfd6q(|qI<;66PoDG=Xk{KxTnHn^Y#`a7xV~E0*<`V?w>){OJd7rj zFh+A6#p8X9>KPUD5@6Re+f@>1IE{P2d5dOobD0MNTJYpBds&*O7vruJZ;1i382Q`Z z0kh!~fUCH#Z!6F~K(SeY^Mguqkq#+$A%rU+G7STF5ADM|d$aV%Sw8p6Gtk9V()aV@ z5tw7&_xtM6-6~!h%x$dw#4eOG^hmFd{P_h=B^|4-NwH&h1T{))qc(J;9wSs08{dsBZ&nU`(7@2A~eFa{D^Go`(0` zUxXKnG;q}^cVnLB;z$G9qRfCJ5sb9zJ78AW+fsg3dcf%(b!4P0Pr^{1$68|e-&z|% z^<2}^n(&{c_9l{#>%>ZXOAb&cQ5^vHL|I2mPPKMNOAgZyJ5(2x9@L5}(`foVv$(#T zhxLc&_e>KEPh{N%unhW7Dwl?u=z-fuAU6a^p+tSx?O@3Ol4%tb2WSMfW{un)uuJr^>Yy5d8u((|i$ z93(`X-pksJU9Z#bz1VB@8lA09uj9vO7MWZ;4HV$>i9)fkxzxWGlVA-^rYm1n=d(tr5%3(7~}I1m>ko_IkC1}*(CGEep$4-8JsxYa z=4pAB6wzFxq^Ln5ep=-~!@nvx(-vZ;fQqS=^Kfj(DU54V~ zN(5RQioBme*a diff --git a/PythonHome/Lib/idlelib/FormatParagraph.py b/PythonHome/Lib/idlelib/FormatParagraph.py new file mode 100644 index 0000000000..9b10c0a760 --- /dev/null +++ b/PythonHome/Lib/idlelib/FormatParagraph.py @@ -0,0 +1,193 @@ +"""Extension to format a paragraph or selection to a max width. + +Does basic, standard text formatting, and also understands Python +comment blocks. Thus, for editing Python source code, this +extension is really only suitable for reformatting these comment +blocks or triple-quoted strings. + +Known problems with comment reformatting: +* If there is a selection marked, and the first line of the + selection is not complete, the block will probably not be detected + as comments, and will have the normal "text formatting" rules + applied. +* If a comment block has leading whitespace that mixes tabs and + spaces, they will not be considered part of the same block. +* Fancy comments, like this bulleted list, aren't handled :-) +""" + +import re +from idlelib.configHandler import idleConf + +class FormatParagraph: + + menudefs = [ + ('format', [ # /s/edit/format dscherer@cmu.edu + ('Format Paragraph', '<>'), + ]) + ] + + def __init__(self, editwin): + self.editwin = editwin + + def close(self): + self.editwin = None + + def format_paragraph_event(self, event, limit=None): + """Formats paragraph to a max width specified in idleConf. + + If text is selected, format_paragraph_event will start breaking lines + at the max width, starting from the beginning selection. + + If no text is selected, format_paragraph_event uses the current + cursor location to determine the paragraph (lines of text surrounded + by blank lines) and formats it. + + The length limit parameter is for testing with a known value. + """ + if limit == None: + limit = idleConf.GetOption( + 'main', 'FormatParagraph', 'paragraph', type='int') + text = self.editwin.text + first, last = self.editwin.get_selection_indices() + if first and last: + data = text.get(first, last) + comment_header = get_comment_header(data) + else: + first, last, comment_header, data = \ + find_paragraph(text, text.index("insert")) + if comment_header: + newdata = reformat_comment(data, limit, comment_header) + else: + newdata = reformat_paragraph(data, limit) + text.tag_remove("sel", "1.0", "end") + + if newdata != data: + text.mark_set("insert", first) + text.undo_block_start() + text.delete(first, last) + text.insert(first, newdata) + text.undo_block_stop() + else: + text.mark_set("insert", last) + text.see("insert") + return "break" + +def find_paragraph(text, mark): + """Returns the start/stop indices enclosing the paragraph that mark is in. + + Also returns the comment format string, if any, and paragraph of text + between the start/stop indices. + """ + lineno, col = map(int, mark.split(".")) + line = text.get("%d.0" % lineno, "%d.end" % lineno) + + # Look for start of next paragraph if the index passed in is a blank line + while text.compare("%d.0" % lineno, "<", "end") and is_all_white(line): + lineno = lineno + 1 + line = text.get("%d.0" % lineno, "%d.end" % lineno) + first_lineno = lineno + comment_header = get_comment_header(line) + comment_header_len = len(comment_header) + + # Once start line found, search for end of paragraph (a blank line) + while get_comment_header(line)==comment_header and \ + not is_all_white(line[comment_header_len:]): + lineno = lineno + 1 + line = text.get("%d.0" % lineno, "%d.end" % lineno) + last = "%d.0" % lineno + + # Search back to beginning of paragraph (first blank line before) + lineno = first_lineno - 1 + line = text.get("%d.0" % lineno, "%d.end" % lineno) + while lineno > 0 and \ + get_comment_header(line)==comment_header and \ + not is_all_white(line[comment_header_len:]): + lineno = lineno - 1 + line = text.get("%d.0" % lineno, "%d.end" % lineno) + first = "%d.0" % (lineno+1) + + return first, last, comment_header, text.get(first, last) + +# This should perhaps be replaced with textwrap.wrap +def reformat_paragraph(data, limit): + """Return data reformatted to specified width (limit).""" + lines = data.split("\n") + i = 0 + n = len(lines) + while i < n and is_all_white(lines[i]): + i = i+1 + if i >= n: + return data + indent1 = get_indent(lines[i]) + if i+1 < n and not is_all_white(lines[i+1]): + indent2 = get_indent(lines[i+1]) + else: + indent2 = indent1 + new = lines[:i] + partial = indent1 + while i < n and not is_all_white(lines[i]): + # XXX Should take double space after period (etc.) into account + words = re.split("(\s+)", lines[i]) + for j in range(0, len(words), 2): + word = words[j] + if not word: + continue # Can happen when line ends in whitespace + if len((partial + word).expandtabs()) > limit and \ + partial != indent1: + new.append(partial.rstrip()) + partial = indent2 + partial = partial + word + " " + if j+1 < len(words) and words[j+1] != " ": + partial = partial + " " + i = i+1 + new.append(partial.rstrip()) + # XXX Should reformat remaining paragraphs as well + new.extend(lines[i:]) + return "\n".join(new) + +def reformat_comment(data, limit, comment_header): + """Return data reformatted to specified width with comment header.""" + + # Remove header from the comment lines + lc = len(comment_header) + data = "\n".join(line[lc:] for line in data.split("\n")) + # Reformat to maxformatwidth chars or a 20 char width, + # whichever is greater. + format_width = max(limit - len(comment_header), 20) + newdata = reformat_paragraph(data, format_width) + # re-split and re-insert the comment header. + newdata = newdata.split("\n") + # If the block ends in a \n, we dont want the comment prefix + # inserted after it. (Im not sure it makes sense to reformat a + # comment block that is not made of complete lines, but whatever!) + # Can't think of a clean solution, so we hack away + block_suffix = "" + if not newdata[-1]: + block_suffix = "\n" + newdata = newdata[:-1] + return '\n'.join(comment_header+line for line in newdata) + block_suffix + +def is_all_white(line): + """Return True if line is empty or all whitespace.""" + + return re.match(r"^\s*$", line) is not None + +def get_indent(line): + """Return the initial space or tab indent of line.""" + return re.match(r"^([ \t]*)", line).group() + +def get_comment_header(line): + """Return string with leading whitespace and '#' from line or ''. + + A null return indicates that the line is not a comment line. A non- + null return, such as ' #', will be used to find the other lines of + a comment block with the same indent. + """ + m = re.match(r"^([ \t]*#*)", line) + if m is None: return "" + return m.group(1) + +if __name__ == "__main__": + import unittest + unittest.main('idlelib.idle_test.test_formatparagraph', + verbosity=2, exit=False) diff --git a/PythonHome/Lib/idlelib/FormatParagraph.pyc b/PythonHome/Lib/idlelib/FormatParagraph.pyc deleted file mode 100644 index 2680d6c3f358c8bd8c2b480b730ec88a46da446b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6912 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 GrepDialop -> OutputWindow -> EditorWindow + +def grep(text, io=None, flist=None): + root = text._root() + engine = SearchEngine.get(root) + if not hasattr(engine, "_grepdialog"): + engine._grepdialog = GrepDialog(root, engine, flist) + dialog = engine._grepdialog + searchphrase = text.get("sel.first", "sel.last") + dialog.open(text, searchphrase, io) + +class GrepDialog(SearchDialogBase): + + title = "Find in Files Dialog" + icon = "Grep" + needwrapbutton = 0 + + def __init__(self, root, engine, flist): + SearchDialogBase.__init__(self, root, engine) + self.flist = flist + self.globvar = StringVar(root) + self.recvar = BooleanVar(root) + + def open(self, text, searchphrase, io=None): + SearchDialogBase.open(self, text, searchphrase) + if io: + path = io.filename or "" + else: + path = "" + dir, base = os.path.split(path) + head, tail = os.path.splitext(base) + if not tail: + tail = ".py" + self.globvar.set(os.path.join(dir, "*" + tail)) + + def create_entries(self): + SearchDialogBase.create_entries(self) + self.globent = self.make_entry("In files:", self.globvar) + + def create_other_buttons(self): + f = self.make_frame() + + btn = Checkbutton(f, anchor="w", + variable=self.recvar, + text="Recurse down subdirectories") + btn.pack(side="top", fill="both") + btn.select() + + def create_command_buttons(self): + SearchDialogBase.create_command_buttons(self) + self.make_button("Search Files", self.default_command, 1) + + def default_command(self, event=None): + prog = self.engine.getprog() + if not prog: + return + path = self.globvar.get() + if not path: + self.top.bell() + return + from idlelib.OutputWindow import OutputWindow # leave here! + save = sys.stdout + try: + sys.stdout = OutputWindow(self.flist) + self.grep_it(prog, path) + finally: + sys.stdout = save + + def grep_it(self, prog, path): + dir, base = os.path.split(path) + list = self.findfiles(dir, base, self.recvar.get()) + list.sort() + self.close() + pat = self.engine.getpat() + print("Searching %r in %s ..." % (pat, path)) + hits = 0 + try: + for fn in list: + try: + with open(fn) as f: + for lineno, line in enumerate(f, 1): + if line[-1:] == '\n': + line = line[:-1] + if prog.search(line): + sys.stdout.write("%s: %s: %s\n" % + (fn, lineno, line)) + hits += 1 + except IOError as msg: + print(msg) + print(("Hits found: %s\n" + "(Hint: right-click to open locations.)" + % hits) if hits else "No hits.") + except AttributeError: + # Tk window has been closed, OutputWindow.text = None, + # so in OW.write, OW.text.insert fails. + pass + + def findfiles(self, dir, base, rec): + try: + names = os.listdir(dir or os.curdir) + except os.error as msg: + print(msg) + return [] + list = [] + subdirs = [] + for name in names: + fn = os.path.join(dir, name) + if os.path.isdir(fn): + subdirs.append(fn) + else: + if fnmatch.fnmatch(name, base): + list.append(fn) + if rec: + for subdir in subdirs: + list.extend(self.findfiles(subdir, base, rec)) + return list + + def close(self, event=None): + if self.top: + self.top.grab_release() + self.top.withdraw() + + +def _grep_dialog(parent): # for htest + from idlelib.PyShell import PyShellFileList + root = Tk() + root.title("Test GrepDialog") + width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) + root.geometry("+%d+%d"%(x, y + 150)) + + flist = PyShellFileList(root) + text = Text(root, height=5) + text.pack() + + def show_grep_dialog(): + text.tag_add(SEL, "1.0", END) + grep(text, flist=flist) + text.tag_remove(SEL, "1.0", END) + + button = Button(root, text="Show GrepDialog", command=show_grep_dialog) + button.pack() + root.mainloop() + +if __name__ == "__main__": + import unittest + unittest.main('idlelib.idle_test.test_grep', verbosity=2, exit=False) + + from idlelib.idle_test.htest import run + run(_grep_dialog) diff --git a/PythonHome/Lib/idlelib/GrepDialog.pyc b/PythonHome/Lib/idlelib/GrepDialog.pyc deleted file mode 100644 index a4e27a52608c78258576243d920c012ae1eb82aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6126 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 and self.bracketing[i][1] > + self.bracketing[i-1][1] + for i in range(len(self.bracketing))] + + self.set_index(index) + + def set_index(self, index): + """Set the index to which the functions relate. + + The index must be in the same statement. + """ + indexinrawtext = (len(self.rawtext) - + len(self.text.get(index, self.stopatindex))) + if indexinrawtext < 0: + raise ValueError("Index %s precedes the analyzed statement" + % index) + self.indexinrawtext = indexinrawtext + # find the rightmost bracket to which index belongs + self.indexbracket = 0 + while (self.indexbracket < len(self.bracketing)-1 and + self.bracketing[self.indexbracket+1][0] < self.indexinrawtext): + self.indexbracket += 1 + if (self.indexbracket < len(self.bracketing)-1 and + self.bracketing[self.indexbracket+1][0] == self.indexinrawtext and + not self.isopener[self.indexbracket+1]): + self.indexbracket += 1 + + def is_in_string(self): + """Is the index given to the HyperParser in a string?""" + # The bracket to which we belong should be an opener. + # If it's an opener, it has to have a character. + return (self.isopener[self.indexbracket] and + self.rawtext[self.bracketing[self.indexbracket][0]] + in ('"', "'")) + + def is_in_code(self): + """Is the index given to the HyperParser in normal code?""" + return (not self.isopener[self.indexbracket] or + self.rawtext[self.bracketing[self.indexbracket][0]] + not in ('#', '"', "'")) + + def get_surrounding_brackets(self, openers='([{', mustclose=False): + """Return bracket indexes or None. + + If the index given to the HyperParser is surrounded by a + bracket defined in openers (or at least has one before it), + return the indices of the opening bracket and the closing + bracket (or the end of line, whichever comes first). + + If it is not surrounded by brackets, or the end of line comes + before the closing bracket and mustclose is True, returns None. + """ + + bracketinglevel = self.bracketing[self.indexbracket][1] + before = self.indexbracket + while (not self.isopener[before] or + self.rawtext[self.bracketing[before][0]] not in openers or + self.bracketing[before][1] > bracketinglevel): + before -= 1 + if before < 0: + return None + bracketinglevel = min(bracketinglevel, self.bracketing[before][1]) + after = self.indexbracket + 1 + while (after < len(self.bracketing) and + self.bracketing[after][1] >= bracketinglevel): + after += 1 + + beforeindex = self.text.index("%s-%dc" % + (self.stopatindex, len(self.rawtext)-self.bracketing[before][0])) + if (after >= len(self.bracketing) or + self.bracketing[after][0] > len(self.rawtext)): + if mustclose: + return None + afterindex = self.stopatindex + else: + # We are after a real char, so it is a ')' and we give the + # index before it. + afterindex = self.text.index( + "%s-%dc" % (self.stopatindex, + len(self.rawtext)-(self.bracketing[after][0]-1))) + + return beforeindex, afterindex + + # Ascii chars that may be in a white space + _whitespace_chars = " \t\n\\" + # Ascii chars that may be in an identifier + _id_chars = string.ascii_letters + string.digits + "_" + # Ascii chars that may be the first char of an identifier + _id_first_chars = string.ascii_letters + "_" + + # Given a string and pos, return the number of chars in the + # identifier which ends at pos, or 0 if there is no such one. Saved + # words are not identifiers. + def _eat_identifier(self, str, limit, pos): + i = pos + while i > limit and str[i-1] in self._id_chars: + i -= 1 + if (i < pos and (str[i] not in self._id_first_chars or + keyword.iskeyword(str[i:pos]))): + i = pos + return pos - i + + def get_expression(self): + """Return a string with the Python expression which ends at the + given index, which is empty if there is no real one. + """ + if not self.is_in_code(): + raise ValueError("get_expression should only be called" + "if index is inside a code.") + + rawtext = self.rawtext + bracketing = self.bracketing + + brck_index = self.indexbracket + brck_limit = bracketing[brck_index][0] + pos = self.indexinrawtext + + last_identifier_pos = pos + postdot_phase = True + + while 1: + # Eat whitespaces, comments, and if postdot_phase is False - a dot + while 1: + if pos>brck_limit and rawtext[pos-1] in self._whitespace_chars: + # Eat a whitespace + pos -= 1 + elif (not postdot_phase and + pos > brck_limit and rawtext[pos-1] == '.'): + # Eat a dot + pos -= 1 + postdot_phase = True + # The next line will fail if we are *inside* a comment, + # but we shouldn't be. + elif (pos == brck_limit and brck_index > 0 and + rawtext[bracketing[brck_index-1][0]] == '#'): + # Eat a comment + brck_index -= 2 + brck_limit = bracketing[brck_index][0] + pos = bracketing[brck_index+1][0] + else: + # If we didn't eat anything, quit. + break + + if not postdot_phase: + # We didn't find a dot, so the expression end at the + # last identifier pos. + break + + ret = self._eat_identifier(rawtext, brck_limit, pos) + if ret: + # There is an identifier to eat + pos = pos - ret + last_identifier_pos = pos + # Now, to continue the search, we must find a dot. + postdot_phase = False + # (the loop continues now) + + elif pos == brck_limit: + # We are at a bracketing limit. If it is a closing + # bracket, eat the bracket, otherwise, stop the search. + level = bracketing[brck_index][1] + while brck_index > 0 and bracketing[brck_index-1][1] > level: + brck_index -= 1 + if bracketing[brck_index][0] == brck_limit: + # We were not at the end of a closing bracket + break + pos = bracketing[brck_index][0] + brck_index -= 1 + brck_limit = bracketing[brck_index][0] + last_identifier_pos = pos + if rawtext[pos] in "([": + # [] and () may be used after an identifier, so we + # continue. postdot_phase is True, so we don't allow a dot. + pass + else: + # We can't continue after other types of brackets + if rawtext[pos] in "'\"": + # Scan a string prefix + while pos > 0 and rawtext[pos - 1] in "rRbBuU": + pos -= 1 + last_identifier_pos = pos + break + + else: + # We've found an operator or something. + break + + return rawtext[last_identifier_pos:self.indexinrawtext] + + +if __name__ == '__main__': + import unittest + unittest.main('idlelib.idle_test.test_hyperparser', verbosity=2) diff --git a/PythonHome/Lib/idlelib/HyperParser.pyc b/PythonHome/Lib/idlelib/HyperParser.pyc deleted file mode 100644 index ba42c645b7def38c5edef388b3029a818759d92e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6520 zcmb_gTW=&s6|U;J&yKy`i*Ly$=_Fd>&2A>yNGMAZ0^|lkusH372xmjno^IQ1x4Xw( zHM@3VODLNco_I&_hduPYtbRoqo^ zLw%&wJ*B?C-cU(X#Z9&Asj?U^ZK?H^N?K~Ct>Tu7QFhclt#uAYo?2TuL*{=)v04^) z(m3&>_)e4$lGqyN&0t_;ux$0vwfg>~>hBfCW{3V(dIuBI9F+GW3j#j=L9#n63sAvGoaD9| z+4KiRoPf$S2S*`_V~AMfQT70_E{OTYmZO0km5EBA|i!jRK zdavq}#tf}QITgrCS5r$i8 z2^%G)wz6Gy)aE+uc=5Qy{bI_(F}mw&=ZsMAsUs}xas`}q5tB6sXN34H2P@W?eugf+ z+fnAvqzg9mFgZu><}M%>81__oS)&AnWr&sIT(s5c z+juA$Ji>2ii25K#UHgB zM$a;(o3zkak{-bICAy6zFn(Ou)`ts3UIPRzLMijFb9SE~B8I~fTNo)w% zk-@FR+IcM91jlfzDB^HPbi{a6TKf=2!i`ay#o=H(D#JAALf9?b9OVO{db7wAk)Bku z!p>lcjkdyJncOL(9Q3INvLlq0(OpU{do;Ef0zGLTIHppV8fKB9Yf%O zU$^myZtC-TNw@WacOLZ_uc^EBNAyf>uHMmSYc=ndH=wgp<=oM0_{<^%!{Om!78tGS zWBg@*o!EqPwRG(9Gy{Wov6pWu94H)pfbIeYKh!D*8MGlVK+7R}OC78VZD6otGRE8` z()f*xwW}FK;$u zL0q)Q(2m)A@X!8afuMw;XS_wf_b(eC2L%}oG7a*oU@|^gE2wi*B5d#o)&)E&;=Tco zymLWf*7u@pl)M3CEiK(h#7gt=furk6S9OpA;!*G@iWNFb;IkmO1Xod;PkM7COu_%(dGb zTkLr(e9LLfso#YUn2k!D0(9CVf-;F&UvUu4WBP;~)2AeO1ka!&=%ZMX{Zl8wH5Q_2 z>Pe!BsOS`m5wu9n31%XFRuVTmLlEX5lbv3o`JJ^zY(IWEKgBO{?A~d?$08oDa`-isW!&X`b*Fg?W|+gaN51fQ86Kfth|%-aH(*d!TZb|sL|;cmAy5WRet zH?}p>?J%3pUlJbfX7(8pR5T&@(nJcRx{`=PstR8}hSh=ucbwd>&*yjmA8y7qP zx4m+0LZfuj5=`VGRLj<3cY5~RwiktGnZug(WXVdcZL&Xr{Xh`Ey{>APXpNFBy{S2GEPIyHn-i-^sDP0GO~`o;u!*`-|60#kP{BrWY#f3 z{U4zL6d-tAC*I&V@?3t2X_o_{B}tbQ;~%>x;I!Y7TPGm|$Z}9EkjW0%DaE)Wem54rW z_-PH<7@5Eobu1TYg|UPHJoQ=0{98sHHmNBT%Xn$wUeGU{ zlz0Ef`kgTeNLcOsPfoNc<48yrRefTQBAZk0GTvZ#fX;jSkvHyYOV@4h0C^|$@AMf| z!%jBHg;nS~G2vzJ9k*-fXcc?rM~W`gH`L?qLCkyzN37yrROO)l-PF2U#pDtHjGlf9um^izpT3}B2FKyajX5>dzKZC-&GyjxGP zGTX%{LqN*$%!y0OAj&d4OKiHZOiC$UO!?j_Sz=$XU(i87tRD~vQ(iRX@nhv(`FZLI z0q8Q=cy;t$cVW3s4Lr?al1sbP`YQV5TF$s5ZxfvSn_kVU=_kDz-O|3-)t%aszJ%XdJzuMPO?>m1)5X`R z^=h;FDU4k7>L@vK$FL*S(cFaFJJ#FwAlD3`0>x815DEC_^*2f(dd{ z3wY-W#4cZFjgJk%n<&I~?xG~RiOe8P!wmXJkeo2?$LUsTP4F^Te3=Ce6x>8{qA01E zOX&NoH@1LxFnLU2s(@X-(3$VFJI%9Ko8ColrqStCo7s!-;uM-EFspj4>+?5+qu4%+ zaGMYM?hQx65R$45WMcME+|vox!E%XLVHg(!Xya{k1UwefTTzyGIFT&)4u{$(MtGGW g8*x<%bK0E>m6x3vUZD~tXf=^3^zgoO;qUzY50w3B", self.return_event) + top.bind("", self.do_ok) + top.protocol("WM_DELETE_WINDOW", self.wm_delete_window) + top.wm_title("I/O Warning") + top.wm_iconname("I/O Warning") + self.top = top + + l1 = Label(top, + text="Non-ASCII found, yet no encoding declared. Add a line like") + l1.pack(side=TOP, anchor=W) + l2 = Entry(top, font="courier") + l2.insert(0, "# -*- coding: %s -*-" % enc) + # For some reason, the text is not selectable anymore if the + # widget is disabled. + # l2['state'] = DISABLED + l2.pack(side=TOP, anchor = W, fill=X) + l3 = Label(top, text="to your file\n" + "Choose OK to save this file as %s\n" + "Edit your general options to silence this warning" % enc) + l3.pack(side=TOP, anchor = W) + + buttons = Frame(top) + buttons.pack(side=TOP, fill=X) + # Both return and cancel mean the same thing: do nothing + self.default = self.cancel = 0 + b1 = Button(buttons, text="Ok", default="active", + command=self.do_ok) + b1.pack(side=LEFT, fill=BOTH, expand=1) + b2 = Button(buttons, text="Edit my file", + command=self.do_edit) + b2.pack(side=LEFT, fill=BOTH, expand=1) + + self._set_transient(master) + + def do_ok(self): + self.done(0) + + def do_edit(self): + self.done(1) + +def coding_spec(str): + """Return the encoding declaration according to PEP 263. + + Raise LookupError if the encoding is declared but unknown. + """ + # Only consider the first two lines + lst = str.split("\n", 2)[:2] + for line in lst: + match = coding_re.match(line) + if match is not None: + break + else: + return None + name = match.group(1) + # Check whether the encoding is known + import codecs + try: + codecs.lookup(name) + except LookupError: + # The standard encoding error does not indicate the encoding + raise LookupError, "Unknown encoding "+name + return name + + +class IOBinding: + + def __init__(self, editwin): + self.editwin = editwin + self.text = editwin.text + self.__id_open = self.text.bind("<>", self.open) + self.__id_save = self.text.bind("<>", self.save) + self.__id_saveas = self.text.bind("<>", + self.save_as) + self.__id_savecopy = self.text.bind("<>", + self.save_a_copy) + self.fileencoding = None + self.__id_print = self.text.bind("<>", self.print_window) + + def close(self): + # Undo command bindings + self.text.unbind("<>", self.__id_open) + self.text.unbind("<>", self.__id_save) + self.text.unbind("<>",self.__id_saveas) + self.text.unbind("<>", self.__id_savecopy) + self.text.unbind("<>", self.__id_print) + # Break cycles + self.editwin = None + self.text = None + self.filename_change_hook = None + + def get_saved(self): + return self.editwin.get_saved() + + def set_saved(self, flag): + self.editwin.set_saved(flag) + + def reset_undo(self): + self.editwin.reset_undo() + + filename_change_hook = None + + def set_filename_change_hook(self, hook): + self.filename_change_hook = hook + + filename = None + dirname = None + + def set_filename(self, filename): + if filename and os.path.isdir(filename): + self.filename = None + self.dirname = filename + else: + self.filename = filename + self.dirname = None + self.set_saved(1) + if self.filename_change_hook: + self.filename_change_hook() + + def open(self, event=None, editFile=None): + flist = self.editwin.flist + # Save in case parent window is closed (ie, during askopenfile()). + if flist: + if not editFile: + filename = self.askopenfile() + else: + filename=editFile + if filename: + # If editFile is valid and already open, flist.open will + # shift focus to its existing window. + # If the current window exists and is a fresh unnamed, + # unmodified editor window (not an interpreter shell), + # pass self.loadfile to flist.open so it will load the file + # in the current window (if the file is not already open) + # instead of a new window. + if (self.editwin and + not getattr(self.editwin, 'interp', None) and + not self.filename and + self.get_saved()): + flist.open(filename, self.loadfile) + else: + flist.open(filename) + else: + if self.text: + self.text.focus_set() + return "break" + + # Code for use outside IDLE: + if self.get_saved(): + reply = self.maybesave() + if reply == "cancel": + self.text.focus_set() + return "break" + if not editFile: + filename = self.askopenfile() + else: + filename=editFile + if filename: + self.loadfile(filename) + else: + self.text.focus_set() + return "break" + + eol = r"(\r\n)|\n|\r" # \r\n (Windows), \n (UNIX), or \r (Mac) + eol_re = re.compile(eol) + eol_convention = os.linesep # Default + + def loadfile(self, filename): + try: + # open the file in binary mode so that we can handle + # end-of-line convention ourselves. + with open(filename, 'rb') as f: + chars = f.read() + except IOError as msg: + tkMessageBox.showerror("I/O Error", str(msg), master=self.text) + return False + + chars = self.decode(chars) + # We now convert all end-of-lines to '\n's + firsteol = self.eol_re.search(chars) + if firsteol: + self.eol_convention = firsteol.group(0) + if isinstance(self.eol_convention, unicode): + # Make sure it is an ASCII string + self.eol_convention = self.eol_convention.encode("ascii") + chars = self.eol_re.sub(r"\n", chars) + + self.text.delete("1.0", "end") + self.set_filename(None) + self.text.insert("1.0", chars) + self.reset_undo() + self.set_filename(filename) + self.text.mark_set("insert", "1.0") + self.text.yview("insert") + self.updaterecentfileslist(filename) + return True + + def decode(self, chars): + """Create a Unicode string + + If that fails, let Tcl try its best + """ + # Check presence of a UTF-8 signature first + if chars.startswith(BOM_UTF8): + try: + chars = chars[3:].decode("utf-8") + except UnicodeError: + # has UTF-8 signature, but fails to decode... + return chars + else: + # Indicates that this file originally had a BOM + self.fileencoding = BOM_UTF8 + return chars + # Next look for coding specification + try: + enc = coding_spec(chars) + except LookupError as name: + tkMessageBox.showerror( + title="Error loading the file", + message="The encoding '%s' is not known to this Python "\ + "installation. The file may not display correctly" % name, + master = self.text) + enc = None + if enc: + try: + return unicode(chars, enc) + except UnicodeError: + pass + # If it is ASCII, we need not to record anything + try: + return unicode(chars, 'ascii') + except UnicodeError: + pass + # Finally, try the locale's encoding. This is deprecated; + # the user should declare a non-ASCII encoding + try: + chars = unicode(chars, encoding) + self.fileencoding = encoding + except UnicodeError: + pass + return chars + + def maybesave(self): + if self.get_saved(): + return "yes" + message = "Do you want to save %s before closing?" % ( + self.filename or "this untitled document") + confirm = tkMessageBox.askyesnocancel( + title="Save On Close", + message=message, + default=tkMessageBox.YES, + master=self.text) + if confirm: + reply = "yes" + self.save(None) + if not self.get_saved(): + reply = "cancel" + elif confirm is None: + reply = "cancel" + else: + reply = "no" + self.text.focus_set() + return reply + + def save(self, event): + if not self.filename: + self.save_as(event) + else: + if self.writefile(self.filename): + self.set_saved(True) + try: + self.editwin.store_file_breaks() + except AttributeError: # may be a PyShell + pass + self.text.focus_set() + return "break" + + def save_as(self, event): + filename = self.asksavefile() + if filename: + if self.writefile(filename): + self.set_filename(filename) + self.set_saved(1) + try: + self.editwin.store_file_breaks() + except AttributeError: + pass + self.text.focus_set() + self.updaterecentfileslist(filename) + return "break" + + def save_a_copy(self, event): + filename = self.asksavefile() + if filename: + self.writefile(filename) + self.text.focus_set() + self.updaterecentfileslist(filename) + return "break" + + def writefile(self, filename): + self.fixlastline() + chars = self.encode(self.text.get("1.0", "end-1c")) + if self.eol_convention != "\n": + chars = chars.replace("\n", self.eol_convention) + try: + with open(filename, "wb") as f: + f.write(chars) + return True + except IOError as msg: + tkMessageBox.showerror("I/O Error", str(msg), + master=self.text) + return False + + def encode(self, chars): + if isinstance(chars, types.StringType): + # This is either plain ASCII, or Tk was returning mixed-encoding + # text to us. Don't try to guess further. + return chars + # See whether there is anything non-ASCII in it. + # If not, no need to figure out the encoding. + try: + return chars.encode('ascii') + except UnicodeError: + pass + # If there is an encoding declared, try this first. + try: + enc = coding_spec(chars) + failed = None + except LookupError as msg: + failed = msg + enc = None + if enc: + try: + return chars.encode(enc) + except UnicodeError: + failed = "Invalid encoding '%s'" % enc + if failed: + tkMessageBox.showerror( + "I/O Error", + "%s. Saving as UTF-8" % failed, + master = self.text) + # If there was a UTF-8 signature, use that. This should not fail + if self.fileencoding == BOM_UTF8 or failed: + return BOM_UTF8 + chars.encode("utf-8") + # Try the original file encoding next, if any + if self.fileencoding: + try: + return chars.encode(self.fileencoding) + except UnicodeError: + tkMessageBox.showerror( + "I/O Error", + "Cannot save this as '%s' anymore. Saving as UTF-8" \ + % self.fileencoding, + master = self.text) + return BOM_UTF8 + chars.encode("utf-8") + # Nothing was declared, and we had not determined an encoding + # on loading. Recommend an encoding line. + config_encoding = idleConf.GetOption("main","EditorWindow", + "encoding") + if config_encoding == 'utf-8': + # User has requested that we save files as UTF-8 + return BOM_UTF8 + chars.encode("utf-8") + ask_user = True + try: + chars = chars.encode(encoding) + enc = encoding + if config_encoding == 'locale': + ask_user = False + except UnicodeError: + chars = BOM_UTF8 + chars.encode("utf-8") + enc = "utf-8" + if not ask_user: + return chars + dialog = EncodingMessage(self.editwin.top, enc) + dialog.go() + if dialog.num == 1: + # User asked us to edit the file + encline = "# -*- coding: %s -*-\n" % enc + firstline = self.text.get("1.0", "2.0") + if firstline.startswith("#!"): + # Insert encoding after #! line + self.text.insert("2.0", encline) + else: + self.text.insert("1.0", encline) + return self.encode(self.text.get("1.0", "end-1c")) + return chars + + def fixlastline(self): + c = self.text.get("end-2c") + if c != '\n': + self.text.insert("end-1c", "\n") + + def print_window(self, event): + confirm = tkMessageBox.askokcancel( + title="Print", + message="Print to Default Printer", + default=tkMessageBox.OK, + master=self.text) + if not confirm: + self.text.focus_set() + return "break" + tempfilename = None + saved = self.get_saved() + if saved: + filename = self.filename + # shell undo is reset after every prompt, looks saved, probably isn't + if not saved or filename is None: + (tfd, tempfilename) = tempfile.mkstemp(prefix='IDLE_tmp_') + filename = tempfilename + os.close(tfd) + if not self.writefile(tempfilename): + os.unlink(tempfilename) + return "break" + platform = os.name + printPlatform = True + if platform == 'posix': #posix platform + command = idleConf.GetOption('main','General', + 'print-command-posix') + command = command + " 2>&1" + elif platform == 'nt': #win32 platform + command = idleConf.GetOption('main','General','print-command-win') + else: #no printing for this platform + printPlatform = False + if printPlatform: #we can try to print for this platform + command = command % pipes.quote(filename) + pipe = os.popen(command, "r") + # things can get ugly on NT if there is no printer available. + output = pipe.read().strip() + status = pipe.close() + if status: + output = "Printing failed (exit status 0x%x)\n" % \ + status + output + if output: + output = "Printing command: %s\n" % repr(command) + output + tkMessageBox.showerror("Print status", output, master=self.text) + else: #no printing for this platform + message = "Printing is not enabled for this platform: %s" % platform + tkMessageBox.showinfo("Print status", message, master=self.text) + if tempfilename: + os.unlink(tempfilename) + return "break" + + opendialog = None + savedialog = None + + filetypes = [ + ("Python files", "*.py *.pyw", "TEXT"), + ("Text files", "*.txt", "TEXT"), + ("All files", "*"), + ] + + def askopenfile(self): + dir, base = self.defaultfilename("open") + if not self.opendialog: + self.opendialog = tkFileDialog.Open(master=self.text, + filetypes=self.filetypes) + filename = self.opendialog.show(initialdir=dir, initialfile=base) + if isinstance(filename, unicode): + filename = filename.encode(filesystemencoding) + return filename + + def defaultfilename(self, mode="open"): + if self.filename: + return os.path.split(self.filename) + elif self.dirname: + return self.dirname, "" + else: + try: + pwd = os.getcwd() + except os.error: + pwd = "" + return pwd, "" + + def asksavefile(self): + dir, base = self.defaultfilename("save") + if not self.savedialog: + self.savedialog = tkFileDialog.SaveAs(master=self.text, + filetypes=self.filetypes) + filename = self.savedialog.show(initialdir=dir, initialfile=base) + if isinstance(filename, unicode): + filename = filename.encode(filesystemencoding) + return filename + + def updaterecentfileslist(self,filename): + "Update recent file list on all editor windows" + self.editwin.update_recent_files_list(filename) + +def _io_binding(parent): + root = Tk() + root.title("Test IOBinding") + width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) + root.geometry("+%d+%d"%(x, y + 150)) + class MyEditWin: + def __init__(self, text): + self.text = text + self.flist = None + self.text.bind("", self.open) + self.text.bind("", self.save) + def get_saved(self): return 0 + def set_saved(self, flag): pass + def reset_undo(self): pass + def open(self, event): + self.text.event_generate("<>") + def save(self, event): + self.text.event_generate("<>") + + text = Text(root) + text.pack() + text.focus_set() + editwin = MyEditWin(text) + io = IOBinding(editwin) + +if __name__ == "__main__": + from idlelib.idle_test.htest import run + run(_io_binding) diff --git a/PythonHome/Lib/idlelib/IOBinding.pyc b/PythonHome/Lib/idlelib/IOBinding.pyc deleted file mode 100644 index d96ef6d365870f04318a85e5b2f8b1a7399081aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16827 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 event (default Alt-N). + history_prev - Bound to <> event (default Alt-P). + ''' + def __init__(self, text): + '''Initialize data attributes and bind event methods. + + .text - Idle wrapper of tk Text widget, with .bell(). + .history - source statements, possibly with multiple lines. + .prefix - source already entered at prompt; filters history list. + .pointer - index into history. + .cyclic - wrap around history list (or not). + ''' + self.text = text + self.history = [] + self.prefix = None + self.pointer = None + self.cyclic = idleConf.GetOption("main", "History", "cyclic", 1, "bool") + text.bind("<>", self.history_prev) + text.bind("<>", self.history_next) + + def history_next(self, event): + "Fetch later statement; start with ealiest if cyclic." + self.fetch(reverse=False) + return "break" + + def history_prev(self, event): + "Fetch earlier statement; start with most recent." + self.fetch(reverse=True) + return "break" + + def fetch(self, reverse): + '''Fetch statememt and replace current line in text widget. + + Set prefix and pointer as needed for successive fetches. + Reset them to None, None when returning to the start line. + Sound bell when return to start line or cannot leave a line + because cyclic is False. + ''' + nhist = len(self.history) + pointer = self.pointer + prefix = self.prefix + if pointer is not None and prefix is not None: + if self.text.compare("insert", "!=", "end-1c") or \ + self.text.get("iomark", "end-1c") != self.history[pointer]: + pointer = prefix = None + self.text.mark_set("insert", "end-1c") # != after cursor move + if pointer is None or prefix is None: + prefix = self.text.get("iomark", "end-1c") + if reverse: + pointer = nhist # will be decremented + else: + if self.cyclic: + pointer = -1 # will be incremented + else: # abort history_next + self.text.bell() + return + nprefix = len(prefix) + while 1: + pointer += -1 if reverse else 1 + if pointer < 0 or pointer >= nhist: + self.text.bell() + if not self.cyclic and pointer < 0: # abort history_prev + return + else: + if self.text.get("iomark", "end-1c") != prefix: + self.text.delete("iomark", "end-1c") + self.text.insert("iomark", prefix) + pointer = prefix = None + break + item = self.history[pointer] + if item[:nprefix] == prefix and len(item) > nprefix: + self.text.delete("iomark", "end-1c") + self.text.insert("iomark", item) + break + self.text.see("insert") + self.text.tag_remove("sel", "1.0", "end") + self.pointer = pointer + self.prefix = prefix + + def store(self, source): + "Store Shell input statement into history list." + source = source.strip() + if len(source) > 2: + # avoid duplicates + try: + self.history.remove(source) + except ValueError: + pass + self.history.append(source) + self.pointer = None + self.prefix = None + +if __name__ == "__main__": + from unittest import main + main('idlelib.idle_test.test_idlehistory', verbosity=2, exit=False) diff --git a/PythonHome/Lib/idlelib/IdleHistory.pyc b/PythonHome/Lib/idlelib/IdleHistory.pyc deleted file mode 100644 index 945a55dc87f452a488a4d505a1ba70ba30e6d648..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3954 zcmb7H+io1k5v`uRaVb)kELpIV!00G1Yg=4cK!PBULO2$zNI}2|vqlmLLI$%lz2s=; zvg+=Y$bfueejqP?&KLL>@(=lj{6SvwmYk}dFFItpl=o;Jk^PI1_o?hr z)u$JIQl?M&fbuQMhm>!V8PK_kR1Ln@XfoR6vwnr%|roiq;O+E7i3|hhq?U?FwJnjJ+1MQ$1 z+K7dQHqZo`atHc!q|<8^g(lFDmj)D1Mr+_@^;PAW(Jd~ z51Nm%v@A`oXSS*IvlFqw*cxYiv-FFl|7a{+X2xen;PP1B!ZY9CQl(ff>O;M-W>y^Q zw6rG8Pc&?6tjPn9*0M=$jy+g?-Yn}}`$j)}*skpH%KpAKZ`dcJ+|1Ht>Gf|)zjx5e zvEqSq-h4X`Uio$&&srW?1WWS67JbB4Ezz7RIweYo4$(&kZrYL#927cT@;!P5r$}&e zNJU8)b*2THV2;Z8qb7H)SJ|^;9}FqM`_`t5g|WJsX+PIr^2*yHKQ#Vch~M!P!98j% zAiG;r!iwJv3U^O08btZDJPDgCxS_yZ(PdE^h`{^#H*Vd1!QvZ!hdPLerds$1dRCN( z1$S}3N?fQ-PEEnF0%@SKIYx`fXhqy0%TBVg$Uw#V>eNaMtu$eldem55H>vc3p9#+W6~A@Ez{|FG~yQ^y^i5=o%G-@&M5marU`Ciwgjhp*5(Q_kWZMk73- zaX&$C{POq3^d%!xi8qJHlYn63#fgAck`#!&BoQ>c&YOor75+X{x75WYVaeo@uz5I) z1)aSD4l4!dnv9sj{TxjIhZ4|Y*VyoYyOyI7C~6Su22LtwI=EmghJlI*4TI|iR{%NY zK|dY}@W{gBv~)%mVis5C5?jbgU&Rg~c{`5B(e%5V~5?Zj!15hyC#`;aWNKVHzqB=%BUl7ci$E;XI+aW$b#PYP+{8Nq zUWo<}BTH+f6J44Vf~2C@MgE(bEL}Qi9kNp4w1Cw55Xk^V?Tqz~A^WGlcAOJTo$uYx z!eUdUb}j|wf#jnC>*PCV0PT+7_s5^g7`sOAtQJdC$IL3`JQ8yi8uP`MR3Mm|A?>EH z1am+cAehfbC9vE^x`F;8M{Y{vO?(H`?cv66^B_G;tf`teW+eQt^C669g1tZ-FW=OH#OLS-Y1 zatwv~?+Siu<-mut(W&%5OLhpNZ7B&xqS@*f7b$oOC(T(U), for all types of events. +Key/Button Press/Release events can have modifiers. +The recognized modifiers are Shift, Control, Option and Command for Mac, and +Control, Alt, Shift, Meta/M for other platforms. + +For all events which were handled by MultiCall, a new member is added to the +event instance passed to the binded functions - mc_type. This is one of the +event type constants defined in this module (such as MC_KEYPRESS). +For Key/Button events (which are handled by MultiCall and may receive +modifiers), another member is added - mc_state. This member gives the state +of the recognized modifiers, as a combination of the modifier constants +also defined in this module (for example, MC_SHIFT). +Using these members is absolutely portable. + +The order by which events are called is defined by these rules: +1. A more-specific event will be called before a less-specific event. +2. A recently-binded event will be called before a previously-binded event, + unless this conflicts with the first rule. +Each function will be called at most once for each event. +""" + +import sys +import string +import re +import Tkinter + +# the event type constants, which define the meaning of mc_type +MC_KEYPRESS=0; MC_KEYRELEASE=1; MC_BUTTONPRESS=2; MC_BUTTONRELEASE=3; +MC_ACTIVATE=4; MC_CIRCULATE=5; MC_COLORMAP=6; MC_CONFIGURE=7; +MC_DEACTIVATE=8; MC_DESTROY=9; MC_ENTER=10; MC_EXPOSE=11; MC_FOCUSIN=12; +MC_FOCUSOUT=13; MC_GRAVITY=14; MC_LEAVE=15; MC_MAP=16; MC_MOTION=17; +MC_MOUSEWHEEL=18; MC_PROPERTY=19; MC_REPARENT=20; MC_UNMAP=21; MC_VISIBILITY=22; +# the modifier state constants, which define the meaning of mc_state +MC_SHIFT = 1<<0; MC_CONTROL = 1<<2; MC_ALT = 1<<3; MC_META = 1<<5 +MC_OPTION = 1<<6; MC_COMMAND = 1<<7 + +# define the list of modifiers, to be used in complex event types. +if sys.platform == "darwin": + _modifiers = (("Shift",), ("Control",), ("Option",), ("Command",)) + _modifier_masks = (MC_SHIFT, MC_CONTROL, MC_OPTION, MC_COMMAND) +else: + _modifiers = (("Control",), ("Alt",), ("Shift",), ("Meta", "M")) + _modifier_masks = (MC_CONTROL, MC_ALT, MC_SHIFT, MC_META) + +# a dictionary to map a modifier name into its number +_modifier_names = dict([(name, number) + for number in range(len(_modifiers)) + for name in _modifiers[number]]) + +# A binder is a class which binds functions to one type of event. It has two +# methods: bind and unbind, which get a function and a parsed sequence, as +# returned by _parse_sequence(). There are two types of binders: +# _SimpleBinder handles event types with no modifiers and no detail. +# No Python functions are called when no events are binded. +# _ComplexBinder handles event types with modifiers and a detail. +# A Python function is called each time an event is generated. + +class _SimpleBinder: + def __init__(self, type, widget, widgetinst): + self.type = type + self.sequence = '<'+_types[type][0]+'>' + self.widget = widget + self.widgetinst = widgetinst + self.bindedfuncs = [] + self.handlerid = None + + def bind(self, triplet, func): + if not self.handlerid: + def handler(event, l = self.bindedfuncs, mc_type = self.type): + event.mc_type = mc_type + wascalled = {} + for i in range(len(l)-1, -1, -1): + func = l[i] + if func not in wascalled: + wascalled[func] = True + r = func(event) + if r: + return r + self.handlerid = self.widget.bind(self.widgetinst, + self.sequence, handler) + self.bindedfuncs.append(func) + + def unbind(self, triplet, func): + self.bindedfuncs.remove(func) + if not self.bindedfuncs: + self.widget.unbind(self.widgetinst, self.sequence, self.handlerid) + self.handlerid = None + + def __del__(self): + if self.handlerid: + self.widget.unbind(self.widgetinst, self.sequence, self.handlerid) + +# An int in range(1 << len(_modifiers)) represents a combination of modifiers +# (if the least significent bit is on, _modifiers[0] is on, and so on). +# _state_subsets gives for each combination of modifiers, or *state*, +# a list of the states which are a subset of it. This list is ordered by the +# number of modifiers is the state - the most specific state comes first. +_states = range(1 << len(_modifiers)) +_state_names = [''.join(m[0]+'-' + for i, m in enumerate(_modifiers) + if (1 << i) & s) + for s in _states] + +def expand_substates(states): + '''For each item of states return a list containing all combinations of + that item with individual bits reset, sorted by the number of set bits. + ''' + def nbits(n): + "number of bits set in n base 2" + nb = 0 + while n: + n, rem = divmod(n, 2) + nb += rem + return nb + statelist = [] + for state in states: + substates = list(set(state & x for x in states)) + substates.sort(key=nbits, reverse=True) + statelist.append(substates) + return statelist + +_state_subsets = expand_substates(_states) + +# _state_codes gives for each state, the portable code to be passed as mc_state +_state_codes = [] +for s in _states: + r = 0 + for i in range(len(_modifiers)): + if (1 << i) & s: + r |= _modifier_masks[i] + _state_codes.append(r) + +class _ComplexBinder: + # This class binds many functions, and only unbinds them when it is deleted. + # self.handlerids is the list of seqs and ids of binded handler functions. + # The binded functions sit in a dictionary of lists of lists, which maps + # a detail (or None) and a state into a list of functions. + # When a new detail is discovered, handlers for all the possible states + # are binded. + + def __create_handler(self, lists, mc_type, mc_state): + def handler(event, lists = lists, + mc_type = mc_type, mc_state = mc_state, + ishandlerrunning = self.ishandlerrunning, + doafterhandler = self.doafterhandler): + ishandlerrunning[:] = [True] + event.mc_type = mc_type + event.mc_state = mc_state + wascalled = {} + r = None + for l in lists: + for i in range(len(l)-1, -1, -1): + func = l[i] + if func not in wascalled: + wascalled[func] = True + r = l[i](event) + if r: + break + if r: + break + ishandlerrunning[:] = [] + # Call all functions in doafterhandler and remove them from list + for f in doafterhandler: + f() + doafterhandler[:] = [] + if r: + return r + return handler + + def __init__(self, type, widget, widgetinst): + self.type = type + self.typename = _types[type][0] + self.widget = widget + self.widgetinst = widgetinst + self.bindedfuncs = {None: [[] for s in _states]} + self.handlerids = [] + # we don't want to change the lists of functions while a handler is + # running - it will mess up the loop and anyway, we usually want the + # change to happen from the next event. So we have a list of functions + # for the handler to run after it finishes calling the binded functions. + # It calls them only once. + # ishandlerrunning is a list. An empty one means no, otherwise - yes. + # this is done so that it would be mutable. + self.ishandlerrunning = [] + self.doafterhandler = [] + for s in _states: + lists = [self.bindedfuncs[None][i] for i in _state_subsets[s]] + handler = self.__create_handler(lists, type, _state_codes[s]) + seq = '<'+_state_names[s]+self.typename+'>' + self.handlerids.append((seq, self.widget.bind(self.widgetinst, + seq, handler))) + + def bind(self, triplet, func): + if triplet[2] not in self.bindedfuncs: + self.bindedfuncs[triplet[2]] = [[] for s in _states] + for s in _states: + lists = [ self.bindedfuncs[detail][i] + for detail in (triplet[2], None) + for i in _state_subsets[s] ] + handler = self.__create_handler(lists, self.type, + _state_codes[s]) + seq = "<%s%s-%s>"% (_state_names[s], self.typename, triplet[2]) + self.handlerids.append((seq, self.widget.bind(self.widgetinst, + seq, handler))) + doit = lambda: self.bindedfuncs[triplet[2]][triplet[0]].append(func) + if not self.ishandlerrunning: + doit() + else: + self.doafterhandler.append(doit) + + def unbind(self, triplet, func): + doit = lambda: self.bindedfuncs[triplet[2]][triplet[0]].remove(func) + if not self.ishandlerrunning: + doit() + else: + self.doafterhandler.append(doit) + + def __del__(self): + for seq, id in self.handlerids: + self.widget.unbind(self.widgetinst, seq, id) + +# define the list of event types to be handled by MultiEvent. the order is +# compatible with the definition of event type constants. +_types = ( + ("KeyPress", "Key"), ("KeyRelease",), ("ButtonPress", "Button"), + ("ButtonRelease",), ("Activate",), ("Circulate",), ("Colormap",), + ("Configure",), ("Deactivate",), ("Destroy",), ("Enter",), ("Expose",), + ("FocusIn",), ("FocusOut",), ("Gravity",), ("Leave",), ("Map",), + ("Motion",), ("MouseWheel",), ("Property",), ("Reparent",), ("Unmap",), + ("Visibility",), +) + +# which binder should be used for every event type? +_binder_classes = (_ComplexBinder,) * 4 + (_SimpleBinder,) * (len(_types)-4) + +# A dictionary to map a type name into its number +_type_names = dict([(name, number) + for number in range(len(_types)) + for name in _types[number]]) + +_keysym_re = re.compile(r"^\w+$") +_button_re = re.compile(r"^[1-5]$") +def _parse_sequence(sequence): + """Get a string which should describe an event sequence. If it is + successfully parsed as one, return a tuple containing the state (as an int), + the event type (as an index of _types), and the detail - None if none, or a + string if there is one. If the parsing is unsuccessful, return None. + """ + if not sequence or sequence[0] != '<' or sequence[-1] != '>': + return None + words = string.split(sequence[1:-1], '-') + + modifiers = 0 + while words and words[0] in _modifier_names: + modifiers |= 1 << _modifier_names[words[0]] + del words[0] + + if words and words[0] in _type_names: + type = _type_names[words[0]] + del words[0] + else: + return None + + if _binder_classes[type] is _SimpleBinder: + if modifiers or words: + return None + else: + detail = None + else: + # _ComplexBinder + if type in [_type_names[s] for s in ("KeyPress", "KeyRelease")]: + type_re = _keysym_re + else: + type_re = _button_re + + if not words: + detail = None + elif len(words) == 1 and type_re.match(words[0]): + detail = words[0] + else: + return None + + return modifiers, type, detail + +def _triplet_to_sequence(triplet): + if triplet[2]: + return '<'+_state_names[triplet[0]]+_types[triplet[1]][0]+'-'+ \ + triplet[2]+'>' + else: + return '<'+_state_names[triplet[0]]+_types[triplet[1]][0]+'>' + +_multicall_dict = {} +def MultiCallCreator(widget): + """Return a MultiCall class which inherits its methods from the + given widget class (for example, Tkinter.Text). This is used + instead of a templating mechanism. + """ + if widget in _multicall_dict: + return _multicall_dict[widget] + + class MultiCall (widget): + assert issubclass(widget, Tkinter.Misc) + + def __init__(self, *args, **kwargs): + widget.__init__(self, *args, **kwargs) + # a dictionary which maps a virtual event to a tuple with: + # 0. the function binded + # 1. a list of triplets - the sequences it is binded to + self.__eventinfo = {} + self.__binders = [_binder_classes[i](i, widget, self) + for i in range(len(_types))] + + def bind(self, sequence=None, func=None, add=None): + #print "bind(%s, %s, %s) called." % (sequence, func, add) + if type(sequence) is str and len(sequence) > 2 and \ + sequence[:2] == "<<" and sequence[-2:] == ">>": + if sequence in self.__eventinfo: + ei = self.__eventinfo[sequence] + if ei[0] is not None: + for triplet in ei[1]: + self.__binders[triplet[1]].unbind(triplet, ei[0]) + ei[0] = func + if ei[0] is not None: + for triplet in ei[1]: + self.__binders[triplet[1]].bind(triplet, func) + else: + self.__eventinfo[sequence] = [func, []] + return widget.bind(self, sequence, func, add) + + def unbind(self, sequence, funcid=None): + if type(sequence) is str and len(sequence) > 2 and \ + sequence[:2] == "<<" and sequence[-2:] == ">>" and \ + sequence in self.__eventinfo: + func, triplets = self.__eventinfo[sequence] + if func is not None: + for triplet in triplets: + self.__binders[triplet[1]].unbind(triplet, func) + self.__eventinfo[sequence][0] = None + return widget.unbind(self, sequence, funcid) + + def event_add(self, virtual, *sequences): + #print "event_add(%s,%s) was called"%(repr(virtual),repr(sequences)) + if virtual not in self.__eventinfo: + self.__eventinfo[virtual] = [None, []] + + func, triplets = self.__eventinfo[virtual] + for seq in sequences: + triplet = _parse_sequence(seq) + if triplet is None: + #print >> sys.stderr, "Seq. %s was added by Tkinter."%seq + widget.event_add(self, virtual, seq) + else: + if func is not None: + self.__binders[triplet[1]].bind(triplet, func) + triplets.append(triplet) + + def event_delete(self, virtual, *sequences): + if virtual not in self.__eventinfo: + return + func, triplets = self.__eventinfo[virtual] + for seq in sequences: + triplet = _parse_sequence(seq) + if triplet is None: + #print >> sys.stderr, "Seq. %s was deleted by Tkinter."%seq + widget.event_delete(self, virtual, seq) + else: + if func is not None: + self.__binders[triplet[1]].unbind(triplet, func) + triplets.remove(triplet) + + def event_info(self, virtual=None): + if virtual is None or virtual not in self.__eventinfo: + return widget.event_info(self, virtual) + else: + return tuple(map(_triplet_to_sequence, + self.__eventinfo[virtual][1])) + \ + widget.event_info(self, virtual) + + def __del__(self): + for virtual in self.__eventinfo: + func, triplets = self.__eventinfo[virtual] + if func: + for triplet in triplets: + self.__binders[triplet[1]].unbind(triplet, func) + + + _multicall_dict[widget] = MultiCall + return MultiCall + + +def _multi_call(parent): + root = Tkinter.Tk() + root.title("Test MultiCall") + width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) + root.geometry("+%d+%d"%(x, y + 150)) + text = MultiCallCreator(Tkinter.Text)(root) + text.pack() + def bindseq(seq, n=[0]): + def handler(event): + print seq + text.bind("<>"%n[0], handler) + text.event_add("<>"%n[0], seq) + n[0] += 1 + bindseq("") + bindseq("") + bindseq("") + bindseq("") + bindseq("") + bindseq("") + bindseq("") + bindseq("") + bindseq("") + bindseq("") + bindseq("") + bindseq("") + root.mainloop() + +if __name__ == "__main__": + from idlelib.idle_test.htest import run + run(_multi_call) diff --git a/PythonHome/Lib/idlelib/MultiCall.pyc b/PythonHome/Lib/idlelib/MultiCall.pyc deleted file mode 100644 index f1a593ab92c92a15abac2b67aa79b9305da03895..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15859 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 XYqPt5(WOUqDm{1+_0tTxsoc2|=s1cO0+17i(v% zq>}yQh{6M}{04py|AZd^-#KH`_AS`nvvcOmoXdAEuKnF<|M}OO-jLRx8s6XFG2ekC z_$kVW`iVzc(MVBJqZ^_X(U0dIC3R-bYozOxG-&Ek70M-_vIgZoo%^J;Pr61cMXG?h zCiQ|Xs80XECs0^fCXehL(6f1F)1Hm(+?>SKdp?~&Y#xGW7!)_)+>K)6aFOkMbmP%^ zgTh`=$GM>g!qG7E0+0CuWPz(h(=DnF*)ZZ*DuQ3uqe+bxa$w=n?;fcX3{eEl1fSW- zZqNX=tgu@a8h3!q)bi%@D$cd#z@jKEQX56q2b0AEotc2$kZVR~BN61WvAPls)2jet z5@J5V>iFU`9bBYIrZc?X$K-hSI%IqN7&b?02j6?j@_NXwv4|z#;xPz~V@4nogx#d- zjKc;C(0~}S2_KL~%NeRI>$IrTM3T9{4k-oRU51vYMdvN^;reic5}yDW9~PvVFxi#J z21zOjW+W;Eqh0KAF&vkb!y`?!EUdn^0iO$*2&AWsoq*MQ)qU}-D|Pa{oSwzQsYr%p zF-k8bEg{<#X@OLPyR3_AN_0sc{vXV?h08|UNbYVkvjakESADGZ)SlN-UGaFGb+(GE zw{awj@-mrcU_&kuNtk$c`s{f>JiyjlS7ddov@?`kNQRT_dprJ+ci0|7CXxr(K_RT9 zs(}}>fW*S|1X*%b;Injvbm6DyqE1VXmNh~$mkq9ziO+SxS;v(c9gIBM=iX&elPiT8 zgbW_5rBA?V0i{?sY0;!fn++(tz25ze=vNfq4$lV^3e2iC4{clj@oh?4WIL3!36o$& zo_a$vZno(cM6*S9S9%wEaOe&#a8-Fr*lw{&cUkJy-?#v;CVS!x`|eg!pj;YVLGh>S z$3GiJ@A2mee(4`rnh!ww+SsF0<_j3{%MANOa=j$;*EK<(ahq4{l>_ zZCQxEJWh+OEN21tfe2@DrD2`5R%K~jZqme#MLO2$<=Bd@YoX4Q5sz;-Gahaf4aAC| z>EQkplG}8u-NV7?o$85@F|I1Z8c4O&6Lnv8WN^1ZF-+9Hw_88NyN&O9pm1nW1tkd0~vBm`cq)6D?!iU^(A)0LlDaoX8reZ%=H7F=280KOOPusT*rw Rb9xK|-uCwIwhlOge*txIhQa^< diff --git a/PythonHome/Lib/idlelib/ObjectBrowser.py b/PythonHome/Lib/idlelib/ObjectBrowser.py new file mode 100644 index 0000000000..e69365c144 --- /dev/null +++ b/PythonHome/Lib/idlelib/ObjectBrowser.py @@ -0,0 +1,156 @@ +# XXX TO DO: +# - popup menu +# - support partial or total redisplay +# - more doc strings +# - tooltips + +# object browser + +# XXX TO DO: +# - for classes/modules, add "open source" to object browser + +import re + +from idlelib.TreeWidget import TreeItem, TreeNode, ScrolledCanvas + +from repr import Repr + +myrepr = Repr() +myrepr.maxstring = 100 +myrepr.maxother = 100 + +class ObjectTreeItem(TreeItem): + def __init__(self, labeltext, object, setfunction=None): + self.labeltext = labeltext + self.object = object + self.setfunction = setfunction + def GetLabelText(self): + return self.labeltext + def GetText(self): + return myrepr.repr(self.object) + def GetIconName(self): + if not self.IsExpandable(): + return "python" + def IsEditable(self): + return self.setfunction is not None + def SetText(self, text): + try: + value = eval(text) + self.setfunction(value) + except: + pass + else: + self.object = value + def IsExpandable(self): + return not not dir(self.object) + def GetSubList(self): + keys = dir(self.object) + sublist = [] + for key in keys: + try: + value = getattr(self.object, key) + except AttributeError: + continue + item = make_objecttreeitem( + str(key) + " =", + value, + lambda value, key=key, object=self.object: + setattr(object, key, value)) + sublist.append(item) + return sublist + +class InstanceTreeItem(ObjectTreeItem): + def IsExpandable(self): + return True + def GetSubList(self): + sublist = ObjectTreeItem.GetSubList(self) + sublist.insert(0, + make_objecttreeitem("__class__ =", self.object.__class__)) + return sublist + +class ClassTreeItem(ObjectTreeItem): + def IsExpandable(self): + return True + def GetSubList(self): + sublist = ObjectTreeItem.GetSubList(self) + if len(self.object.__bases__) == 1: + item = make_objecttreeitem("__bases__[0] =", + self.object.__bases__[0]) + else: + item = make_objecttreeitem("__bases__ =", self.object.__bases__) + sublist.insert(0, item) + return sublist + +class AtomicObjectTreeItem(ObjectTreeItem): + def IsExpandable(self): + return 0 + +class SequenceTreeItem(ObjectTreeItem): + def IsExpandable(self): + return len(self.object) > 0 + def keys(self): + return range(len(self.object)) + def GetSubList(self): + sublist = [] + for key in self.keys(): + try: + value = self.object[key] + except KeyError: + continue + def setfunction(value, key=key, object=self.object): + object[key] = value + item = make_objecttreeitem("%r:" % (key,), value, setfunction) + sublist.append(item) + return sublist + +class DictTreeItem(SequenceTreeItem): + def keys(self): + keys = self.object.keys() + try: + keys.sort() + except: + pass + return keys + +from types import * + +dispatch = { + IntType: AtomicObjectTreeItem, + LongType: AtomicObjectTreeItem, + FloatType: AtomicObjectTreeItem, + StringType: AtomicObjectTreeItem, + TupleType: SequenceTreeItem, + ListType: SequenceTreeItem, + DictType: DictTreeItem, + InstanceType: InstanceTreeItem, + ClassType: ClassTreeItem, +} + +def make_objecttreeitem(labeltext, object, setfunction=None): + t = type(object) + if t in dispatch: + c = dispatch[t] + else: + c = ObjectTreeItem + return c(labeltext, object, setfunction) + + +def _object_browser(parent): + import sys + from Tkinter import Tk + root = Tk() + root.title("Test ObjectBrowser") + width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) + root.geometry("+%d+%d"%(x, y + 150)) + root.configure(bd=0, bg="yellow") + root.focus_set() + sc = ScrolledCanvas(root, bg="white", highlightthickness=0, takefocus=1) + sc.frame.pack(expand=1, fill="both") + item = make_objecttreeitem("sys", sys) + node = TreeNode(sc.canvas, None, item) + node.update() + root.mainloop() + +if __name__ == '__main__': + from idlelib.idle_test.htest import run + run(_object_browser) diff --git a/PythonHome/Lib/idlelib/ObjectBrowser.pyc b/PythonHome/Lib/idlelib/ObjectBrowser.pyc deleted file mode 100644 index 73a8fe6726aa5f905a105fae2df52ad24f395b66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6647 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 diff --git a/PythonHome/Lib/idlelib/OutputWindow.py b/PythonHome/Lib/idlelib/OutputWindow.py new file mode 100644 index 0000000000..e18d846d8d --- /dev/null +++ b/PythonHome/Lib/idlelib/OutputWindow.py @@ -0,0 +1,149 @@ +from Tkinter import * +from idlelib.EditorWindow import EditorWindow +import re +import tkMessageBox +from idlelib import IOBinding + +class OutputWindow(EditorWindow): + + """An editor window that can serve as an output file. + + Also the future base class for the Python shell window. + This class has no input facilities. + """ + + def __init__(self, *args): + EditorWindow.__init__(self, *args) + self.text.bind("<>", self.goto_file_line) + + # Customize EditorWindow + + def ispythonsource(self, filename): + # No colorization needed + return 0 + + def short_title(self): + return "Output" + + def maybesave(self): + # Override base class method -- don't ask any questions + if self.get_saved(): + return "yes" + else: + return "no" + + # Act as output file + + def write(self, s, tags=(), mark="insert"): + # Tk assumes that byte strings are Latin-1; + # we assume that they are in the locale's encoding + if isinstance(s, str): + try: + s = unicode(s, IOBinding.encoding) + except UnicodeError: + # some other encoding; let Tcl deal with it + pass + self.text.insert(mark, s, tags) + self.text.see(mark) + self.text.update() + + def writelines(self, lines): + for line in lines: + self.write(line) + + def flush(self): + pass + + # Our own right-button menu + + rmenu_specs = [ + ("Cut", "<>", "rmenu_check_cut"), + ("Copy", "<>", "rmenu_check_copy"), + ("Paste", "<>", "rmenu_check_paste"), + (None, None, None), + ("Go to file/line", "<>", None), + ] + + file_line_pats = [ + # order of patterns matters + r'file "([^"]*)", line (\d+)', + r'([^\s]+)\((\d+)\)', + r'^(\s*\S.*?):\s*(\d+):', # Win filename, maybe starting with spaces + r'([^\s]+):\s*(\d+):', # filename or path, ltrim + r'^\s*(\S.*?):\s*(\d+):', # Win abs path with embedded spaces, ltrim + ] + + file_line_progs = None + + def goto_file_line(self, event=None): + if self.file_line_progs is None: + l = [] + for pat in self.file_line_pats: + l.append(re.compile(pat, re.IGNORECASE)) + self.file_line_progs = l + # x, y = self.event.x, self.event.y + # self.text.mark_set("insert", "@%d,%d" % (x, y)) + line = self.text.get("insert linestart", "insert lineend") + result = self._file_line_helper(line) + if not result: + # Try the previous line. This is handy e.g. in tracebacks, + # where you tend to right-click on the displayed source line + line = self.text.get("insert -1line linestart", + "insert -1line lineend") + result = self._file_line_helper(line) + if not result: + tkMessageBox.showerror( + "No special line", + "The line you point at doesn't look like " + "a valid file name followed by a line number.", + master=self.text) + return + filename, lineno = result + edit = self.flist.open(filename) + edit.gotoline(lineno) + + def _file_line_helper(self, line): + for prog in self.file_line_progs: + match = prog.search(line) + if match: + filename, lineno = match.group(1, 2) + try: + f = open(filename, "r") + f.close() + break + except IOError: + continue + else: + return None + try: + return filename, int(lineno) + except TypeError: + return None + +# These classes are currently not used but might come in handy + +class OnDemandOutputWindow: + + tagdefs = { + # XXX Should use IdlePrefs.ColorPrefs + "stdout": {"foreground": "blue"}, + "stderr": {"foreground": "#007700"}, + } + + def __init__(self, flist): + self.flist = flist + self.owin = None + + def write(self, s, tags, mark): + if not self.owin: + self.setup() + self.owin.write(s, tags, mark) + + def setup(self): + self.owin = owin = OutputWindow(self.flist) + text = owin.text + for tag, cnf in self.tagdefs.items(): + if cnf: + text.tag_configure(tag, **cnf) + text.tag_raise('sel') + self.write = self.owin.write diff --git a/PythonHome/Lib/idlelib/OutputWindow.pyc b/PythonHome/Lib/idlelib/OutputWindow.pyc deleted file mode 100644 index 011d7bdf91f981f0a69306f1a98e90092c5a57c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5007 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 diff --git a/PythonHome/Lib/idlelib/ParenMatch.py b/PythonHome/Lib/idlelib/ParenMatch.py new file mode 100644 index 0000000000..19bad8ce38 --- /dev/null +++ b/PythonHome/Lib/idlelib/ParenMatch.py @@ -0,0 +1,178 @@ +"""ParenMatch -- An IDLE extension for parenthesis matching. + +When you hit a right paren, the cursor should move briefly to the left +paren. Paren here is used generically; the matching applies to +parentheses, square brackets, and curly braces. +""" + +from idlelib.HyperParser import HyperParser +from idlelib.configHandler import idleConf + +_openers = {')':'(',']':'[','}':'{'} +CHECK_DELAY = 100 # miliseconds + +class ParenMatch: + """Highlight matching parentheses + + There are three supported style of paren matching, based loosely + on the Emacs options. The style is select based on the + HILITE_STYLE attribute; it can be changed used the set_style + method. + + The supported styles are: + + default -- When a right paren is typed, highlight the matching + left paren for 1/2 sec. + + expression -- When a right paren is typed, highlight the entire + expression from the left paren to the right paren. + + TODO: + - extend IDLE with configuration dialog to change options + - implement rest of Emacs highlight styles (see below) + - print mismatch warning in IDLE status window + + Note: In Emacs, there are several styles of highlight where the + matching paren is highlighted whenever the cursor is immediately + to the right of a right paren. I don't know how to do that in Tk, + so I haven't bothered. + """ + menudefs = [ + ('edit', [ + ("Show surrounding parens", "<>"), + ]) + ] + STYLE = idleConf.GetOption('extensions','ParenMatch','style', + default='expression') + FLASH_DELAY = idleConf.GetOption('extensions','ParenMatch','flash-delay', + type='int',default=500) + HILITE_CONFIG = idleConf.GetHighlight(idleConf.CurrentTheme(),'hilite') + BELL = idleConf.GetOption('extensions','ParenMatch','bell', + type='bool',default=1) + + RESTORE_VIRTUAL_EVENT_NAME = "<>" + # We want the restore event be called before the usual return and + # backspace events. + RESTORE_SEQUENCES = ("", "", + "", "") + + def __init__(self, editwin): + self.editwin = editwin + self.text = editwin.text + # Bind the check-restore event to the function restore_event, + # so that we can then use activate_restore (which calls event_add) + # and deactivate_restore (which calls event_delete). + editwin.text.bind(self.RESTORE_VIRTUAL_EVENT_NAME, + self.restore_event) + self.counter = 0 + self.is_restore_active = 0 + self.set_style(self.STYLE) + + def activate_restore(self): + if not self.is_restore_active: + for seq in self.RESTORE_SEQUENCES: + self.text.event_add(self.RESTORE_VIRTUAL_EVENT_NAME, seq) + self.is_restore_active = True + + def deactivate_restore(self): + if self.is_restore_active: + for seq in self.RESTORE_SEQUENCES: + self.text.event_delete(self.RESTORE_VIRTUAL_EVENT_NAME, seq) + self.is_restore_active = False + + def set_style(self, style): + self.STYLE = style + if style == "default": + self.create_tag = self.create_tag_default + self.set_timeout = self.set_timeout_last + elif style == "expression": + self.create_tag = self.create_tag_expression + self.set_timeout = self.set_timeout_none + + def flash_paren_event(self, event): + indices = (HyperParser(self.editwin, "insert") + .get_surrounding_brackets()) + if indices is None: + self.warn_mismatched() + return + self.activate_restore() + self.create_tag(indices) + self.set_timeout_last() + + def paren_closed_event(self, event): + # If it was a shortcut and not really a closing paren, quit. + closer = self.text.get("insert-1c") + if closer not in _openers: + return + hp = HyperParser(self.editwin, "insert-1c") + if not hp.is_in_code(): + return + indices = hp.get_surrounding_brackets(_openers[closer], True) + if indices is None: + self.warn_mismatched() + return + self.activate_restore() + self.create_tag(indices) + self.set_timeout() + + def restore_event(self, event=None): + self.text.tag_delete("paren") + self.deactivate_restore() + self.counter += 1 # disable the last timer, if there is one. + + def handle_restore_timer(self, timer_count): + if timer_count == self.counter: + self.restore_event() + + def warn_mismatched(self): + if self.BELL: + self.text.bell() + + # any one of the create_tag_XXX methods can be used depending on + # the style + + def create_tag_default(self, indices): + """Highlight the single paren that matches""" + self.text.tag_add("paren", indices[0]) + self.text.tag_config("paren", self.HILITE_CONFIG) + + def create_tag_expression(self, indices): + """Highlight the entire expression""" + if self.text.get(indices[1]) in (')', ']', '}'): + rightindex = indices[1]+"+1c" + else: + rightindex = indices[1] + self.text.tag_add("paren", indices[0], rightindex) + self.text.tag_config("paren", self.HILITE_CONFIG) + + # any one of the set_timeout_XXX methods can be used depending on + # the style + + def set_timeout_none(self): + """Highlight will remain until user input turns it off + or the insert has moved""" + # After CHECK_DELAY, call a function which disables the "paren" tag + # if the event is for the most recent timer and the insert has changed, + # or schedules another call for itself. + self.counter += 1 + def callme(callme, self=self, c=self.counter, + index=self.text.index("insert")): + if index != self.text.index("insert"): + self.handle_restore_timer(c) + else: + self.editwin.text_frame.after(CHECK_DELAY, callme, callme) + self.editwin.text_frame.after(CHECK_DELAY, callme, callme) + + def set_timeout_last(self): + """The last highlight created will be removed after .5 sec""" + # associate a counter with an event; only disable the "paren" + # tag if the event is for the most recent timer. + self.counter += 1 + self.editwin.text_frame.after( + self.FLASH_DELAY, + lambda self=self, c=self.counter: self.handle_restore_timer(c)) + + +if __name__ == '__main__': + import unittest + unittest.main('idlelib.idle_test.test_parenmatch', verbosity=2) diff --git a/PythonHome/Lib/idlelib/ParenMatch.pyc b/PythonHome/Lib/idlelib/ParenMatch.pyc deleted file mode 100644 index c3aa4989dbb6970b35ececdfa2e203f7c8d1b5ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6874 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 diff --git a/PythonHome/Lib/idlelib/Percolator.py b/PythonHome/Lib/idlelib/Percolator.py new file mode 100644 index 0000000000..e0e8cade0d --- /dev/null +++ b/PythonHome/Lib/idlelib/Percolator.py @@ -0,0 +1,103 @@ +from idlelib.WidgetRedirector import WidgetRedirector +from idlelib.Delegator import Delegator + +class Percolator: + + def __init__(self, text): + # XXX would be nice to inherit from Delegator + self.text = text + self.redir = WidgetRedirector(text) + self.top = self.bottom = Delegator(text) + self.bottom.insert = self.redir.register("insert", self.insert) + self.bottom.delete = self.redir.register("delete", self.delete) + self.filters = [] + + def close(self): + while self.top is not self.bottom: + self.removefilter(self.top) + self.top = None + self.bottom.setdelegate(None); self.bottom = None + self.redir.close(); self.redir = None + self.text = None + + def insert(self, index, chars, tags=None): + # Could go away if inheriting from Delegator + self.top.insert(index, chars, tags) + + def delete(self, index1, index2=None): + # Could go away if inheriting from Delegator + self.top.delete(index1, index2) + + def insertfilter(self, filter): + # Perhaps rename to pushfilter()? + assert isinstance(filter, Delegator) + assert filter.delegate is None + filter.setdelegate(self.top) + self.top = filter + + def removefilter(self, filter): + # XXX Perhaps should only support popfilter()? + assert isinstance(filter, Delegator) + assert filter.delegate is not None + f = self.top + if f is filter: + self.top = filter.delegate + filter.setdelegate(None) + else: + while f.delegate is not filter: + assert f is not self.bottom + f.resetcache() + f = f.delegate + f.setdelegate(filter.delegate) + filter.setdelegate(None) + + +def _percolator(parent): + import Tkinter as tk + import re + class Tracer(Delegator): + def __init__(self, name): + self.name = name + Delegator.__init__(self, None) + def insert(self, *args): + print self.name, ": insert", args + self.delegate.insert(*args) + def delete(self, *args): + print self.name, ": delete", args + self.delegate.delete(*args) + root = tk.Tk() + root.title("Test Percolator") + width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) + root.geometry("+%d+%d"%(x, y + 150)) + text = tk.Text(root) + p = Percolator(text) + t1 = Tracer("t1") + t2 = Tracer("t2") + + def toggle1(): + if var1.get() == 0: + var1.set(1) + p.insertfilter(t1) + elif var1.get() == 1: + var1.set(0) + p.removefilter(t1) + + def toggle2(): + if var2.get() == 0: + var2.set(1) + p.insertfilter(t2) + elif var2.get() == 1: + var2.set(0) + p.removefilter(t2) + + text.pack() + var1 = tk.IntVar() + cb1 = tk.Checkbutton(root, text="Tracer1", command=toggle1, variable=var1) + cb1.pack() + var2 = tk.IntVar() + cb2 = tk.Checkbutton(root, text="Tracer2", command=toggle2, variable=var2) + cb2.pack() + +if __name__ == "__main__": + from idlelib.idle_test.htest import run + run(_percolator) diff --git a/PythonHome/Lib/idlelib/Percolator.pyc b/PythonHome/Lib/idlelib/Percolator.pyc deleted file mode 100644 index b13cbae41baf1959d846a2aa80cce78eb6936796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4383 zcmd5<>uwuG6h5=IW3TJbP)NB6Xt^3H1yX(>0YX5F0un@MQm9BvEoXP)Y+|p|-6^C} z{HH;*Nc=`T0?)v6@FqL}eBYUM99mEli61zb*}0rKbLKmjIaB*%zWwX(ch?fBel>hQ zKq)g+DgKQNMMg%}jTrVL8AdXy$$Aa_nxwI$b@^W8K;-N7x}*(u)*IsHB%PC;ND8NX znlfz4s3q$yF|H-9AqU`?gJVn9x^3*1{fS@Kpyd}(UCq*g^VX$V;SxVC!c2^r%Wmif zeGGXn`@$8;c*ySIAtDTagi>BcpI$Cy&cImc2TMSo^;kB6p8SfNLU&oYpd*0$JzJaPBmR14gYCqo9 zMH^%9$0OfTia}O-S6I$l<-n6~W-;*hrfi9v2Yv37uF$ruP7{f_H83Ou@v13D1r&Y zgBjhd$yK02c&3Egu*EQ0O$5Lj1pfg0RHM*+SOm`o7gN!Z01ptI>x3& zfqEJP0S!Pzi-i5u;GpFDV^GQ5HZ*}L|m>+9?gpA`9hH*;df-5YNz$ zAyv63K9W0%<~D+b$WBYj*N+SaXNEDs{;D7Vx1PaG^U(m6mGDsC&l4AX?-5LVSkh;+ zasF{pAdb<>4sD3@mdaOUsng9s2nKlkldJ892oaV(55^_;lV}lkwO}-?{Y_85Ve%nZ z#7D4z7dB)9i^D%0v?awgHh>!a5ip^x$PlUgn(VzxQceeV{zX@UOOxJR-kD+y8U#RC zf1t(=H*d&QcIGPn74$RiN8sm0Vb8Ks|D)~MCs`@H>f4Gjp-?py4vw7klPx#1JNp!8 z$zb#NklT6Czk*V7zW{S=I`~_N&H(bZnFs8vT}oI*#k@aqy`GBE>y5_gts%OWVMilD zkeNEtm~83py30%`Z9OaoTbevwL1XV+6vuI^Q}5K{X2LTP8N$Jh${ZuOq<|>y{|OqQ zZK!G7n{bXzjNsA?SN}xS38g||6Wn%nVF0eHcOb05Yd!8aRVh*gMuC{5@HGA#xn7qE ztY}UqO_{WGJuW&Z8mn58Hsy)UNX||b-X;M$lUNXf_rc1@kMLeNDoh4#_^sw9Y)5ie zNl(i?9M{w) z9og^51IqvcSR5`}&}FA|8D+0c=4F3=x=aoCQQ*F+S&#;~D@8v+Zi7MnQ9~c0lrN(C z*Q5p+4YHd$bCw$D)VZgDZjGy-MFqj=nrhleN6^Op(8JMCTnC-r0<_KGLu!vSl37f$ z=h#I#UJ{@t{Vu3WvKQQG36DhqS+1g#FQKA+h^)ZoRv_!jC+q`E4KP22%X>|QSk+MW z&bbibg5#b8gW&2!U?!`creB=+PJ16*DtQqt{~LL$M2!L}gh5_{GLzSyXBXv|*mCuU zD2K9kd7WD-+&;%j^`~3vMi@E?dtMyxpp?9e=S*CSYb7J-6<7Lmvs6!azqWVb8>PGO za*F@#XV4*Hpjr-}iwQdV}UDnz|yZ71W=sGp~LNdoVzzk%ls;S59V!{{-tOV+`E9OIi`HD_Y`X*7e9Jt8_Zf4S zPPEusY_-ukj|_%&mAj1kS>Ee~*EyvuZsn`WCL}n_fvN}L()~~R@HFMMH>J2decFc` zhxpl#Suu)vCUH|retRCVXK9PIUBO(~7LDUYOg+GRA>DeP!9dM&0cqM}Z^cVU*UVqA Ckmf-E diff --git a/PythonHome/Lib/idlelib/PyParse.py b/PythonHome/Lib/idlelib/PyParse.py new file mode 100644 index 0000000000..1a9db6743c --- /dev/null +++ b/PythonHome/Lib/idlelib/PyParse.py @@ -0,0 +1,594 @@ +import re +import sys + +# Reason last stmt is continued (or C_NONE if it's not). +(C_NONE, C_BACKSLASH, C_STRING_FIRST_LINE, + C_STRING_NEXT_LINES, C_BRACKET) = range(5) + +if 0: # for throwaway debugging output + def dump(*stuff): + sys.__stdout__.write(" ".join(map(str, stuff)) + "\n") + +# Find what looks like the start of a popular stmt. + +_synchre = re.compile(r""" + ^ + [ \t]* + (?: while + | else + | def + | return + | assert + | break + | class + | continue + | elif + | try + | except + | raise + | import + | yield + ) + \b +""", re.VERBOSE | re.MULTILINE).search + +# Match blank line or non-indenting comment line. + +_junkre = re.compile(r""" + [ \t]* + (?: \# \S .* )? + \n +""", re.VERBOSE).match + +# Match any flavor of string; the terminating quote is optional +# so that we're robust in the face of incomplete program text. + +_match_stringre = re.compile(r""" + \""" [^"\\]* (?: + (?: \\. | "(?!"") ) + [^"\\]* + )* + (?: \""" )? + +| " [^"\\\n]* (?: \\. [^"\\\n]* )* "? + +| ''' [^'\\]* (?: + (?: \\. | '(?!'') ) + [^'\\]* + )* + (?: ''' )? + +| ' [^'\\\n]* (?: \\. [^'\\\n]* )* '? +""", re.VERBOSE | re.DOTALL).match + +# Match a line that starts with something interesting; +# used to find the first item of a bracket structure. + +_itemre = re.compile(r""" + [ \t]* + [^\s#\\] # if we match, m.end()-1 is the interesting char +""", re.VERBOSE).match + +# Match start of stmts that should be followed by a dedent. + +_closere = re.compile(r""" + \s* + (?: return + | break + | continue + | raise + | pass + ) + \b +""", re.VERBOSE).match + +# Chew up non-special chars as quickly as possible. If match is +# successful, m.end() less 1 is the index of the last boring char +# matched. If match is unsuccessful, the string starts with an +# interesting char. + +_chew_ordinaryre = re.compile(r""" + [^[\](){}#'"\\]+ +""", re.VERBOSE).match + +# Build translation table to map uninteresting chars to "x", open +# brackets to "(", and close brackets to ")". + +_tran = ['x'] * 256 +for ch in "({[": + _tran[ord(ch)] = '(' +for ch in ")}]": + _tran[ord(ch)] = ')' +for ch in "\"'\\\n#": + _tran[ord(ch)] = ch +_tran = ''.join(_tran) +del ch + +try: + UnicodeType = type(unicode("")) +except NameError: + UnicodeType = None + +class Parser: + + def __init__(self, indentwidth, tabwidth): + self.indentwidth = indentwidth + self.tabwidth = tabwidth + + def set_str(self, str): + assert len(str) == 0 or str[-1] == '\n' + if type(str) is UnicodeType: + # The parse functions have no idea what to do with Unicode, so + # replace all Unicode characters with "x". This is "safe" + # so long as the only characters germane to parsing the structure + # of Python are 7-bit ASCII. It's *necessary* because Unicode + # strings don't have a .translate() method that supports + # deletechars. + uniphooey = str + str = [] + push = str.append + for raw in map(ord, uniphooey): + push(raw < 127 and chr(raw) or "x") + str = "".join(str) + self.str = str + self.study_level = 0 + + # Return index of a good place to begin parsing, as close to the + # end of the string as possible. This will be the start of some + # popular stmt like "if" or "def". Return None if none found: + # the caller should pass more prior context then, if possible, or + # if not (the entire program text up until the point of interest + # has already been tried) pass 0 to set_lo. + # + # This will be reliable iff given a reliable is_char_in_string + # function, meaning that when it says "no", it's absolutely + # guaranteed that the char is not in a string. + + def find_good_parse_start(self, is_char_in_string=None, + _synchre=_synchre): + str, pos = self.str, None + + if not is_char_in_string: + # no clue -- make the caller pass everything + return None + + # Peek back from the end for a good place to start, + # but don't try too often; pos will be left None, or + # bumped to a legitimate synch point. + limit = len(str) + for tries in range(5): + i = str.rfind(":\n", 0, limit) + if i < 0: + break + i = str.rfind('\n', 0, i) + 1 # start of colon line + m = _synchre(str, i, limit) + if m and not is_char_in_string(m.start()): + pos = m.start() + break + limit = i + if pos is None: + # Nothing looks like a block-opener, or stuff does + # but is_char_in_string keeps returning true; most likely + # we're in or near a giant string, the colorizer hasn't + # caught up enough to be helpful, or there simply *aren't* + # any interesting stmts. In any of these cases we're + # going to have to parse the whole thing to be sure, so + # give it one last try from the start, but stop wasting + # time here regardless of the outcome. + m = _synchre(str) + if m and not is_char_in_string(m.start()): + pos = m.start() + return pos + + # Peeking back worked; look forward until _synchre no longer + # matches. + i = pos + 1 + while 1: + m = _synchre(str, i) + if m: + s, i = m.span() + if not is_char_in_string(s): + pos = s + else: + break + return pos + + # Throw away the start of the string. Intended to be called with + # find_good_parse_start's result. + + def set_lo(self, lo): + assert lo == 0 or self.str[lo-1] == '\n' + if lo > 0: + self.str = self.str[lo:] + + # As quickly as humanly possible , find the line numbers (0- + # based) of the non-continuation lines. + # Creates self.{goodlines, continuation}. + + def _study1(self): + if self.study_level >= 1: + return + self.study_level = 1 + + # Map all uninteresting characters to "x", all open brackets + # to "(", all close brackets to ")", then collapse runs of + # uninteresting characters. This can cut the number of chars + # by a factor of 10-40, and so greatly speed the following loop. + str = self.str + str = str.translate(_tran) + str = str.replace('xxxxxxxx', 'x') + str = str.replace('xxxx', 'x') + str = str.replace('xx', 'x') + str = str.replace('xx', 'x') + str = str.replace('\nx', '\n') + # note that replacing x\n with \n would be incorrect, because + # x may be preceded by a backslash + + # March over the squashed version of the program, accumulating + # the line numbers of non-continued stmts, and determining + # whether & why the last stmt is a continuation. + continuation = C_NONE + level = lno = 0 # level is nesting level; lno is line number + self.goodlines = goodlines = [0] + push_good = goodlines.append + i, n = 0, len(str) + while i < n: + ch = str[i] + i = i+1 + + # cases are checked in decreasing order of frequency + if ch == 'x': + continue + + if ch == '\n': + lno = lno + 1 + if level == 0: + push_good(lno) + # else we're in an unclosed bracket structure + continue + + if ch == '(': + level = level + 1 + continue + + if ch == ')': + if level: + level = level - 1 + # else the program is invalid, but we can't complain + continue + + if ch == '"' or ch == "'": + # consume the string + quote = ch + if str[i-1:i+2] == quote * 3: + quote = quote * 3 + firstlno = lno + w = len(quote) - 1 + i = i+w + while i < n: + ch = str[i] + i = i+1 + + if ch == 'x': + continue + + if str[i-1:i+w] == quote: + i = i+w + break + + if ch == '\n': + lno = lno + 1 + if w == 0: + # unterminated single-quoted string + if level == 0: + push_good(lno) + break + continue + + if ch == '\\': + assert i < n + if str[i] == '\n': + lno = lno + 1 + i = i+1 + continue + + # else comment char or paren inside string + + else: + # didn't break out of the loop, so we're still + # inside a string + if (lno - 1) == firstlno: + # before the previous \n in str, we were in the first + # line of the string + continuation = C_STRING_FIRST_LINE + else: + continuation = C_STRING_NEXT_LINES + continue # with outer loop + + if ch == '#': + # consume the comment + i = str.find('\n', i) + assert i >= 0 + continue + + assert ch == '\\' + assert i < n + if str[i] == '\n': + lno = lno + 1 + if i+1 == n: + continuation = C_BACKSLASH + i = i+1 + + # The last stmt may be continued for all 3 reasons. + # String continuation takes precedence over bracket + # continuation, which beats backslash continuation. + if (continuation != C_STRING_FIRST_LINE + and continuation != C_STRING_NEXT_LINES and level > 0): + continuation = C_BRACKET + self.continuation = continuation + + # Push the final line number as a sentinel value, regardless of + # whether it's continued. + assert (continuation == C_NONE) == (goodlines[-1] == lno) + if goodlines[-1] != lno: + push_good(lno) + + def get_continuation_type(self): + self._study1() + return self.continuation + + # study1 was sufficient to determine the continuation status, + # but doing more requires looking at every character. study2 + # does this for the last interesting statement in the block. + # Creates: + # self.stmt_start, stmt_end + # slice indices of last interesting stmt + # self.stmt_bracketing + # the bracketing structure of the last interesting stmt; + # for example, for the statement "say(boo) or die", stmt_bracketing + # will be [(0, 0), (3, 1), (8, 0)]. Strings and comments are + # treated as brackets, for the matter. + # self.lastch + # last non-whitespace character before optional trailing + # comment + # self.lastopenbracketpos + # if continuation is C_BRACKET, index of last open bracket + + def _study2(self): + if self.study_level >= 2: + return + self._study1() + self.study_level = 2 + + # Set p and q to slice indices of last interesting stmt. + str, goodlines = self.str, self.goodlines + i = len(goodlines) - 1 + p = len(str) # index of newest line + while i: + assert p + # p is the index of the stmt at line number goodlines[i]. + # Move p back to the stmt at line number goodlines[i-1]. + q = p + for nothing in range(goodlines[i-1], goodlines[i]): + # tricky: sets p to 0 if no preceding newline + p = str.rfind('\n', 0, p-1) + 1 + # The stmt str[p:q] isn't a continuation, but may be blank + # or a non-indenting comment line. + if _junkre(str, p): + i = i-1 + else: + break + if i == 0: + # nothing but junk! + assert p == 0 + q = p + self.stmt_start, self.stmt_end = p, q + + # Analyze this stmt, to find the last open bracket (if any) + # and last interesting character (if any). + lastch = "" + stack = [] # stack of open bracket indices + push_stack = stack.append + bracketing = [(p, 0)] + while p < q: + # suck up all except ()[]{}'"#\\ + m = _chew_ordinaryre(str, p, q) + if m: + # we skipped at least one boring char + newp = m.end() + # back up over totally boring whitespace + i = newp - 1 # index of last boring char + while i >= p and str[i] in " \t\n": + i = i-1 + if i >= p: + lastch = str[i] + p = newp + if p >= q: + break + + ch = str[p] + + if ch in "([{": + push_stack(p) + bracketing.append((p, len(stack))) + lastch = ch + p = p+1 + continue + + if ch in ")]}": + if stack: + del stack[-1] + lastch = ch + p = p+1 + bracketing.append((p, len(stack))) + continue + + if ch == '"' or ch == "'": + # consume string + # Note that study1 did this with a Python loop, but + # we use a regexp here; the reason is speed in both + # cases; the string may be huge, but study1 pre-squashed + # strings to a couple of characters per line. study1 + # also needed to keep track of newlines, and we don't + # have to. + bracketing.append((p, len(stack)+1)) + lastch = ch + p = _match_stringre(str, p, q).end() + bracketing.append((p, len(stack))) + continue + + if ch == '#': + # consume comment and trailing newline + bracketing.append((p, len(stack)+1)) + p = str.find('\n', p, q) + 1 + assert p > 0 + bracketing.append((p, len(stack))) + continue + + assert ch == '\\' + p = p+1 # beyond backslash + assert p < q + if str[p] != '\n': + # the program is invalid, but can't complain + lastch = ch + str[p] + p = p+1 # beyond escaped char + + # end while p < q: + + self.lastch = lastch + if stack: + self.lastopenbracketpos = stack[-1] + self.stmt_bracketing = tuple(bracketing) + + # Assuming continuation is C_BRACKET, return the number + # of spaces the next line should be indented. + + def compute_bracket_indent(self): + self._study2() + assert self.continuation == C_BRACKET + j = self.lastopenbracketpos + str = self.str + n = len(str) + origi = i = str.rfind('\n', 0, j) + 1 + j = j+1 # one beyond open bracket + # find first list item; set i to start of its line + while j < n: + m = _itemre(str, j) + if m: + j = m.end() - 1 # index of first interesting char + extra = 0 + break + else: + # this line is junk; advance to next line + i = j = str.find('\n', j) + 1 + else: + # nothing interesting follows the bracket; + # reproduce the bracket line's indentation + a level + j = i = origi + while str[j] in " \t": + j = j+1 + extra = self.indentwidth + return len(str[i:j].expandtabs(self.tabwidth)) + extra + + # Return number of physical lines in last stmt (whether or not + # it's an interesting stmt! this is intended to be called when + # continuation is C_BACKSLASH). + + def get_num_lines_in_stmt(self): + self._study1() + goodlines = self.goodlines + return goodlines[-1] - goodlines[-2] + + # Assuming continuation is C_BACKSLASH, return the number of spaces + # the next line should be indented. Also assuming the new line is + # the first one following the initial line of the stmt. + + def compute_backslash_indent(self): + self._study2() + assert self.continuation == C_BACKSLASH + str = self.str + i = self.stmt_start + while str[i] in " \t": + i = i+1 + startpos = i + + # See whether the initial line starts an assignment stmt; i.e., + # look for an = operator + endpos = str.find('\n', startpos) + 1 + found = level = 0 + while i < endpos: + ch = str[i] + if ch in "([{": + level = level + 1 + i = i+1 + elif ch in ")]}": + if level: + level = level - 1 + i = i+1 + elif ch == '"' or ch == "'": + i = _match_stringre(str, i, endpos).end() + elif ch == '#': + break + elif level == 0 and ch == '=' and \ + (i == 0 or str[i-1] not in "=<>!") and \ + str[i+1] != '=': + found = 1 + break + else: + i = i+1 + + if found: + # found a legit =, but it may be the last interesting + # thing on the line + i = i+1 # move beyond the = + found = re.match(r"\s*\\", str[i:endpos]) is None + + if not found: + # oh well ... settle for moving beyond the first chunk + # of non-whitespace chars + i = startpos + while str[i] not in " \t\n": + i = i+1 + + return len(str[self.stmt_start:i].expandtabs(\ + self.tabwidth)) + 1 + + # Return the leading whitespace on the initial line of the last + # interesting stmt. + + def get_base_indent_string(self): + self._study2() + i, n = self.stmt_start, self.stmt_end + j = i + str = self.str + while j < n and str[j] in " \t": + j = j + 1 + return str[i:j] + + # Did the last interesting stmt open a block? + + def is_block_opener(self): + self._study2() + return self.lastch == ':' + + # Did the last interesting stmt close a block? + + def is_block_closer(self): + self._study2() + return _closere(self.str, self.stmt_start) is not None + + # index of last open bracket ({[, or None if none + lastopenbracketpos = None + + def get_last_open_bracket_pos(self): + self._study2() + return self.lastopenbracketpos + + # the structure of the bracketing of the last interesting statement, + # in the format defined in _study2, or None if the text didn't contain + # anything + stmt_bracketing = None + + def get_last_stmt_bracketing(self): + self._study2() + return self.stmt_bracketing diff --git a/PythonHome/Lib/idlelib/PyParse.pyc b/PythonHome/Lib/idlelib/PyParse.pyc deleted file mode 100644 index d40b320400dc9672129020e382e1a9b91f1f0443..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9749 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 Y#y3}MxQC8?wEYZf+p_T$7P&a>sys.__stderr__, "** IDLE can't import Tkinter. " \ + "Your Python may not be configured for Tk. **" + sys.exit(1) +import tkMessageBox + +from idlelib.EditorWindow import EditorWindow, fixwordbreaks +from idlelib.FileList import FileList +from idlelib.ColorDelegator import ColorDelegator +from idlelib.UndoDelegator import UndoDelegator +from idlelib.OutputWindow import OutputWindow +from idlelib.configHandler import idleConf +from idlelib import idlever +from idlelib import rpc +from idlelib import Debugger +from idlelib import RemoteDebugger +from idlelib import macosxSupport + +IDENTCHARS = string.ascii_letters + string.digits + "_" +HOST = '127.0.0.1' # python execution server on localhost loopback +PORT = 0 # someday pass in host, port for remote debug capability + +try: + from signal import SIGTERM +except ImportError: + SIGTERM = 15 + +# Override warnings module to write to warning_stream. Initialize to send IDLE +# internal warnings to the console. ScriptBinding.check_syntax() will +# temporarily redirect the stream to the shell window to display warnings when +# checking user's code. +warning_stream = sys.__stderr__ # None, at least on Windows, if no console. +import warnings + +def idle_formatwarning(message, category, filename, lineno, line=None): + """Format warnings the IDLE way.""" + + s = "\nWarning (from warnings module):\n" + s += ' File \"%s\", line %s\n' % (filename, lineno) + if line is None: + line = linecache.getline(filename, lineno) + line = line.strip() + if line: + s += " %s\n" % line + s += "%s: %s\n" % (category.__name__, message) + return s + +def idle_showwarning( + message, category, filename, lineno, file=None, line=None): + """Show Idle-format warning (after replacing warnings.showwarning). + + The differences are the formatter called, the file=None replacement, + which can be None, the capture of the consequence AttributeError, + and the output of a hard-coded prompt. + """ + if file is None: + file = warning_stream + try: + file.write(idle_formatwarning( + message, category, filename, lineno, line=line)) + file.write(">>> ") + except (AttributeError, IOError): + pass # if file (probably __stderr__) is invalid, skip warning. + +_warnings_showwarning = None + +def capture_warnings(capture): + "Replace warning.showwarning with idle_showwarning, or reverse." + + global _warnings_showwarning + if capture: + if _warnings_showwarning is None: + _warnings_showwarning = warnings.showwarning + warnings.showwarning = idle_showwarning + else: + if _warnings_showwarning is not None: + warnings.showwarning = _warnings_showwarning + _warnings_showwarning = None + +capture_warnings(True) + +def extended_linecache_checkcache(filename=None, + orig_checkcache=linecache.checkcache): + """Extend linecache.checkcache to preserve the entries + + Rather than repeating the linecache code, patch it to save the + entries, call the original linecache.checkcache() + (skipping them), and then restore the saved entries. + + orig_checkcache is bound at definition time to the original + method, allowing it to be patched. + """ + cache = linecache.cache + save = {} + for key in list(cache): + if key[:1] + key[-1:] == '<>': + save[key] = cache.pop(key) + orig_checkcache(filename) + cache.update(save) + +# Patch linecache.checkcache(): +linecache.checkcache = extended_linecache_checkcache + + +class PyShellEditorWindow(EditorWindow): + "Regular text edit window in IDLE, supports breakpoints" + + def __init__(self, *args): + self.breakpoints = [] + EditorWindow.__init__(self, *args) + self.text.bind("<>", self.set_breakpoint_here) + self.text.bind("<>", self.clear_breakpoint_here) + self.text.bind("<>", self.flist.open_shell) + + self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(), + 'breakpoints.lst') + # whenever a file is changed, restore breakpoints + def filename_changed_hook(old_hook=self.io.filename_change_hook, + self=self): + self.restore_file_breaks() + old_hook() + self.io.set_filename_change_hook(filename_changed_hook) + if self.io.filename: + self.restore_file_breaks() + + rmenu_specs = [ + ("Cut", "<>", "rmenu_check_cut"), + ("Copy", "<>", "rmenu_check_copy"), + ("Paste", "<>", "rmenu_check_paste"), + ("Set Breakpoint", "<>", None), + ("Clear Breakpoint", "<>", None) + ] + + def set_breakpoint(self, lineno): + text = self.text + filename = self.io.filename + text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1)) + try: + i = self.breakpoints.index(lineno) + except ValueError: # only add if missing, i.e. do once + self.breakpoints.append(lineno) + try: # update the subprocess debugger + debug = self.flist.pyshell.interp.debugger + debug.set_breakpoint_here(filename, lineno) + except: # but debugger may not be active right now.... + pass + + def set_breakpoint_here(self, event=None): + text = self.text + filename = self.io.filename + if not filename: + text.bell() + return + lineno = int(float(text.index("insert"))) + self.set_breakpoint(lineno) + + def clear_breakpoint_here(self, event=None): + text = self.text + filename = self.io.filename + if not filename: + text.bell() + return + lineno = int(float(text.index("insert"))) + try: + self.breakpoints.remove(lineno) + except: + pass + text.tag_remove("BREAK", "insert linestart",\ + "insert lineend +1char") + try: + debug = self.flist.pyshell.interp.debugger + debug.clear_breakpoint_here(filename, lineno) + except: + pass + + def clear_file_breaks(self): + if self.breakpoints: + text = self.text + filename = self.io.filename + if not filename: + text.bell() + return + self.breakpoints = [] + text.tag_remove("BREAK", "1.0", END) + try: + debug = self.flist.pyshell.interp.debugger + debug.clear_file_breaks(filename) + except: + pass + + def store_file_breaks(self): + "Save breakpoints when file is saved" + # XXX 13 Dec 2002 KBK Currently the file must be saved before it can + # be run. The breaks are saved at that time. If we introduce + # a temporary file save feature the save breaks functionality + # needs to be re-verified, since the breaks at the time the + # temp file is created may differ from the breaks at the last + # permanent save of the file. Currently, a break introduced + # after a save will be effective, but not persistent. + # This is necessary to keep the saved breaks synched with the + # saved file. + # + # Breakpoints are set as tagged ranges in the text. Certain + # kinds of edits cause these ranges to be deleted: Inserting + # or deleting a line just before a breakpoint, and certain + # deletions prior to a breakpoint. These issues need to be + # investigated and understood. It's not clear if they are + # Tk issues or IDLE issues, or whether they can actually + # be fixed. Since a modified file has to be saved before it is + # run, and since self.breakpoints (from which the subprocess + # debugger is loaded) is updated during the save, the visible + # breaks stay synched with the subprocess even if one of these + # unexpected breakpoint deletions occurs. + breaks = self.breakpoints + filename = self.io.filename + try: + with open(self.breakpointPath,"r") as old_file: + lines = old_file.readlines() + except IOError: + lines = [] + try: + with open(self.breakpointPath,"w") as new_file: + for line in lines: + if not line.startswith(filename + '='): + new_file.write(line) + self.update_breakpoints() + breaks = self.breakpoints + if breaks: + new_file.write(filename + '=' + str(breaks) + '\n') + except IOError as err: + if not getattr(self.root, "breakpoint_error_displayed", False): + self.root.breakpoint_error_displayed = True + tkMessageBox.showerror(title='IDLE Error', + message='Unable to update breakpoint list:\n%s' + % str(err), + parent=self.text) + + def restore_file_breaks(self): + self.text.update() # this enables setting "BREAK" tags to be visible + if self.io is None: + # can happen if IDLE closes due to the .update() call + return + filename = self.io.filename + if filename is None: + return + if os.path.isfile(self.breakpointPath): + lines = open(self.breakpointPath,"r").readlines() + for line in lines: + if line.startswith(filename + '='): + breakpoint_linenumbers = eval(line[len(filename)+1:]) + for breakpoint_linenumber in breakpoint_linenumbers: + self.set_breakpoint(breakpoint_linenumber) + + def update_breakpoints(self): + "Retrieves all the breakpoints in the current window" + text = self.text + ranges = text.tag_ranges("BREAK") + linenumber_list = self.ranges_to_linenumbers(ranges) + self.breakpoints = linenumber_list + + def ranges_to_linenumbers(self, ranges): + lines = [] + for index in range(0, len(ranges), 2): + lineno = int(float(ranges[index].string)) + end = int(float(ranges[index+1].string)) + while lineno < end: + lines.append(lineno) + lineno += 1 + return lines + +# XXX 13 Dec 2002 KBK Not used currently +# def saved_change_hook(self): +# "Extend base method - clear breaks if module is modified" +# if not self.get_saved(): +# self.clear_file_breaks() +# EditorWindow.saved_change_hook(self) + + def _close(self): + "Extend base method - clear breaks when module is closed" + self.clear_file_breaks() + EditorWindow._close(self) + + +class PyShellFileList(FileList): + "Extend base class: IDLE supports a shell and breakpoints" + + # override FileList's class variable, instances return PyShellEditorWindow + # instead of EditorWindow when new edit windows are created. + EditorWindow = PyShellEditorWindow + + pyshell = None + + def open_shell(self, event=None): + if self.pyshell: + self.pyshell.top.wakeup() + else: + self.pyshell = PyShell(self) + if self.pyshell: + if not self.pyshell.begin(): + return None + return self.pyshell + + +class ModifiedColorDelegator(ColorDelegator): + "Extend base class: colorizer for the shell window itself" + + def __init__(self): + ColorDelegator.__init__(self) + self.LoadTagDefs() + + def recolorize_main(self): + self.tag_remove("TODO", "1.0", "iomark") + self.tag_add("SYNC", "1.0", "iomark") + ColorDelegator.recolorize_main(self) + + def LoadTagDefs(self): + ColorDelegator.LoadTagDefs(self) + theme = idleConf.GetOption('main','Theme','name') + self.tagdefs.update({ + "stdin": {'background':None,'foreground':None}, + "stdout": idleConf.GetHighlight(theme, "stdout"), + "stderr": idleConf.GetHighlight(theme, "stderr"), + "console": idleConf.GetHighlight(theme, "console"), + }) + + def removecolors(self): + # Don't remove shell color tags before "iomark" + for tag in self.tagdefs: + self.tag_remove(tag, "iomark", "end") + +class ModifiedUndoDelegator(UndoDelegator): + "Extend base class: forbid insert/delete before the I/O mark" + + def insert(self, index, chars, tags=None): + try: + if self.delegate.compare(index, "<", "iomark"): + self.delegate.bell() + return + except TclError: + pass + UndoDelegator.insert(self, index, chars, tags) + + def delete(self, index1, index2=None): + try: + if self.delegate.compare(index1, "<", "iomark"): + self.delegate.bell() + return + except TclError: + pass + UndoDelegator.delete(self, index1, index2) + + +class MyRPCClient(rpc.RPCClient): + + def handle_EOF(self): + "Override the base class - just re-raise EOFError" + raise EOFError + + +class ModifiedInterpreter(InteractiveInterpreter): + + def __init__(self, tkconsole): + self.tkconsole = tkconsole + locals = sys.modules['__main__'].__dict__ + InteractiveInterpreter.__init__(self, locals=locals) + self.save_warnings_filters = None + self.restarting = False + self.subprocess_arglist = None + self.port = PORT + self.original_compiler_flags = self.compile.compiler.flags + + _afterid = None + rpcclt = None + rpcpid = None + + def spawn_subprocess(self): + if self.subprocess_arglist is None: + self.subprocess_arglist = self.build_subprocess_arglist() + args = self.subprocess_arglist + self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args) + + def build_subprocess_arglist(self): + assert (self.port!=0), ( + "Socket should have been assigned a port number.") + w = ['-W' + s for s in sys.warnoptions] + if 1/2 > 0: # account for new division + w.append('-Qnew') + # Maybe IDLE is installed and is being accessed via sys.path, + # or maybe it's not installed and the idle.py script is being + # run from the IDLE source directory. + del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc', + default=False, type='bool') + if __name__ == 'idlelib.PyShell': + command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,) + else: + command = "__import__('run').main(%r)" % (del_exitf,) + if sys.platform[:3] == 'win' and ' ' in sys.executable: + # handle embedded space in path by quoting the argument + decorated_exec = '"%s"' % sys.executable + else: + decorated_exec = sys.executable + return [decorated_exec] + w + ["-c", command, str(self.port)] + + def start_subprocess(self): + addr = (HOST, self.port) + # GUI makes several attempts to acquire socket, listens for connection + for i in range(3): + time.sleep(i) + try: + self.rpcclt = MyRPCClient(addr) + break + except socket.error as err: + pass + else: + self.display_port_binding_error() + return None + # if PORT was 0, system will assign an 'ephemeral' port. Find it out: + self.port = self.rpcclt.listening_sock.getsockname()[1] + # if PORT was not 0, probably working with a remote execution server + if PORT != 0: + # To allow reconnection within the 2MSL wait (cf. Stevens TCP + # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic + # on Windows since the implementation allows two active sockets on + # the same address! + self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET, + socket.SO_REUSEADDR, 1) + self.spawn_subprocess() + #time.sleep(20) # test to simulate GUI not accepting connection + # Accept the connection from the Python execution server + self.rpcclt.listening_sock.settimeout(10) + try: + self.rpcclt.accept() + except socket.timeout as err: + self.display_no_subprocess_error() + return None + self.rpcclt.register("console", self.tkconsole) + self.rpcclt.register("stdin", self.tkconsole.stdin) + self.rpcclt.register("stdout", self.tkconsole.stdout) + self.rpcclt.register("stderr", self.tkconsole.stderr) + self.rpcclt.register("flist", self.tkconsole.flist) + self.rpcclt.register("linecache", linecache) + self.rpcclt.register("interp", self) + self.transfer_path(with_cwd=True) + self.poll_subprocess() + return self.rpcclt + + def restart_subprocess(self, with_cwd=False): + if self.restarting: + return self.rpcclt + self.restarting = True + # close only the subprocess debugger + debug = self.getdebugger() + if debug: + try: + # Only close subprocess debugger, don't unregister gui_adap! + RemoteDebugger.close_subprocess_debugger(self.rpcclt) + except: + pass + # Kill subprocess, spawn a new one, accept connection. + self.rpcclt.close() + self.unix_terminate() + console = self.tkconsole + was_executing = console.executing + console.executing = False + self.spawn_subprocess() + try: + self.rpcclt.accept() + except socket.timeout as err: + self.display_no_subprocess_error() + return None + self.transfer_path(with_cwd=with_cwd) + console.stop_readline() + # annotate restart in shell window and mark it + console.text.delete("iomark", "end-1c") + if was_executing: + console.write('\n') + console.showprompt() + halfbar = ((int(console.width) - 16) // 2) * '=' + console.write(halfbar + ' RESTART ' + halfbar) + console.text.mark_set("restart", "end-1c") + console.text.mark_gravity("restart", "left") + console.showprompt() + # restart subprocess debugger + if debug: + # Restarted debugger connects to current instance of debug GUI + gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt) + # reload remote debugger breakpoints for all PyShellEditWindows + debug.load_breakpoints() + self.compile.compiler.flags = self.original_compiler_flags + self.restarting = False + return self.rpcclt + + def __request_interrupt(self): + self.rpcclt.remotecall("exec", "interrupt_the_server", (), {}) + + def interrupt_subprocess(self): + threading.Thread(target=self.__request_interrupt).start() + + def kill_subprocess(self): + if self._afterid is not None: + self.tkconsole.text.after_cancel(self._afterid) + try: + self.rpcclt.close() + except AttributeError: # no socket + pass + self.unix_terminate() + self.tkconsole.executing = False + self.rpcclt = None + + def unix_terminate(self): + "UNIX: make sure subprocess is terminated and collect status" + if hasattr(os, 'kill'): + try: + os.kill(self.rpcpid, SIGTERM) + except OSError: + # process already terminated: + return + else: + try: + os.waitpid(self.rpcpid, 0) + except OSError: + return + + def transfer_path(self, with_cwd=False): + if with_cwd: # Issue 13506 + path = [''] # include Current Working Directory + path.extend(sys.path) + else: + path = sys.path + + self.runcommand("""if 1: + import sys as _sys + _sys.path = %r + del _sys + \n""" % (path,)) + + active_seq = None + + def poll_subprocess(self): + clt = self.rpcclt + if clt is None: + return + try: + response = clt.pollresponse(self.active_seq, wait=0.05) + except (EOFError, IOError, KeyboardInterrupt): + # lost connection or subprocess terminated itself, restart + # [the KBI is from rpc.SocketIO.handle_EOF()] + if self.tkconsole.closing: + return + response = None + self.restart_subprocess() + if response: + self.tkconsole.resetoutput() + self.active_seq = None + how, what = response + console = self.tkconsole.console + if how == "OK": + if what is not None: + print >>console, repr(what) + elif how == "EXCEPTION": + if self.tkconsole.getvar("<>"): + self.remote_stack_viewer() + elif how == "ERROR": + errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n" + print >>sys.__stderr__, errmsg, what + print >>console, errmsg, what + # we received a response to the currently active seq number: + try: + self.tkconsole.endexecuting() + except AttributeError: # shell may have closed + pass + # Reschedule myself + if not self.tkconsole.closing: + self._afterid = self.tkconsole.text.after( + self.tkconsole.pollinterval, self.poll_subprocess) + + debugger = None + + def setdebugger(self, debugger): + self.debugger = debugger + + def getdebugger(self): + return self.debugger + + def open_remote_stack_viewer(self): + """Initiate the remote stack viewer from a separate thread. + + This method is called from the subprocess, and by returning from this + method we allow the subprocess to unblock. After a bit the shell + requests the subprocess to open the remote stack viewer which returns a + static object looking at the last exception. It is queried through + the RPC mechanism. + + """ + self.tkconsole.text.after(300, self.remote_stack_viewer) + return + + def remote_stack_viewer(self): + from idlelib import RemoteObjectBrowser + oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {}) + if oid is None: + self.tkconsole.root.bell() + return + item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid) + from idlelib.TreeWidget import ScrolledCanvas, TreeNode + top = Toplevel(self.tkconsole.root) + theme = idleConf.GetOption('main','Theme','name') + background = idleConf.GetHighlight(theme, 'normal')['background'] + sc = ScrolledCanvas(top, bg=background, highlightthickness=0) + sc.frame.pack(expand=1, fill="both") + node = TreeNode(sc.canvas, None, item) + node.expand() + # XXX Should GC the remote tree when closing the window + + gid = 0 + + def execsource(self, source): + "Like runsource() but assumes complete exec source" + filename = self.stuffsource(source) + self.execfile(filename, source) + + def execfile(self, filename, source=None): + "Execute an existing file" + if source is None: + source = open(filename, "r").read() + try: + code = compile(source, filename, "exec") + except (OverflowError, SyntaxError): + self.tkconsole.resetoutput() + tkerr = self.tkconsole.stderr + print>>tkerr, '*** Error in script or command!\n' + print>>tkerr, 'Traceback (most recent call last):' + InteractiveInterpreter.showsyntaxerror(self, filename) + self.tkconsole.showprompt() + else: + self.runcode(code) + + def runsource(self, source): + "Extend base class method: Stuff the source in the line cache first" + filename = self.stuffsource(source) + self.more = 0 + self.save_warnings_filters = warnings.filters[:] + warnings.filterwarnings(action="error", category=SyntaxWarning) + if isinstance(source, types.UnicodeType): + from idlelib import IOBinding + try: + source = source.encode(IOBinding.encoding) + except UnicodeError: + self.tkconsole.resetoutput() + self.write("Unsupported characters in input\n") + return + try: + # InteractiveInterpreter.runsource() calls its runcode() method, + # which is overridden (see below) + return InteractiveInterpreter.runsource(self, source, filename) + finally: + if self.save_warnings_filters is not None: + warnings.filters[:] = self.save_warnings_filters + self.save_warnings_filters = None + + def stuffsource(self, source): + "Stuff source in the filename cache" + filename = "" % self.gid + self.gid = self.gid + 1 + lines = source.split("\n") + linecache.cache[filename] = len(source)+1, 0, lines, filename + return filename + + def prepend_syspath(self, filename): + "Prepend sys.path with file's directory if not already included" + self.runcommand("""if 1: + _filename = %r + import sys as _sys + from os.path import dirname as _dirname + _dir = _dirname(_filename) + if not _dir in _sys.path: + _sys.path.insert(0, _dir) + del _filename, _sys, _dirname, _dir + \n""" % (filename,)) + + def showsyntaxerror(self, filename=None): + """Extend base class method: Add Colorizing + + Color the offending position instead of printing it and pointing at it + with a caret. + + """ + text = self.tkconsole.text + stuff = self.unpackerror() + if stuff: + msg, lineno, offset, line = stuff + if lineno == 1: + pos = "iomark + %d chars" % (offset-1) + else: + pos = "iomark linestart + %d lines + %d chars" % \ + (lineno-1, offset-1) + text.tag_add("ERROR", pos) + text.see(pos) + char = text.get(pos) + if char and char in IDENTCHARS: + text.tag_add("ERROR", pos + " wordstart", pos) + self.tkconsole.resetoutput() + self.write("SyntaxError: %s\n" % str(msg)) + else: + self.tkconsole.resetoutput() + InteractiveInterpreter.showsyntaxerror(self, filename) + self.tkconsole.showprompt() + + def unpackerror(self): + type, value, tb = sys.exc_info() + ok = type is SyntaxError + if ok: + try: + msg, (dummy_filename, lineno, offset, line) = value + if not offset: + offset = 0 + except: + ok = 0 + if ok: + return msg, lineno, offset, line + else: + return None + + def showtraceback(self): + "Extend base class method to reset output properly" + self.tkconsole.resetoutput() + self.checklinecache() + InteractiveInterpreter.showtraceback(self) + if self.tkconsole.getvar("<>"): + self.tkconsole.open_stack_viewer() + + def checklinecache(self): + c = linecache.cache + for key in c.keys(): + if key[:1] + key[-1:] != "<>": + del c[key] + + def runcommand(self, code): + "Run the code without invoking the debugger" + # The code better not raise an exception! + if self.tkconsole.executing: + self.display_executing_dialog() + return 0 + if self.rpcclt: + self.rpcclt.remotequeue("exec", "runcode", (code,), {}) + else: + exec code in self.locals + return 1 + + def runcode(self, code): + "Override base class method" + if self.tkconsole.executing: + self.interp.restart_subprocess() + self.checklinecache() + if self.save_warnings_filters is not None: + warnings.filters[:] = self.save_warnings_filters + self.save_warnings_filters = None + debugger = self.debugger + try: + self.tkconsole.beginexecuting() + if not debugger and self.rpcclt is not None: + self.active_seq = self.rpcclt.asyncqueue("exec", "runcode", + (code,), {}) + elif debugger: + debugger.run(code, self.locals) + else: + exec code in self.locals + except SystemExit: + if not self.tkconsole.closing: + if tkMessageBox.askyesno( + "Exit?", + "Do you want to exit altogether?", + default="yes", + master=self.tkconsole.text): + raise + else: + self.showtraceback() + else: + raise + except: + if use_subprocess: + print >>self.tkconsole.stderr, \ + "IDLE internal error in runcode()" + self.showtraceback() + self.tkconsole.endexecuting() + else: + if self.tkconsole.canceled: + self.tkconsole.canceled = False + print >>self.tkconsole.stderr, "KeyboardInterrupt" + else: + self.showtraceback() + finally: + if not use_subprocess: + try: + self.tkconsole.endexecuting() + except AttributeError: # shell may have closed + pass + + def write(self, s): + "Override base class method" + self.tkconsole.stderr.write(s) + + def display_port_binding_error(self): + tkMessageBox.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 " + "because no networking is installed on this computer. " + "Run IDLE with the -n command line switch to start without a " + "subprocess and refer to Help/IDLE Help 'Running without a " + "subprocess' for further details.", + master=self.tkconsole.text) + + def display_no_subprocess_error(self): + tkMessageBox.showerror( + "Subprocess Startup Error", + "IDLE's subprocess didn't make connection. Either IDLE can't " + "start a subprocess or personal firewall software is blocking " + "the connection.", + master=self.tkconsole.text) + + def display_executing_dialog(self): + tkMessageBox.showerror( + "Already executing", + "The Python Shell window is already executing a command; " + "please wait until it is finished.", + master=self.tkconsole.text) + + +class PyShell(OutputWindow): + + shell_title = "Python " + python_version() + " Shell" + + # Override classes + ColorDelegator = ModifiedColorDelegator + UndoDelegator = ModifiedUndoDelegator + + # Override menus + menu_specs = [ + ("file", "_File"), + ("edit", "_Edit"), + ("debug", "_Debug"), + ("options", "_Options"), + ("windows", "_Windows"), + ("help", "_Help"), + ] + + if sys.platform == "darwin": + menu_specs[-2] = ("windows", "_Window") + + + # New classes + from idlelib.IdleHistory import History + + def __init__(self, flist=None): + if use_subprocess: + ms = self.menu_specs + if ms[2][0] != "shell": + ms.insert(2, ("shell", "She_ll")) + self.interp = ModifiedInterpreter(self) + if flist is None: + root = Tk() + fixwordbreaks(root) + root.withdraw() + flist = PyShellFileList(root) + # + OutputWindow.__init__(self, flist, None, None) + # +## self.config(usetabs=1, indentwidth=8, context_use_ps1=1) + self.usetabs = True + # indentwidth must be 8 when using tabs. See note in EditorWindow: + self.indentwidth = 8 + self.context_use_ps1 = True + # + text = self.text + text.configure(wrap="char") + text.bind("<>", self.enter_callback) + text.bind("<>", self.linefeed_callback) + text.bind("<>", self.cancel_callback) + text.bind("<>", self.eof_callback) + text.bind("<>", self.open_stack_viewer) + text.bind("<>", self.toggle_debugger) + text.bind("<>", self.toggle_jit_stack_viewer) + if use_subprocess: + text.bind("<>", self.view_restart_mark) + text.bind("<>", self.restart_shell) + # + self.save_stdout = sys.stdout + self.save_stderr = sys.stderr + self.save_stdin = sys.stdin + from idlelib import IOBinding + self.stdin = PseudoInputFile(self, "stdin", IOBinding.encoding) + self.stdout = PseudoOutputFile(self, "stdout", IOBinding.encoding) + self.stderr = PseudoOutputFile(self, "stderr", IOBinding.encoding) + self.console = PseudoOutputFile(self, "console", IOBinding.encoding) + if not use_subprocess: + sys.stdout = self.stdout + sys.stderr = self.stderr + sys.stdin = self.stdin + # + self.history = self.History(self.text) + # + self.pollinterval = 50 # millisec + + def get_standard_extension_names(self): + return idleConf.GetExtensions(shell_only=True) + + reading = False + executing = False + canceled = False + endoffile = False + closing = False + _stop_readline_flag = False + + def set_warning_stream(self, stream): + global warning_stream + warning_stream = stream + + def get_warning_stream(self): + return warning_stream + + def toggle_debugger(self, event=None): + if self.executing: + tkMessageBox.showerror("Don't debug now", + "You can only toggle the debugger when idle", + master=self.text) + self.set_debugger_indicator() + return "break" + else: + db = self.interp.getdebugger() + if db: + self.close_debugger() + else: + self.open_debugger() + + def set_debugger_indicator(self): + db = self.interp.getdebugger() + self.setvar("<>", not not db) + + def toggle_jit_stack_viewer(self, event=None): + pass # All we need is the variable + + def close_debugger(self): + db = self.interp.getdebugger() + if db: + self.interp.setdebugger(None) + db.close() + if self.interp.rpcclt: + RemoteDebugger.close_remote_debugger(self.interp.rpcclt) + self.resetoutput() + self.console.write("[DEBUG OFF]\n") + sys.ps1 = ">>> " + self.showprompt() + self.set_debugger_indicator() + + def open_debugger(self): + if self.interp.rpcclt: + dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt, + self) + else: + dbg_gui = Debugger.Debugger(self) + self.interp.setdebugger(dbg_gui) + dbg_gui.load_breakpoints() + sys.ps1 = "[DEBUG ON]\n>>> " + self.showprompt() + self.set_debugger_indicator() + + def beginexecuting(self): + "Helper for ModifiedInterpreter" + self.resetoutput() + self.executing = 1 + + def endexecuting(self): + "Helper for ModifiedInterpreter" + self.executing = 0 + self.canceled = 0 + self.showprompt() + + def close(self): + "Extend EditorWindow.close()" + if self.executing: + response = tkMessageBox.askokcancel( + "Kill?", + "The program is still running!\n Do you want to kill it?", + default="ok", + parent=self.text) + if response is False: + return "cancel" + self.stop_readline() + self.canceled = True + self.closing = True + return EditorWindow.close(self) + + def _close(self): + "Extend EditorWindow._close(), shut down debugger and execution server" + self.close_debugger() + if use_subprocess: + self.interp.kill_subprocess() + # Restore std streams + sys.stdout = self.save_stdout + sys.stderr = self.save_stderr + sys.stdin = self.save_stdin + # Break cycles + self.interp = None + self.console = None + self.flist.pyshell = None + self.history = None + EditorWindow._close(self) + + def ispythonsource(self, filename): + "Override EditorWindow method: never remove the colorizer" + return True + + def short_title(self): + return self.shell_title + + COPYRIGHT = \ + 'Type "copyright", "credits" or "license()" for more information.' + + def begin(self): + self.resetoutput() + if use_subprocess: + nosub = '' + client = self.interp.start_subprocess() + if not client: + self.close() + return False + else: + nosub = "==== No Subprocess ====" + self.write("Python %s on %s\n%s\n%s" % + (sys.version, sys.platform, self.COPYRIGHT, nosub)) + self.showprompt() + import Tkinter + Tkinter._default_root = None # 03Jan04 KBK What's this? + return True + + def stop_readline(self): + if not self.reading: # no nested mainloop to exit. + return + self._stop_readline_flag = True + self.top.quit() + + def readline(self): + save = self.reading + try: + self.reading = 1 + self.top.mainloop() # nested mainloop() + finally: + self.reading = save + if self._stop_readline_flag: + self._stop_readline_flag = False + return "" + line = self.text.get("iomark", "end-1c") + if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C + line = "\n" + if isinstance(line, unicode): + from idlelib import IOBinding + try: + line = line.encode(IOBinding.encoding) + except UnicodeError: + pass + self.resetoutput() + if self.canceled: + self.canceled = 0 + if not use_subprocess: + raise KeyboardInterrupt + if self.endoffile: + self.endoffile = 0 + line = "" + return line + + def isatty(self): + return True + + def cancel_callback(self, event=None): + try: + if self.text.compare("sel.first", "!=", "sel.last"): + return # Active selection -- always use default binding + except: + pass + if not (self.executing or self.reading): + self.resetoutput() + self.interp.write("KeyboardInterrupt\n") + self.showprompt() + return "break" + self.endoffile = 0 + self.canceled = 1 + if (self.executing and self.interp.rpcclt): + if self.interp.getdebugger(): + self.interp.restart_subprocess() + else: + self.interp.interrupt_subprocess() + if self.reading: + self.top.quit() # exit the nested mainloop() in readline() + return "break" + + def eof_callback(self, event): + if self.executing and not self.reading: + return # Let the default binding (delete next char) take over + if not (self.text.compare("iomark", "==", "insert") and + self.text.compare("insert", "==", "end-1c")): + return # Let the default binding (delete next char) take over + if not self.executing: + self.resetoutput() + self.close() + else: + self.canceled = 0 + self.endoffile = 1 + self.top.quit() + return "break" + + def linefeed_callback(self, event): + # Insert a linefeed without entering anything (still autoindented) + if self.reading: + self.text.insert("insert", "\n") + self.text.see("insert") + else: + self.newline_and_indent_event(event) + return "break" + + def enter_callback(self, event): + if self.executing and not self.reading: + return # Let the default binding (insert '\n') take over + # If some text is selected, recall the selection + # (but only if this before the I/O mark) + try: + sel = self.text.get("sel.first", "sel.last") + if sel: + if self.text.compare("sel.last", "<=", "iomark"): + self.recall(sel, event) + return "break" + except: + pass + # If we're strictly before the line containing iomark, recall + # the current line, less a leading prompt, less leading or + # trailing whitespace + if self.text.compare("insert", "<", "iomark linestart"): + # Check if there's a relevant stdin range -- if so, use it + prev = self.text.tag_prevrange("stdin", "insert") + if prev and self.text.compare("insert", "<", prev[1]): + self.recall(self.text.get(prev[0], prev[1]), event) + return "break" + next = self.text.tag_nextrange("stdin", "insert") + if next and self.text.compare("insert lineend", ">=", next[0]): + self.recall(self.text.get(next[0], next[1]), event) + return "break" + # No stdin mark -- just get the current line, less any prompt + indices = self.text.tag_nextrange("console", "insert linestart") + if indices and \ + self.text.compare(indices[0], "<=", "insert linestart"): + self.recall(self.text.get(indices[1], "insert lineend"), event) + else: + self.recall(self.text.get("insert linestart", "insert lineend"), event) + return "break" + # If we're between the beginning of the line and the iomark, i.e. + # in the prompt area, move to the end of the prompt + if self.text.compare("insert", "<", "iomark"): + self.text.mark_set("insert", "iomark") + # If we're in the current input and there's only whitespace + # beyond the cursor, erase that whitespace first + s = self.text.get("insert", "end-1c") + if s and not s.strip(): + self.text.delete("insert", "end-1c") + # If we're in the current input before its last line, + # insert a newline right at the insert point + if self.text.compare("insert", "<", "end-1c linestart"): + self.newline_and_indent_event(event) + return "break" + # We're in the last line; append a newline and submit it + self.text.mark_set("insert", "end-1c") + if self.reading: + self.text.insert("insert", "\n") + self.text.see("insert") + else: + self.newline_and_indent_event(event) + self.text.tag_add("stdin", "iomark", "end-1c") + self.text.update_idletasks() + if self.reading: + self.top.quit() # Break out of recursive mainloop() in raw_input() + else: + self.runit() + return "break" + + def recall(self, s, event): + # remove leading and trailing empty or whitespace lines + s = re.sub(r'^\s*\n', '' , s) + s = re.sub(r'\n\s*$', '', s) + lines = s.split('\n') + self.text.undo_block_start() + try: + self.text.tag_remove("sel", "1.0", "end") + self.text.mark_set("insert", "end-1c") + prefix = self.text.get("insert linestart", "insert") + if prefix.rstrip().endswith(':'): + self.newline_and_indent_event(event) + prefix = self.text.get("insert linestart", "insert") + self.text.insert("insert", lines[0].strip()) + if len(lines) > 1: + orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0) + new_base_indent = re.search(r'^([ \t]*)', prefix).group(0) + for line in lines[1:]: + if line.startswith(orig_base_indent): + # replace orig base indentation with new indentation + line = new_base_indent + line[len(orig_base_indent):] + self.text.insert('insert', '\n'+line.rstrip()) + finally: + self.text.see("insert") + self.text.undo_block_stop() + + def runit(self): + line = self.text.get("iomark", "end-1c") + # Strip off last newline and surrounding whitespace. + # (To allow you to hit return twice to end a statement.) + i = len(line) + while i > 0 and line[i-1] in " \t": + i = i-1 + if i > 0 and line[i-1] == "\n": + i = i-1 + while i > 0 and line[i-1] in " \t": + i = i-1 + line = line[:i] + more = self.interp.runsource(line) + + def open_stack_viewer(self, event=None): + if self.interp.rpcclt: + return self.interp.remote_stack_viewer() + try: + sys.last_traceback + except: + tkMessageBox.showerror("No stack trace", + "There is no stack trace yet.\n" + "(sys.last_traceback is not defined)", + master=self.text) + return + from idlelib.StackViewer import StackBrowser + sv = StackBrowser(self.root, self.flist) + + def view_restart_mark(self, event=None): + self.text.see("iomark") + self.text.see("restart") + + def restart_shell(self, event=None): + "Callback for Run/Restart Shell Cntl-F6" + self.interp.restart_subprocess(with_cwd=True) + + def showprompt(self): + self.resetoutput() + try: + s = str(sys.ps1) + except: + s = "" + self.console.write(s) + self.text.mark_set("insert", "end-1c") + self.set_line_and_column() + self.io.reset_undo() + + def resetoutput(self): + source = self.text.get("iomark", "end-1c") + if self.history: + self.history.store(source) + if self.text.get("end-2c") != "\n": + self.text.insert("end-1c", "\n") + self.text.mark_set("iomark", "end-1c") + self.set_line_and_column() + sys.stdout.softspace = 0 + + def write(self, s, tags=()): + try: + self.text.mark_gravity("iomark", "right") + OutputWindow.write(self, s, tags, "iomark") + self.text.mark_gravity("iomark", "left") + except: + pass + if self.canceled: + self.canceled = 0 + if not use_subprocess: + raise KeyboardInterrupt + + def rmenu_check_cut(self): + try: + if self.text.compare('sel.first', '<', 'iomark'): + return 'disabled' + except TclError: # no selection, so the index 'sel.first' doesn't exist + return 'disabled' + return super(PyShell, self).rmenu_check_cut() + + def rmenu_check_paste(self): + if self.text.compare('insert', '<', 'iomark'): + return 'disabled' + return super(PyShell, self).rmenu_check_paste() + +class PseudoFile(io.TextIOBase): + + def __init__(self, shell, tags, encoding=None): + self.shell = shell + self.tags = tags + self.softspace = 0 + self._encoding = encoding + + @property + def encoding(self): + return self._encoding + + @property + def name(self): + return '<%s>' % self.tags + + def isatty(self): + return True + + +class PseudoOutputFile(PseudoFile): + + def writable(self): + return True + + def write(self, s): + if self.closed: + raise ValueError("write to closed file") + if type(s) not in (unicode, str, bytearray): + # See issue #19481 + if isinstance(s, unicode): + s = unicode.__getslice__(s, None, None) + elif isinstance(s, str): + s = str.__str__(s) + elif isinstance(s, bytearray): + s = bytearray.__str__(s) + else: + raise TypeError('must be string, not ' + type(s).__name__) + return self.shell.write(s, self.tags) + + +class PseudoInputFile(PseudoFile): + + def __init__(self, shell, tags, encoding=None): + PseudoFile.__init__(self, shell, tags, encoding) + self._line_buffer = '' + + def readable(self): + return True + + def read(self, size=-1): + if self.closed: + raise ValueError("read from closed file") + if size is None: + size = -1 + elif not isinstance(size, int): + raise TypeError('must be int, not ' + type(size).__name__) + result = self._line_buffer + self._line_buffer = '' + if size < 0: + while True: + line = self.shell.readline() + if not line: break + result += line + else: + while len(result) < size: + line = self.shell.readline() + if not line: break + result += line + self._line_buffer = result[size:] + result = result[:size] + return result + + def readline(self, size=-1): + if self.closed: + raise ValueError("read from closed file") + if size is None: + size = -1 + elif not isinstance(size, int): + raise TypeError('must be int, not ' + type(size).__name__) + line = self._line_buffer or self.shell.readline() + if size < 0: + size = len(line) + eol = line.find('\n', 0, size) + if eol >= 0: + size = eol + 1 + self._line_buffer = line[size:] + return line[:size] + + def close(self): + self.shell.close() + + +usage_msg = """\ + +USAGE: idle [-deins] [-t title] [file]* + idle [-dns] [-t title] (-c cmd | -r file) [arg]* + idle [-dns] [-t title] - [arg]* + + -h print this help message and exit + -n run IDLE without a subprocess (see Help/IDLE Help for details) + +The following options will override the IDLE 'settings' configuration: + + -e open an edit window + -i open a shell window + +The following options imply -i and will open a shell: + + -c cmd run the command in a shell, or + -r file run script from file + + -d enable the debugger + -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else + -t title set title of shell window + +A default edit window will be bypassed when -c, -r, or - are used. + +[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:]. + +Examples: + +idle + Open an edit window or shell depending on IDLE's configuration. + +idle foo.py foobar.py + Edit the files, also open a shell if configured to start with shell. + +idle -est "Baz" foo.py + Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell + window with the title "Baz". + +idle -c "import sys; print sys.argv" "foo" + Open a shell window and run the command, passing "-c" in sys.argv[0] + and "foo" in sys.argv[1]. + +idle -d -s -r foo.py "Hello World" + 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]. + +echo "import sys; print sys.argv" | idle - "foobar" + Open a shell window, run the script piped in, passing '' in sys.argv[0] + and "foobar" in sys.argv[1]. +""" + +def main(): + global flist, root, use_subprocess + + capture_warnings(True) + use_subprocess = True + enable_shell = False + enable_edit = False + debug = False + cmd = None + script = None + startup = False + try: + opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:") + except getopt.error as msg: + sys.stderr.write("Error: %s\n" % str(msg)) + sys.stderr.write(usage_msg) + sys.exit(2) + for o, a in opts: + if o == '-c': + cmd = a + enable_shell = True + if o == '-d': + debug = True + enable_shell = True + if o == '-e': + enable_edit = True + if o == '-h': + sys.stdout.write(usage_msg) + sys.exit() + if o == '-i': + enable_shell = True + if o == '-n': + use_subprocess = False + if o == '-r': + script = a + if os.path.isfile(script): + pass + else: + print "No script file: ", script + sys.exit() + enable_shell = True + if o == '-s': + startup = True + enable_shell = True + if o == '-t': + PyShell.shell_title = a + enable_shell = True + if args and args[0] == '-': + cmd = sys.stdin.read() + enable_shell = True + # process sys.argv and sys.path: + for i in range(len(sys.path)): + sys.path[i] = os.path.abspath(sys.path[i]) + if args and args[0] == '-': + sys.argv = [''] + args[1:] + elif cmd: + sys.argv = ['-c'] + args + elif script: + sys.argv = [script] + args + elif args: + enable_edit = True + pathx = [] + for filename in args: + pathx.append(os.path.dirname(filename)) + for dir in pathx: + dir = os.path.abspath(dir) + if dir not in sys.path: + sys.path.insert(0, dir) + else: + dir = os.getcwd() + if not dir in sys.path: + sys.path.insert(0, dir) + # check the IDLE settings configuration (but command line overrides) + edit_start = idleConf.GetOption('main', 'General', + 'editor-on-startup', type='bool') + enable_edit = enable_edit or edit_start + enable_shell = enable_shell or not enable_edit + # start editor and/or shell windows: + root = Tk(className="Idle") + + # set application icon + icondir = os.path.join(os.path.dirname(__file__), 'Icons') + if system() == 'Windows': + iconfile = os.path.join(icondir, 'idle.ico') + root.wm_iconbitmap(default=iconfile) + elif TkVersion >= 8.5: + ext = '.png' if TkVersion >= 8.6 else '.gif' + iconfiles = [os.path.join(icondir, 'idle_%d%s' % (size, ext)) + for size in (16, 32, 48)] + icons = [PhotoImage(file=iconfile) for iconfile in iconfiles] + root.tk.call('wm', 'iconphoto', str(root), "-default", *icons) + + fixwordbreaks(root) + root.withdraw() + flist = PyShellFileList(root) + macosxSupport.setupApp(root, flist) + + if enable_edit: + if not (cmd or script): + for filename in args[:]: + if flist.open(filename) is None: + # filename is a directory actually, disconsider it + args.remove(filename) + if not args: + flist.new() + + if enable_shell: + shell = flist.open_shell() + if not shell: + return # couldn't open shell + if macosxSupport.isAquaTk() and flist.dict: + # On OSX: when the user has double-clicked on a file that causes + # IDLE to be launched the shell window will open just in front of + # the file she wants to see. Lower the interpreter window when + # there are open files. + shell.top.lower() + else: + shell = flist.pyshell + + # Handle remaining options. If any of these are set, enable_shell + # was set also, so shell must be true to reach here. + if debug: + shell.open_debugger() + if startup: + filename = os.environ.get("IDLESTARTUP") or \ + os.environ.get("PYTHONSTARTUP") + if filename and os.path.isfile(filename): + shell.interp.execfile(filename) + if cmd or script: + shell.interp.runcommand("""if 1: + import sys as _sys + _sys.argv = %r + del _sys + \n""" % (sys.argv,)) + if cmd: + shell.interp.execsource(cmd) + elif script: + shell.interp.prepend_syspath(script) + shell.interp.execfile(script) + elif shell: + # If there is a shell window and no cmd or script in progress, + # check for problematic OS X Tk versions and print a warning + # message in the IDLE shell window; this is less intrusive + # than always opening a separate window. + tkversionwarning = macosxSupport.tkVersionWarning(root) + if tkversionwarning: + shell.interp.runcommand("print('%s')" % tkversionwarning) + + while flist.inversedict: # keep IDLE running while files are open. + root.mainloop() + root.destroy() + capture_warnings(False) + +if __name__ == "__main__": + sys.modules['PyShell'] = sys.modules['__main__'] + main() + +capture_warnings(False) # Make sure turned off; see issue 18081 diff --git a/PythonHome/Lib/idlelib/PyShell.pyc b/PythonHome/Lib/idlelib/PyShell.pyc deleted file mode 100644 index 167b5742f1eb580c6b06be093280f46ee41ba700..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50039 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 a_1DSo@cWIuJ9h2dHBXuEoZ!9jq5mKJXVXCd diff --git a/PythonHome/Lib/idlelib/RemoteDebugger.py b/PythonHome/Lib/idlelib/RemoteDebugger.py new file mode 100644 index 0000000000..647285fe4e --- /dev/null +++ b/PythonHome/Lib/idlelib/RemoteDebugger.py @@ -0,0 +1,380 @@ +"""Support for remote Python debugging. + +Some ASCII art to describe the structure: + + IN PYTHON SUBPROCESS # IN IDLE PROCESS + # + # oid='gui_adapter' + +----------+ # +------------+ +-----+ + | GUIProxy |--remote#call-->| GUIAdapter |--calls-->| GUI | ++-----+--calls-->+----------+ # +------------+ +-----+ +| Idb | # / ++-----+<-calls--+------------+ # +----------+<--calls-/ + | IdbAdapter |<--remote#call--| IdbProxy | + +------------+ # +----------+ + oid='idb_adapter' # + +The purpose of the Proxy and Adapter classes is to translate certain +arguments and return values that cannot be transported through the RPC +barrier, in particular frame and traceback objects. + +""" + +import types +from idlelib import rpc +from idlelib import Debugger + +debugging = 0 + +idb_adap_oid = "idb_adapter" +gui_adap_oid = "gui_adapter" + +#======================================= +# +# In the PYTHON subprocess: + +frametable = {} +dicttable = {} +codetable = {} +tracebacktable = {} + +def wrap_frame(frame): + fid = id(frame) + frametable[fid] = frame + return fid + +def wrap_info(info): + "replace info[2], a traceback instance, by its ID" + if info is None: + return None + else: + traceback = info[2] + assert isinstance(traceback, types.TracebackType) + traceback_id = id(traceback) + tracebacktable[traceback_id] = traceback + modified_info = (info[0], info[1], traceback_id) + return modified_info + +class GUIProxy: + + def __init__(self, conn, gui_adap_oid): + self.conn = conn + self.oid = gui_adap_oid + + def interaction(self, message, frame, info=None): + # calls rpc.SocketIO.remotecall() via run.MyHandler instance + # pass frame and traceback object IDs instead of the objects themselves + self.conn.remotecall(self.oid, "interaction", + (message, wrap_frame(frame), wrap_info(info)), + {}) + +class IdbAdapter: + + def __init__(self, idb): + self.idb = idb + + #----------called by an IdbProxy---------- + + def set_step(self): + self.idb.set_step() + + def set_quit(self): + self.idb.set_quit() + + def set_continue(self): + self.idb.set_continue() + + def set_next(self, fid): + frame = frametable[fid] + self.idb.set_next(frame) + + def set_return(self, fid): + frame = frametable[fid] + self.idb.set_return(frame) + + def get_stack(self, fid, tbid): + ##print >>sys.__stderr__, "get_stack(%r, %r)" % (fid, tbid) + frame = frametable[fid] + if tbid is None: + tb = None + else: + tb = tracebacktable[tbid] + stack, i = self.idb.get_stack(frame, tb) + ##print >>sys.__stderr__, "get_stack() ->", stack + stack = [(wrap_frame(frame), k) for frame, k in stack] + ##print >>sys.__stderr__, "get_stack() ->", stack + return stack, i + + def run(self, cmd): + import __main__ + self.idb.run(cmd, __main__.__dict__) + + def set_break(self, filename, lineno): + msg = self.idb.set_break(filename, lineno) + return msg + + def clear_break(self, filename, lineno): + msg = self.idb.clear_break(filename, lineno) + return msg + + def clear_all_file_breaks(self, filename): + msg = self.idb.clear_all_file_breaks(filename) + return msg + + #----------called by a FrameProxy---------- + + def frame_attr(self, fid, name): + frame = frametable[fid] + return getattr(frame, name) + + def frame_globals(self, fid): + frame = frametable[fid] + dict = frame.f_globals + did = id(dict) + dicttable[did] = dict + return did + + def frame_locals(self, fid): + frame = frametable[fid] + dict = frame.f_locals + did = id(dict) + dicttable[did] = dict + return did + + def frame_code(self, fid): + frame = frametable[fid] + code = frame.f_code + cid = id(code) + codetable[cid] = code + return cid + + #----------called by a CodeProxy---------- + + def code_name(self, cid): + code = codetable[cid] + return code.co_name + + def code_filename(self, cid): + code = codetable[cid] + return code.co_filename + + #----------called by a DictProxy---------- + + def dict_keys(self, did): + dict = dicttable[did] + return dict.keys() + + def dict_item(self, did, key): + dict = dicttable[did] + value = dict[key] + value = repr(value) + return value + +#----------end class IdbAdapter---------- + + +def start_debugger(rpchandler, gui_adap_oid): + """Start the debugger and its RPC link in the Python subprocess + + Start the subprocess side of the split debugger and set up that side of the + RPC link by instantiating the GUIProxy, Idb debugger, and IdbAdapter + objects and linking them together. Register the IdbAdapter with the + RPCServer to handle RPC requests from the split debugger GUI via the + IdbProxy. + + """ + gui_proxy = GUIProxy(rpchandler, gui_adap_oid) + idb = Debugger.Idb(gui_proxy) + idb_adap = IdbAdapter(idb) + rpchandler.register(idb_adap_oid, idb_adap) + return idb_adap_oid + + +#======================================= +# +# In the IDLE process: + + +class FrameProxy: + + def __init__(self, conn, fid): + self._conn = conn + self._fid = fid + self._oid = "idb_adapter" + self._dictcache = {} + + def __getattr__(self, name): + if name[:1] == "_": + raise AttributeError, name + if name == "f_code": + return self._get_f_code() + if name == "f_globals": + return self._get_f_globals() + if name == "f_locals": + return self._get_f_locals() + return self._conn.remotecall(self._oid, "frame_attr", + (self._fid, name), {}) + + def _get_f_code(self): + cid = self._conn.remotecall(self._oid, "frame_code", (self._fid,), {}) + return CodeProxy(self._conn, self._oid, cid) + + def _get_f_globals(self): + did = self._conn.remotecall(self._oid, "frame_globals", + (self._fid,), {}) + return self._get_dict_proxy(did) + + def _get_f_locals(self): + did = self._conn.remotecall(self._oid, "frame_locals", + (self._fid,), {}) + return self._get_dict_proxy(did) + + def _get_dict_proxy(self, did): + if did in self._dictcache: + return self._dictcache[did] + dp = DictProxy(self._conn, self._oid, did) + self._dictcache[did] = dp + return dp + + +class CodeProxy: + + def __init__(self, conn, oid, cid): + self._conn = conn + self._oid = oid + self._cid = cid + + def __getattr__(self, name): + if name == "co_name": + return self._conn.remotecall(self._oid, "code_name", + (self._cid,), {}) + if name == "co_filename": + return self._conn.remotecall(self._oid, "code_filename", + (self._cid,), {}) + + +class DictProxy: + + def __init__(self, conn, oid, did): + self._conn = conn + self._oid = oid + self._did = did + + def keys(self): + return self._conn.remotecall(self._oid, "dict_keys", (self._did,), {}) + + def __getitem__(self, key): + return self._conn.remotecall(self._oid, "dict_item", + (self._did, key), {}) + + def __getattr__(self, name): + ##print >>sys.__stderr__, "failed DictProxy.__getattr__:", name + raise AttributeError, name + + +class GUIAdapter: + + def __init__(self, conn, gui): + self.conn = conn + self.gui = gui + + def interaction(self, message, fid, modified_info): + ##print "interaction: (%s, %s, %s)" % (message, fid, modified_info) + frame = FrameProxy(self.conn, fid) + self.gui.interaction(message, frame, modified_info) + + +class IdbProxy: + + def __init__(self, conn, shell, oid): + self.oid = oid + self.conn = conn + self.shell = shell + + def call(self, methodname, *args, **kwargs): + ##print "**IdbProxy.call %s %s %s" % (methodname, args, kwargs) + value = self.conn.remotecall(self.oid, methodname, args, kwargs) + ##print "**IdbProxy.call %s returns %r" % (methodname, value) + return value + + def run(self, cmd, locals): + # Ignores locals on purpose! + seq = self.conn.asyncqueue(self.oid, "run", (cmd,), {}) + self.shell.interp.active_seq = seq + + def get_stack(self, frame, tbid): + # passing frame and traceback IDs, not the objects themselves + stack, i = self.call("get_stack", frame._fid, tbid) + stack = [(FrameProxy(self.conn, fid), k) for fid, k in stack] + return stack, i + + def set_continue(self): + self.call("set_continue") + + def set_step(self): + self.call("set_step") + + def set_next(self, frame): + self.call("set_next", frame._fid) + + def set_return(self, frame): + self.call("set_return", frame._fid) + + def set_quit(self): + self.call("set_quit") + + def set_break(self, filename, lineno): + msg = self.call("set_break", filename, lineno) + return msg + + def clear_break(self, filename, lineno): + msg = self.call("clear_break", filename, lineno) + return msg + + def clear_all_file_breaks(self, filename): + msg = self.call("clear_all_file_breaks", filename) + return msg + +def start_remote_debugger(rpcclt, pyshell): + """Start the subprocess debugger, initialize the debugger GUI and RPC link + + Request the RPCServer start the Python subprocess debugger and link. Set + up the Idle side of the split debugger by instantiating the IdbProxy, + debugger GUI, and debugger GUIAdapter objects and linking them together. + + Register the GUIAdapter with the RPCClient to handle debugger GUI + interaction requests coming from the subprocess debugger via the GUIProxy. + + The IdbAdapter will pass execution and environment requests coming from the + Idle debugger GUI to the subprocess debugger via the IdbProxy. + + """ + global idb_adap_oid + + idb_adap_oid = rpcclt.remotecall("exec", "start_the_debugger",\ + (gui_adap_oid,), {}) + idb_proxy = IdbProxy(rpcclt, pyshell, idb_adap_oid) + gui = Debugger.Debugger(pyshell, idb_proxy) + gui_adap = GUIAdapter(rpcclt, gui) + rpcclt.register(gui_adap_oid, gui_adap) + return gui + +def close_remote_debugger(rpcclt): + """Shut down subprocess debugger and Idle side of debugger RPC link + + Request that the RPCServer shut down the subprocess debugger and link. + Unregister the GUIAdapter, which will cause a GC on the Idle process + debugger and RPC link objects. (The second reference to the debugger GUI + is deleted in PyShell.close_remote_debugger().) + + """ + close_subprocess_debugger(rpcclt) + rpcclt.unregister(gui_adap_oid) + +def close_subprocess_debugger(rpcclt): + rpcclt.remotecall("exec", "stop_the_debugger", (idb_adap_oid,), {}) + +def restart_subprocess_debugger(rpcclt): + idb_adap_oid_ret = rpcclt.remotecall("exec", "start_the_debugger",\ + (gui_adap_oid,), {}) + assert idb_adap_oid_ret == idb_adap_oid, 'Idb restarted with different oid' diff --git a/PythonHome/Lib/idlelib/RemoteDebugger.pyc b/PythonHome/Lib/idlelib/RemoteDebugger.pyc deleted file mode 100644 index d33e1fcc18b5a12fb442c7921fb09f1078fa51f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15420 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 YmuPZ=g(mJixb;*UjkOOO7x*0iZ$$hNssI20 diff --git a/PythonHome/Lib/idlelib/RstripExtension.py b/PythonHome/Lib/idlelib/RstripExtension.py new file mode 100644 index 0000000000..2ce3c7eafe --- /dev/null +++ b/PythonHome/Lib/idlelib/RstripExtension.py @@ -0,0 +1,33 @@ +'Provides "Strip trailing whitespace" under the "Format" menu.' + +class RstripExtension: + + menudefs = [ + ('format', [None, ('Strip trailing whitespace', '<>'), ] ), ] + + def __init__(self, editwin): + self.editwin = editwin + self.editwin.text.bind("<>", self.do_rstrip) + + def do_rstrip(self, event=None): + + text = self.editwin.text + undo = self.editwin.undo + + undo.undo_block_start() + + end_line = int(float(text.index('end'))) + for cur in range(1, end_line): + txt = text.get('%i.0' % cur, '%i.end' % cur) + raw = len(txt) + cut = len(txt.rstrip()) + # Since text.delete() marks file as changed, even if not, + # only call it when needed to actually delete something. + if cut < raw: + text.delete('%i.%i' % (cur, cut), '%i.end' % cur) + + undo.undo_block_stop() + +if __name__ == "__main__": + import unittest + unittest.main('idlelib.idle_test.test_rstrip', verbosity=2, exit=False) diff --git a/PythonHome/Lib/idlelib/RstripExtension.pyc b/PythonHome/Lib/idlelib/RstripExtension.pyc deleted file mode 100644 index 1e73c0fe4fa72a0a3bd0093023d336502beaab3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1553 zcmbVM+invv5FLAyv`tfiKvbfD6jdt93lZYERESHTXat)FL{((Av0I#OcFWpni-p$RGi1Yrp{u}%|BLzIU? zRm|UMjm{>_4iz@3@m)N9b41hGQPdE8)M*tN;t9Lc27&CP!RFJ2xjt-i3|?8J3El-d zA}&r2x6GvnW2__jKX_8_cL?t*#@G^!k_66uFD8(#uwG#n?i;>)KkyzDYy_qcb;EbK z2IP)YHj-;c<(Ba(zF0B)c{w;TA!bz+zepgi0u`2**-S$QkxgE!vf|LmDNHiwu8?}1 zrB+nyau=Pn!A}9o;|^ygWtig4oxoUNrMw|o1$cv2n*|w+D+v-&ON_qCPGug9<3CnR z%II4dVHJXOOSN=U-%_h;O|{guq@^}=PYUy2TdE^;W(8SfBWFx(B7!la(vEZfJJ|=55sF+2HRL zyDa9tD4luYs{Jzf_`!283SM{S=T|KB7_2e292g^^(=|TGe8%WO_9s>xTQa+y<-z?A VG4Z)MySgo@ZVuAW*KZ?Z>MK)pN|^uv diff --git a/PythonHome/Lib/idlelib/ScriptBinding.py b/PythonHome/Lib/idlelib/ScriptBinding.py new file mode 100644 index 0000000000..ab2a3f29b9 --- /dev/null +++ b/PythonHome/Lib/idlelib/ScriptBinding.py @@ -0,0 +1,222 @@ +"""Extension to execute code outside the Python shell window. + +This adds the following commands: + +- Check module does a full syntax check of the current module. + It also runs the tabnanny to catch any inconsistent tabs. + +- Run module executes the module's code in the __main__ namespace. The window + must have been saved previously. The module is added to sys.modules, and is + also added to the __main__ namespace. + +XXX GvR Redesign this interface (yet again) as follows: + +- Present a dialog box for ``Run Module'' + +- Allow specify command line arguments in the dialog box + +""" + +import os +import re +import string +import tabnanny +import tokenize +import tkMessageBox +from idlelib import PyShell + +from idlelib.configHandler import idleConf +from idlelib import macosxSupport + +IDENTCHARS = string.ascii_letters + string.digits + "_" + +indent_message = """Error: Inconsistent indentation detected! + +1) Your indentation is outright incorrect (easy to fix), OR + +2) Your indentation mixes tabs and spaces. + +To fix case 2, change all tabs to spaces by using Edit->Select All followed \ +by Format->Untabify Region and specify the number of columns used by each tab. +""" + +class ScriptBinding: + + menudefs = [ + ('run', [None, + ('Check Module', '<>'), + ('Run Module', '<>'), ]), ] + + def __init__(self, editwin): + self.editwin = editwin + # Provide instance variables referenced by Debugger + # XXX This should be done differently + self.flist = self.editwin.flist + self.root = self.editwin.root + + if macosxSupport.isCocoaTk(): + self.editwin.text_frame.bind('<>', self._run_module_event) + + def check_module_event(self, event): + filename = self.getfilename() + if not filename: + return 'break' + if not self.checksyntax(filename): + return 'break' + if not self.tabnanny(filename): + return 'break' + + def tabnanny(self, filename): + f = open(filename, 'r') + try: + tabnanny.process_tokens(tokenize.generate_tokens(f.readline)) + except tokenize.TokenError as msg: + msgtxt, (lineno, start) = msg + self.editwin.gotoline(lineno) + self.errorbox("Tabnanny Tokenizing Error", + "Token Error: %s" % msgtxt) + return False + except tabnanny.NannyNag as nag: + # The error messages from tabnanny are too confusing... + self.editwin.gotoline(nag.get_lineno()) + self.errorbox("Tab/space error", indent_message) + return False + return True + + def checksyntax(self, filename): + self.shell = shell = self.flist.open_shell() + saved_stream = shell.get_warning_stream() + shell.set_warning_stream(shell.stderr) + with open(filename, 'r') as f: + source = f.read() + if '\r' in source: + source = re.sub(r"\r\n", "\n", source) + source = re.sub(r"\r", "\n", source) + if source and source[-1] != '\n': + source = source + '\n' + text = self.editwin.text + text.tag_remove("ERROR", "1.0", "end") + try: + try: + # If successful, return the compiled code + return compile(source, filename, "exec") + except (SyntaxError, OverflowError, ValueError) as err: + try: + msg, (errorfilename, lineno, offset, line) = err + if not errorfilename: + err.args = msg, (filename, lineno, offset, line) + err.filename = filename + self.colorize_syntax_error(msg, lineno, offset) + except: + msg = "*** " + str(err) + self.errorbox("Syntax error", + "There's an error in your program:\n" + msg) + return False + finally: + shell.set_warning_stream(saved_stream) + + def colorize_syntax_error(self, msg, lineno, offset): + text = self.editwin.text + pos = "0.0 + %d lines + %d chars" % (lineno-1, offset-1) + text.tag_add("ERROR", pos) + char = text.get(pos) + if char and char in IDENTCHARS: + text.tag_add("ERROR", pos + " wordstart", pos) + if '\n' == text.get(pos): # error at line end + text.mark_set("insert", pos) + else: + text.mark_set("insert", pos + "+1c") + text.see(pos) + + def run_module_event(self, event): + """Run the module after setting up the environment. + + First check the syntax. If OK, make sure the shell is active and + then transfer the arguments, set the run environment's working + directory to the directory of the module being executed and also + add that directory to its sys.path if not already included. + + """ + filename = self.getfilename() + if not filename: + return 'break' + code = self.checksyntax(filename) + if not code: + return 'break' + if not self.tabnanny(filename): + return 'break' + interp = self.shell.interp + if PyShell.use_subprocess: + interp.restart_subprocess(with_cwd=False) + dirname = os.path.dirname(filename) + # XXX Too often this discards arguments the user just set... + interp.runcommand("""if 1: + __file__ = {filename!r} + import sys as _sys + from os.path import basename as _basename + if (not _sys.argv or + _basename(_sys.argv[0]) != _basename(__file__)): + _sys.argv = [__file__] + import os as _os + _os.chdir({dirname!r}) + del _sys, _basename, _os + \n""".format(filename=filename, dirname=dirname)) + interp.prepend_syspath(filename) + # XXX KBK 03Jul04 When run w/o subprocess, runtime warnings still + # go to __stderr__. With subprocess, they go to the shell. + # Need to change streams in PyShell.ModifiedInterpreter. + interp.runcode(code) + return 'break' + + if macosxSupport.isCocoaTk(): + # Tk-Cocoa in MacOSX is broken until at least + # Tk 8.5.9, and without this rather + # crude workaround IDLE would hang when a user + # tries to run a module using the keyboard shortcut + # (the menu item works fine). + _run_module_event = run_module_event + + def run_module_event(self, event): + self.editwin.text_frame.after(200, + lambda: self.editwin.text_frame.event_generate('<>')) + return 'break' + + def getfilename(self): + """Get source filename. If not saved, offer to save (or create) file + + The debugger requires a source file. Make sure there is one, and that + the current version of the source buffer has been saved. If the user + declines to save or cancels the Save As dialog, return None. + + If the user has configured IDLE for Autosave, the file will be + silently saved if it already exists and is dirty. + + """ + filename = self.editwin.io.filename + if not self.editwin.get_saved(): + autosave = idleConf.GetOption('main', 'General', + 'autosave', type='bool') + if autosave and filename: + self.editwin.io.save(None) + else: + confirm = self.ask_save_dialog() + self.editwin.text.focus_set() + if confirm: + self.editwin.io.save(None) + filename = self.editwin.io.filename + else: + filename = None + return filename + + def ask_save_dialog(self): + msg = "Source Must Be Saved\n" + 5*' ' + "OK to Save?" + confirm = tkMessageBox.askokcancel(title="Save Before Run or Check", + message=msg, + default=tkMessageBox.OK, + master=self.editwin.text) + return confirm + + def errorbox(self, title, message): + # XXX This should really be a function of EditorWindow... + tkMessageBox.showerror(title, message, master=self.editwin.text) + self.editwin.text.focus_set() diff --git a/PythonHome/Lib/idlelib/ScriptBinding.pyc b/PythonHome/Lib/idlelib/ScriptBinding.pyc deleted file mode 100644 index ef44401723f2f669350bffa96736323de8caaa87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7973 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", self.click_event) + listbox.bind("", self.double_click_event) + listbox.bind("", self.popup_event) + listbox.bind("", self.up_event) + listbox.bind("", self.down_event) + # Mark as empty + self.clear() + + def close(self): + self.frame.destroy() + + def clear(self): + self.listbox.delete(0, "end") + self.empty = 1 + self.listbox.insert("end", self.default) + + def append(self, item): + if self.empty: + self.listbox.delete(0, "end") + self.empty = 0 + self.listbox.insert("end", str(item)) + + def get(self, index): + return self.listbox.get(index) + + def click_event(self, event): + self.listbox.activate("@%d,%d" % (event.x, event.y)) + index = self.listbox.index("active") + self.select(index) + self.on_select(index) + return "break" + + def double_click_event(self, event): + index = self.listbox.index("active") + self.select(index) + self.on_double(index) + return "break" + + menu = None + + def popup_event(self, event): + if not self.menu: + self.make_menu() + menu = self.menu + self.listbox.activate("@%d,%d" % (event.x, event.y)) + index = self.listbox.index("active") + self.select(index) + menu.tk_popup(event.x_root, event.y_root) + + def make_menu(self): + menu = Menu(self.listbox, tearoff=0) + self.menu = menu + self.fill_menu() + + def up_event(self, event): + index = self.listbox.index("active") + if self.listbox.selection_includes(index): + index = index - 1 + else: + index = self.listbox.size() - 1 + if index < 0: + self.listbox.bell() + else: + self.select(index) + self.on_select(index) + return "break" + + def down_event(self, event): + index = self.listbox.index("active") + if self.listbox.selection_includes(index): + index = index + 1 + else: + index = 0 + if index >= self.listbox.size(): + self.listbox.bell() + else: + self.select(index) + self.on_select(index) + return "break" + + def select(self, index): + self.listbox.focus_set() + self.listbox.activate(index) + self.listbox.selection_clear(0, "end") + self.listbox.selection_set(index) + self.listbox.see(index) + + # Methods to override for specific actions + + def fill_menu(self): + pass + + def on_select(self, index): + pass + + def on_double(self, index): + pass + + +def _scrolled_list(parent): + root = Tk() + root.title("Test ScrolledList") + width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) + root.geometry("+%d+%d"%(x, y + 150)) + class MyScrolledList(ScrolledList): + def fill_menu(self): self.menu.add_command(label="right click") + def on_select(self, index): print "select", self.get(index) + def on_double(self, index): print "double", self.get(index) + + scrolled_list = MyScrolledList(root) + for i in range(30): + scrolled_list.append("Item %02d" % i) + + root.mainloop() + +if __name__ == '__main__': + from idlelib.idle_test.htest import run + run(_scrolled_list) diff --git a/PythonHome/Lib/idlelib/ScrolledList.pyc b/PythonHome/Lib/idlelib/ScrolledList.pyc deleted file mode 100644 index dadf68bc644dfb82f5276e4b5ce5381b1cbb9109..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5974 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 E0>P9K{Qv*} diff --git a/PythonHome/Lib/idlelib/SearchDialog.py b/PythonHome/Lib/idlelib/SearchDialog.py new file mode 100644 index 0000000000..2aadb8431f --- /dev/null +++ b/PythonHome/Lib/idlelib/SearchDialog.py @@ -0,0 +1,89 @@ +from Tkinter import * + +from idlelib import SearchEngine +from idlelib.SearchDialogBase import SearchDialogBase + +def _setup(text): + root = text._root() + engine = SearchEngine.get(root) + if not hasattr(engine, "_searchdialog"): + engine._searchdialog = SearchDialog(root, engine) + return engine._searchdialog + +def find(text): + pat = text.get("sel.first", "sel.last") + return _setup(text).open(text,pat) + +def find_again(text): + return _setup(text).find_again(text) + +def find_selection(text): + return _setup(text).find_selection(text) + +class SearchDialog(SearchDialogBase): + + def create_widgets(self): + f = SearchDialogBase.create_widgets(self) + self.make_button("Find Next", self.default_command, 1) + + def default_command(self, event=None): + if not self.engine.getprog(): + return + self.find_again(self.text) + + def find_again(self, text): + if not self.engine.getpat(): + self.open(text) + return False + if not self.engine.getprog(): + return False + res = self.engine.search_text(text) + if res: + line, m = res + i, j = m.span() + first = "%d.%d" % (line, i) + last = "%d.%d" % (line, j) + try: + selfirst = text.index("sel.first") + sellast = text.index("sel.last") + if selfirst == first and sellast == last: + text.bell() + return False + except TclError: + pass + text.tag_remove("sel", "1.0", "end") + text.tag_add("sel", first, last) + text.mark_set("insert", self.engine.isback() and first or last) + text.see("insert") + return True + else: + text.bell() + return False + + def find_selection(self, text): + pat = text.get("sel.first", "sel.last") + if pat: + self.engine.setcookedpat(pat) + return self.find_again(text) + +def _search_dialog(parent): + root = Tk() + root.title("Test SearchDialog") + width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) + root.geometry("+%d+%d"%(x, y + 150)) + text = Text(root) + text.pack() + text.insert("insert","This is a sample string.\n"*10) + + def show_find(): + text.tag_add(SEL, "1.0", END) + s = _setup(text) + s.open(text) + text.tag_remove(SEL, "1.0", END) + + button = Button(root, text="Search", command=show_find) + button.pack() + +if __name__ == '__main__': + from idlelib.idle_test.htest import run + run(_search_dialog) diff --git a/PythonHome/Lib/idlelib/SearchDialog.pyc b/PythonHome/Lib/idlelib/SearchDialog.pyc deleted file mode 100644 index 4c64ee1e388eb2d90fb46ffc998eb246f75d1be9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3811 zcmbtX-EJF26h7m>*lyDFkG6m+MW6_mBJ)!&xIh$|rsAUV#X1rYf>vAa#NK4Rwst0M zBPCaknl1 ztK#`Niu(ywihm=y$Oc;#$&HLFvRM(sepT|SjBB!4L%$|ZMKOf>i zr8_j-cc&r;hDRS(#8>5@LP(A(;_isA@fAkUMIF}#(xI_ahkzAq)$>cJW2e%jdTytI z5ntzUIhpuKrRVuW>-_?rqr@fNm;OYJAaKM<9acCNm3`v1!CgEzwLx37q{GVHK-JxP zkUiYW(%j~F23W#=-RZtAgLHmx$_-qb%gmx##@}m3(V-SRa}C9D+kg%rfIC3#fDr}( z5Rt+JMW?Tl_FRkWY~J0@O6Og3*2@#;bwWfSqI0NJm&w!?3S7jQKwD&*c-2O$GpIyt zwzC30f`i!+b1A4oq^XXoav2S;+E8#9Q8nnRuk?ZlDitB&c5yOHvO-_0Y_B3yw2VzI zqBtHe|3ex&y-EW}?Z9V~|0)rq;R?!3qKJ++K+zwiyo=)AM`aP!Ft%ur!uM-*|EGpQ z4-a@6V!o=4hD7}i4SMW3#9!gQi3Z?41{!WdN77hgqpI#yRbDymI`;wnN)N7{(Rv;3 z7g0P=7Y6kf*r6(i;K-WnG`NN%bvZmSUO@kTJ_Y5Z?33A3Y~|bLP*i=9@;$j6mesaub1Vd^tyR6j7vM7JhJMM9^E8Ob>28BcbPGQQ0`$e z*qzC3b;FHv&vtmYI_wFJm)7a~90^(DZme~t^^QuVDI!cldeGAtrA!&c}txIue3{_;B`RR4GYje&1}%-pOT_-0lg(ynWhEWgUMvqrnEIlEo4p- zg5n!7)x8pn(Tnb&Xg+3sY(V2)he<$TkK-a4+c;Kdh~x1j-OJI9$bM>|-lVWfD}klB z--!U)dU>YSoO5k1MWfQHE!JB%2IP4kJ1yI)WtbsP!r8U!AwE1JgZg$x40eLyha z3WAMj#B9Bs0P?LG?`?sHz&%_KRsr`Q*b)CVxkd`2t)O|Z(vKoPV4oKEF>HY?lqwMD zR~Yuskc1&bQ@)2x4aOQ4;!ca3EH1DI;1p8`ls!iXHxLUer>|m~O}>3{ z>pNxWTdOJlv*(x@y@ARx;cSdDw}Ss<#U&@uW(945yLH9 zxhatQ+m-3%egVG5veD#m%$rV+ohB-Qi!LH41EtVA0)k2n^YpGvNRc;ol~R1>^T11a z1{SH}%{ZCrGb=nW0jFD?>85!WIA>@lW9!R(b@Yw-Eqe;0Q)?*k-PIdLhjM9unv_V& z5hd5%a3%30eKWGzaO9Qco@l)vkwElaxTkc`4S=a?X8?$IpV>D>96l=6G2%!FVp_oH zws{j+wat~va^pH38}s8a?yqqiEJGm5y`raIQHtQkE&xG>AqUL97Q&~=^^<|_X`kiy zlU~Jw=_%6*8E9-r4>8@2Mo|SE3vCip9W(3O#O^muU!G1 US6U0LTC3WsUhTFnErQ", self.default_command) + top.bind("", self.close) + top.protocol("WM_DELETE_WINDOW", self.close) + top.wm_title(self.title) + top.wm_iconname(self.icon) + self.top = top + + self.row = 0 + self.top.grid_columnconfigure(0, pad=2, weight=0) + self.top.grid_columnconfigure(1, pad=2, minsize=100, weight=100) + + self.create_entries() # row 0 (and maybe 1), cols 0, 1 + self.create_option_buttons() # next row, cols 0, 1 + self.create_other_buttons() # next row, cols 0, 1 + self.create_command_buttons() # col 2, all rows + + def make_entry(self, label, var): + "Return gridded labeled Entry." + l = Label(self.top, text=label) + l.grid(row=self.row, column=0, sticky="nw") + e = Entry(self.top, textvariable=var, exportselection=0) + e.grid(row=self.row, column=1, sticky="nwe") + self.row = self.row + 1 + return e + + def create_entries(self): + "Create one or more entry lines with make_entry." + self.ent = self.make_entry("Find:", self.engine.patvar) + + def make_frame(self,labeltext=None): + "Return gridded labeled Frame for option or other buttons." + if labeltext: + l = Label(self.top, text=labeltext) + l.grid(row=self.row, column=0, sticky="nw") + f = Frame(self.top) + f.grid(row=self.row, column=1, columnspan=1, sticky="nwe") + self.row = self.row + 1 + return f + + def create_option_buttons(self): + "Fill frame with Checkbuttons bound to SearchEngine booleanvars." + f = self.make_frame("Options") + + btn = Checkbutton(f, anchor="w", + variable=self.engine.revar, + text="Regular expression") + btn.pack(side="left", fill="both") + if self.engine.isre(): + btn.select() + + btn = Checkbutton(f, anchor="w", + variable=self.engine.casevar, + text="Match case") + btn.pack(side="left", fill="both") + if self.engine.iscase(): + btn.select() + + btn = Checkbutton(f, anchor="w", + variable=self.engine.wordvar, + text="Whole word") + btn.pack(side="left", fill="both") + if self.engine.isword(): + btn.select() + + if self.needwrapbutton: + btn = Checkbutton(f, anchor="w", + variable=self.engine.wrapvar, + text="Wrap around") + btn.pack(side="left", fill="both") + if self.engine.iswrap(): + btn.select() + + def create_other_buttons(self): + "Fill frame with buttons tied to other options." + f = self.make_frame("Direction") + + btn = Radiobutton(f, anchor="w", + variable=self.engine.backvar, value=1, + text="Up") + btn.pack(side="left", fill="both") + if self.engine.isback(): + btn.select() + + btn = Radiobutton(f, anchor="w", + variable=self.engine.backvar, value=0, + text="Down") + btn.pack(side="left", fill="both") + if not self.engine.isback(): + btn.select() + + def make_button(self, label, command, isdef=0): + "Return command button gridded in command frame." + b = Button(self.buttonframe, + text=label, command=command, + default=isdef and "active" or "normal") + cols,rows=self.buttonframe.grid_size() + b.grid(pady=1,row=rows,column=0,sticky="ew") + self.buttonframe.grid(rowspan=rows+1) + return b + + def create_command_buttons(self): + "Place buttons in vertical command frame gridded on right." + f = self.buttonframe = Frame(self.top) + f.grid(row=0,column=2,padx=2,pady=2,ipadx=2,ipady=2) + + b = self.make_button("close", self.close) + b.lower() + +if __name__ == '__main__': + import unittest + unittest.main( + 'idlelib.idle_test.test_searchdialogbase', verbosity=2) diff --git a/PythonHome/Lib/idlelib/SearchDialogBase.pyc b/PythonHome/Lib/idlelib/SearchDialogBase.pyc deleted file mode 100644 index 1d287af026ad6fb409c6a55c00115386d0afb857..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7626 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 W&Pwm`^Kt@f)ZVOL{u7<7;r$l{C9Dnr diff --git a/PythonHome/Lib/idlelib/SearchEngine.py b/PythonHome/Lib/idlelib/SearchEngine.py new file mode 100644 index 0000000000..b3b7b4df0a --- /dev/null +++ b/PythonHome/Lib/idlelib/SearchEngine.py @@ -0,0 +1,233 @@ +'''Define SearchEngine for search dialogs.''' +import re +from Tkinter import StringVar, BooleanVar, TclError +import tkMessageBox + +def get(root): + '''Return the singleton SearchEngine instance for the process. + + The single SearchEngine saves settings between dialog instances. + If there is not a SearchEngine already, make one. + ''' + if not hasattr(root, "_searchengine"): + root._searchengine = SearchEngine(root) + # This creates a cycle that persists until root is deleted. + return root._searchengine + +class SearchEngine: + """Handles searching a text widget for Find, Replace, and Grep.""" + + def __init__(self, root): + '''Initialize Variables that save search state. + + The dialogs bind these to the UI elements present in the dialogs. + ''' + self.root = root # need for report_error() + self.patvar = StringVar(root, '') # search pattern + self.revar = BooleanVar(root, False) # regular expression? + self.casevar = BooleanVar(root, False) # match case? + self.wordvar = BooleanVar(root, False) # match whole word? + self.wrapvar = BooleanVar(root, True) # wrap around buffer? + self.backvar = BooleanVar(root, False) # search backwards? + + # Access methods + + def getpat(self): + return self.patvar.get() + + def setpat(self, pat): + self.patvar.set(pat) + + def isre(self): + return self.revar.get() + + def iscase(self): + return self.casevar.get() + + def isword(self): + return self.wordvar.get() + + def iswrap(self): + return self.wrapvar.get() + + def isback(self): + return self.backvar.get() + + # Higher level access methods + + def setcookedpat(self, pat): + "Set pattern after escaping if re." + # called only in SearchDialog.py: 66 + if self.isre(): + pat = re.escape(pat) + self.setpat(pat) + + def getcookedpat(self): + pat = self.getpat() + if not self.isre(): # if True, see setcookedpat + pat = re.escape(pat) + if self.isword(): + pat = r"\b%s\b" % pat + return pat + + def getprog(self): + "Return compiled cooked search pattern." + pat = self.getpat() + if not pat: + self.report_error(pat, "Empty regular expression") + return None + pat = self.getcookedpat() + flags = 0 + if not self.iscase(): + flags = flags | re.IGNORECASE + try: + prog = re.compile(pat, flags) + except re.error as what: + args = what.args + msg = args[0] + col = arg[1] if len(args) >= 2 else -1 + self.report_error(pat, msg, col) + return None + return prog + + def report_error(self, pat, msg, col=-1): + # Derived class could override this with something fancier + msg = "Error: " + str(msg) + if pat: + msg = msg + "\nPattern: " + str(pat) + if col >= 0: + msg = msg + "\nOffset: " + str(col) + tkMessageBox.showerror("Regular expression error", + msg, master=self.root) + + def search_text(self, text, prog=None, ok=0): + '''Return (lineno, matchobj) or None for forward/backward search. + + This function calls the right function with the right arguments. + It directly return the result of that call. + + Text is a text widget. Prog is a precompiled pattern. + The ok parameteris a bit complicated as it has two effects. + + If there is a selection, the search begin at either end, + depending on the direction setting and ok, with ok meaning that + the search starts with the selection. Otherwise, search begins + at the insert mark. + + To aid progress, the search functions do not return an empty + match at the starting position unless ok is True. + ''' + + if not prog: + prog = self.getprog() + if not prog: + return None # Compilation failed -- stop + wrap = self.wrapvar.get() + first, last = get_selection(text) + if self.isback(): + if ok: + start = last + else: + start = first + line, col = get_line_col(start) + res = self.search_backward(text, prog, line, col, wrap, ok) + else: + if ok: + start = first + else: + start = last + line, col = get_line_col(start) + res = self.search_forward(text, prog, line, col, wrap, ok) + return res + + def search_forward(self, text, prog, line, col, wrap, ok=0): + wrapped = 0 + startline = line + chars = text.get("%d.0" % line, "%d.0" % (line+1)) + while chars: + m = prog.search(chars[:-1], col) + if m: + if ok or m.end() > col: + return line, m + line = line + 1 + if wrapped and line > startline: + break + col = 0 + ok = 1 + chars = text.get("%d.0" % line, "%d.0" % (line+1)) + if not chars and wrap: + wrapped = 1 + wrap = 0 + line = 1 + chars = text.get("1.0", "2.0") + return None + + def search_backward(self, text, prog, line, col, wrap, ok=0): + wrapped = 0 + startline = line + chars = text.get("%d.0" % line, "%d.0" % (line+1)) + while 1: + m = search_reverse(prog, chars[:-1], col) + if m: + if ok or m.start() < col: + return line, m + line = line - 1 + if wrapped and line < startline: + break + ok = 1 + if line <= 0: + if not wrap: + break + wrapped = 1 + wrap = 0 + pos = text.index("end-1c") + line, col = map(int, pos.split(".")) + chars = text.get("%d.0" % line, "%d.0" % (line+1)) + col = len(chars) - 1 + return None + +def search_reverse(prog, chars, col): + '''Search backwards and return an re match object or None. + + This is done by searching forwards until there is no match. + Prog: compiled re object with a search method returning a match. + Chars: line of text, without \n. + Col: stop index for the search; the limit for match.end(). + ''' + m = prog.search(chars) + if not m: + return None + found = None + i, j = m.span() # m.start(), m.end() == match slice indexes + while i < col and j <= col: + found = m + if i == j: + j = j+1 + m = prog.search(chars, j) + if not m: + break + i, j = m.span() + return found + +def get_selection(text): + '''Return tuple of 'line.col' indexes from selection or insert mark. + ''' + try: + first = text.index("sel.first") + last = text.index("sel.last") + except TclError: + first = last = None + if not first: + first = text.index("insert") + if not last: + last = first + return first, last + +def get_line_col(index): + '''Return (line, col) tuple of ints from 'line.col' string.''' + line, col = map(int, index.split(".")) # Fails on invalid index + return line, col + +if __name__ == "__main__": + import unittest + unittest.main('idlelib.idle_test.test_searchengine', verbosity=2, exit=False) diff --git a/PythonHome/Lib/idlelib/SearchEngine.pyc b/PythonHome/Lib/idlelib/SearchEngine.pyc deleted file mode 100644 index 005f454196563db1929cf0309b788d65bdeb73a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7992 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 diff --git a/PythonHome/Lib/idlelib/StackViewer.py b/PythonHome/Lib/idlelib/StackViewer.py new file mode 100644 index 0000000000..74c9136700 --- /dev/null +++ b/PythonHome/Lib/idlelib/StackViewer.py @@ -0,0 +1,152 @@ +import os +import sys +import linecache +import re +import Tkinter as tk + +from idlelib.TreeWidget import TreeNode, TreeItem, ScrolledCanvas +from idlelib.ObjectBrowser import ObjectTreeItem, make_objecttreeitem +from idlelib.PyShell import PyShellFileList + +def StackBrowser(root, flist=None, tb=None, top=None): + if top is None: + from Tkinter import Toplevel + top = Toplevel(root) + sc = ScrolledCanvas(top, bg="white", highlightthickness=0) + sc.frame.pack(expand=1, fill="both") + item = StackTreeItem(flist, tb) + node = TreeNode(sc.canvas, None, item) + node.expand() + +class StackTreeItem(TreeItem): + + def __init__(self, flist=None, tb=None): + self.flist = flist + self.stack = self.get_stack(tb) + self.text = self.get_exception() + + def get_stack(self, tb): + if tb is None: + tb = sys.last_traceback + stack = [] + if tb and tb.tb_frame is None: + tb = tb.tb_next + while tb is not None: + stack.append((tb.tb_frame, tb.tb_lineno)) + tb = tb.tb_next + return stack + + def get_exception(self): + type = sys.last_type + value = sys.last_value + if hasattr(type, "__name__"): + type = type.__name__ + s = str(type) + if value is not None: + s = s + ": " + str(value) + return s + + def GetText(self): + return self.text + + def GetSubList(self): + sublist = [] + for info in self.stack: + item = FrameTreeItem(info, self.flist) + sublist.append(item) + return sublist + +class FrameTreeItem(TreeItem): + + def __init__(self, info, flist): + self.info = info + self.flist = flist + + def GetText(self): + frame, lineno = self.info + try: + modname = frame.f_globals["__name__"] + except: + modname = "?" + code = frame.f_code + filename = code.co_filename + funcname = code.co_name + sourceline = linecache.getline(filename, lineno) + sourceline = sourceline.strip() + if funcname in ("?", "", None): + item = "%s, line %d: %s" % (modname, lineno, sourceline) + else: + item = "%s.%s(...), line %d: %s" % (modname, funcname, + lineno, sourceline) + return item + + def GetSubList(self): + frame, lineno = self.info + sublist = [] + if frame.f_globals is not frame.f_locals: + item = VariablesTreeItem("", frame.f_locals, self.flist) + sublist.append(item) + item = VariablesTreeItem("", frame.f_globals, self.flist) + sublist.append(item) + return sublist + + def OnDoubleClick(self): + if self.flist: + frame, lineno = self.info + filename = frame.f_code.co_filename + if os.path.isfile(filename): + self.flist.gotofileline(filename, lineno) + +class VariablesTreeItem(ObjectTreeItem): + + def GetText(self): + return self.labeltext + + def GetLabelText(self): + return None + + def IsExpandable(self): + return len(self.object) > 0 + + def keys(self): + return self.object.keys() + + def GetSubList(self): + sublist = [] + for key in self.keys(): + try: + value = self.object[key] + except KeyError: + continue + def setfunction(value, key=key, object=self.object): + object[key] = value + item = make_objecttreeitem(key + " =", value, setfunction) + sublist.append(item) + return sublist + +def _stack_viewer(parent): + root = tk.Tk() + root.title("Test StackViewer") + width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) + root.geometry("+%d+%d"%(x, y + 150)) + flist = PyShellFileList(root) + try: # to obtain a traceback object + a + except: + exc_type, exc_value, exc_tb = sys.exc_info() + + # inject stack trace to sys + sys.last_type = exc_type + sys.last_value = exc_value + sys.last_traceback = exc_tb + + StackBrowser(root, flist=flist, top=root, tb=exc_tb) + + # restore sys to original state + del sys.last_type + del sys.last_value + del sys.last_traceback + +if __name__ == '__main__': + from idlelib.idle_test.htest import run + run(_stack_viewer) diff --git a/PythonHome/Lib/idlelib/StackViewer.pyc b/PythonHome/Lib/idlelib/StackViewer.pyc deleted file mode 100644 index b93582d2d1055b236536e832841afac8cf274a60..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6076 zcmbVQ>uwvz6+S~!6sfyqTe54nRSKw~;Y3N}UQ@?OeJj!$bh;AambI}amqTf#sL4iI{-=PoC2WY?V3@>uyz>-PsaAtO{-#Oo1#; z3_lh8e}Si{8Idl2MiP#+BLAC`R~Uaux>d0?>7jC3UWvRE`9tfR zbZev9`nYykx-(*Dwe9S<_PliGSZG}kdr`XcvR9J4qRUy3WJUU`(pnW`SH)hCmqtvg z0BklEfk^yce433ivaW_?E4Q|pb?vzDrL%pvfH#{_o+XLx-f5@L+eM?q9;|=Z*|m{l zKW%y*RsHs!4KuBGsE;v31Hg;pj9(pY?${)`A1C%fT)3!$I?i0ha|ciHHzY?2`(91* z>k1bzH_|W3aYf8gMUDWIk>j#pE3T}q(V-$;NT`ZerQ<0%nv&g$?4o9xV0P;S@1>NC ztICm)qmsPDcvW%J+7vA?EjpLw7&X(fTc;=p<7Q(POKK`qejkcdHc0Gqn>ZrT*>+R- zd$EJPx@F{c;_aOTk8?Y5w3phVh*2w;Tf`m=+G#gdM7aB2oFtB!PUdzRGi=6EGfOQN z2bt`}sk3>&zJcP-xq5lKZ?)l|9qqY!RBbxsMv@3n;pdA~VgUzkaOK)5&oZZL?j?|d zZo+kdC0=I(ol5J9NLy2cnn|G>4Kxx>imS+NJbn;&9>?9pCivGid>z{tHs2T=x;Zq^ zs@r+?qOduUES8XnnKMgf(Ofc@kzO>xIn+gb!4KDQ8&B~|Bo?|2>wqNH0AImEA#I~N z51E%VgI8tERH+EB&}CYJ%?2@xI2s>fcLz_gfrL6B5+WnA>-E9cl(eQy>9YZ5pbAi0 z%?5!FE+BDrB-_@71u<73eU5Tqy*-HRz{OdrusM6+ypd6|g-v=oN^lXSv%pF5g<+h= zE(}*W689&jZkA2N-HmptyF5Szc8TTFkS>WcvI~_rw3=;^V{Ft&{yEd#vAy|XW!UWC zlhFuu$qO0{49d4>T9qEm2$aHt_IY+&9--9;FRE`qNK~_m!$K(|X%{YZc{{Qlg2zp{ zPUsbyJy1vim>NraFtBM?;YM{5r#8(L$>94On*avX!ZV;4TtR#GDQKxw#5q%i3eG_h zFPnK2QPz|b(NrX#BI8s|fF3h|v82qSR1PA^KU7#oxIrNRiRUQ5K@kAJ$I4VCS>-{TsnbsoLLfpxTKEj@21`<^Ry+C|&BJb0h2 zx&8tL3ZTIaDP~?F*`M0%yK=|HSs?r_I&hAmE!UxfiwfkNS@i&NNInW6cR)LvSQ1|a z-$SC7r3*X5{K|{Jwr&e*@*@nQNXbNU+^kOg88X|@bt4BK4_9#a$+}8UZJvwro&at{ z?Etc%Mn7AEBAc-yD|*x!CEEMs-Z9aV4}x_hCotxQi~WvrEBnT2FAFZQ4W84IC*_Mx zZti#JDSwPo!772aF2Ul@nWpl&7dGF7VL$8cCr}-gd9a2$)%Jk$3O-_T1Ic6&ntLma zD>>8DbpC2-ajHIBpQ)FFk5L!l(GNwcr2PRhL(&$dVpxEuYtW3RYp|-P>nXA{5&9-e zub>tpfQZP_O3R_r*@#_e9>FI}D1sBLFsVcRDbZH2s4fLpLrzs5pvBQnRGa>Rj925w zN~9ox!*i-P$^(~S&5zP~F~(qQPCGiHE1pMujv(oV)-1Tg`F|} zS}#6WBaN=DcRyWQFABPm^y`WooNT!B?_!{b0MZ-{)IsGk)K5S<@_1X+rzOCKF znH0q0W|Bpa(XE1@-W*EomIg-Nc7BF>bvwP#H+2lfzHaAnyOY@B4K&AXdiP851h<%w zh0lyHxo8v5(2FdB*p?9yF5!8T8)j2)e!z?wBV%Yicr>sw16;sH(^4)UHb#3Gm0A%T zwt4oDaZq>SkqDNL%9K8S&f+hSXdIjs>NW>$x1;J97gRV6Z?`j-u|N%*cz|F64K+x4 zR+G1qt$LV;>D>(O!`?}7e0YKZhRpBX?6UFld!K8hUr_Rz@O$u^*QPw(yh`Sbw^ePb zrFx~lT%QT7nDv5aG3{X|N~MKqt|N>0PE%jeyU7(8i(}oy2dLntn@neI6MwvsY!GREyZN zhs8TBCin_NWdFAS9%uL{I)6fjjEUIo*>ELT#@#0o!#Da}WdQg-?{_aq1*W<;Bl#Ef zz|YQm_p5OOcEAWk{V+%reZZruBm+;iAXz=Zz!#Hh(borm1im?rOjuI7T0jP~V;FS1 zc|v(mKa4{@L{0;602C0dvoL_3lC7f~;}P-@-G}O{e`}xlgD4Tyv6a4mYY*?`d6oxM zXdjOfN>9{E&%a}l3kw1!XADO*a?H`OV6?>`^t}4Rc{6R6ODph<{-81;rH?qv111ld z=yGo$H-X}m%tQ_X%A@eJUiM$55xV#q9#xrtBLjo-3Jb;YUIC(~R3Q$iEMg7V5nKU1 zDVo-(+i(c{!Ji;7)6fk88$&f{1#X5^PoNv%u~nRSS9G*G-y(-V?yx2}jG0I2Rcan$ zpxrr+`dIIh5UU;6y)I4*-i7mm5RI7yIjU=BQQQ(oV?d`-AM-X?Vc`Z zy6EYOn{KM-+_HsRJ8|)%5$qoiu0PT1f$QsC{Nlf(xp!}jtNqOb9lgK$+0(x*f0N;2 z2j50D((?<|zTY0GHsdBrTjs-ffEqr z9b9Ab118@=;xD|Yse^V7jti6&Im(N;JM^|YRVb}Zs5=>t?Rc7He8Y+SiIxMh zRPi75tY?4bSDWMuDZPlN#$&G4#KMdA;H1Y8eu>g?6G2cTH-Cj}k_Mt%7oIw;o04%2|%Xo95X q-X6)+(CMZ>lHTGrG>+zVi+)R2&5BtnEzhj{aOK*{mHH}g1pfyVAudh; diff --git a/PythonHome/Lib/idlelib/ToolTip.py b/PythonHome/Lib/idlelib/ToolTip.py new file mode 100644 index 0000000000..11136c4429 --- /dev/null +++ b/PythonHome/Lib/idlelib/ToolTip.py @@ -0,0 +1,97 @@ +# general purpose 'tooltip' routines - currently unused in idlefork +# (although the 'calltips' extension is partly based on this code) +# may be useful for some purposes in (or almost in ;) the current project scope +# Ideas gleaned from PySol + +from Tkinter import * + +class ToolTipBase: + + def __init__(self, button): + self.button = button + self.tipwindow = None + self.id = None + self.x = self.y = 0 + self._id1 = self.button.bind("", self.enter) + self._id2 = self.button.bind("", self.leave) + self._id3 = self.button.bind("", self.leave) + + def enter(self, event=None): + self.schedule() + + def leave(self, event=None): + self.unschedule() + self.hidetip() + + def schedule(self): + self.unschedule() + self.id = self.button.after(1500, self.showtip) + + def unschedule(self): + id = self.id + self.id = None + if id: + self.button.after_cancel(id) + + def showtip(self): + if self.tipwindow: + return + # The tip window must be completely outside the button; + # otherwise when the mouse enters the tip window we get + # a leave event and it disappears, and then we get an enter + # event and it reappears, and so on forever :-( + x = self.button.winfo_rootx() + 20 + y = self.button.winfo_rooty() + self.button.winfo_height() + 1 + self.tipwindow = tw = Toplevel(self.button) + tw.wm_overrideredirect(1) + tw.wm_geometry("+%d+%d" % (x, y)) + self.showcontents() + + def showcontents(self, text="Your text here"): + # Override this in derived class + label = Label(self.tipwindow, text=text, justify=LEFT, + background="#ffffe0", relief=SOLID, borderwidth=1) + label.pack() + + def hidetip(self): + tw = self.tipwindow + self.tipwindow = None + if tw: + tw.destroy() + +class ToolTip(ToolTipBase): + def __init__(self, button, text): + ToolTipBase.__init__(self, button) + self.text = text + def showcontents(self): + ToolTipBase.showcontents(self, self.text) + +class ListboxToolTip(ToolTipBase): + def __init__(self, button, items): + ToolTipBase.__init__(self, button) + self.items = items + def showcontents(self): + listbox = Listbox(self.tipwindow, background="#ffffe0") + listbox.pack() + for item in self.items: + listbox.insert(END, item) + +def _tooltip(parent): + root = Tk() + root.title("Test tooltip") + width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) + root.geometry("+%d+%d"%(x, y + 150)) + label = Label(root, text="Place your mouse over buttons") + label.pack() + button1 = Button(root, text="Button 1") + button2 = Button(root, text="Button 2") + button1.pack() + button2.pack() + ToolTip(button1, "This is tooltip text for button1.") + ListboxToolTip(button2, ["This is","multiple line", + "tooltip text","for button2"]) + root.mainloop() + +if __name__ == '__main__': + from idlelib.idle_test.htest import run + run(_tooltip) diff --git a/PythonHome/Lib/idlelib/ToolTip.pyc b/PythonHome/Lib/idlelib/ToolTip.pyc deleted file mode 100644 index 88c95e8842eaef8959e24521b81e8faad174ca16..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4414 zcmd5<-EJF26rQymJ9d*2TAEb+x}p_s1A(RzLZS+&O^c8sx7t`j4Xsv=cN}lJ_L`k> zlZaFxxe`19&%gt5$s=&b1Hkv4*^Qm3ihRKZNoI0(e!ug7rug?_?e{-^+3u+9r-=Vw zqnV%3h4}MStW+y3sBl4rMfFOlu~JWVJQbFd_EZ%8;~iv7O1LZs=76ki7o?}Hnrt1@0tz>d#6q!7GQJ&eA zt<)_6gA!hpdI^S$SzsaC{6J6>F&r0Ex1g3~7?;iSC}(~|)r{UkA5lJr;b8Sfh`$Ey z+81$&b<&s+5xPl`CW$?iU_ALgvJ|5G?&)Z+XT@b($uQP0bZqG$2mK&`oW$~`r4-M6k1OwK~x!7(+~i3OrOwvT9-s5doZgxUBQ;?Xohx0wUp*Adv$Nw zTl7{ui6c*vQChe9(AIlECUK;QrR3;7n)wo)%@sk{fXzV%a1+FLxW=5aAS7#yy*a1{ z@^<=iLZ&@5CGPPO@sRzIu~GNP(&u;Eo#%ULG8%*uus`hLM}H=fIYk`QU6Imml0t3= zh{Qcnm3W}|-Bx>7$D%2@W9z}gmW*#d+WK}=hK9JIL6*c1{SU|wEj#AUS>^a1HmswG zji|y^?}{_-Q;s=_Cube=2F2!#T(bPcB?Xx1nUshp)W)XC(Uc?7v1Ua|WBYuFR0qBoBt%B;XwDw2LV-;n`v<6JF0}lk)otEeqUBugNznn4Ta5L_|G+ z3(r^s*>|!QO!CPfFe?%YK*UELl;@(zEs*{yJ5e;(OwJSPeD*%Zh7B}fuk2NemXNk0 zV|SCo|APX>rz5NT=ByUiPVss^n-tE&oK59rTBNDaN5#Ir0WlpA5e>(l$Gmmo;)mBH zLlxELvt`AQC@BmGVTaWC4>#3!qIDkJ^sk|xj(!bBd-04+zAh7egi)W&NOX(_1_cLV zuTl@1n-iX8U+nZE@sBc@sQP^NX%^q2Wx?YL%BH3N$bdc}P##S|(ttWNY{nXLE0X;S z1SC5~K6lbYs&Qou(hWETJCNb2=L1%YNRi#2mMCge0xv;8)R4I=0q|>QFl)nBg%7+o%-$Rk99*!YxN>i$6t1v%l+LX-+p^dOfg#}FQ@*9uwq@0 zqk$H<(|Zk5#bp0_gIr0O(t0jVX(JoE2NBIuEVkbs%KvC!Wo4>mr5VPNtDW+i$iGg$ zY58LGjw_$R$frR`M(ekuL7XH*DcWS&u$`iQ66Oy+ho_3Gnt5 zy*{JoxYU}7ReMi$VrWK8fu;2vf4<#aS?x;y9bB}iJ& zAts%=Ty?^_zlnLDVcjyXWY5Mm{tqmyX|2cJXE2-aAk?`bKw#Z5Q;Nh|;qvFp MmE~G>X#oM@U)vJ;NdN!< diff --git a/PythonHome/Lib/idlelib/TreeWidget.py b/PythonHome/Lib/idlelib/TreeWidget.py new file mode 100644 index 0000000000..ebb1f02a15 --- /dev/null +++ b/PythonHome/Lib/idlelib/TreeWidget.py @@ -0,0 +1,466 @@ +# XXX TO DO: +# - popup menu +# - support partial or total redisplay +# - key bindings (instead of quick-n-dirty bindings on Canvas): +# - up/down arrow keys to move focus around +# - ditto for page up/down, home/end +# - left/right arrows to expand/collapse & move out/in +# - more doc strings +# - add icons for "file", "module", "class", "method"; better "python" icon +# - callback for selection??? +# - multiple-item selection +# - tooltips +# - redo geometry without magic numbers +# - keep track of object ids to allow more careful cleaning +# - optimize tree redraw after expand of subnode + +import os +from Tkinter import * +import imp + +from idlelib import ZoomHeight +from idlelib.configHandler import idleConf + +ICONDIR = "Icons" + +# Look for Icons subdirectory in the same directory as this module +try: + _icondir = os.path.join(os.path.dirname(__file__), ICONDIR) +except NameError: + _icondir = ICONDIR +if os.path.isdir(_icondir): + ICONDIR = _icondir +elif not os.path.isdir(ICONDIR): + raise RuntimeError, "can't find icon directory (%r)" % (ICONDIR,) + +def listicons(icondir=ICONDIR): + """Utility to display the available icons.""" + root = Tk() + import glob + list = glob.glob(os.path.join(icondir, "*.gif")) + list.sort() + images = [] + row = column = 0 + for file in list: + name = os.path.splitext(os.path.basename(file))[0] + image = PhotoImage(file=file, master=root) + images.append(image) + label = Label(root, image=image, bd=1, relief="raised") + label.grid(row=row, column=column) + label = Label(root, text=name) + label.grid(row=row+1, column=column) + column = column + 1 + if column >= 10: + row = row+2 + column = 0 + root.images = images + + +class TreeNode: + + def __init__(self, canvas, parent, item): + self.canvas = canvas + self.parent = parent + self.item = item + self.state = 'collapsed' + self.selected = False + self.children = [] + self.x = self.y = None + self.iconimages = {} # cache of PhotoImage instances for icons + + def destroy(self): + for c in self.children[:]: + self.children.remove(c) + c.destroy() + self.parent = None + + def geticonimage(self, name): + try: + return self.iconimages[name] + except KeyError: + pass + file, ext = os.path.splitext(name) + ext = ext or ".gif" + fullname = os.path.join(ICONDIR, file + ext) + image = PhotoImage(master=self.canvas, file=fullname) + self.iconimages[name] = image + return image + + def select(self, event=None): + if self.selected: + return + self.deselectall() + self.selected = True + self.canvas.delete(self.image_id) + self.drawicon() + self.drawtext() + + def deselect(self, event=None): + if not self.selected: + return + self.selected = False + self.canvas.delete(self.image_id) + self.drawicon() + self.drawtext() + + def deselectall(self): + if self.parent: + self.parent.deselectall() + else: + self.deselecttree() + + def deselecttree(self): + if self.selected: + self.deselect() + for child in self.children: + child.deselecttree() + + def flip(self, event=None): + if self.state == 'expanded': + self.collapse() + else: + self.expand() + self.item.OnDoubleClick() + return "break" + + def expand(self, event=None): + if not self.item._IsExpandable(): + return + if self.state != 'expanded': + self.state = 'expanded' + self.update() + self.view() + + def collapse(self, event=None): + if self.state != 'collapsed': + self.state = 'collapsed' + self.update() + + def view(self): + top = self.y - 2 + bottom = self.lastvisiblechild().y + 17 + height = bottom - top + visible_top = self.canvas.canvasy(0) + visible_height = self.canvas.winfo_height() + visible_bottom = self.canvas.canvasy(visible_height) + if visible_top <= top and bottom <= visible_bottom: + return + x0, y0, x1, y1 = self.canvas._getints(self.canvas['scrollregion']) + if top >= visible_top and height <= visible_height: + fraction = top + height - visible_height + else: + fraction = top + fraction = float(fraction) / y1 + self.canvas.yview_moveto(fraction) + + def lastvisiblechild(self): + if self.children and self.state == 'expanded': + return self.children[-1].lastvisiblechild() + else: + return self + + def update(self): + if self.parent: + self.parent.update() + else: + oldcursor = self.canvas['cursor'] + self.canvas['cursor'] = "watch" + self.canvas.update() + self.canvas.delete(ALL) # XXX could be more subtle + self.draw(7, 2) + x0, y0, x1, y1 = self.canvas.bbox(ALL) + self.canvas.configure(scrollregion=(0, 0, x1, y1)) + self.canvas['cursor'] = oldcursor + + def draw(self, x, y): + # XXX This hard-codes too many geometry constants! + self.x, self.y = x, y + self.drawicon() + self.drawtext() + if self.state != 'expanded': + return y+17 + # draw children + if not self.children: + sublist = self.item._GetSubList() + if not sublist: + # _IsExpandable() was mistaken; that's allowed + return y+17 + for item in sublist: + child = self.__class__(self.canvas, self, item) + self.children.append(child) + cx = x+20 + cy = y+17 + cylast = 0 + for child in self.children: + cylast = cy + self.canvas.create_line(x+9, cy+7, cx, cy+7, fill="gray50") + cy = child.draw(cx, cy) + if child.item._IsExpandable(): + if child.state == 'expanded': + iconname = "minusnode" + callback = child.collapse + else: + iconname = "plusnode" + callback = child.expand + image = self.geticonimage(iconname) + id = self.canvas.create_image(x+9, cylast+7, image=image) + # XXX This leaks bindings until canvas is deleted: + self.canvas.tag_bind(id, "<1>", callback) + self.canvas.tag_bind(id, "", lambda x: None) + id = self.canvas.create_line(x+9, y+10, x+9, cylast+7, + ##stipple="gray50", # XXX Seems broken in Tk 8.0.x + fill="gray50") + self.canvas.tag_lower(id) # XXX .lower(id) before Python 1.5.2 + return cy + + def drawicon(self): + if self.selected: + imagename = (self.item.GetSelectedIconName() or + self.item.GetIconName() or + "openfolder") + else: + imagename = self.item.GetIconName() or "folder" + image = self.geticonimage(imagename) + id = self.canvas.create_image(self.x, self.y, anchor="nw", image=image) + self.image_id = id + self.canvas.tag_bind(id, "<1>", self.select) + self.canvas.tag_bind(id, "", self.flip) + + def drawtext(self): + textx = self.x+20-1 + texty = self.y-1 + labeltext = self.item.GetLabelText() + if labeltext: + id = self.canvas.create_text(textx, texty, anchor="nw", + text=labeltext) + self.canvas.tag_bind(id, "<1>", self.select) + self.canvas.tag_bind(id, "", self.flip) + x0, y0, x1, y1 = self.canvas.bbox(id) + textx = max(x1, 200) + 10 + text = self.item.GetText() or "" + try: + self.entry + except AttributeError: + pass + else: + self.edit_finish() + try: + label = self.label + except AttributeError: + # padding carefully selected (on Windows) to match Entry widget: + self.label = Label(self.canvas, text=text, bd=0, padx=2, pady=2) + theme = idleConf.GetOption('main','Theme','name') + if self.selected: + self.label.configure(idleConf.GetHighlight(theme, 'hilite')) + else: + self.label.configure(idleConf.GetHighlight(theme, 'normal')) + id = self.canvas.create_window(textx, texty, + anchor="nw", window=self.label) + self.label.bind("<1>", self.select_or_edit) + self.label.bind("", self.flip) + self.text_id = id + + def select_or_edit(self, event=None): + if self.selected and self.item.IsEditable(): + self.edit(event) + else: + self.select(event) + + def edit(self, event=None): + self.entry = Entry(self.label, bd=0, highlightthickness=1, width=0) + self.entry.insert(0, self.label['text']) + self.entry.selection_range(0, END) + self.entry.pack(ipadx=5) + self.entry.focus_set() + self.entry.bind("", self.edit_finish) + self.entry.bind("", self.edit_cancel) + + def edit_finish(self, event=None): + try: + entry = self.entry + del self.entry + except AttributeError: + return + text = entry.get() + entry.destroy() + if text and text != self.item.GetText(): + self.item.SetText(text) + text = self.item.GetText() + self.label['text'] = text + self.drawtext() + self.canvas.focus_set() + + def edit_cancel(self, event=None): + try: + entry = self.entry + del self.entry + except AttributeError: + return + entry.destroy() + self.drawtext() + self.canvas.focus_set() + + +class TreeItem: + + """Abstract class representing tree items. + + Methods should typically be overridden, otherwise a default action + is used. + + """ + + def __init__(self): + """Constructor. Do whatever you need to do.""" + + def GetText(self): + """Return text string to display.""" + + def GetLabelText(self): + """Return label text string to display in front of text (if any).""" + + expandable = None + + def _IsExpandable(self): + """Do not override! Called by TreeNode.""" + if self.expandable is None: + self.expandable = self.IsExpandable() + return self.expandable + + def IsExpandable(self): + """Return whether there are subitems.""" + return 1 + + def _GetSubList(self): + """Do not override! Called by TreeNode.""" + if not self.IsExpandable(): + return [] + sublist = self.GetSubList() + if not sublist: + self.expandable = 0 + return sublist + + def IsEditable(self): + """Return whether the item's text may be edited.""" + + def SetText(self, text): + """Change the item's text (if it is editable).""" + + def GetIconName(self): + """Return name of icon to be displayed normally.""" + + def GetSelectedIconName(self): + """Return name of icon to be displayed when selected.""" + + def GetSubList(self): + """Return list of items forming sublist.""" + + def OnDoubleClick(self): + """Called on a double-click on the item.""" + + +# Example application + +class FileTreeItem(TreeItem): + + """Example TreeItem subclass -- browse the file system.""" + + def __init__(self, path): + self.path = path + + def GetText(self): + return os.path.basename(self.path) or self.path + + def IsEditable(self): + return os.path.basename(self.path) != "" + + def SetText(self, text): + newpath = os.path.dirname(self.path) + newpath = os.path.join(newpath, text) + if os.path.dirname(newpath) != os.path.dirname(self.path): + return + try: + os.rename(self.path, newpath) + self.path = newpath + except os.error: + pass + + def GetIconName(self): + if not self.IsExpandable(): + return "python" # XXX wish there was a "file" icon + + def IsExpandable(self): + return os.path.isdir(self.path) + + def GetSubList(self): + try: + names = os.listdir(self.path) + except os.error: + return [] + names.sort(key = os.path.normcase) + sublist = [] + for name in names: + item = FileTreeItem(os.path.join(self.path, name)) + sublist.append(item) + return sublist + + +# A canvas widget with scroll bars and some useful bindings + +class ScrolledCanvas: + def __init__(self, master, **opts): + if 'yscrollincrement' not in opts: + opts['yscrollincrement'] = 17 + self.master = master + self.frame = Frame(master) + self.frame.rowconfigure(0, weight=1) + self.frame.columnconfigure(0, weight=1) + self.canvas = Canvas(self.frame, **opts) + self.canvas.grid(row=0, column=0, sticky="nsew") + self.vbar = Scrollbar(self.frame, name="vbar") + self.vbar.grid(row=0, column=1, sticky="nse") + self.hbar = Scrollbar(self.frame, name="hbar", orient="horizontal") + self.hbar.grid(row=1, column=0, sticky="ews") + self.canvas['yscrollcommand'] = self.vbar.set + self.vbar['command'] = self.canvas.yview + self.canvas['xscrollcommand'] = self.hbar.set + self.hbar['command'] = self.canvas.xview + self.canvas.bind("", self.page_up) + self.canvas.bind("", self.page_down) + self.canvas.bind("", self.unit_up) + self.canvas.bind("", self.unit_down) + #if isinstance(master, Toplevel) or isinstance(master, Tk): + self.canvas.bind("", self.zoom_height) + self.canvas.focus_set() + def page_up(self, event): + self.canvas.yview_scroll(-1, "page") + return "break" + def page_down(self, event): + self.canvas.yview_scroll(1, "page") + return "break" + def unit_up(self, event): + self.canvas.yview_scroll(-1, "unit") + return "break" + def unit_down(self, event): + self.canvas.yview_scroll(1, "unit") + return "break" + def zoom_height(self, event): + ZoomHeight.zoom_height(self.master) + return "break" + + +def _tree_widget(parent): + root = Tk() + root.title("Test TreeWidget") + width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) + root.geometry("+%d+%d"%(x, y + 150)) + sc = ScrolledCanvas(root, bg="white", highlightthickness=0, takefocus=1) + sc.frame.pack(expand=1, fill="both", side=LEFT) + item = FileTreeItem(os.getcwd()) + node = TreeNode(sc.canvas, None, item) + node.expand() + root.mainloop() + +if __name__ == '__main__': + from idlelib.idle_test.htest import run + run(_tree_widget) diff --git a/PythonHome/Lib/idlelib/TreeWidget.pyc b/PythonHome/Lib/idlelib/TreeWidget.pyc deleted file mode 100644 index 993dfce69922be29c697ade936e46e867ba1d329..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16916 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 O%)<2JIH|;D=l=mBj^R)M diff --git a/PythonHome/Lib/idlelib/UndoDelegator.py b/PythonHome/Lib/idlelib/UndoDelegator.py new file mode 100644 index 0000000000..cdeacea32f --- /dev/null +++ b/PythonHome/Lib/idlelib/UndoDelegator.py @@ -0,0 +1,365 @@ +import string +from Tkinter import * + +from idlelib.Delegator import Delegator + +#$ event <> +#$ win +#$ unix + +#$ event <> +#$ win +#$ unix + +#$ event <> +#$ win +#$ unix + + +class UndoDelegator(Delegator): + + max_undo = 1000 + + def __init__(self): + Delegator.__init__(self) + self.reset_undo() + + def setdelegate(self, delegate): + if self.delegate is not None: + self.unbind("<>") + self.unbind("<>") + self.unbind("<>") + Delegator.setdelegate(self, delegate) + if delegate is not None: + self.bind("<>", self.undo_event) + self.bind("<>", self.redo_event) + self.bind("<>", self.dump_event) + + def dump_event(self, event): + from pprint import pprint + pprint(self.undolist[:self.pointer]) + print "pointer:", self.pointer, + print "saved:", self.saved, + print "can_merge:", self.can_merge, + print "get_saved():", self.get_saved() + pprint(self.undolist[self.pointer:]) + return "break" + + def reset_undo(self): + self.was_saved = -1 + self.pointer = 0 + self.undolist = [] + self.undoblock = 0 # or a CommandSequence instance + self.set_saved(1) + + def set_saved(self, flag): + if flag: + self.saved = self.pointer + else: + self.saved = -1 + self.can_merge = False + self.check_saved() + + def get_saved(self): + return self.saved == self.pointer + + saved_change_hook = None + + def set_saved_change_hook(self, hook): + self.saved_change_hook = hook + + was_saved = -1 + + def check_saved(self): + is_saved = self.get_saved() + if is_saved != self.was_saved: + self.was_saved = is_saved + if self.saved_change_hook: + self.saved_change_hook() + + def insert(self, index, chars, tags=None): + self.addcmd(InsertCommand(index, chars, tags)) + + def delete(self, index1, index2=None): + self.addcmd(DeleteCommand(index1, index2)) + + # Clients should call undo_block_start() and undo_block_stop() + # around a sequence of editing cmds to be treated as a unit by + # undo & redo. Nested matching calls are OK, and the inner calls + # then act like nops. OK too if no editing cmds, or only one + # editing cmd, is issued in between: if no cmds, the whole + # sequence has no effect; and if only one cmd, that cmd is entered + # directly into the undo list, as if undo_block_xxx hadn't been + # called. The intent of all that is to make this scheme easy + # to use: all the client has to worry about is making sure each + # _start() call is matched by a _stop() call. + + def undo_block_start(self): + if self.undoblock == 0: + self.undoblock = CommandSequence() + self.undoblock.bump_depth() + + def undo_block_stop(self): + if self.undoblock.bump_depth(-1) == 0: + cmd = self.undoblock + self.undoblock = 0 + if len(cmd) > 0: + if len(cmd) == 1: + # no need to wrap a single cmd + cmd = cmd.getcmd(0) + # this blk of cmds, or single cmd, has already + # been done, so don't execute it again + self.addcmd(cmd, 0) + + def addcmd(self, cmd, execute=True): + if execute: + cmd.do(self.delegate) + if self.undoblock != 0: + self.undoblock.append(cmd) + return + if self.can_merge and self.pointer > 0: + lastcmd = self.undolist[self.pointer-1] + if lastcmd.merge(cmd): + return + self.undolist[self.pointer:] = [cmd] + if self.saved > self.pointer: + self.saved = -1 + self.pointer = self.pointer + 1 + if len(self.undolist) > self.max_undo: + ##print "truncating undo list" + del self.undolist[0] + self.pointer = self.pointer - 1 + if self.saved >= 0: + self.saved = self.saved - 1 + self.can_merge = True + self.check_saved() + + def undo_event(self, event): + if self.pointer == 0: + self.bell() + return "break" + cmd = self.undolist[self.pointer - 1] + cmd.undo(self.delegate) + self.pointer = self.pointer - 1 + self.can_merge = False + self.check_saved() + return "break" + + def redo_event(self, event): + if self.pointer >= len(self.undolist): + self.bell() + return "break" + cmd = self.undolist[self.pointer] + cmd.redo(self.delegate) + self.pointer = self.pointer + 1 + self.can_merge = False + self.check_saved() + return "break" + + +class Command: + + # Base class for Undoable commands + + tags = None + + def __init__(self, index1, index2, chars, tags=None): + self.marks_before = {} + self.marks_after = {} + self.index1 = index1 + self.index2 = index2 + self.chars = chars + if tags: + self.tags = tags + + def __repr__(self): + s = self.__class__.__name__ + t = (self.index1, self.index2, self.chars, self.tags) + if self.tags is None: + t = t[:-1] + return s + repr(t) + + def do(self, text): + pass + + def redo(self, text): + pass + + def undo(self, text): + pass + + def merge(self, cmd): + return 0 + + def save_marks(self, text): + marks = {} + for name in text.mark_names(): + if name != "insert" and name != "current": + marks[name] = text.index(name) + return marks + + def set_marks(self, text, marks): + for name, index in marks.items(): + text.mark_set(name, index) + + +class InsertCommand(Command): + + # Undoable insert command + + def __init__(self, index1, chars, tags=None): + Command.__init__(self, index1, None, chars, tags) + + def do(self, text): + self.marks_before = self.save_marks(text) + self.index1 = text.index(self.index1) + if text.compare(self.index1, ">", "end-1c"): + # Insert before the final newline + self.index1 = text.index("end-1c") + text.insert(self.index1, self.chars, self.tags) + self.index2 = text.index("%s+%dc" % (self.index1, len(self.chars))) + self.marks_after = self.save_marks(text) + ##sys.__stderr__.write("do: %s\n" % self) + + def redo(self, text): + text.mark_set('insert', self.index1) + text.insert(self.index1, self.chars, self.tags) + self.set_marks(text, self.marks_after) + text.see('insert') + ##sys.__stderr__.write("redo: %s\n" % self) + + def undo(self, text): + text.mark_set('insert', self.index1) + text.delete(self.index1, self.index2) + self.set_marks(text, self.marks_before) + text.see('insert') + ##sys.__stderr__.write("undo: %s\n" % self) + + def merge(self, cmd): + if self.__class__ is not cmd.__class__: + return False + if self.index2 != cmd.index1: + return False + if self.tags != cmd.tags: + return False + if len(cmd.chars) != 1: + return False + if self.chars and \ + self.classify(self.chars[-1]) != self.classify(cmd.chars): + return False + self.index2 = cmd.index2 + self.chars = self.chars + cmd.chars + return True + + alphanumeric = string.ascii_letters + string.digits + "_" + + def classify(self, c): + if c in self.alphanumeric: + return "alphanumeric" + if c == "\n": + return "newline" + return "punctuation" + + +class DeleteCommand(Command): + + # Undoable delete command + + def __init__(self, index1, index2=None): + Command.__init__(self, index1, index2, None, None) + + def do(self, text): + self.marks_before = self.save_marks(text) + self.index1 = text.index(self.index1) + if self.index2: + self.index2 = text.index(self.index2) + else: + self.index2 = text.index(self.index1 + " +1c") + if text.compare(self.index2, ">", "end-1c"): + # Don't delete the final newline + self.index2 = text.index("end-1c") + self.chars = text.get(self.index1, self.index2) + text.delete(self.index1, self.index2) + self.marks_after = self.save_marks(text) + ##sys.__stderr__.write("do: %s\n" % self) + + def redo(self, text): + text.mark_set('insert', self.index1) + text.delete(self.index1, self.index2) + self.set_marks(text, self.marks_after) + text.see('insert') + ##sys.__stderr__.write("redo: %s\n" % self) + + def undo(self, text): + text.mark_set('insert', self.index1) + text.insert(self.index1, self.chars) + self.set_marks(text, self.marks_before) + text.see('insert') + ##sys.__stderr__.write("undo: %s\n" % self) + +class CommandSequence(Command): + + # Wrapper for a sequence of undoable cmds to be undone/redone + # as a unit + + def __init__(self): + self.cmds = [] + self.depth = 0 + + def __repr__(self): + s = self.__class__.__name__ + strs = [] + for cmd in self.cmds: + strs.append(" %r" % (cmd,)) + return s + "(\n" + ",\n".join(strs) + "\n)" + + def __len__(self): + return len(self.cmds) + + def append(self, cmd): + self.cmds.append(cmd) + + def getcmd(self, i): + return self.cmds[i] + + def redo(self, text): + for cmd in self.cmds: + cmd.redo(text) + + def undo(self, text): + cmds = self.cmds[:] + cmds.reverse() + for cmd in cmds: + cmd.undo(text) + + def bump_depth(self, incr=1): + self.depth = self.depth + incr + return self.depth + +def _undo_delegator(parent): + from idlelib.Percolator import Percolator + root = Tk() + root.title("Test UndoDelegator") + width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) + root.geometry("+%d+%d"%(x, y + 150)) + + text = Text(root) + text.config(height=10) + text.pack() + text.focus_set() + p = Percolator(text) + d = UndoDelegator() + p.insertfilter(d) + + undo = Button(root, text="Undo", command=lambda:d.undo_event(None)) + undo.pack(side='left') + redo = Button(root, text="Redo", command=lambda:d.redo_event(None)) + redo.pack(side='left') + dump = Button(root, text="Dump", command=lambda:d.dump_event(None)) + dump.pack(side='left') + + root.mainloop() + +if __name__ == "__main__": + from idlelib.idle_test.htest import run + run(_undo_delegator) diff --git a/PythonHome/Lib/idlelib/UndoDelegator.pyc b/PythonHome/Lib/idlelib/UndoDelegator.pyc deleted file mode 100644 index d392d2606d257cf15c75eee80d38af806d324c02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12790 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 BN*DkD diff --git a/PythonHome/Lib/idlelib/WidgetRedirector.py b/PythonHome/Lib/idlelib/WidgetRedirector.py new file mode 100644 index 0000000000..b1534a71b2 --- /dev/null +++ b/PythonHome/Lib/idlelib/WidgetRedirector.py @@ -0,0 +1,125 @@ +from Tkinter import * + +class WidgetRedirector: + + """Support for redirecting arbitrary widget subcommands. + + Some Tk operations don't normally pass through Tkinter. For example, if a + character is inserted into a Text widget by pressing a key, a default Tk + binding to the widget's 'insert' operation is activated, and the Tk library + processes the insert without calling back into Tkinter. + + Although a binding to could be made via Tkinter, what we really want + to do is to hook the Tk 'insert' operation itself. + + When a widget is instantiated, a Tcl command is created whose name is the + same as the pathname widget._w. This command is used to invoke the various + widget operations, e.g. insert (for a Text widget). We are going to hook + this command and provide a facility ('register') to intercept the widget + operation. + + In IDLE, the function being registered provides access to the top of a + Percolator chain. At the bottom of the chain is a call to the original + Tk widget operation. + + """ + def __init__(self, widget): + self._operations = {} + self.widget = widget # widget instance + self.tk = tk = widget.tk # widget's root + w = widget._w # widget's (full) Tk pathname + self.orig = w + "_orig" + # Rename the Tcl command within Tcl: + tk.call("rename", w, self.orig) + # Create a new Tcl command whose name is the widget's pathname, and + # whose action is to dispatch on the operation passed to the widget: + tk.createcommand(w, self.dispatch) + + def __repr__(self): + return "WidgetRedirector(%s<%s>)" % (self.widget.__class__.__name__, + self.widget._w) + + def close(self): + for operation in list(self._operations): + self.unregister(operation) + widget = self.widget; del self.widget + orig = self.orig; del self.orig + tk = widget.tk + w = widget._w + tk.deletecommand(w) + # restore the original widget Tcl command: + tk.call("rename", orig, w) + + def register(self, operation, function): + self._operations[operation] = function + setattr(self.widget, operation, function) + return OriginalCommand(self, operation) + + def unregister(self, operation): + if operation in self._operations: + function = self._operations[operation] + del self._operations[operation] + if hasattr(self.widget, operation): + delattr(self.widget, operation) + return function + else: + return None + + def dispatch(self, operation, *args): + '''Callback from Tcl which runs when the widget is referenced. + + If an operation has been registered in self._operations, apply the + associated function to the args passed into Tcl. Otherwise, pass the + operation through to Tk via the original Tcl function. + + Note that if a registered function is called, the operation is not + passed through to Tk. Apply the function returned by self.register() + to *args to accomplish that. For an example, see ColorDelegator.py. + + ''' + m = self._operations.get(operation) + try: + if m: + return m(*args) + else: + return self.tk.call((self.orig, operation) + args) + except TclError: + return "" + + +class OriginalCommand: + + def __init__(self, redir, operation): + self.redir = redir + self.operation = operation + self.tk = redir.tk + self.orig = redir.orig + self.tk_call = self.tk.call + self.orig_and_operation = (self.orig, self.operation) + + def __repr__(self): + return "OriginalCommand(%r, %r)" % (self.redir, self.operation) + + def __call__(self, *args): + return self.tk_call(self.orig_and_operation + args) + + +def _widget_redirector(parent): + root = Tk() + root.title("Test WidgetRedirector") + width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) + root.geometry("+%d+%d"%(x, y + 150)) + text = Text(root) + text.pack() + text.focus_set() + redir = WidgetRedirector(text) + global previous_tcl_fcn + def my_insert(*args): + print "insert", args + previous_tcl_fcn(*args) + previous_tcl_fcn = redir.register("insert", my_insert) + root.mainloop() + +if __name__ == "__main__": + from idlelib.idle_test.htest import run + run(_widget_redirector) diff --git a/PythonHome/Lib/idlelib/WidgetRedirector.pyc b/PythonHome/Lib/idlelib/WidgetRedirector.pyc deleted file mode 100644 index 4fb60b164d61ed1cc92083885bf8115f22261216..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5341 zcmbVQ-EP~+6&^~mY$^8UuT8ow3QVx|T25R6MbVog4R+Vrrok?pf->ON^@63zkwl9k zRdQsJ zRehTH{|r|-L=)rZsZ^=MxS`^%iks?NrQRv^`(sbVEfwEU@!H}MrnGr;+*Af*>uS``D~UK zRuA(+7uC*5Hqv2nn%E*NF7<_QrOWwgluxH&7MJ~QSK~9tr$!%6bUrghXp=lEb)08A zR%dxJ4b${e&%(0Qc3kB1(HJw6%$lOF^{=s)c^gh=soB%XP=`V;8iz#~VTMjhon)mc ztclUFxeoQAd24GXZWhrdxiMiavgxCzjd1|qX5Iaq>nB!P%$EI4jQ|cW@cxTBp zcf+>Hd5G;mDT`$VGLvc*S9jMxIKDRo8u-xo4j3$oZT2=?t=PBm_ zf>5vU_53Sy`9eqeJdO3K(bF(C`aFTC4yQeRF%BWKfm#I2i!igo3uKCOvW?C-&nGp% z-zA$ZO**Xfbu=~^Sg7>rK(-*7RFdn%C`LCq|e)4~rz9mqM>%YiUe-+Vn^L8tWbn^ndJN zx37=DL1FYLuT)Jm97L;oQ>D<~c>;h#Jq)8HP3)!a?G$E|lrXrRUB?%?k(pUx&9NiI z7A#dbzRvXPmtTLmC-a8$491gZP$8M9NkY_WOIjCAr#3~K&vahf{BN;io`&#s4f9Vj z!1lS@|1`HYpK>M*P6owN#n@_Ed6A5gEKG$>SnN#oi$X8PaEpGA@@yn-BediMw-VQXsN4)IzxEDFb0%5YpHil8<1PuMz1h5mfi-s_Ku7!B8ZGTF)X>Z6Zs1+Ecq7-?9k)v7CU02m6cgi zjFS@P7>#?JC#&cJJ~{BYxy0Lx9(qce@(FtVldqH0lO#?Joc`qKMjYYrH zzFof96*+``+rhLTh*Ct=AgDMZl0o1zo=ZCMnO#0my28wgAovsnN`j}nyPn8I*!VzX z`ZGFjf1<2d4`f1Sd-=^nb?w9yqhYf9(>--WSz$kTrqmy6W1%_Wwzi{d*J-QkHFece zXY1-}jWj*pYzTT-fJd;gmjW0?OMW3Qmeh-cE9(nh@j%vG0EGVK-ycSsh6gO}z zXEX55=P+L02+9~BC|2;qAY5)BCUD?PM(~h4Z)|97;cVzGNWQ7U#=Z;A;-ezE|9y;# zVbx*ny+tM1HT=Ioza*~8+wvZI5{7CS_c?Zi#zi0a$E2-_H%nPRc6NgS%=p!+;1IO< zN;$b56pS{gu7JpZHo~hyLfn3V#5gRMNDvy>0UwAF9pst00fqlD=DaTi{zEMKC9Wz& z+=cL6?*Ra4H3R~(L%v>d&IuZ)U-%NW=rQ14{*0lt*p`6WP=AF$PVew1cHlG~BM2mZ zj1_~U?15?_%1*kfI8vVHA?gf%hZyYwaM^;_>?3AMg)%IVSeWZC#z{2R#ThRb1B)hR2{*>iAvN}vl$A)x_BTdM6o=Q z+C$gYR_C>_7?n~y3N_RW;I^;dV0Ceklqedj!qQbDB(~TJTexzQt0q!VQLH*sirn>f zD{>v=mL&-aF4m)~($tfsA_9ag5`|)&vpA6Dt~4VnU<(5C}S2mt0^7DZmTXu`DO!UNZlBT1yw_x27Z{Fk_#cWgfJnqJ%M zHlDysB%u2|30cPRAeiRyJVko5^wl7U^9ZSqiPyi+<`EkvV{tj3l$Y#C?{>-Euama$ z)P97ZyxD1W?sV2VU7xu*!X+P0`~p|`2^v!$#J>GMXEB_!i0>k^{gOXN!XiBSZ7TZ$q{^9MjZv=v8+cAF0-!MDEB{e;j%W|cp zDMIj9knz=T00{n(o>yv9Il{Qt3}P7aY6mYY&Uw@gY?KDWD3cNYgA9XOnO@>3!Z##y zveZID_wsk~-(!U*ho-}cgaMn_)cACBXbDThnf&9$ip)Y1qDhs=D^`qdWbj_c7MD^K z@x6<5W_Y(DmGLl-AV!ItA)Y4T_bG{Q2=OFK^L*w?bK1@f2XyR27KPChUrVAzMVZ=${Ju3B(|V_riL`eU~K jXBb1nB_dEACaSHt}l<=-A diff --git a/PythonHome/Lib/idlelib/WindowList.py b/PythonHome/Lib/idlelib/WindowList.py new file mode 100644 index 0000000000..658502b20b --- /dev/null +++ b/PythonHome/Lib/idlelib/WindowList.py @@ -0,0 +1,90 @@ +from Tkinter import * + +class WindowList: + + def __init__(self): + self.dict = {} + self.callbacks = [] + + def add(self, window): + window.after_idle(self.call_callbacks) + self.dict[str(window)] = window + + def delete(self, window): + try: + del self.dict[str(window)] + except KeyError: + # Sometimes, destroy() is called twice + pass + self.call_callbacks() + + def add_windows_to_menu(self, menu): + list = [] + for key in self.dict.keys(): + window = self.dict[key] + try: + title = window.get_title() + except TclError: + continue + list.append((title, window)) + list.sort() + for title, window in list: + menu.add_command(label=title, command=window.wakeup) + + def register_callback(self, callback): + self.callbacks.append(callback) + + def unregister_callback(self, callback): + try: + self.callbacks.remove(callback) + except ValueError: + pass + + def call_callbacks(self): + for callback in self.callbacks: + try: + callback() + except: + print "warning: callback failed in WindowList", \ + sys.exc_type, ":", sys.exc_value + +registry = WindowList() + +add_windows_to_menu = registry.add_windows_to_menu +register_callback = registry.register_callback +unregister_callback = registry.unregister_callback + + +class ListedToplevel(Toplevel): + + def __init__(self, master, **kw): + Toplevel.__init__(self, master, kw) + registry.add(self) + self.focused_widget = self + + def destroy(self): + registry.delete(self) + Toplevel.destroy(self) + # If this is Idle's last window then quit the mainloop + # (Needed for clean exit on Windows 98) + if not registry.dict: + self.quit() + + def update_windowlist_registry(self, window): + registry.call_callbacks() + + def get_title(self): + # Subclass can override + return self.wm_title() + + def wakeup(self): + try: + if self.wm_state() == "iconic": + self.wm_withdraw() + self.wm_deiconify() + self.tkraise() + self.focused_widget.focus_set() + except TclError: + # This can happen when the window menu was torn off. + # Simply ignore it. + pass diff --git a/PythonHome/Lib/idlelib/WindowList.pyc b/PythonHome/Lib/idlelib/WindowList.pyc deleted file mode 100644 index 7570f208dde14a3b2670a0f5d5418a3019b0ac36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3411 zcmbVO>uwuG6h5tttK z$5QgEybABYd+`A9eP``BElA*|o$=YZoa=Yanefln${(Fyw!1R@3-S8}hWiOqivLD( zk)1Satsx6m&y+M$-D(O|WUmc6%B8 zv%m1yHlRGG5B&<}PFAGD@x#pdGo`qB55sL@vJeV}LWYnI1xbVg6-m^lT2|7z(wIu$ zRmoggmT0@Z1YTWo<_IwEW4J4rGLaLJSY*E&};I zWTY1xSQ%?X7O;nGk~F1rrlzdUO`(Bm%4Z-ZYpS{epi=#Ar?@CJA4q>i%4=ebDU3X# zeIfB?Ua(B{j_5%3;sZPRsw{_P#OTh=h^Wc}2GHu%!cn#b$`O`gLbGOCL9MccCpgrS z-$4K?r-2;*Jhg|R5!rbBt(+n#&>jH`<&D#tOjhNj#%N*xv@V@u4d#Yw?sqiz=!&St z$f}y0)Oomv!-z9>Iwx4Jt0RtY2tGC*UzNRpjKG?}0NMcuq+Xz6mT)#ON5|4p$A!>z z%QFOd^2FwzZt4yPgQQ3`BP$p%@_jpT3h#aEW1o3AgI?b0=IUTiToxP8yNY4u(&ymV_UYd}KAAb88}2 zs|Bo}^GC%$?6`_$N5o7M$7rpkVFZA>djrJr-Kobn9)B#SMkW{3@wnAFT46c>&70^B z$d^q(TFFp0zsBYxjB}`V?}ObqDT}Pwzr8+l=Xx*6a+|Ja#rnMFYPY$ql~LoV2z0791*f`dh#PML5j&giP zjC;i56Y*~JCa1SKy~9aM9Eb&i6|p4{2#y_~5j1P~x7=(s!)8O90^6=lcZP?#eQNVA z4(T7S-NSI7VzTI<3pQZ1TiT-SjN%D_2N>=KCXec<9Sj+ViuNoNgYu7Zk5tt5rb!v2 zvCo?txmEROs;c@*S1Kfy6Lp*#)f;w4&ZhA=OHs_)RAAoR1_{#-0#Sp;{~z`$?+z|G zRyIL7X;lb+?ltiVw$99>EzcRootn5?ngLZ&FZ9thYu#EjsZ$mIYvjhLrxs0mIGGpg zqfzFy-K$*-SiyqwCB`&UTc#DBdv(y3``jg3Dm$LR)^l;7+alFa(Wsvc?xGEs&>kJ8 ziMNOn-+ycj@hp_zV0Ts%sncwzZp@FWXhXM|=XgTVFdkIR>!rN23N8;ZD%pWnFmfjP zRQ4W-$;Mnfid8?5^180*3&2n{?ezw+Mjv2P3!COd?5vO2g4uGVI#WAi7tzXw&*4&UWv$Hj#Z`p>!}>E$lu1$HyH|8 z9px)**0w4>%h*wSclud@wAOl8;q!&!$y`!q3o4+#zf)D{&xr*s>np+KTg{+}7ke}O E8v!<0-~a#s diff --git a/PythonHome/Lib/idlelib/ZoomHeight.py b/PythonHome/Lib/idlelib/ZoomHeight.py new file mode 100644 index 0000000000..a5d679e499 --- /dev/null +++ b/PythonHome/Lib/idlelib/ZoomHeight.py @@ -0,0 +1,51 @@ +# Sample extension: zoom a window to maximum height + +import re +import sys + +from idlelib import macosxSupport + +class ZoomHeight: + + menudefs = [ + ('windows', [ + ('_Zoom Height', '<>'), + ]) + ] + + def __init__(self, editwin): + self.editwin = editwin + + def zoom_height_event(self, event): + top = self.editwin.top + zoom_height(top) + +def zoom_height(top): + geom = top.wm_geometry() + m = re.match(r"(\d+)x(\d+)\+(-?\d+)\+(-?\d+)", geom) + if not m: + top.bell() + return + width, height, x, y = map(int, m.groups()) + newheight = top.winfo_screenheight() + if sys.platform == 'win32': + newy = 0 + newheight = newheight - 72 + + elif macosxSupport.isAquaTk(): + # The '88' below is a magic number that avoids placing the bottom + # of the window below the panel on my machine. I don't know how + # to calculate the correct value for this with tkinter. + newy = 22 + newheight = newheight - newy - 88 + + else: + #newy = 24 + newy = 0 + #newheight = newheight - 96 + newheight = newheight - 88 + if height >= newheight: + newgeom = "" + else: + newgeom = "%dx%d+%d+%d" % (width, newheight, x, newy) + top.wm_geometry(newgeom) diff --git a/PythonHome/Lib/idlelib/ZoomHeight.pyc b/PythonHome/Lib/idlelib/ZoomHeight.pyc deleted file mode 100644 index 75b3692f572c184d9667a698dda82dd7fda8b5e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1571 zcmb7E&2G~`5T3Q2q-j(2Pbw7%2@XX@r9HIQs{CDgKs`7}KorS@?51_hnAjNEbn-Bc6NTg{nq}k#rf}V-Z#56dwhJKVc0_mjaN}h)VkCa zwUpRBNvRiy-W&}E z#n8EVSXxDq9h&6$#9b@r1(xg+2m_Zgd4-M@^*oj>kC2{op$Mq}*`sDy#RkWD&yrjh zXVx~L$DHCpnZqu@u)qHqmhBVCdT`M7VEa2>LbqJ$M9~C$1%swEFl&Ru8=W|$2zi$a zc#BDU5yKc_l)~PFw$px+H7UMVz3vRgZVu~loaBj%<7McUqmhzwI22E%oV!p^ zOCPVIsYlMEiANU-XF$N2!95Cjhg9HLbH%_d;LDB1Wuv7B7wakz=99@?#DM)r$t%}G z#u8)=M$2(YHIzVdE7(J>Vg^Fq$xIvzAL2MG^eE*i1C*J3q)pF8>>br1uF4hdCYU3J zha*`QRo_=jLEZ1NmFdS}1>~PlN{}yzriz@RK3E18D7x?%c3^II#m8sD3-~yEpox`! zm2Gfr2Q>9*3R$6PRorX5G_7&7{W@unPCXiaVFpjdz1PVbr{bhdml1v z>#fJ*uTa2RBnZJYXhQ*X%|^34+po@Mc|DKg`R zV-Odu83~tlT=zuo&IgmGLfWh|kZ+PZ$HY7y7Ndc6t5A`=SH!kEG$t?UES`33g(ZWu z<9fv~i{M&vDzVQ$jykVTLq24ox#Z$XaI)altS9YGB-bn`FP)3S*fBV{Ih(C8!7&@l z?*$4+5(0|2k%j!%xPxIILGVRcRaG^w0`(C367)r{5mePmQ1#|vse9|HjLtwr{CkLa myJVmJPNZ3(cf`@Jin&!qg4=$1*A9H_m;2FB4R6_7Tlxd;jw+r2 diff --git a/PythonHome/Lib/idlelib/__init__.py b/PythonHome/Lib/idlelib/__init__.py new file mode 100644 index 0000000000..7a83ddea76 --- /dev/null +++ b/PythonHome/Lib/idlelib/__init__.py @@ -0,0 +1 @@ +# Dummy file to make this a package. diff --git a/PythonHome/Lib/idlelib/__init__.pyc b/PythonHome/Lib/idlelib/__init__.pyc deleted file mode 100644 index e56d5ddf451eff22316099eee1af91af8e13a155..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 112 zcmZSn%*(YSJRvxl0SXv_v;z',self.Ok) #dismiss dialog + self.bind('',self.Ok) #dismiss dialog + self.wait_window() + + def CreateWidgets(self): + frameMain = Frame(self, borderwidth=2, relief=SUNKEN) + frameButtons = Frame(self) + frameButtons.pack(side=BOTTOM, fill=X) + frameMain.pack(side=TOP, expand=TRUE, fill=BOTH) + self.buttonOk = Button(frameButtons, text='Close', + command=self.Ok) + self.buttonOk.pack(padx=5, pady=5) + #self.picture = Image('photo', data=self.pictureData) + frameBg = Frame(frameMain, bg=self.bg) + frameBg.pack(expand=TRUE, fill=BOTH) + labelTitle = Label(frameBg, text='IDLE', fg=self.fg, bg=self.bg, + font=('courier', 24, 'bold')) + labelTitle.grid(row=0, column=0, sticky=W, padx=10, pady=10) + #labelPicture = Label(frameBg, text='[picture]') + #image=self.picture, bg=self.bg) + #labelPicture.grid(row=1, column=1, sticky=W, rowspan=2, + # padx=0, pady=3) + byline = "Python's Integrated DeveLopment Environment" + 5*'\n' + labelDesc = Label(frameBg, text=byline, justify=LEFT, + fg=self.fg, bg=self.bg) + labelDesc.grid(row=2, column=0, sticky=W, columnspan=3, padx=10, pady=5) + labelEmail = Label(frameBg, text='email: idle-dev@python.org', + justify=LEFT, fg=self.fg, bg=self.bg) + labelEmail.grid(row=6, column=0, columnspan=2, + sticky=W, padx=10, pady=0) + labelWWW = Label(frameBg, text='www: http://www.python.org/idle/', + justify=LEFT, fg=self.fg, bg=self.bg) + labelWWW.grid(row=7, column=0, columnspan=2, sticky=W, padx=10, pady=0) + Frame(frameBg, borderwidth=1, relief=SUNKEN, + height=2, bg=self.bg).grid(row=8, column=0, sticky=EW, + columnspan=3, padx=5, pady=5) + labelPythonVer = Label(frameBg, text='Python version: ' + \ + sys.version.split()[0], fg=self.fg, bg=self.bg) + labelPythonVer.grid(row=9, column=0, sticky=W, padx=10, pady=0) + tkVer = self.tk.call('info', 'patchlevel') + labelTkVer = Label(frameBg, text='Tk version: '+ + tkVer, fg=self.fg, bg=self.bg) + labelTkVer.grid(row=9, column=1, sticky=W, padx=2, pady=0) + py_button_f = Frame(frameBg, bg=self.bg) + py_button_f.grid(row=10, column=0, columnspan=2, sticky=NSEW) + buttonLicense = Button(py_button_f, text='License', width=8, + highlightbackground=self.bg, + command=self.ShowLicense) + buttonLicense.pack(side=LEFT, padx=10, pady=10) + buttonCopyright = Button(py_button_f, text='Copyright', width=8, + highlightbackground=self.bg, + command=self.ShowCopyright) + buttonCopyright.pack(side=LEFT, padx=10, pady=10) + buttonCredits = Button(py_button_f, text='Credits', width=8, + highlightbackground=self.bg, + command=self.ShowPythonCredits) + buttonCredits.pack(side=LEFT, padx=10, pady=10) + Frame(frameBg, borderwidth=1, relief=SUNKEN, + height=2, bg=self.bg).grid(row=11, column=0, sticky=EW, + columnspan=3, padx=5, pady=5) + idle_v = Label(frameBg, text='IDLE version: ' + idlever.IDLE_VERSION, + fg=self.fg, bg=self.bg) + idle_v.grid(row=12, column=0, sticky=W, padx=10, pady=0) + idle_button_f = Frame(frameBg, bg=self.bg) + idle_button_f.grid(row=13, column=0, columnspan=3, sticky=NSEW) + idle_about_b = Button(idle_button_f, text='README', width=8, + highlightbackground=self.bg, + command=self.ShowIDLEAbout) + idle_about_b.pack(side=LEFT, padx=10, pady=10) + idle_news_b = Button(idle_button_f, text='NEWS', width=8, + highlightbackground=self.bg, + command=self.ShowIDLENEWS) + idle_news_b.pack(side=LEFT, padx=10, pady=10) + idle_credits_b = Button(idle_button_f, text='Credits', width=8, + highlightbackground=self.bg, + command=self.ShowIDLECredits) + idle_credits_b.pack(side=LEFT, padx=10, pady=10) + + def ShowLicense(self): + self.display_printer_text('About - License', license) + + def ShowCopyright(self): + self.display_printer_text('About - Copyright', copyright) + + def ShowPythonCredits(self): + self.display_printer_text('About - Python Credits', credits) + + def ShowIDLECredits(self): + self.display_file_text('About - Credits', 'CREDITS.txt', 'iso-8859-1') + + def ShowIDLEAbout(self): + self.display_file_text('About - Readme', 'README.txt') + + def ShowIDLENEWS(self): + self.display_file_text('About - NEWS', 'NEWS.txt') + + def display_printer_text(self, title, printer): + printer._Printer__setup() + text = '\n'.join(printer._Printer__lines) + textView.view_text(self, title, text) + + def display_file_text(self, title, filename, encoding=None): + fn = os.path.join(os.path.abspath(os.path.dirname(__file__)), filename) + textView.view_file(self, title, fn, encoding) + + def Ok(self, event=None): + self.destroy() + +if __name__ == '__main__': + from idlelib.idle_test.htest import run + run(AboutDialog) diff --git a/PythonHome/Lib/idlelib/aboutDialog.pyc b/PythonHome/Lib/idlelib/aboutDialog.pyc deleted file mode 100644 index 5074eaaa162bfe3db802adf55fb82891db763b3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6448 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 Ur1ayNf;FAtL*U}eX=~2',self.Cancel) #dismiss dialog, no save + #self.bind('',self.Apply) #apply changes, save + #self.bind('',self.Help) #context help + self.LoadConfigs() + self.AttachVarCallbacks() #avoid callbacks during LoadConfigs + + self.wm_deiconify() + self.wait_window() + + def CreateWidgets(self): + self.tabPages = TabbedPageSet(self, + page_names=['Fonts/Tabs','Highlighting','Keys','General']) + frameActionButtons = Frame(self,pady=2) + #action buttons + if macosxSupport.isAquaTk(): + # Changing the default padding on OSX results in unreadable + # text in the buttons + paddingArgs={} + else: + paddingArgs={'padx':6, 'pady':3} + +# Comment out button creation and packing until implement self.Help +## self.buttonHelp = Button(frameActionButtons,text='Help', +## command=self.Help,takefocus=FALSE, +## **paddingArgs) + self.buttonOk = Button(frameActionButtons,text='Ok', + command=self.Ok,takefocus=FALSE, + **paddingArgs) + self.buttonApply = Button(frameActionButtons,text='Apply', + command=self.Apply,takefocus=FALSE, + **paddingArgs) + self.buttonCancel = Button(frameActionButtons,text='Cancel', + command=self.Cancel,takefocus=FALSE, + **paddingArgs) + self.CreatePageFontTab() + self.CreatePageHighlight() + self.CreatePageKeys() + self.CreatePageGeneral() +## self.buttonHelp.pack(side=RIGHT,padx=5) + self.buttonOk.pack(side=LEFT,padx=5) + self.buttonApply.pack(side=LEFT,padx=5) + self.buttonCancel.pack(side=LEFT,padx=5) + frameActionButtons.pack(side=BOTTOM) + Frame(self, height=2, borderwidth=0).pack(side=BOTTOM) + self.tabPages.pack(side=TOP,expand=TRUE,fill=BOTH) + + def CreatePageFontTab(self): + #tkVars + self.fontSize=StringVar(self) + self.fontBold=BooleanVar(self) + self.fontName=StringVar(self) + self.spaceNum=IntVar(self) + self.editFont=tkFont.Font(self,('courier',10,'normal')) + ##widget creation + #body frame + frame=self.tabPages.pages['Fonts/Tabs'].frame + #body section frames + frameFont=LabelFrame(frame,borderwidth=2,relief=GROOVE, + text=' Base Editor Font ') + frameIndent=LabelFrame(frame,borderwidth=2,relief=GROOVE, + text=' Indentation Width ') + #frameFont + frameFontName=Frame(frameFont) + frameFontParam=Frame(frameFont) + labelFontNameTitle=Label(frameFontName,justify=LEFT, + text='Font Face :') + self.listFontName=Listbox(frameFontName,height=5,takefocus=FALSE, + exportselection=FALSE) + self.listFontName.bind('',self.OnListFontButtonRelease) + scrollFont=Scrollbar(frameFontName) + scrollFont.config(command=self.listFontName.yview) + self.listFontName.config(yscrollcommand=scrollFont.set) + labelFontSizeTitle=Label(frameFontParam,text='Size :') + self.optMenuFontSize=DynOptionMenu(frameFontParam,self.fontSize,None, + command=self.SetFontSample) + checkFontBold=Checkbutton(frameFontParam,variable=self.fontBold, + onvalue=1,offvalue=0,text='Bold',command=self.SetFontSample) + frameFontSample=Frame(frameFont,relief=SOLID,borderwidth=1) + self.labelFontSample=Label(frameFontSample, + text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]', + justify=LEFT,font=self.editFont) + #frameIndent + frameIndentSize=Frame(frameIndent) + labelSpaceNumTitle=Label(frameIndentSize, justify=LEFT, + text='Python Standard: 4 Spaces!') + self.scaleSpaceNum=Scale(frameIndentSize, variable=self.spaceNum, + orient='horizontal', + tickinterval=2, from_=2, to=16) + #widget packing + #body + frameFont.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH) + frameIndent.pack(side=LEFT,padx=5,pady=5,fill=Y) + #frameFont + frameFontName.pack(side=TOP,padx=5,pady=5,fill=X) + frameFontParam.pack(side=TOP,padx=5,pady=5,fill=X) + labelFontNameTitle.pack(side=TOP,anchor=W) + self.listFontName.pack(side=LEFT,expand=TRUE,fill=X) + scrollFont.pack(side=LEFT,fill=Y) + labelFontSizeTitle.pack(side=LEFT,anchor=W) + self.optMenuFontSize.pack(side=LEFT,anchor=W) + checkFontBold.pack(side=LEFT,anchor=W,padx=20) + frameFontSample.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) + self.labelFontSample.pack(expand=TRUE,fill=BOTH) + #frameIndent + frameIndentSize.pack(side=TOP,fill=X) + labelSpaceNumTitle.pack(side=TOP,anchor=W,padx=5) + self.scaleSpaceNum.pack(side=TOP,padx=5,fill=X) + return frame + + def CreatePageHighlight(self): + self.builtinTheme=StringVar(self) + self.customTheme=StringVar(self) + self.fgHilite=BooleanVar(self) + self.colour=StringVar(self) + self.fontName=StringVar(self) + self.themeIsBuiltin=BooleanVar(self) + self.highlightTarget=StringVar(self) + ##widget creation + #body frame + frame=self.tabPages.pages['Highlighting'].frame + #body section frames + frameCustom=LabelFrame(frame,borderwidth=2,relief=GROOVE, + text=' Custom Highlighting ') + frameTheme=LabelFrame(frame,borderwidth=2,relief=GROOVE, + text=' Highlighting Theme ') + #frameCustom + self.textHighlightSample=Text(frameCustom,relief=SOLID,borderwidth=1, + font=('courier',12,''),cursor='hand2',width=21,height=11, + takefocus=FALSE,highlightthickness=0,wrap=NONE) + text=self.textHighlightSample + text.bind('',lambda e: 'break') + text.bind('',lambda e: 'break') + textAndTags=(('#you can click here','comment'),('\n','normal'), + ('#to choose items','comment'),('\n','normal'),('def','keyword'), + (' ','normal'),('func','definition'),('(param):','normal'), + ('\n ','normal'),('"""string"""','string'),('\n var0 = ','normal'), + ("'string'",'string'),('\n var1 = ','normal'),("'selected'",'hilite'), + ('\n var2 = ','normal'),("'found'",'hit'), + ('\n var3 = ','normal'),('list', 'builtin'), ('(','normal'), + ('None', 'builtin'),(')\n\n','normal'), + (' error ','error'),(' ','normal'),('cursor |','cursor'), + ('\n ','normal'),('shell','console'),(' ','normal'),('stdout','stdout'), + (' ','normal'),('stderr','stderr'),('\n','normal')) + for txTa in textAndTags: + text.insert(END,txTa[0],txTa[1]) + for element in self.themeElements.keys(): + text.tag_bind(self.themeElements[element][0],'', + lambda event,elem=element: event.widget.winfo_toplevel() + .highlightTarget.set(elem)) + text.config(state=DISABLED) + self.frameColourSet=Frame(frameCustom,relief=SOLID,borderwidth=1) + frameFgBg=Frame(frameCustom) + buttonSetColour=Button(self.frameColourSet,text='Choose Colour for :', + command=self.GetColour,highlightthickness=0) + self.optMenuHighlightTarget=DynOptionMenu(self.frameColourSet, + self.highlightTarget,None,highlightthickness=0)#,command=self.SetHighlightTargetBinding + self.radioFg=Radiobutton(frameFgBg,variable=self.fgHilite, + value=1,text='Foreground',command=self.SetColourSampleBinding) + self.radioBg=Radiobutton(frameFgBg,variable=self.fgHilite, + value=0,text='Background',command=self.SetColourSampleBinding) + self.fgHilite.set(1) + buttonSaveCustomTheme=Button(frameCustom, + text='Save as New Custom Theme',command=self.SaveAsNewTheme) + #frameTheme + labelTypeTitle=Label(frameTheme,text='Select : ') + self.radioThemeBuiltin=Radiobutton(frameTheme,variable=self.themeIsBuiltin, + value=1,command=self.SetThemeType,text='a Built-in Theme') + self.radioThemeCustom=Radiobutton(frameTheme,variable=self.themeIsBuiltin, + value=0,command=self.SetThemeType,text='a Custom Theme') + self.optMenuThemeBuiltin=DynOptionMenu(frameTheme, + self.builtinTheme,None,command=None) + self.optMenuThemeCustom=DynOptionMenu(frameTheme, + self.customTheme,None,command=None) + self.buttonDeleteCustomTheme=Button(frameTheme,text='Delete Custom Theme', + command=self.DeleteCustomTheme) + ##widget packing + #body + frameCustom.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH) + frameTheme.pack(side=LEFT,padx=5,pady=5,fill=Y) + #frameCustom + self.frameColourSet.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=X) + frameFgBg.pack(side=TOP,padx=5,pady=0) + self.textHighlightSample.pack(side=TOP,padx=5,pady=5,expand=TRUE, + fill=BOTH) + buttonSetColour.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=4) + self.optMenuHighlightTarget.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=3) + self.radioFg.pack(side=LEFT,anchor=E) + self.radioBg.pack(side=RIGHT,anchor=W) + buttonSaveCustomTheme.pack(side=BOTTOM,fill=X,padx=5,pady=5) + #frameTheme + labelTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5) + self.radioThemeBuiltin.pack(side=TOP,anchor=W,padx=5) + self.radioThemeCustom.pack(side=TOP,anchor=W,padx=5,pady=2) + self.optMenuThemeBuiltin.pack(side=TOP,fill=X,padx=5,pady=5) + self.optMenuThemeCustom.pack(side=TOP,fill=X,anchor=W,padx=5,pady=5) + self.buttonDeleteCustomTheme.pack(side=TOP,fill=X,padx=5,pady=5) + return frame + + def CreatePageKeys(self): + #tkVars + self.bindingTarget=StringVar(self) + self.builtinKeys=StringVar(self) + self.customKeys=StringVar(self) + self.keysAreBuiltin=BooleanVar(self) + self.keyBinding=StringVar(self) + ##widget creation + #body frame + frame=self.tabPages.pages['Keys'].frame + #body section frames + frameCustom=LabelFrame(frame,borderwidth=2,relief=GROOVE, + text=' Custom Key Bindings ') + frameKeySets=LabelFrame(frame,borderwidth=2,relief=GROOVE, + text=' Key Set ') + #frameCustom + frameTarget=Frame(frameCustom) + labelTargetTitle=Label(frameTarget,text='Action - Key(s)') + scrollTargetY=Scrollbar(frameTarget) + scrollTargetX=Scrollbar(frameTarget,orient=HORIZONTAL) + self.listBindings=Listbox(frameTarget,takefocus=FALSE, + exportselection=FALSE) + self.listBindings.bind('',self.KeyBindingSelected) + scrollTargetY.config(command=self.listBindings.yview) + scrollTargetX.config(command=self.listBindings.xview) + self.listBindings.config(yscrollcommand=scrollTargetY.set) + self.listBindings.config(xscrollcommand=scrollTargetX.set) + self.buttonNewKeys=Button(frameCustom,text='Get New Keys for Selection', + command=self.GetNewKeys,state=DISABLED) + #frameKeySets + frames = [Frame(frameKeySets, padx=2, pady=2, borderwidth=0) + for i in range(2)] + self.radioKeysBuiltin=Radiobutton(frames[0],variable=self.keysAreBuiltin, + value=1,command=self.SetKeysType,text='Use a Built-in Key Set') + self.radioKeysCustom=Radiobutton(frames[0],variable=self.keysAreBuiltin, + value=0,command=self.SetKeysType,text='Use a Custom Key Set') + self.optMenuKeysBuiltin=DynOptionMenu(frames[0], + self.builtinKeys,None,command=None) + self.optMenuKeysCustom=DynOptionMenu(frames[0], + self.customKeys,None,command=None) + self.buttonDeleteCustomKeys=Button(frames[1],text='Delete Custom Key Set', + command=self.DeleteCustomKeys) + buttonSaveCustomKeys=Button(frames[1], + text='Save as New Custom Key Set',command=self.SaveAsNewKeySet) + ##widget packing + #body + frameCustom.pack(side=BOTTOM,padx=5,pady=5,expand=TRUE,fill=BOTH) + frameKeySets.pack(side=BOTTOM,padx=5,pady=5,fill=BOTH) + #frameCustom + self.buttonNewKeys.pack(side=BOTTOM,fill=X,padx=5,pady=5) + frameTarget.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH) + #frame target + frameTarget.columnconfigure(0,weight=1) + frameTarget.rowconfigure(1,weight=1) + labelTargetTitle.grid(row=0,column=0,columnspan=2,sticky=W) + self.listBindings.grid(row=1,column=0,sticky=NSEW) + scrollTargetY.grid(row=1,column=1,sticky=NS) + scrollTargetX.grid(row=2,column=0,sticky=EW) + #frameKeySets + self.radioKeysBuiltin.grid(row=0, column=0, sticky=W+NS) + self.radioKeysCustom.grid(row=1, column=0, sticky=W+NS) + self.optMenuKeysBuiltin.grid(row=0, column=1, sticky=NSEW) + self.optMenuKeysCustom.grid(row=1, column=1, sticky=NSEW) + self.buttonDeleteCustomKeys.pack(side=LEFT,fill=X,expand=True,padx=2) + buttonSaveCustomKeys.pack(side=LEFT,fill=X,expand=True,padx=2) + frames[0].pack(side=TOP, fill=BOTH, expand=True) + frames[1].pack(side=TOP, fill=X, expand=True, pady=2) + return frame + + def CreatePageGeneral(self): + #tkVars + self.winWidth=StringVar(self) + self.winHeight=StringVar(self) + self.paraWidth=StringVar(self) + self.startupEdit=IntVar(self) + self.autoSave=IntVar(self) + self.encoding=StringVar(self) + self.userHelpBrowser=BooleanVar(self) + self.helpBrowser=StringVar(self) + #widget creation + #body + frame=self.tabPages.pages['General'].frame + #body section frames + frameRun=LabelFrame(frame,borderwidth=2,relief=GROOVE, + text=' Startup Preferences ') + frameSave=LabelFrame(frame,borderwidth=2,relief=GROOVE, + text=' Autosave Preferences ') + frameWinSize=Frame(frame,borderwidth=2,relief=GROOVE) + frameParaSize=Frame(frame,borderwidth=2,relief=GROOVE) + frameEncoding=Frame(frame,borderwidth=2,relief=GROOVE) + frameHelp=LabelFrame(frame,borderwidth=2,relief=GROOVE, + text=' Additional Help Sources ') + #frameRun + labelRunChoiceTitle=Label(frameRun,text='At Startup') + radioStartupEdit=Radiobutton(frameRun,variable=self.startupEdit, + value=1,command=self.SetKeysType,text="Open Edit Window") + radioStartupShell=Radiobutton(frameRun,variable=self.startupEdit, + value=0,command=self.SetKeysType,text='Open Shell Window') + #frameSave + labelRunSaveTitle=Label(frameSave,text='At Start of Run (F5) ') + radioSaveAsk=Radiobutton(frameSave,variable=self.autoSave, + value=0,command=self.SetKeysType,text="Prompt to Save") + radioSaveAuto=Radiobutton(frameSave,variable=self.autoSave, + value=1,command=self.SetKeysType,text='No Prompt') + #frameWinSize + labelWinSizeTitle=Label(frameWinSize,text='Initial Window Size'+ + ' (in characters)') + labelWinWidthTitle=Label(frameWinSize,text='Width') + entryWinWidth=Entry(frameWinSize,textvariable=self.winWidth, + width=3) + labelWinHeightTitle=Label(frameWinSize,text='Height') + entryWinHeight=Entry(frameWinSize,textvariable=self.winHeight, + width=3) + #paragraphFormatWidth + labelParaWidthTitle=Label(frameParaSize,text='Paragraph reformat'+ + ' width (in characters)') + entryParaWidth=Entry(frameParaSize,textvariable=self.paraWidth, + width=3) + #frameEncoding + labelEncodingTitle=Label(frameEncoding,text="Default Source Encoding") + radioEncLocale=Radiobutton(frameEncoding,variable=self.encoding, + value="locale",text="Locale-defined") + radioEncUTF8=Radiobutton(frameEncoding,variable=self.encoding, + value="utf-8",text="UTF-8") + radioEncNone=Radiobutton(frameEncoding,variable=self.encoding, + value="none",text="None") + #frameHelp + frameHelpList=Frame(frameHelp) + frameHelpListButtons=Frame(frameHelpList) + scrollHelpList=Scrollbar(frameHelpList) + self.listHelp=Listbox(frameHelpList,height=5,takefocus=FALSE, + exportselection=FALSE) + scrollHelpList.config(command=self.listHelp.yview) + self.listHelp.config(yscrollcommand=scrollHelpList.set) + self.listHelp.bind('',self.HelpSourceSelected) + self.buttonHelpListEdit=Button(frameHelpListButtons,text='Edit', + state=DISABLED,width=8,command=self.HelpListItemEdit) + self.buttonHelpListAdd=Button(frameHelpListButtons,text='Add', + width=8,command=self.HelpListItemAdd) + self.buttonHelpListRemove=Button(frameHelpListButtons,text='Remove', + state=DISABLED,width=8,command=self.HelpListItemRemove) + #widget packing + #body + frameRun.pack(side=TOP,padx=5,pady=5,fill=X) + frameSave.pack(side=TOP,padx=5,pady=5,fill=X) + frameWinSize.pack(side=TOP,padx=5,pady=5,fill=X) + frameParaSize.pack(side=TOP,padx=5,pady=5,fill=X) + frameEncoding.pack(side=TOP,padx=5,pady=5,fill=X) + frameHelp.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) + #frameRun + labelRunChoiceTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) + radioStartupShell.pack(side=RIGHT,anchor=W,padx=5,pady=5) + radioStartupEdit.pack(side=RIGHT,anchor=W,padx=5,pady=5) + #frameSave + labelRunSaveTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) + radioSaveAuto.pack(side=RIGHT,anchor=W,padx=5,pady=5) + radioSaveAsk.pack(side=RIGHT,anchor=W,padx=5,pady=5) + #frameWinSize + labelWinSizeTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) + entryWinHeight.pack(side=RIGHT,anchor=E,padx=10,pady=5) + labelWinHeightTitle.pack(side=RIGHT,anchor=E,pady=5) + entryWinWidth.pack(side=RIGHT,anchor=E,padx=10,pady=5) + labelWinWidthTitle.pack(side=RIGHT,anchor=E,pady=5) + #paragraphFormatWidth + labelParaWidthTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) + entryParaWidth.pack(side=RIGHT,anchor=E,padx=10,pady=5) + #frameEncoding + labelEncodingTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) + radioEncNone.pack(side=RIGHT,anchor=E,pady=5) + radioEncUTF8.pack(side=RIGHT,anchor=E,pady=5) + radioEncLocale.pack(side=RIGHT,anchor=E,pady=5) + #frameHelp + frameHelpListButtons.pack(side=RIGHT,padx=5,pady=5,fill=Y) + frameHelpList.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) + scrollHelpList.pack(side=RIGHT,anchor=W,fill=Y) + self.listHelp.pack(side=LEFT,anchor=E,expand=TRUE,fill=BOTH) + self.buttonHelpListEdit.pack(side=TOP,anchor=W,pady=5) + self.buttonHelpListAdd.pack(side=TOP,anchor=W) + self.buttonHelpListRemove.pack(side=TOP,anchor=W,pady=5) + return frame + + def AttachVarCallbacks(self): + self.fontSize.trace_variable('w',self.VarChanged_fontSize) + self.fontName.trace_variable('w',self.VarChanged_fontName) + self.fontBold.trace_variable('w',self.VarChanged_fontBold) + self.spaceNum.trace_variable('w',self.VarChanged_spaceNum) + self.colour.trace_variable('w',self.VarChanged_colour) + self.builtinTheme.trace_variable('w',self.VarChanged_builtinTheme) + self.customTheme.trace_variable('w',self.VarChanged_customTheme) + self.themeIsBuiltin.trace_variable('w',self.VarChanged_themeIsBuiltin) + self.highlightTarget.trace_variable('w',self.VarChanged_highlightTarget) + self.keyBinding.trace_variable('w',self.VarChanged_keyBinding) + self.builtinKeys.trace_variable('w',self.VarChanged_builtinKeys) + self.customKeys.trace_variable('w',self.VarChanged_customKeys) + self.keysAreBuiltin.trace_variable('w',self.VarChanged_keysAreBuiltin) + self.winWidth.trace_variable('w',self.VarChanged_winWidth) + self.winHeight.trace_variable('w',self.VarChanged_winHeight) + self.paraWidth.trace_variable('w',self.VarChanged_paraWidth) + self.startupEdit.trace_variable('w',self.VarChanged_startupEdit) + self.autoSave.trace_variable('w',self.VarChanged_autoSave) + self.encoding.trace_variable('w',self.VarChanged_encoding) + + def VarChanged_fontSize(self,*params): + value=self.fontSize.get() + self.AddChangedItem('main','EditorWindow','font-size',value) + + def VarChanged_fontName(self,*params): + value=self.fontName.get() + self.AddChangedItem('main','EditorWindow','font',value) + + def VarChanged_fontBold(self,*params): + value=self.fontBold.get() + self.AddChangedItem('main','EditorWindow','font-bold',value) + + def VarChanged_spaceNum(self,*params): + value=self.spaceNum.get() + self.AddChangedItem('main','Indent','num-spaces',value) + + def VarChanged_colour(self,*params): + self.OnNewColourSet() + + def VarChanged_builtinTheme(self,*params): + value=self.builtinTheme.get() + self.AddChangedItem('main','Theme','name',value) + self.PaintThemeSample() + + def VarChanged_customTheme(self,*params): + value=self.customTheme.get() + if value != '- no custom themes -': + self.AddChangedItem('main','Theme','name',value) + self.PaintThemeSample() + + def VarChanged_themeIsBuiltin(self,*params): + value=self.themeIsBuiltin.get() + self.AddChangedItem('main','Theme','default',value) + if value: + self.VarChanged_builtinTheme() + else: + self.VarChanged_customTheme() + + def VarChanged_highlightTarget(self,*params): + self.SetHighlightTarget() + + def VarChanged_keyBinding(self,*params): + value=self.keyBinding.get() + keySet=self.customKeys.get() + event=self.listBindings.get(ANCHOR).split()[0] + if idleConf.IsCoreBinding(event): + #this is a core keybinding + self.AddChangedItem('keys',keySet,event,value) + else: #this is an extension key binding + extName=idleConf.GetExtnNameForEvent(event) + extKeybindSection=extName+'_cfgBindings' + self.AddChangedItem('extensions',extKeybindSection,event,value) + + def VarChanged_builtinKeys(self,*params): + value=self.builtinKeys.get() + self.AddChangedItem('main','Keys','name',value) + self.LoadKeysList(value) + + def VarChanged_customKeys(self,*params): + value=self.customKeys.get() + if value != '- no custom keys -': + self.AddChangedItem('main','Keys','name',value) + self.LoadKeysList(value) + + def VarChanged_keysAreBuiltin(self,*params): + value=self.keysAreBuiltin.get() + self.AddChangedItem('main','Keys','default',value) + if value: + self.VarChanged_builtinKeys() + else: + self.VarChanged_customKeys() + + def VarChanged_winWidth(self,*params): + value=self.winWidth.get() + self.AddChangedItem('main','EditorWindow','width',value) + + def VarChanged_winHeight(self,*params): + value=self.winHeight.get() + self.AddChangedItem('main','EditorWindow','height',value) + + def VarChanged_paraWidth(self,*params): + value=self.paraWidth.get() + self.AddChangedItem('main','FormatParagraph','paragraph',value) + + def VarChanged_startupEdit(self,*params): + value=self.startupEdit.get() + self.AddChangedItem('main','General','editor-on-startup',value) + + def VarChanged_autoSave(self,*params): + value=self.autoSave.get() + self.AddChangedItem('main','General','autosave',value) + + def VarChanged_encoding(self,*params): + value=self.encoding.get() + self.AddChangedItem('main','EditorWindow','encoding',value) + + def ResetChangedItems(self): + #When any config item is changed in this dialog, an entry + #should be made in the relevant section (config type) of this + #dictionary. The key should be the config file section name and the + #value a dictionary, whose key:value pairs are item=value pairs for + #that config file section. + self.changedItems={'main':{},'highlight':{},'keys':{},'extensions':{}} + + def AddChangedItem(self,type,section,item,value): + value=str(value) #make sure we use a string + if section not in self.changedItems[type]: + self.changedItems[type][section]={} + self.changedItems[type][section][item]=value + + def GetDefaultItems(self): + dItems={'main':{},'highlight':{},'keys':{},'extensions':{}} + for configType in dItems.keys(): + sections=idleConf.GetSectionList('default',configType) + for section in sections: + dItems[configType][section]={} + options=idleConf.defaultCfg[configType].GetOptionList(section) + for option in options: + dItems[configType][section][option]=( + idleConf.defaultCfg[configType].Get(section,option)) + return dItems + + def SetThemeType(self): + if self.themeIsBuiltin.get(): + self.optMenuThemeBuiltin.config(state=NORMAL) + self.optMenuThemeCustom.config(state=DISABLED) + self.buttonDeleteCustomTheme.config(state=DISABLED) + else: + self.optMenuThemeBuiltin.config(state=DISABLED) + self.radioThemeCustom.config(state=NORMAL) + self.optMenuThemeCustom.config(state=NORMAL) + self.buttonDeleteCustomTheme.config(state=NORMAL) + + def SetKeysType(self): + if self.keysAreBuiltin.get(): + self.optMenuKeysBuiltin.config(state=NORMAL) + self.optMenuKeysCustom.config(state=DISABLED) + self.buttonDeleteCustomKeys.config(state=DISABLED) + else: + self.optMenuKeysBuiltin.config(state=DISABLED) + self.radioKeysCustom.config(state=NORMAL) + self.optMenuKeysCustom.config(state=NORMAL) + self.buttonDeleteCustomKeys.config(state=NORMAL) + + def GetNewKeys(self): + listIndex=self.listBindings.index(ANCHOR) + binding=self.listBindings.get(listIndex) + bindName=binding.split()[0] #first part, up to first space + if self.keysAreBuiltin.get(): + currentKeySetName=self.builtinKeys.get() + else: + currentKeySetName=self.customKeys.get() + currentBindings=idleConf.GetCurrentKeySet() + if currentKeySetName in self.changedItems['keys'].keys(): #unsaved changes + keySetChanges=self.changedItems['keys'][currentKeySetName] + for event in keySetChanges.keys(): + currentBindings[event]=keySetChanges[event].split() + currentKeySequences=currentBindings.values() + newKeys=GetKeysDialog(self,'Get New Keys',bindName, + currentKeySequences).result + if newKeys: #new keys were specified + if self.keysAreBuiltin.get(): #current key set is a built-in + message=('Your changes will be saved as a new Custom Key Set. '+ + 'Enter a name for your new Custom Key Set below.') + newKeySet=self.GetNewKeysName(message) + if not newKeySet: #user cancelled custom key set creation + self.listBindings.select_set(listIndex) + self.listBindings.select_anchor(listIndex) + return + else: #create new custom key set based on previously active key set + self.CreateNewKeySet(newKeySet) + self.listBindings.delete(listIndex) + self.listBindings.insert(listIndex,bindName+' - '+newKeys) + self.listBindings.select_set(listIndex) + self.listBindings.select_anchor(listIndex) + self.keyBinding.set(newKeys) + else: + self.listBindings.select_set(listIndex) + self.listBindings.select_anchor(listIndex) + + def GetNewKeysName(self,message): + usedNames=(idleConf.GetSectionList('user','keys')+ + idleConf.GetSectionList('default','keys')) + newKeySet=GetCfgSectionNameDialog(self,'New Custom Key Set', + message,usedNames).result + return newKeySet + + def SaveAsNewKeySet(self): + newKeysName=self.GetNewKeysName('New Key Set Name:') + if newKeysName: + self.CreateNewKeySet(newKeysName) + + def KeyBindingSelected(self,event): + self.buttonNewKeys.config(state=NORMAL) + + def CreateNewKeySet(self,newKeySetName): + #creates new custom key set based on the previously active key set, + #and makes the new key set active + if self.keysAreBuiltin.get(): + prevKeySetName=self.builtinKeys.get() + else: + prevKeySetName=self.customKeys.get() + prevKeys=idleConf.GetCoreKeys(prevKeySetName) + newKeys={} + for event in prevKeys.keys(): #add key set to changed items + eventName=event[2:-2] #trim off the angle brackets + binding=string.join(prevKeys[event]) + newKeys[eventName]=binding + #handle any unsaved changes to prev key set + if prevKeySetName in self.changedItems['keys'].keys(): + keySetChanges=self.changedItems['keys'][prevKeySetName] + for event in keySetChanges.keys(): + newKeys[event]=keySetChanges[event] + #save the new theme + self.SaveNewKeySet(newKeySetName,newKeys) + #change gui over to the new key set + customKeyList=idleConf.GetSectionList('user','keys') + customKeyList.sort() + self.optMenuKeysCustom.SetMenu(customKeyList,newKeySetName) + self.keysAreBuiltin.set(0) + self.SetKeysType() + + def LoadKeysList(self,keySetName): + reselect=0 + newKeySet=0 + if self.listBindings.curselection(): + reselect=1 + listIndex=self.listBindings.index(ANCHOR) + keySet=idleConf.GetKeySet(keySetName) + bindNames=keySet.keys() + bindNames.sort() + self.listBindings.delete(0,END) + for bindName in bindNames: + key=string.join(keySet[bindName]) #make key(s) into a string + bindName=bindName[2:-2] #trim off the angle brackets + if keySetName in self.changedItems['keys'].keys(): + #handle any unsaved changes to this key set + if bindName in self.changedItems['keys'][keySetName].keys(): + key=self.changedItems['keys'][keySetName][bindName] + self.listBindings.insert(END, bindName+' - '+key) + if reselect: + self.listBindings.see(listIndex) + self.listBindings.select_set(listIndex) + self.listBindings.select_anchor(listIndex) + + def DeleteCustomKeys(self): + keySetName=self.customKeys.get() + if not tkMessageBox.askyesno('Delete Key Set','Are you sure you wish '+ + 'to delete the key set %r ?' % (keySetName), + parent=self): + return + #remove key set from config + idleConf.userCfg['keys'].remove_section(keySetName) + if keySetName in self.changedItems['keys']: + del(self.changedItems['keys'][keySetName]) + #write changes + idleConf.userCfg['keys'].Save() + #reload user key set list + itemList=idleConf.GetSectionList('user','keys') + itemList.sort() + if not itemList: + self.radioKeysCustom.config(state=DISABLED) + self.optMenuKeysCustom.SetMenu(itemList,'- no custom keys -') + else: + self.optMenuKeysCustom.SetMenu(itemList,itemList[0]) + #revert to default key set + self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys','default')) + self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys','name')) + #user can't back out of these changes, they must be applied now + self.Apply() + self.SetKeysType() + + def DeleteCustomTheme(self): + themeName=self.customTheme.get() + if not tkMessageBox.askyesno('Delete Theme','Are you sure you wish '+ + 'to delete the theme %r ?' % (themeName,), + parent=self): + return + #remove theme from config + idleConf.userCfg['highlight'].remove_section(themeName) + if themeName in self.changedItems['highlight']: + del(self.changedItems['highlight'][themeName]) + #write changes + idleConf.userCfg['highlight'].Save() + #reload user theme list + itemList=idleConf.GetSectionList('user','highlight') + itemList.sort() + if not itemList: + self.radioThemeCustom.config(state=DISABLED) + self.optMenuThemeCustom.SetMenu(itemList,'- no custom themes -') + else: + self.optMenuThemeCustom.SetMenu(itemList,itemList[0]) + #revert to default theme + self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme','default')) + self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme','name')) + #user can't back out of these changes, they must be applied now + self.Apply() + self.SetThemeType() + + def GetColour(self): + target=self.highlightTarget.get() + prevColour=self.frameColourSet.cget('bg') + rgbTuplet, colourString = tkColorChooser.askcolor(parent=self, + title='Pick new colour for : '+target,initialcolor=prevColour) + if colourString and (colourString!=prevColour): + #user didn't cancel, and they chose a new colour + if self.themeIsBuiltin.get(): #current theme is a built-in + message=('Your changes will be saved as a new Custom Theme. '+ + 'Enter a name for your new Custom Theme below.') + newTheme=self.GetNewThemeName(message) + if not newTheme: #user cancelled custom theme creation + return + else: #create new custom theme based on previously active theme + self.CreateNewTheme(newTheme) + self.colour.set(colourString) + else: #current theme is user defined + self.colour.set(colourString) + + def OnNewColourSet(self): + newColour=self.colour.get() + self.frameColourSet.config(bg=newColour)#set sample + if self.fgHilite.get(): plane='foreground' + else: plane='background' + sampleElement=self.themeElements[self.highlightTarget.get()][0] + self.textHighlightSample.tag_config(sampleElement, **{plane:newColour}) + theme=self.customTheme.get() + themeElement=sampleElement+'-'+plane + self.AddChangedItem('highlight',theme,themeElement,newColour) + + def GetNewThemeName(self,message): + usedNames=(idleConf.GetSectionList('user','highlight')+ + idleConf.GetSectionList('default','highlight')) + newTheme=GetCfgSectionNameDialog(self,'New Custom Theme', + message,usedNames).result + return newTheme + + def SaveAsNewTheme(self): + newThemeName=self.GetNewThemeName('New Theme Name:') + if newThemeName: + self.CreateNewTheme(newThemeName) + + def CreateNewTheme(self,newThemeName): + #creates new custom theme based on the previously active theme, + #and makes the new theme active + if self.themeIsBuiltin.get(): + themeType='default' + themeName=self.builtinTheme.get() + else: + themeType='user' + themeName=self.customTheme.get() + newTheme=idleConf.GetThemeDict(themeType,themeName) + #apply any of the old theme's unsaved changes to the new theme + if themeName in self.changedItems['highlight'].keys(): + themeChanges=self.changedItems['highlight'][themeName] + for element in themeChanges.keys(): + newTheme[element]=themeChanges[element] + #save the new theme + self.SaveNewTheme(newThemeName,newTheme) + #change gui over to the new theme + customThemeList=idleConf.GetSectionList('user','highlight') + customThemeList.sort() + self.optMenuThemeCustom.SetMenu(customThemeList,newThemeName) + self.themeIsBuiltin.set(0) + self.SetThemeType() + + def OnListFontButtonRelease(self,event): + font = self.listFontName.get(ANCHOR) + self.fontName.set(font.lower()) + self.SetFontSample() + + def SetFontSample(self,event=None): + fontName=self.fontName.get() + if self.fontBold.get(): + fontWeight=tkFont.BOLD + else: + fontWeight=tkFont.NORMAL + newFont = (fontName, self.fontSize.get(), fontWeight) + self.labelFontSample.config(font=newFont) + self.textHighlightSample.configure(font=newFont) + + def SetHighlightTarget(self): + if self.highlightTarget.get()=='Cursor': #bg not possible + self.radioFg.config(state=DISABLED) + self.radioBg.config(state=DISABLED) + self.fgHilite.set(1) + else: #both fg and bg can be set + self.radioFg.config(state=NORMAL) + self.radioBg.config(state=NORMAL) + self.fgHilite.set(1) + self.SetColourSample() + + def SetColourSampleBinding(self,*args): + self.SetColourSample() + + def SetColourSample(self): + #set the colour smaple area + tag=self.themeElements[self.highlightTarget.get()][0] + if self.fgHilite.get(): plane='foreground' + else: plane='background' + colour=self.textHighlightSample.tag_cget(tag,plane) + self.frameColourSet.config(bg=colour) + + def PaintThemeSample(self): + if self.themeIsBuiltin.get(): #a default theme + theme=self.builtinTheme.get() + else: #a user theme + theme=self.customTheme.get() + for elementTitle in self.themeElements.keys(): + element=self.themeElements[elementTitle][0] + colours=idleConf.GetHighlight(theme,element) + if element=='cursor': #cursor sample needs special painting + colours['background']=idleConf.GetHighlight(theme, + 'normal', fgBg='bg') + #handle any unsaved changes to this theme + if theme in self.changedItems['highlight'].keys(): + themeDict=self.changedItems['highlight'][theme] + if element+'-foreground' in themeDict: + colours['foreground']=themeDict[element+'-foreground'] + if element+'-background' in themeDict: + colours['background']=themeDict[element+'-background'] + self.textHighlightSample.tag_config(element, **colours) + self.SetColourSample() + + def HelpSourceSelected(self,event): + self.SetHelpListButtonStates() + + def SetHelpListButtonStates(self): + if self.listHelp.size()<1: #no entries in list + self.buttonHelpListEdit.config(state=DISABLED) + self.buttonHelpListRemove.config(state=DISABLED) + else: #there are some entries + if self.listHelp.curselection(): #there currently is a selection + self.buttonHelpListEdit.config(state=NORMAL) + self.buttonHelpListRemove.config(state=NORMAL) + else: #there currently is not a selection + self.buttonHelpListEdit.config(state=DISABLED) + self.buttonHelpListRemove.config(state=DISABLED) + + def HelpListItemAdd(self): + helpSource=GetHelpSourceDialog(self,'New Help Source').result + if helpSource: + self.userHelpList.append( (helpSource[0],helpSource[1]) ) + self.listHelp.insert(END,helpSource[0]) + self.UpdateUserHelpChangedItems() + self.SetHelpListButtonStates() + + def HelpListItemEdit(self): + itemIndex=self.listHelp.index(ANCHOR) + helpSource=self.userHelpList[itemIndex] + newHelpSource=GetHelpSourceDialog(self,'Edit Help Source', + menuItem=helpSource[0],filePath=helpSource[1]).result + if (not newHelpSource) or (newHelpSource==helpSource): + return #no changes + self.userHelpList[itemIndex]=newHelpSource + self.listHelp.delete(itemIndex) + self.listHelp.insert(itemIndex,newHelpSource[0]) + self.UpdateUserHelpChangedItems() + self.SetHelpListButtonStates() + + def HelpListItemRemove(self): + itemIndex=self.listHelp.index(ANCHOR) + del(self.userHelpList[itemIndex]) + self.listHelp.delete(itemIndex) + self.UpdateUserHelpChangedItems() + self.SetHelpListButtonStates() + + def UpdateUserHelpChangedItems(self): + "Clear and rebuild the HelpFiles section in self.changedItems" + self.changedItems['main']['HelpFiles'] = {} + for num in range(1,len(self.userHelpList)+1): + self.AddChangedItem('main','HelpFiles',str(num), + string.join(self.userHelpList[num-1][:2],';')) + + def LoadFontCfg(self): + ##base editor font selection list + fonts=list(tkFont.families(self)) + fonts.sort() + for font in fonts: + self.listFontName.insert(END,font) + configuredFont=idleConf.GetOption('main','EditorWindow','font', + default='courier') + lc_configuredFont = configuredFont.lower() + self.fontName.set(lc_configuredFont) + lc_fonts = [s.lower() for s in fonts] + if lc_configuredFont in lc_fonts: + currentFontIndex = lc_fonts.index(lc_configuredFont) + self.listFontName.see(currentFontIndex) + self.listFontName.select_set(currentFontIndex) + self.listFontName.select_anchor(currentFontIndex) + ##font size dropdown + fontSize=idleConf.GetOption('main','EditorWindow','font-size', + type='int', default='10') + self.optMenuFontSize.SetMenu(('7','8','9','10','11','12','13','14', + '16','18','20','22'),fontSize ) + ##fontWeight + self.fontBold.set(idleConf.GetOption('main','EditorWindow', + 'font-bold',default=0,type='bool')) + ##font sample + self.SetFontSample() + + def LoadTabCfg(self): + ##indent sizes + spaceNum=idleConf.GetOption('main','Indent','num-spaces', + default=4,type='int') + self.spaceNum.set(spaceNum) + + def LoadThemeCfg(self): + ##current theme type radiobutton + self.themeIsBuiltin.set(idleConf.GetOption('main','Theme','default', + type='bool',default=1)) + ##currently set theme + currentOption=idleConf.CurrentTheme() + ##load available theme option menus + if self.themeIsBuiltin.get(): #default theme selected + itemList=idleConf.GetSectionList('default','highlight') + itemList.sort() + self.optMenuThemeBuiltin.SetMenu(itemList,currentOption) + itemList=idleConf.GetSectionList('user','highlight') + itemList.sort() + if not itemList: + self.radioThemeCustom.config(state=DISABLED) + self.customTheme.set('- no custom themes -') + else: + self.optMenuThemeCustom.SetMenu(itemList,itemList[0]) + else: #user theme selected + itemList=idleConf.GetSectionList('user','highlight') + itemList.sort() + self.optMenuThemeCustom.SetMenu(itemList,currentOption) + itemList=idleConf.GetSectionList('default','highlight') + itemList.sort() + self.optMenuThemeBuiltin.SetMenu(itemList,itemList[0]) + self.SetThemeType() + ##load theme element option menu + themeNames=self.themeElements.keys() + themeNames.sort(key=lambda x: self.themeElements[x][1]) + self.optMenuHighlightTarget.SetMenu(themeNames,themeNames[0]) + self.PaintThemeSample() + self.SetHighlightTarget() + + def LoadKeyCfg(self): + ##current keys type radiobutton + self.keysAreBuiltin.set(idleConf.GetOption('main','Keys','default', + type='bool',default=1)) + ##currently set keys + currentOption=idleConf.CurrentKeys() + ##load available keyset option menus + if self.keysAreBuiltin.get(): #default theme selected + itemList=idleConf.GetSectionList('default','keys') + itemList.sort() + self.optMenuKeysBuiltin.SetMenu(itemList,currentOption) + itemList=idleConf.GetSectionList('user','keys') + itemList.sort() + if not itemList: + self.radioKeysCustom.config(state=DISABLED) + self.customKeys.set('- no custom keys -') + else: + self.optMenuKeysCustom.SetMenu(itemList,itemList[0]) + else: #user key set selected + itemList=idleConf.GetSectionList('user','keys') + itemList.sort() + self.optMenuKeysCustom.SetMenu(itemList,currentOption) + itemList=idleConf.GetSectionList('default','keys') + itemList.sort() + self.optMenuKeysBuiltin.SetMenu(itemList,itemList[0]) + self.SetKeysType() + ##load keyset element list + keySetName=idleConf.CurrentKeys() + self.LoadKeysList(keySetName) + + def LoadGeneralCfg(self): + #startup state + self.startupEdit.set(idleConf.GetOption('main','General', + 'editor-on-startup',default=1,type='bool')) + #autosave state + self.autoSave.set(idleConf.GetOption('main', 'General', 'autosave', + default=0, type='bool')) + #initial window size + self.winWidth.set(idleConf.GetOption('main','EditorWindow','width', + type='int')) + self.winHeight.set(idleConf.GetOption('main','EditorWindow','height', + type='int')) + #initial paragraph reformat size + self.paraWidth.set(idleConf.GetOption('main','FormatParagraph','paragraph', + type='int')) + # default source encoding + self.encoding.set(idleConf.GetOption('main', 'EditorWindow', + 'encoding', default='none')) + # additional help sources + self.userHelpList = idleConf.GetAllExtraHelpSourcesList() + for helpItem in self.userHelpList: + self.listHelp.insert(END,helpItem[0]) + self.SetHelpListButtonStates() + + def LoadConfigs(self): + """ + load configuration from default and user config files and populate + the widgets on the config dialog pages. + """ + ### fonts / tabs page + self.LoadFontCfg() + self.LoadTabCfg() + ### highlighting page + self.LoadThemeCfg() + ### keys page + self.LoadKeyCfg() + ### general page + self.LoadGeneralCfg() + + def SaveNewKeySet(self,keySetName,keySet): + """ + save a newly created core key set. + keySetName - string, the name of the new key set + keySet - dictionary containing the new key set + """ + if not idleConf.userCfg['keys'].has_section(keySetName): + idleConf.userCfg['keys'].add_section(keySetName) + for event in keySet.keys(): + value=keySet[event] + idleConf.userCfg['keys'].SetOption(keySetName,event,value) + + def SaveNewTheme(self,themeName,theme): + """ + save a newly created theme. + themeName - string, the name of the new theme + theme - dictionary containing the new theme + """ + if not idleConf.userCfg['highlight'].has_section(themeName): + idleConf.userCfg['highlight'].add_section(themeName) + for element in theme.keys(): + value=theme[element] + idleConf.userCfg['highlight'].SetOption(themeName,element,value) + + def SetUserValue(self,configType,section,item,value): + if idleConf.defaultCfg[configType].has_option(section,item): + if idleConf.defaultCfg[configType].Get(section,item)==value: + #the setting equals a default setting, remove it from user cfg + return idleConf.userCfg[configType].RemoveOption(section,item) + #if we got here set the option + return idleConf.userCfg[configType].SetOption(section,item,value) + + def SaveAllChangedConfigs(self): + "Save configuration changes to the user config file." + idleConf.userCfg['main'].Save() + for configType in self.changedItems.keys(): + cfgTypeHasChanges = False + for section in self.changedItems[configType].keys(): + if section == 'HelpFiles': + #this section gets completely replaced + idleConf.userCfg['main'].remove_section('HelpFiles') + cfgTypeHasChanges = True + for item in self.changedItems[configType][section].keys(): + value = self.changedItems[configType][section][item] + if self.SetUserValue(configType,section,item,value): + cfgTypeHasChanges = True + if cfgTypeHasChanges: + idleConf.userCfg[configType].Save() + for configType in ['keys', 'highlight']: + # save these even if unchanged! + idleConf.userCfg[configType].Save() + self.ResetChangedItems() #clear the changed items dict + + def DeactivateCurrentConfig(self): + #Before a config is saved, some cleanup of current + #config must be done - remove the previous keybindings + winInstances=self.parent.instance_dict.keys() + for instance in winInstances: + instance.RemoveKeybindings() + + def ActivateConfigChanges(self): + "Dynamically apply configuration changes" + winInstances=self.parent.instance_dict.keys() + for instance in winInstances: + instance.ResetColorizer() + instance.ResetFont() + instance.set_notabs_indentwidth() + instance.ApplyKeybindings() + instance.reset_help_menu_entries() + + def Cancel(self): + self.destroy() + + def Ok(self): + self.Apply() + self.destroy() + + def Apply(self): + self.DeactivateCurrentConfig() + self.SaveAllChangedConfigs() + self.ActivateConfigChanges() + + def Help(self): + pass + +if __name__ == '__main__': + from idlelib.idle_test.htest import run + run(ConfigDialog) diff --git a/PythonHome/Lib/idlelib/configDialog.pyc b/PythonHome/Lib/idlelib/configDialog.pyc deleted file mode 100644 index 4d8a8c1ad02b50663b7c9f1e2e4b171525419e14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43516 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�s>O6;%xa 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 diff --git a/PythonHome/Lib/idlelib/configHandler.py b/PythonHome/Lib/idlelib/configHandler.py new file mode 100644 index 0000000000..67ab1f653d --- /dev/null +++ b/PythonHome/Lib/idlelib/configHandler.py @@ -0,0 +1,721 @@ +"""Provides access to stored IDLE configuration information. + +Refer to the comments at the beginning of config-main.def for a description of +the available configuration files and the design implemented to update user +configuration information. In particular, user configuration choices which +duplicate the defaults will be removed from the user's configuration files, +and if a file becomes empty, it will be deleted. + +The contents of the user files may be altered using the Options/Configure IDLE +menu to access the configuration GUI (configDialog.py), or manually. + +Throughout this module there is an emphasis on returning useable defaults +when a problem occurs in returning a requested configuration value back to +idle. This is to allow IDLE to continue to function in spite of errors in +the retrieval of config information. When a default is returned instead of +a requested config value, a message is printed to stderr to aid in +configuration problem notification and resolution. + +""" +import os +import sys +import string +from ConfigParser import ConfigParser, NoOptionError, NoSectionError + +class InvalidConfigType(Exception): pass +class InvalidConfigSet(Exception): pass +class InvalidFgBg(Exception): pass +class InvalidTheme(Exception): pass + +class IdleConfParser(ConfigParser): + """ + A ConfigParser specialised for idle configuration file handling + """ + def __init__(self, cfgFile, cfgDefaults=None): + """ + cfgFile - string, fully specified configuration file name + """ + self.file=cfgFile + ConfigParser.__init__(self,defaults=cfgDefaults) + + def Get(self, section, option, type=None, default=None, raw=False): + """ + Get an option value for given section/option or return default. + If type is specified, return as type. + """ + if not self.has_option(section, option): + return default + if type=='bool': + return self.getboolean(section, option) + elif type=='int': + return self.getint(section, option) + else: + return self.get(section, option, raw=raw) + + def GetOptionList(self,section): + """ + Get an option list for given section + """ + if self.has_section(section): + return self.options(section) + else: #return a default value + return [] + + def Load(self): + """ + Load the configuration file from disk + """ + self.read(self.file) + +class IdleUserConfParser(IdleConfParser): + """ + IdleConfigParser specialised for user configuration handling. + """ + + def AddSection(self,section): + """ + if section doesn't exist, add it + """ + if not self.has_section(section): + self.add_section(section) + + def RemoveEmptySections(self): + """ + remove any sections that have no options + """ + for section in self.sections(): + if not self.GetOptionList(section): + self.remove_section(section) + + def IsEmpty(self): + """ + Remove empty sections and then return 1 if parser has no sections + left, else return 0. + """ + self.RemoveEmptySections() + if self.sections(): + return 0 + else: + return 1 + + def RemoveOption(self,section,option): + """ + If section/option exists, remove it. + Returns 1 if option was removed, 0 otherwise. + """ + if self.has_section(section): + return self.remove_option(section,option) + + def SetOption(self,section,option,value): + """ + Sets option to value, adding section if required. + Returns 1 if option was added or changed, otherwise 0. + """ + if self.has_option(section,option): + if self.get(section,option)==value: + return 0 + else: + self.set(section,option,value) + return 1 + else: + if not self.has_section(section): + self.add_section(section) + self.set(section,option,value) + return 1 + + def RemoveFile(self): + """ + Removes the user config file from disk if it exists. + """ + if os.path.exists(self.file): + os.remove(self.file) + + def Save(self): + """Update user configuration file. + + Remove empty sections. If resulting config isn't empty, write the file + to disk. If config is empty, remove the file from disk if it exists. + + """ + if not self.IsEmpty(): + fname = self.file + try: + cfgFile = open(fname, 'w') + except IOError: + os.unlink(fname) + cfgFile = open(fname, 'w') + self.write(cfgFile) + else: + self.RemoveFile() + +class IdleConf: + """ + holds config parsers for all idle config files: + default config files + (idle install dir)/config-main.def + (idle install dir)/config-extensions.def + (idle install dir)/config-highlight.def + (idle install dir)/config-keys.def + user config files + (user home dir)/.idlerc/config-main.cfg + (user home dir)/.idlerc/config-extensions.cfg + (user home dir)/.idlerc/config-highlight.cfg + (user home dir)/.idlerc/config-keys.cfg + """ + def __init__(self): + self.defaultCfg={} + self.userCfg={} + self.cfg={} + self.CreateConfigHandlers() + self.LoadCfgFiles() + #self.LoadCfg() + + def CreateConfigHandlers(self): + """ + set up a dictionary of config parsers for default and user + configurations respectively + """ + #build idle install path + if __name__ != '__main__': # we were imported + idleDir=os.path.dirname(__file__) + else: # we were exec'ed (for testing only) + idleDir=os.path.abspath(sys.path[0]) + userDir=self.GetUserCfgDir() + configTypes=('main','extensions','highlight','keys') + defCfgFiles={} + usrCfgFiles={} + for cfgType in configTypes: #build config file names + defCfgFiles[cfgType]=os.path.join(idleDir,'config-'+cfgType+'.def') + usrCfgFiles[cfgType]=os.path.join(userDir,'config-'+cfgType+'.cfg') + for cfgType in configTypes: #create config parsers + self.defaultCfg[cfgType]=IdleConfParser(defCfgFiles[cfgType]) + self.userCfg[cfgType]=IdleUserConfParser(usrCfgFiles[cfgType]) + + def GetUserCfgDir(self): + """ + Creates (if required) and returns a filesystem directory for storing + user config files. + + """ + cfgDir = '.idlerc' + userDir = os.path.expanduser('~') + if userDir != '~': # expanduser() found user home dir + if not os.path.exists(userDir): + warn = ('\n Warning: os.path.expanduser("~") points to\n '+ + userDir+',\n but the path does not exist.\n') + try: + sys.stderr.write(warn) + except IOError: + pass + userDir = '~' + if userDir == "~": # still no path to home! + # traditionally IDLE has defaulted to os.getcwd(), is this adequate? + userDir = os.getcwd() + userDir = os.path.join(userDir, cfgDir) + if not os.path.exists(userDir): + try: + os.mkdir(userDir) + except (OSError, IOError): + warn = ('\n Warning: unable to create user config directory\n'+ + userDir+'\n Check path and permissions.\n Exiting!\n\n') + sys.stderr.write(warn) + raise SystemExit + return userDir + + def GetOption(self, configType, section, option, default=None, type=None, + warn_on_default=True, raw=False): + """ + Get an option value for given config type and given general + configuration section/option or return a default. If type is specified, + return as type. Firstly the user configuration is checked, with a + fallback to the default configuration, and a final 'catch all' + fallback to a useable passed-in default if the option isn't present in + either the user or the default configuration. + configType must be one of ('main','extensions','highlight','keys') + If a default is returned, and warn_on_default is True, a warning is + printed to stderr. + + """ + try: + if self.userCfg[configType].has_option(section,option): + return self.userCfg[configType].Get(section, option, + type=type, raw=raw) + except ValueError: + warning = ('\n Warning: configHandler.py - IdleConf.GetOption -\n' + ' invalid %r value for configuration option %r\n' + ' from section %r: %r\n' % + (type, option, section, + self.userCfg[configType].Get(section, option, + raw=raw))) + try: + sys.stderr.write(warning) + except IOError: + pass + try: + if self.defaultCfg[configType].has_option(section,option): + return self.defaultCfg[configType].Get(section, option, + type=type, raw=raw) + except ValueError: + pass + #returning default, print warning + if warn_on_default: + warning = ('\n Warning: configHandler.py - IdleConf.GetOption -\n' + ' problem retrieving configuration option %r\n' + ' from section %r.\n' + ' returning default value: %r\n' % + (option, section, default)) + try: + sys.stderr.write(warning) + except IOError: + pass + return default + + def SetOption(self, configType, section, option, value): + """In user's config file, set section's option to value. + + """ + self.userCfg[configType].SetOption(section, option, value) + + def GetSectionList(self, configSet, configType): + """ + Get a list of sections from either the user or default config for + the given config type. + configSet must be either 'user' or 'default' + configType must be one of ('main','extensions','highlight','keys') + """ + if not (configType in ('main','extensions','highlight','keys')): + raise InvalidConfigType, 'Invalid configType specified' + if configSet == 'user': + cfgParser=self.userCfg[configType] + elif configSet == 'default': + cfgParser=self.defaultCfg[configType] + else: + raise InvalidConfigSet, 'Invalid configSet specified' + return cfgParser.sections() + + def GetHighlight(self, theme, element, fgBg=None): + """ + return individual highlighting theme elements. + fgBg - string ('fg'or'bg') or None, if None return a dictionary + containing fg and bg colours (appropriate for passing to Tkinter in, + e.g., a tag_config call), otherwise fg or bg colour only as specified. + """ + if self.defaultCfg['highlight'].has_section(theme): + themeDict=self.GetThemeDict('default',theme) + else: + themeDict=self.GetThemeDict('user',theme) + fore=themeDict[element+'-foreground'] + if element=='cursor': #there is no config value for cursor bg + back=themeDict['normal-background'] + else: + back=themeDict[element+'-background'] + highlight={"foreground": fore,"background": back} + if not fgBg: #return dict of both colours + return highlight + else: #return specified colour only + if fgBg == 'fg': + return highlight["foreground"] + if fgBg == 'bg': + return highlight["background"] + else: + raise InvalidFgBg, 'Invalid fgBg specified' + + def GetThemeDict(self,type,themeName): + """ + type - string, 'default' or 'user' theme type + themeName - string, theme name + Returns a dictionary which holds {option:value} for each element + in the specified theme. Values are loaded over a set of ultimate last + fallback defaults to guarantee that all theme elements are present in + a newly created theme. + """ + if type == 'user': + cfgParser=self.userCfg['highlight'] + elif type == 'default': + cfgParser=self.defaultCfg['highlight'] + else: + raise InvalidTheme, 'Invalid theme type specified' + #foreground and background values are provded for each theme element + #(apart from cursor) even though all these values are not yet used + #by idle, to allow for their use in the future. Default values are + #generally black and white. + theme={ 'normal-foreground':'#000000', + 'normal-background':'#ffffff', + 'keyword-foreground':'#000000', + 'keyword-background':'#ffffff', + 'builtin-foreground':'#000000', + 'builtin-background':'#ffffff', + 'comment-foreground':'#000000', + 'comment-background':'#ffffff', + 'string-foreground':'#000000', + 'string-background':'#ffffff', + 'definition-foreground':'#000000', + 'definition-background':'#ffffff', + 'hilite-foreground':'#000000', + 'hilite-background':'gray', + 'break-foreground':'#ffffff', + 'break-background':'#000000', + 'hit-foreground':'#ffffff', + 'hit-background':'#000000', + 'error-foreground':'#ffffff', + 'error-background':'#000000', + #cursor (only foreground can be set) + 'cursor-foreground':'#000000', + #shell window + 'stdout-foreground':'#000000', + 'stdout-background':'#ffffff', + 'stderr-foreground':'#000000', + 'stderr-background':'#ffffff', + 'console-foreground':'#000000', + 'console-background':'#ffffff' } + for element in theme.keys(): + if not cfgParser.has_option(themeName,element): + #we are going to return a default, print warning + warning=('\n Warning: configHandler.py - IdleConf.GetThemeDict' + ' -\n problem retrieving theme element %r' + '\n from theme %r.\n' + ' returning default value: %r\n' % + (element, themeName, theme[element])) + try: + sys.stderr.write(warning) + except IOError: + pass + colour=cfgParser.Get(themeName,element,default=theme[element]) + theme[element]=colour + return theme + + def CurrentTheme(self): + """ + Returns the name of the currently active theme + """ + return self.GetOption('main','Theme','name',default='') + + def CurrentKeys(self): + """ + Returns the name of the currently active key set + """ + return self.GetOption('main','Keys','name',default='') + + def GetExtensions(self, active_only=True, editor_only=False, shell_only=False): + """ + Gets a list of all idle extensions declared in the config files. + active_only - boolean, if true only return active (enabled) extensions + """ + extns=self.RemoveKeyBindNames( + self.GetSectionList('default','extensions')) + userExtns=self.RemoveKeyBindNames( + self.GetSectionList('user','extensions')) + for extn in userExtns: + if extn not in extns: #user has added own extension + extns.append(extn) + if active_only: + activeExtns=[] + for extn in extns: + if self.GetOption('extensions', extn, 'enable', default=True, + type='bool'): + #the extension is enabled + if editor_only or shell_only: + if editor_only: + option = "enable_editor" + else: + option = "enable_shell" + if self.GetOption('extensions', extn,option, + default=True, type='bool', + warn_on_default=False): + activeExtns.append(extn) + else: + activeExtns.append(extn) + return activeExtns + else: + return extns + + def RemoveKeyBindNames(self,extnNameList): + #get rid of keybinding section names + names=extnNameList + kbNameIndicies=[] + for name in names: + if name.endswith(('_bindings', '_cfgBindings')): + kbNameIndicies.append(names.index(name)) + kbNameIndicies.sort() + kbNameIndicies.reverse() + for index in kbNameIndicies: #delete each keybinding section name + del(names[index]) + return names + + def GetExtnNameForEvent(self,virtualEvent): + """ + Returns the name of the extension that virtualEvent is bound in, or + None if not bound in any extension. + virtualEvent - string, name of the virtual event to test for, without + the enclosing '<< >>' + """ + extName=None + vEvent='<<'+virtualEvent+'>>' + for extn in self.GetExtensions(active_only=0): + for event in self.GetExtensionKeys(extn).keys(): + if event == vEvent: + extName=extn + return extName + + def GetExtensionKeys(self,extensionName): + """ + returns a dictionary of the configurable keybindings for a particular + extension,as they exist in the dictionary returned by GetCurrentKeySet; + that is, where previously used bindings are disabled. + """ + keysName=extensionName+'_cfgBindings' + activeKeys=self.GetCurrentKeySet() + extKeys={} + if self.defaultCfg['extensions'].has_section(keysName): + eventNames=self.defaultCfg['extensions'].GetOptionList(keysName) + for eventName in eventNames: + event='<<'+eventName+'>>' + binding=activeKeys[event] + extKeys[event]=binding + return extKeys + + def __GetRawExtensionKeys(self,extensionName): + """ + returns a dictionary of the configurable keybindings for a particular + extension, as defined in the configuration files, or an empty dictionary + if no bindings are found + """ + keysName=extensionName+'_cfgBindings' + extKeys={} + if self.defaultCfg['extensions'].has_section(keysName): + eventNames=self.defaultCfg['extensions'].GetOptionList(keysName) + for eventName in eventNames: + binding=self.GetOption('extensions',keysName, + eventName,default='').split() + event='<<'+eventName+'>>' + extKeys[event]=binding + return extKeys + + def GetExtensionBindings(self,extensionName): + """ + Returns a dictionary of all the event bindings for a particular + extension. The configurable keybindings are returned as they exist in + the dictionary returned by GetCurrentKeySet; that is, where re-used + keybindings are disabled. + """ + bindsName=extensionName+'_bindings' + extBinds=self.GetExtensionKeys(extensionName) + #add the non-configurable bindings + if self.defaultCfg['extensions'].has_section(bindsName): + eventNames=self.defaultCfg['extensions'].GetOptionList(bindsName) + for eventName in eventNames: + binding=self.GetOption('extensions',bindsName, + eventName,default='').split() + event='<<'+eventName+'>>' + extBinds[event]=binding + + return extBinds + + def GetKeyBinding(self, keySetName, eventStr): + """ + returns the keybinding for a specific event. + keySetName - string, name of key binding set + eventStr - string, the virtual event we want the binding for, + represented as a string, eg. '<>' + """ + eventName=eventStr[2:-2] #trim off the angle brackets + binding=self.GetOption('keys',keySetName,eventName,default='').split() + return binding + + def GetCurrentKeySet(self): + result = self.GetKeySet(self.CurrentKeys()) + + if sys.platform == "darwin": + # OS X Tk variants do not support the "Alt" keyboard modifier. + # So replace all keybingings that use "Alt" with ones that + # use the "Option" keyboard modifier. + # TO DO: the "Option" modifier does not work properly for + # Cocoa Tk and XQuartz Tk so we should not use it + # in default OS X KeySets. + for k, v in result.items(): + v2 = [ x.replace('>' + """ + return ('<<'+virtualEvent+'>>') in self.GetCoreKeys().keys() + + def GetCoreKeys(self, keySetName=None): + """ + returns the requested set of core keybindings, with fallbacks if + required. + Keybindings loaded from the config file(s) are loaded _over_ these + defaults, so if there is a problem getting any core binding there will + be an 'ultimate last resort fallback' to the CUA-ish bindings + defined here. + """ + keyBindings={ + '<>': ['', ''], + '<>': ['', ''], + '<>': ['', ''], + '<>': ['', ''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': ['', ''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': ['', ''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''] + } + if keySetName: + for event in keyBindings.keys(): + binding=self.GetKeyBinding(keySetName,event) + if binding: + keyBindings[event]=binding + else: #we are going to return a default, print warning + warning=('\n Warning: configHandler.py - IdleConf.GetCoreKeys' + ' -\n problem retrieving key binding for event %r' + '\n from key set %r.\n' + ' returning default value: %r\n' % + (event, keySetName, keyBindings[event])) + try: + sys.stderr.write(warning) + except IOError: + pass + return keyBindings + + def GetExtraHelpSourceList(self,configSet): + """Fetch list of extra help sources from a given configSet. + + Valid configSets are 'user' or 'default'. Return a list of tuples of + the form (menu_item , path_to_help_file , option), or return the empty + list. 'option' is the sequence number of the help resource. 'option' + values determine the position of the menu items on the Help menu, + therefore the returned list must be sorted by 'option'. + + """ + helpSources=[] + if configSet=='user': + cfgParser=self.userCfg['main'] + elif configSet=='default': + cfgParser=self.defaultCfg['main'] + else: + raise InvalidConfigSet, 'Invalid configSet specified' + options=cfgParser.GetOptionList('HelpFiles') + for option in options: + value=cfgParser.Get('HelpFiles',option,default=';') + if value.find(';')==-1: #malformed config entry with no ';' + menuItem='' #make these empty + helpPath='' #so value won't be added to list + else: #config entry contains ';' as expected + value=string.split(value,';') + menuItem=value[0].strip() + helpPath=value[1].strip() + if menuItem and helpPath: #neither are empty strings + helpSources.append( (menuItem,helpPath,option) ) + helpSources.sort(key=lambda x: int(x[2])) + return helpSources + + def GetAllExtraHelpSourcesList(self): + """ + Returns a list of tuples containing the details of all additional help + sources configured, or an empty list if there are none. Tuples are of + the format returned by GetExtraHelpSourceList. + """ + allHelpSources=( self.GetExtraHelpSourceList('default')+ + self.GetExtraHelpSourceList('user') ) + return allHelpSources + + def LoadCfgFiles(self): + """ + load all configuration files. + """ + for key in self.defaultCfg.keys(): + self.defaultCfg[key].Load() + self.userCfg[key].Load() #same keys + + def SaveUserCfgFiles(self): + """ + write all loaded user configuration files back to disk + """ + for key in self.userCfg.keys(): + self.userCfg[key].Save() + +idleConf=IdleConf() + +### module test +if __name__ == '__main__': + def dumpCfg(cfg): + print '\n',cfg,'\n' + for key in cfg.keys(): + sections=cfg[key].sections() + print key + print sections + for section in sections: + options=cfg[key].options(section) + print section + print options + for option in options: + print option, '=', cfg[key].Get(section,option) + dumpCfg(idleConf.defaultCfg) + dumpCfg(idleConf.userCfg) + print idleConf.userCfg['main'].Get('Theme','name') + #print idleConf.userCfg['highlight'].GetDefHighlight('Foo','normal') diff --git a/PythonHome/Lib/idlelib/configHandler.pyc b/PythonHome/Lib/idlelib/configHandler.pyc deleted file mode 100644 index ca3dead51a7091d83c49cc41a2897b7e8821ec93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26737 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