From 65789d9ba1e576a172bddb6c3fa66b8738641ada Mon Sep 17 00:00:00 2001 From: Israel Brewster Date: Wed, 10 Feb 2016 12:46:06 -0900 Subject: [PATCH] Add full range of options for parameter markers Fix bug with parsing results in Python 3 --- .gitignore | 1 + README | 9 + p4d/p4d.py | 28 +- setup.py | 5 +- virtualenv/.Python | 1 - virtualenv/bin/activate | 80 - virtualenv/bin/activate.csh | 42 - virtualenv/bin/activate.fish | 74 - virtualenv/bin/activate_this.py | 34 - virtualenv/bin/easy_install | 11 - virtualenv/bin/easy_install-3.5 | 11 - virtualenv/bin/pip | 11 - virtualenv/bin/pip3 | 11 - virtualenv/bin/pip3.5 | 11 - virtualenv/bin/python | 1 - virtualenv/bin/python3 | 1 - virtualenv/bin/python3.5 | Bin 25384 -> 0 bytes virtualenv/bin/wheel | 11 - virtualenv/include/python3.5m | 1 - virtualenv/lib/python3.5/__future__.py | 1 - virtualenv/lib/python3.5/_bootlocale.py | 1 - virtualenv/lib/python3.5/_collections_abc.py | 1 - virtualenv/lib/python3.5/_dummy_thread.py | 1 - virtualenv/lib/python3.5/_weakrefset.py | 1 - virtualenv/lib/python3.5/abc.py | 1 - virtualenv/lib/python3.5/base64.py | 1 - virtualenv/lib/python3.5/bisect.py | 1 - virtualenv/lib/python3.5/codecs.py | 1 - virtualenv/lib/python3.5/collections | 1 - virtualenv/lib/python3.5/config-3.5m | 1 - virtualenv/lib/python3.5/copy.py | 1 - virtualenv/lib/python3.5/copyreg.py | 1 - .../lib/python3.5/distutils/__init__.py | 101 - .../lib/python3.5/distutils/distutils.cfg | 6 - virtualenv/lib/python3.5/encodings | 1 - virtualenv/lib/python3.5/fnmatch.py | 1 - virtualenv/lib/python3.5/functools.py | 1 - virtualenv/lib/python3.5/genericpath.py | 1 - virtualenv/lib/python3.5/hashlib.py | 1 - virtualenv/lib/python3.5/heapq.py | 1 - virtualenv/lib/python3.5/hmac.py | 1 - virtualenv/lib/python3.5/imp.py | 1 - virtualenv/lib/python3.5/importlib | 1 - virtualenv/lib/python3.5/io.py | 1 - virtualenv/lib/python3.5/keyword.py | 1 - virtualenv/lib/python3.5/lib-dynload | 1 - virtualenv/lib/python3.5/linecache.py | 1 - virtualenv/lib/python3.5/locale.py | 1 - .../lib/python3.5/no-global-site-packages.txt | 0 virtualenv/lib/python3.5/ntpath.py | 1 - virtualenv/lib/python3.5/operator.py | 1 - virtualenv/lib/python3.5/orig-prefix.txt | 1 - virtualenv/lib/python3.5/os.py | 1 - virtualenv/lib/python3.5/plat-darwin | 1 - virtualenv/lib/python3.5/posixpath.py | 1 - virtualenv/lib/python3.5/random.py | 1 - virtualenv/lib/python3.5/re.py | 1 - virtualenv/lib/python3.5/readline.so | 1 - virtualenv/lib/python3.5/reprlib.py | 1 - virtualenv/lib/python3.5/rlcompleter.py | 1 - virtualenv/lib/python3.5/shutil.py | 1 - .../site-packages/_markerlib/__init__.py | 16 - .../site-packages/_markerlib/markers.py | 119 - .../EGG-INFO/PKG-INFO | 31 - .../EGG-INFO/SOURCES.txt | 147 - .../EGG-INFO/dependency_links.txt | 1 - .../EGG-INFO/entry_points.txt | 3 - .../EGG-INFO/native_libs.txt | 1 - .../EGG-INFO/not-zip-safe | 1 - .../EGG-INFO/requires.txt | 1 - .../EGG-INFO/top_level.txt | 2 - .../_cffi_backend.cpython-35m-darwin.so | Bin 180928 -> 0 bytes .../_cffi_backend.py | 7 - .../cffi/__init__.py | 13 - .../cffi/_cffi_include.h | 229 - .../cffi/api.py | 724 --- .../cffi/backend_ctypes.py | 1068 ---- .../cffi/cffi_opcode.py | 178 - .../cffi/commontypes.py | 76 - .../cffi/cparser.py | 772 --- .../cffi/ffiplatform.py | 115 - .../cffi/gc_weakref.py | 22 - .../cffi/lock.py | 30 - .../cffi/model.py | 602 -- .../cffi/parse_c_type.h | 169 - .../cffi/recompiler.py | 1290 ----- .../cffi/setuptools_ext.py | 161 - .../cffi/vengine_cpy.py | 1007 ---- .../cffi/vengine_gen.py | 668 --- .../cffi/verifier.py | 313 - .../site-packages/dateutil/__init__.py | 2 - .../site-packages/dateutil/easter.py | 89 - .../site-packages/dateutil/parser.py | 1205 ---- .../site-packages/dateutil/relativedelta.py | 450 -- .../python3.5/site-packages/dateutil/rrule.py | 1375 ----- .../python3.5/site-packages/dateutil/tz.py | 986 ---- .../python3.5/site-packages/dateutil/tzwin.py | 184 - .../dateutil/zoneinfo/__init__.py | 108 - .../zoneinfo/dateutil-zoneinfo.tar.gz | Bin 151011 -> 0 bytes .../python3.5/site-packages/easy-install.pth | 3 - .../python3.5/site-packages/easy_install.py | 5 - .../pip-7.1.2.dist-info/DESCRIPTION.rst | 25 - .../pip-7.1.2.dist-info/METADATA | 53 - .../site-packages/pip-7.1.2.dist-info/RECORD | 461 -- .../site-packages/pip-7.1.2.dist-info/WHEEL | 6 - .../pip-7.1.2.dist-info/entry_points.txt | 5 - .../pip-7.1.2.dist-info/metadata.json | 1 - .../pip-7.1.2.dist-info/pbr.json | 1 - .../pip-7.1.2.dist-info/top_level.txt | 1 - .../python3.5/site-packages/pip/__init__.py | 315 -- .../python3.5/site-packages/pip/__main__.py | 19 - .../site-packages/pip/_vendor/__init__.py | 66 - .../pip/_vendor/_markerlib/__init__.py | 16 - .../pip/_vendor/_markerlib/markers.py | 119 - .../pip/_vendor/cachecontrol/__init__.py | 11 - .../pip/_vendor/cachecontrol/adapter.py | 117 - .../pip/_vendor/cachecontrol/cache.py | 39 - .../_vendor/cachecontrol/caches/__init__.py | 18 - .../_vendor/cachecontrol/caches/file_cache.py | 116 - .../cachecontrol/caches/redis_cache.py | 41 - .../pip/_vendor/cachecontrol/compat.py | 14 - .../pip/_vendor/cachecontrol/controller.py | 299 - .../pip/_vendor/cachecontrol/filewrapper.py | 63 - .../pip/_vendor/cachecontrol/heuristics.py | 134 - .../pip/_vendor/cachecontrol/serialize.py | 184 - .../pip/_vendor/cachecontrol/wrapper.py | 21 - .../pip/_vendor/colorama/__init__.py | 7 - .../pip/_vendor/colorama/ansi.py | 99 - .../pip/_vendor/colorama/ansitowin32.py | 228 - .../pip/_vendor/colorama/initialise.py | 66 - .../pip/_vendor/colorama/win32.py | 146 - .../pip/_vendor/colorama/winterm.py | 151 - .../pip/_vendor/distlib/__init__.py | 23 - .../pip/_vendor/distlib/_backport/__init__.py | 6 - .../pip/_vendor/distlib/_backport/misc.py | 41 - .../pip/_vendor/distlib/_backport/shutil.py | 761 --- .../_vendor/distlib/_backport/sysconfig.cfg | 84 - .../_vendor/distlib/_backport/sysconfig.py | 788 --- .../pip/_vendor/distlib/_backport/tarfile.py | 2607 --------- .../pip/_vendor/distlib/compat.py | 1102 ---- .../pip/_vendor/distlib/database.py | 1305 ----- .../pip/_vendor/distlib/index.py | 513 -- .../pip/_vendor/distlib/locators.py | 1264 ----- .../pip/_vendor/distlib/manifest.py | 367 -- .../pip/_vendor/distlib/markers.py | 190 - .../pip/_vendor/distlib/metadata.py | 1058 ---- .../pip/_vendor/distlib/resources.py | 350 -- .../pip/_vendor/distlib/scripts.py | 365 -- .../site-packages/pip/_vendor/distlib/t32.exe | Bin 89088 -> 0 bytes .../site-packages/pip/_vendor/distlib/t64.exe | Bin 97792 -> 0 bytes .../site-packages/pip/_vendor/distlib/util.py | 1579 ------ .../pip/_vendor/distlib/version.py | 742 --- .../site-packages/pip/_vendor/distlib/w32.exe | Bin 85504 -> 0 bytes .../site-packages/pip/_vendor/distlib/w64.exe | Bin 94208 -> 0 bytes .../pip/_vendor/distlib/wheel.py | 976 ---- .../pip/_vendor/html5lib/__init__.py | 23 - .../pip/_vendor/html5lib/constants.py | 3102 ---------- .../pip/_vendor/html5lib/filters/__init__.py | 0 .../pip/_vendor/html5lib/filters/_base.py | 12 - .../filters/alphabeticalattributes.py | 20 - .../html5lib/filters/inject_meta_charset.py | 65 - .../pip/_vendor/html5lib/filters/lint.py | 90 - .../_vendor/html5lib/filters/optionaltags.py | 205 - .../pip/_vendor/html5lib/filters/sanitizer.py | 12 - .../_vendor/html5lib/filters/whitespace.py | 38 - .../pip/_vendor/html5lib/html5parser.py | 2724 --------- .../pip/_vendor/html5lib/ihatexml.py | 285 - .../pip/_vendor/html5lib/inputstream.py | 903 --- .../pip/_vendor/html5lib/sanitizer.py | 296 - .../_vendor/html5lib/serializer/__init__.py | 16 - .../html5lib/serializer/htmlserializer.py | 317 -- .../pip/_vendor/html5lib/tokenizer.py | 1731 ------ .../_vendor/html5lib/treeadapters/__init__.py | 0 .../pip/_vendor/html5lib/treeadapters/sax.py | 44 - .../_vendor/html5lib/treebuilders/__init__.py | 76 - .../_vendor/html5lib/treebuilders/_base.py | 377 -- .../pip/_vendor/html5lib/treebuilders/dom.py | 227 - .../_vendor/html5lib/treebuilders/etree.py | 337 -- .../html5lib/treebuilders/etree_lxml.py | 369 -- .../_vendor/html5lib/treewalkers/__init__.py | 147 - .../pip/_vendor/html5lib/treewalkers/_base.py | 200 - .../pip/_vendor/html5lib/treewalkers/dom.py | 43 - .../pip/_vendor/html5lib/treewalkers/etree.py | 136 - .../html5lib/treewalkers/genshistream.py | 69 - .../_vendor/html5lib/treewalkers/lxmletree.py | 201 - .../_vendor/html5lib/treewalkers/pulldom.py | 63 - .../pip/_vendor/html5lib/trie/__init__.py | 12 - .../pip/_vendor/html5lib/trie/_base.py | 37 - .../pip/_vendor/html5lib/trie/datrie.py | 44 - .../pip/_vendor/html5lib/trie/py.py | 67 - .../pip/_vendor/html5lib/utils.py | 103 - .../site-packages/pip/_vendor/ipaddress.py | 2411 -------- .../pip/_vendor/lockfile/__init__.py | 326 -- .../pip/_vendor/lockfile/linklockfile.py | 73 - .../pip/_vendor/lockfile/mkdirlockfile.py | 83 - .../pip/_vendor/lockfile/pidlockfile.py | 193 - .../pip/_vendor/lockfile/sqlitelockfile.py | 155 - .../pip/_vendor/lockfile/symlinklockfile.py | 69 - .../pip/_vendor/packaging/__about__.py | 31 - .../pip/_vendor/packaging/__init__.py | 24 - .../pip/_vendor/packaging/_compat.py | 40 - .../pip/_vendor/packaging/_structures.py | 78 - .../pip/_vendor/packaging/specifiers.py | 784 --- .../pip/_vendor/packaging/version.py | 403 -- .../pip/_vendor/pkg_resources/__init__.py | 3107 ---------- .../pip/_vendor/progress/__init__.py | 123 - .../site-packages/pip/_vendor/progress/bar.py | 86 - .../pip/_vendor/progress/counter.py | 49 - .../pip/_vendor/progress/helpers.py | 92 - .../pip/_vendor/progress/spinner.py | 42 - .../site-packages/pip/_vendor/re-vendor.py | 34 - .../pip/_vendor/requests/__init__.py | 77 - .../pip/_vendor/requests/adapters.py | 437 -- .../site-packages/pip/_vendor/requests/api.py | 147 - .../pip/_vendor/requests/auth.py | 212 - .../pip/_vendor/requests/cacert.pem | 5026 ----------------- .../pip/_vendor/requests/certs.py | 25 - .../pip/_vendor/requests/compat.py | 62 - .../pip/_vendor/requests/cookies.py | 479 -- .../pip/_vendor/requests/exceptions.py | 99 - .../pip/_vendor/requests/hooks.py | 45 - .../pip/_vendor/requests/models.py | 859 --- .../pip/_vendor/requests/packages/__init__.py | 3 - .../requests/packages/chardet/__init__.py | 32 - .../requests/packages/chardet/big5freq.py | 925 --- .../requests/packages/chardet/big5prober.py | 42 - .../requests/packages/chardet/chardetect.py | 80 - .../packages/chardet/chardistribution.py | 231 - .../packages/chardet/charsetgroupprober.py | 106 - .../packages/chardet/charsetprober.py | 62 - .../packages/chardet/codingstatemachine.py | 61 - .../requests/packages/chardet/compat.py | 34 - .../requests/packages/chardet/constants.py | 39 - .../requests/packages/chardet/cp949prober.py | 44 - .../requests/packages/chardet/escprober.py | 86 - .../requests/packages/chardet/escsm.py | 242 - .../requests/packages/chardet/eucjpprober.py | 90 - .../requests/packages/chardet/euckrfreq.py | 596 -- .../requests/packages/chardet/euckrprober.py | 42 - .../requests/packages/chardet/euctwfreq.py | 428 -- .../requests/packages/chardet/euctwprober.py | 41 - .../requests/packages/chardet/gb2312freq.py | 472 -- .../requests/packages/chardet/gb2312prober.py | 41 - .../requests/packages/chardet/hebrewprober.py | 283 - .../requests/packages/chardet/jisfreq.py | 569 -- .../requests/packages/chardet/jpcntx.py | 227 - .../packages/chardet/langbulgarianmodel.py | 229 - .../packages/chardet/langcyrillicmodel.py | 329 -- .../packages/chardet/langgreekmodel.py | 225 - .../packages/chardet/langhebrewmodel.py | 201 - .../packages/chardet/langhungarianmodel.py | 225 - .../packages/chardet/langthaimodel.py | 200 - .../requests/packages/chardet/latin1prober.py | 139 - .../packages/chardet/mbcharsetprober.py | 86 - .../packages/chardet/mbcsgroupprober.py | 54 - .../requests/packages/chardet/mbcssm.py | 572 -- .../packages/chardet/sbcharsetprober.py | 120 - .../packages/chardet/sbcsgroupprober.py | 69 - .../requests/packages/chardet/sjisprober.py | 91 - .../packages/chardet/universaldetector.py | 170 - .../requests/packages/chardet/utf8prober.py | 76 - .../requests/packages/urllib3/__init__.py | 69 - .../requests/packages/urllib3/_collections.py | 323 -- .../requests/packages/urllib3/connection.py | 264 - .../packages/urllib3/connectionpool.py | 795 --- .../packages/urllib3/contrib/__init__.py | 0 .../packages/urllib3/contrib/ntlmpool.py | 114 - .../packages/urllib3/contrib/pyopenssl.py | 293 - .../requests/packages/urllib3/exceptions.py | 169 - .../requests/packages/urllib3/fields.py | 177 - .../requests/packages/urllib3/filepost.py | 93 - .../packages/urllib3/packages/__init__.py | 4 - .../packages/urllib3/packages/ordered_dict.py | 259 - .../requests/packages/urllib3/packages/six.py | 385 -- .../packages/ssl_match_hostname/__init__.py | 13 - .../ssl_match_hostname/_implementation.py | 105 - .../requests/packages/urllib3/poolmanager.py | 280 - .../requests/packages/urllib3/request.py | 141 - .../requests/packages/urllib3/response.py | 466 -- .../packages/urllib3/util/__init__.py | 24 - .../packages/urllib3/util/connection.py | 98 - .../requests/packages/urllib3/util/request.py | 71 - .../packages/urllib3/util/response.py | 22 - .../requests/packages/urllib3/util/retry.py | 285 - .../requests/packages/urllib3/util/ssl_.py | 280 - .../requests/packages/urllib3/util/timeout.py | 240 - .../requests/packages/urllib3/util/url.py | 214 - .../pip/_vendor/requests/sessions.py | 677 --- .../pip/_vendor/requests/status_codes.py | 89 - .../pip/_vendor/requests/structures.py | 104 - .../pip/_vendor/requests/utils.py | 707 --- .../site-packages/pip/_vendor/retrying.py | 267 - .../site-packages/pip/_vendor/six.py | 838 --- .../site-packages/pip/basecommand.py | 305 - .../python3.5/site-packages/pip/baseparser.py | 292 - .../python3.5/site-packages/pip/cmdoptions.py | 581 -- .../site-packages/pip/commands/__init__.py | 79 - .../site-packages/pip/commands/completion.py | 68 - .../site-packages/pip/commands/freeze.py | 71 - .../site-packages/pip/commands/help.py | 35 - .../site-packages/pip/commands/install.py | 380 -- .../site-packages/pip/commands/list.py | 202 - .../site-packages/pip/commands/search.py | 139 - .../site-packages/pip/commands/show.py | 130 - .../site-packages/pip/commands/uninstall.py | 76 - .../site-packages/pip/commands/wheel.py | 203 - .../site-packages/pip/compat/__init__.py | 116 - .../site-packages/pip/compat/dictconfig.py | 565 -- .../python3.5/site-packages/pip/download.py | 911 --- .../python3.5/site-packages/pip/exceptions.py | 51 - .../lib/python3.5/site-packages/pip/index.py | 1299 ----- .../python3.5/site-packages/pip/locations.py | 219 - .../site-packages/pip/models/__init__.py | 4 - .../site-packages/pip/models/index.py | 16 - .../site-packages/pip/operations/__init__.py | 0 .../site-packages/pip/operations/freeze.py | 114 - .../python3.5/site-packages/pip/pep425tags.py | 136 - .../site-packages/pip/req/__init__.py | 10 - .../site-packages/pip/req/req_file.py | 282 - .../site-packages/pip/req/req_install.py | 1141 ---- .../site-packages/pip/req/req_set.py | 660 --- .../site-packages/pip/req/req_uninstall.py | 205 - .../site-packages/pip/status_codes.py | 8 - .../site-packages/pip/utils/__init__.py | 865 --- .../site-packages/pip/utils/appdirs.py | 256 - .../site-packages/pip/utils/build.py | 42 - .../site-packages/pip/utils/deprecation.py | 68 - .../site-packages/pip/utils/filesystem.py | 28 - .../site-packages/pip/utils/logging.py | 130 - .../site-packages/pip/utils/outdated.py | 163 - .../python3.5/site-packages/pip/utils/ui.py | 199 - .../site-packages/pip/vcs/__init__.py | 344 -- .../python3.5/site-packages/pip/vcs/bazaar.py | 132 - .../python3.5/site-packages/pip/vcs/git.py | 209 - .../site-packages/pip/vcs/mercurial.py | 139 - .../site-packages/pip/vcs/subversion.py | 291 - .../lib/python3.5/site-packages/pip/wheel.py | 807 --- .../site-packages/pkg_resources/__init__.py | 3113 ---------- .../pkg_resources/_vendor/__init__.py | 0 .../_vendor/packaging/__about__.py | 31 - .../_vendor/packaging/__init__.py | 24 - .../_vendor/packaging/_compat.py | 40 - .../_vendor/packaging/_structures.py | 78 - .../_vendor/packaging/specifiers.py | 784 --- .../_vendor/packaging/version.py | 403 -- .../pycparser-2.14.dist-info/DESCRIPTION.rst | 7 - .../pycparser-2.14.dist-info/METADATA | 19 - .../pycparser-2.14.dist-info/RECORD | 39 - .../pycparser-2.14.dist-info/WHEEL | 5 - .../pycparser-2.14.dist-info/metadata.json | 1 - .../pycparser-2.14.dist-info/top_level.txt | 1 - .../site-packages/pycparser/__init__.py | 93 - .../site-packages/pycparser/_ast_gen.py | 278 - .../site-packages/pycparser/_build_tables.py | 33 - .../site-packages/pycparser/_c_ast.cfg | 189 - .../site-packages/pycparser/ast_transforms.py | 105 - .../site-packages/pycparser/c_ast.py | 797 --- .../site-packages/pycparser/c_generator.py | 399 -- .../site-packages/pycparser/c_lexer.py | 485 -- .../site-packages/pycparser/c_parser.py | 1701 ------ .../site-packages/pycparser/lextab.py | 9 - .../site-packages/pycparser/ply/__init__.py | 4 - .../site-packages/pycparser/ply/cpp.py | 898 --- .../site-packages/pycparser/ply/ctokens.py | 133 - .../site-packages/pycparser/ply/lex.py | 1058 ---- .../site-packages/pycparser/ply/yacc.py | 3276 ----------- .../site-packages/pycparser/plyparser.py | 55 - .../site-packages/pycparser/yacctab.py | 292 - .../DESCRIPTION.rst | 4 - .../python_dateutil-2.4.2.dist-info/METADATA | 28 - .../python_dateutil-2.4.2.dist-info/RECORD | 24 - .../python_dateutil-2.4.2.dist-info/WHEEL | 6 - .../metadata.json | 1 - .../top_level.txt | 1 - .../python_dateutil-2.4.2.dist-info/zip-safe | 1 - .../setuptools-18.2.dist-info/DESCRIPTION.rst | 227 - .../setuptools-18.2.dist-info/METADATA | 258 - .../setuptools-18.2.dist-info/RECORD | 124 - .../setuptools-18.2.dist-info/WHEEL | 6 - .../dependency_links.txt | 2 - .../entry_points.txt | 61 - .../setuptools-18.2.dist-info/metadata.json | 1 - .../setuptools-18.2.dist-info/top_level.txt | 4 - .../setuptools-18.2.dist-info/zip-safe | 1 - .../site-packages/setuptools/__init__.py | 152 - .../site-packages/setuptools/archive_util.py | 170 - .../site-packages/setuptools/cli-32.exe | Bin 65536 -> 0 bytes .../site-packages/setuptools/cli-64.exe | Bin 74752 -> 0 bytes .../site-packages/setuptools/cli-arm-32.exe | Bin 69120 -> 0 bytes .../site-packages/setuptools/cli.exe | Bin 65536 -> 0 bytes .../setuptools/command/__init__.py | 18 - .../site-packages/setuptools/command/alias.py | 78 - .../setuptools/command/bdist_egg.py | 470 -- .../setuptools/command/bdist_rpm.py | 43 - .../setuptools/command/bdist_wininst.py | 21 - .../setuptools/command/build_ext.py | 296 - .../setuptools/command/build_py.py | 215 - .../setuptools/command/develop.py | 169 - .../setuptools/command/easy_install.py | 2267 -------- .../setuptools/command/egg_info.py | 480 -- .../setuptools/command/install.py | 125 - .../setuptools/command/install_egg_info.py | 116 - .../setuptools/command/install_lib.py | 118 - .../setuptools/command/install_scripts.py | 60 - .../setuptools/command/launcher manifest.xml | 15 - .../setuptools/command/register.py | 10 - .../setuptools/command/rotate.py | 61 - .../setuptools/command/saveopts.py | 22 - .../site-packages/setuptools/command/sdist.py | 197 - .../setuptools/command/setopt.py | 150 - .../site-packages/setuptools/command/test.py | 175 - .../setuptools/command/upload_docs.py | 190 - .../site-packages/setuptools/compat.py | 66 - .../site-packages/setuptools/depends.py | 215 - .../site-packages/setuptools/dist.py | 864 --- .../site-packages/setuptools/extension.py | 55 - .../site-packages/setuptools/gui-32.exe | Bin 65536 -> 0 bytes .../site-packages/setuptools/gui-64.exe | Bin 75264 -> 0 bytes .../site-packages/setuptools/gui-arm-32.exe | Bin 69120 -> 0 bytes .../site-packages/setuptools/gui.exe | Bin 65536 -> 0 bytes .../site-packages/setuptools/lib2to3_ex.py | 58 - .../site-packages/setuptools/msvc9_support.py | 63 - .../site-packages/setuptools/package_index.py | 1049 ---- .../site-packages/setuptools/py26compat.py | 19 - .../site-packages/setuptools/py27compat.py | 15 - .../site-packages/setuptools/py31compat.py | 52 - .../site-packages/setuptools/sandbox.py | 489 -- .../setuptools/script (dev).tmpl | 5 - .../site-packages/setuptools/script.tmpl | 3 - .../site-packages/setuptools/site-patch.py | 76 - .../site-packages/setuptools/ssl_support.py | 241 - .../site-packages/setuptools/unicode_utils.py | 41 - .../site-packages/setuptools/utils.py | 11 - .../site-packages/setuptools/version.py | 1 - .../setuptools/windows_support.py | 29 - .../six-1.10.0.dist-info/DESCRIPTION.rst | 18 - .../six-1.10.0.dist-info/METADATA | 34 - .../site-packages/six-1.10.0.dist-info/RECORD | 8 - .../site-packages/six-1.10.0.dist-info/WHEEL | 6 - .../six-1.10.0.dist-info/metadata.json | 1 - .../six-1.10.0.dist-info/top_level.txt | 1 - virtualenv/lib/python3.5/site-packages/six.py | 868 --- .../wheel-0.24.0.dist-info/DESCRIPTION.rst | 275 - .../wheel-0.24.0.dist-info/LICENSE.txt | 22 - .../wheel-0.24.0.dist-info/METADATA | 304 - .../wheel-0.24.0.dist-info/RECORD | 82 - .../wheel-0.24.0.dist-info/RECORD.jws | 1 - .../wheel-0.24.0.dist-info/WHEEL | 6 - .../wheel-0.24.0.dist-info/entry_points.txt | 5 - .../wheel-0.24.0.dist-info/metadata.json | 1 - .../wheel-0.24.0.dist-info/top_level.txt | 1 - .../python3.5/site-packages/wheel/__init__.py | 2 - .../python3.5/site-packages/wheel/__main__.py | 17 - .../python3.5/site-packages/wheel/archive.py | 61 - .../site-packages/wheel/bdist_wheel.py | 446 -- .../site-packages/wheel/decorator.py | 19 - .../site-packages/wheel/egg2wheel.py | 73 - .../site-packages/wheel/eggnames.txt | 87 - .../python3.5/site-packages/wheel/install.py | 480 -- .../python3.5/site-packages/wheel/metadata.py | 304 - .../python3.5/site-packages/wheel/paths.py | 41 - .../site-packages/wheel/pep425tags.py | 97 - .../python3.5/site-packages/wheel/pkginfo.py | 44 - .../wheel/signatures/__init__.py | 106 - .../site-packages/wheel/signatures/djbec.py | 270 - .../wheel/signatures/ed25519py.py | 52 - .../site-packages/wheel/signatures/keys.py | 99 - .../site-packages/wheel/test/__init__.py | 1 - .../test/complex-dist/complexdist/__init__.py | 2 - .../wheel/test/complex-dist/setup.py | 25 - .../wheel/test/headers.dist/header.h | 0 .../wheel/test/headers.dist/headersdist.py | 0 .../wheel/test/headers.dist/setup.py | 16 - .../wheel/test/pydist-schema.json | 362 -- .../wheel/test/simple.dist/setup.py | 17 - .../test/simple.dist/simpledist/__init__.py | 0 .../test/test-1.0-py2.py3-none-win32.whl | Bin 5226 -> 0 bytes .../site-packages/wheel/test/test_basic.py | 176 - .../site-packages/wheel/test/test_install.py | 55 - .../site-packages/wheel/test/test_keys.py | 98 - .../site-packages/wheel/test/test_paths.py | 6 - .../site-packages/wheel/test/test_ranking.py | 43 - .../wheel/test/test_signatures.py | 47 - .../site-packages/wheel/test/test_tagopt.py | 112 - .../site-packages/wheel/test/test_tool.py | 28 - .../wheel/test/test_wheelfile.py | 69 - .../site-packages/wheel/tool/__init__.py | 362 -- .../lib/python3.5/site-packages/wheel/util.py | 146 - .../site-packages/wheel/wininst2wheel.py | 187 - virtualenv/lib/python3.5/site.py | 758 --- virtualenv/lib/python3.5/sre_compile.py | 1 - virtualenv/lib/python3.5/sre_constants.py | 1 - virtualenv/lib/python3.5/sre_parse.py | 1 - virtualenv/lib/python3.5/stat.py | 1 - virtualenv/lib/python3.5/struct.py | 1 - virtualenv/lib/python3.5/tarfile.py | 1 - virtualenv/lib/python3.5/tempfile.py | 1 - virtualenv/lib/python3.5/token.py | 1 - virtualenv/lib/python3.5/tokenize.py | 1 - virtualenv/lib/python3.5/types.py | 1 - virtualenv/lib/python3.5/warnings.py | 1 - virtualenv/lib/python3.5/weakref.py | 1 - virtualenv/pip-selfcheck.json | 1 - 503 files changed, 36 insertions(+), 115473 deletions(-) delete mode 120000 virtualenv/.Python delete mode 100644 virtualenv/bin/activate delete mode 100644 virtualenv/bin/activate.csh delete mode 100644 virtualenv/bin/activate.fish delete mode 100644 virtualenv/bin/activate_this.py delete mode 100755 virtualenv/bin/easy_install delete mode 100755 virtualenv/bin/easy_install-3.5 delete mode 100755 virtualenv/bin/pip delete mode 100755 virtualenv/bin/pip3 delete mode 100755 virtualenv/bin/pip3.5 delete mode 120000 virtualenv/bin/python delete mode 120000 virtualenv/bin/python3 delete mode 100755 virtualenv/bin/python3.5 delete mode 100755 virtualenv/bin/wheel delete mode 120000 virtualenv/include/python3.5m delete mode 120000 virtualenv/lib/python3.5/__future__.py delete mode 120000 virtualenv/lib/python3.5/_bootlocale.py delete mode 120000 virtualenv/lib/python3.5/_collections_abc.py delete mode 120000 virtualenv/lib/python3.5/_dummy_thread.py delete mode 120000 virtualenv/lib/python3.5/_weakrefset.py delete mode 120000 virtualenv/lib/python3.5/abc.py delete mode 120000 virtualenv/lib/python3.5/base64.py delete mode 120000 virtualenv/lib/python3.5/bisect.py delete mode 120000 virtualenv/lib/python3.5/codecs.py delete mode 120000 virtualenv/lib/python3.5/collections delete mode 120000 virtualenv/lib/python3.5/config-3.5m delete mode 120000 virtualenv/lib/python3.5/copy.py delete mode 120000 virtualenv/lib/python3.5/copyreg.py delete mode 100644 virtualenv/lib/python3.5/distutils/__init__.py delete mode 100644 virtualenv/lib/python3.5/distutils/distutils.cfg delete mode 120000 virtualenv/lib/python3.5/encodings delete mode 120000 virtualenv/lib/python3.5/fnmatch.py delete mode 120000 virtualenv/lib/python3.5/functools.py delete mode 120000 virtualenv/lib/python3.5/genericpath.py delete mode 120000 virtualenv/lib/python3.5/hashlib.py delete mode 120000 virtualenv/lib/python3.5/heapq.py delete mode 120000 virtualenv/lib/python3.5/hmac.py delete mode 120000 virtualenv/lib/python3.5/imp.py delete mode 120000 virtualenv/lib/python3.5/importlib delete mode 120000 virtualenv/lib/python3.5/io.py delete mode 120000 virtualenv/lib/python3.5/keyword.py delete mode 120000 virtualenv/lib/python3.5/lib-dynload delete mode 120000 virtualenv/lib/python3.5/linecache.py delete mode 120000 virtualenv/lib/python3.5/locale.py delete mode 100644 virtualenv/lib/python3.5/no-global-site-packages.txt delete mode 120000 virtualenv/lib/python3.5/ntpath.py delete mode 120000 virtualenv/lib/python3.5/operator.py delete mode 100644 virtualenv/lib/python3.5/orig-prefix.txt delete mode 120000 virtualenv/lib/python3.5/os.py delete mode 120000 virtualenv/lib/python3.5/plat-darwin delete mode 120000 virtualenv/lib/python3.5/posixpath.py delete mode 120000 virtualenv/lib/python3.5/random.py delete mode 120000 virtualenv/lib/python3.5/re.py delete mode 120000 virtualenv/lib/python3.5/readline.so delete mode 120000 virtualenv/lib/python3.5/reprlib.py delete mode 120000 virtualenv/lib/python3.5/rlcompleter.py delete mode 120000 virtualenv/lib/python3.5/shutil.py delete mode 100644 virtualenv/lib/python3.5/site-packages/_markerlib/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/_markerlib/markers.py delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/PKG-INFO delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/SOURCES.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/dependency_links.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/entry_points.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/native_libs.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/not-zip-safe delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/requires.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/top_level.txt delete mode 100755 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/_cffi_backend.cpython-35m-darwin.so delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/_cffi_backend.py delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/_cffi_include.h delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/api.py delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/backend_ctypes.py delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/cffi_opcode.py delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/commontypes.py delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/cparser.py delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/ffiplatform.py delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/gc_weakref.py delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/lock.py delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/model.py delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/parse_c_type.h delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/recompiler.py delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/setuptools_ext.py delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/vengine_cpy.py delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/vengine_gen.py delete mode 100644 virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/verifier.py delete mode 100644 virtualenv/lib/python3.5/site-packages/dateutil/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/dateutil/easter.py delete mode 100644 virtualenv/lib/python3.5/site-packages/dateutil/parser.py delete mode 100644 virtualenv/lib/python3.5/site-packages/dateutil/relativedelta.py delete mode 100644 virtualenv/lib/python3.5/site-packages/dateutil/rrule.py delete mode 100644 virtualenv/lib/python3.5/site-packages/dateutil/tz.py delete mode 100644 virtualenv/lib/python3.5/site-packages/dateutil/tzwin.py delete mode 100644 virtualenv/lib/python3.5/site-packages/dateutil/zoneinfo/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz delete mode 100644 virtualenv/lib/python3.5/site-packages/easy-install.pth delete mode 100644 virtualenv/lib/python3.5/site-packages/easy_install.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/DESCRIPTION.rst delete mode 100644 virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/METADATA delete mode 100644 virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/RECORD delete mode 100644 virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/WHEEL delete mode 100644 virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/entry_points.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/metadata.json delete mode 100644 virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/pbr.json delete mode 100644 virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/top_level.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/__main__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/_markerlib/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/_markerlib/markers.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/adapter.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/cache.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/caches/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/compat.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/controller.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/filewrapper.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/heuristics.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/serialize.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/wrapper.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/ansi.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/ansitowin32.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/initialise.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/win32.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/winterm.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/misc.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/shutil.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/sysconfig.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/tarfile.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/compat.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/database.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/index.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/locators.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/manifest.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/markers.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/metadata.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/resources.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/scripts.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/t32.exe delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/t64.exe delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/util.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/version.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/w32.exe delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/w64.exe delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/wheel.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/constants.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/_base.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/lint.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/optionaltags.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/sanitizer.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/whitespace.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/html5parser.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/ihatexml.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/inputstream.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/sanitizer.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/serializer/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/serializer/htmlserializer.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/tokenizer.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/treeadapters/sax.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/treebuilders/_base.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/treebuilders/dom.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/treebuilders/etree.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/treewalkers/_base.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/treewalkers/dom.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/treewalkers/etree.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/treewalkers/genshistream.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/treewalkers/lxmletree.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/treewalkers/pulldom.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/trie/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/trie/_base.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/trie/datrie.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/trie/py.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/utils.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/ipaddress.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/lockfile/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/lockfile/linklockfile.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/lockfile/mkdirlockfile.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/lockfile/pidlockfile.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/lockfile/sqlitelockfile.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/lockfile/symlinklockfile.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/packaging/__about__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/packaging/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/packaging/_compat.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/packaging/_structures.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/packaging/specifiers.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/packaging/version.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/pkg_resources/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/progress/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/progress/bar.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/progress/counter.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/progress/helpers.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/progress/spinner.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/re-vendor.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/adapters.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/api.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/auth.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/cacert.pem delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/certs.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/compat.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/cookies.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/exceptions.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/hooks.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/models.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/big5freq.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/big5prober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/chardetect.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/chardistribution.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/charsetgroupprober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/charsetprober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/codingstatemachine.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/compat.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/constants.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/cp949prober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/escprober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/escsm.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/eucjpprober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/euckrfreq.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/euckrprober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/euctwfreq.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/euctwprober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/gb2312freq.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/gb2312prober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/hebrewprober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/jisfreq.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/jpcntx.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/langbulgarianmodel.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/langcyrillicmodel.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/langgreekmodel.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/langhebrewmodel.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/langhungarianmodel.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/langthaimodel.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/latin1prober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/mbcharsetprober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/mbcsgroupprober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/mbcssm.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/sbcharsetprober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/sbcsgroupprober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/sjisprober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/universaldetector.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/chardet/utf8prober.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/_collections.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/connection.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/connectionpool.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/contrib/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/contrib/ntlmpool.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/contrib/pyopenssl.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/exceptions.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/fields.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/filepost.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/packages/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/packages/ordered_dict.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/packages/six.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/poolmanager.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/request.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/response.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/util/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/util/connection.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/util/request.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/util/response.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/util/retry.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/util/timeout.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/packages/urllib3/util/url.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/sessions.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/status_codes.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/structures.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/requests/utils.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/retrying.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/_vendor/six.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/basecommand.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/baseparser.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/cmdoptions.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/commands/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/commands/completion.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/commands/freeze.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/commands/help.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/commands/install.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/commands/list.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/commands/search.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/commands/show.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/commands/uninstall.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/commands/wheel.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/compat/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/compat/dictconfig.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/download.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/exceptions.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/index.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/locations.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/models/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/models/index.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/operations/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/operations/freeze.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/pep425tags.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/req/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/req/req_file.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/req/req_install.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/req/req_set.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/req/req_uninstall.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/status_codes.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/utils/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/utils/appdirs.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/utils/build.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/utils/deprecation.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/utils/filesystem.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/utils/logging.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/utils/outdated.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/utils/ui.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/vcs/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/vcs/bazaar.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/vcs/git.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/vcs/mercurial.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/vcs/subversion.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pip/wheel.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pkg_resources/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pkg_resources/_vendor/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pkg_resources/_vendor/packaging/__about__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pkg_resources/_vendor/packaging/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pkg_resources/_vendor/packaging/_compat.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pkg_resources/_vendor/packaging/_structures.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pkg_resources/_vendor/packaging/specifiers.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pkg_resources/_vendor/packaging/version.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser-2.14.dist-info/DESCRIPTION.rst delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser-2.14.dist-info/METADATA delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser-2.14.dist-info/RECORD delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser-2.14.dist-info/WHEEL delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser-2.14.dist-info/metadata.json delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser-2.14.dist-info/top_level.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/_ast_gen.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/_build_tables.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/_c_ast.cfg delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/ast_transforms.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/c_ast.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/c_generator.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/c_lexer.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/c_parser.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/lextab.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/ply/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/ply/cpp.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/ply/ctokens.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/ply/lex.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/ply/yacc.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/plyparser.py delete mode 100644 virtualenv/lib/python3.5/site-packages/pycparser/yacctab.py delete mode 100644 virtualenv/lib/python3.5/site-packages/python_dateutil-2.4.2.dist-info/DESCRIPTION.rst delete mode 100644 virtualenv/lib/python3.5/site-packages/python_dateutil-2.4.2.dist-info/METADATA delete mode 100644 virtualenv/lib/python3.5/site-packages/python_dateutil-2.4.2.dist-info/RECORD delete mode 100644 virtualenv/lib/python3.5/site-packages/python_dateutil-2.4.2.dist-info/WHEEL delete mode 100644 virtualenv/lib/python3.5/site-packages/python_dateutil-2.4.2.dist-info/metadata.json delete mode 100644 virtualenv/lib/python3.5/site-packages/python_dateutil-2.4.2.dist-info/top_level.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/python_dateutil-2.4.2.dist-info/zip-safe delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools-18.2.dist-info/DESCRIPTION.rst delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools-18.2.dist-info/METADATA delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools-18.2.dist-info/RECORD delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools-18.2.dist-info/WHEEL delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools-18.2.dist-info/dependency_links.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools-18.2.dist-info/entry_points.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools-18.2.dist-info/metadata.json delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools-18.2.dist-info/top_level.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools-18.2.dist-info/zip-safe delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/archive_util.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/cli-32.exe delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/cli-64.exe delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/cli-arm-32.exe delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/cli.exe delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/alias.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/bdist_egg.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/bdist_rpm.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/bdist_wininst.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/build_ext.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/build_py.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/develop.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/easy_install.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/egg_info.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/install.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/install_egg_info.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/install_lib.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/install_scripts.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/launcher manifest.xml delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/register.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/rotate.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/saveopts.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/sdist.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/setopt.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/test.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/command/upload_docs.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/compat.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/depends.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/dist.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/extension.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/gui-32.exe delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/gui-64.exe delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/gui-arm-32.exe delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/gui.exe delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/lib2to3_ex.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/msvc9_support.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/package_index.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/py26compat.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/py27compat.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/py31compat.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/sandbox.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/script (dev).tmpl delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/script.tmpl delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/site-patch.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/ssl_support.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/unicode_utils.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/utils.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/version.py delete mode 100644 virtualenv/lib/python3.5/site-packages/setuptools/windows_support.py delete mode 100644 virtualenv/lib/python3.5/site-packages/six-1.10.0.dist-info/DESCRIPTION.rst delete mode 100644 virtualenv/lib/python3.5/site-packages/six-1.10.0.dist-info/METADATA delete mode 100644 virtualenv/lib/python3.5/site-packages/six-1.10.0.dist-info/RECORD delete mode 100644 virtualenv/lib/python3.5/site-packages/six-1.10.0.dist-info/WHEEL delete mode 100644 virtualenv/lib/python3.5/site-packages/six-1.10.0.dist-info/metadata.json delete mode 100644 virtualenv/lib/python3.5/site-packages/six-1.10.0.dist-info/top_level.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/six.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel-0.24.0.dist-info/DESCRIPTION.rst delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel-0.24.0.dist-info/LICENSE.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel-0.24.0.dist-info/METADATA delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel-0.24.0.dist-info/RECORD delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel-0.24.0.dist-info/RECORD.jws delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel-0.24.0.dist-info/WHEEL delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel-0.24.0.dist-info/entry_points.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel-0.24.0.dist-info/metadata.json delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel-0.24.0.dist-info/top_level.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/__main__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/archive.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/bdist_wheel.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/decorator.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/egg2wheel.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/eggnames.txt delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/install.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/metadata.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/paths.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/pep425tags.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/pkginfo.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/signatures/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/signatures/djbec.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/signatures/ed25519py.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/signatures/keys.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/complex-dist/complexdist/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/complex-dist/setup.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/headers.dist/header.h delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/headers.dist/headersdist.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/headers.dist/setup.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/pydist-schema.json delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/simple.dist/setup.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/simple.dist/simpledist/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/test-1.0-py2.py3-none-win32.whl delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/test_basic.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/test_install.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/test_keys.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/test_paths.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/test_ranking.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/test_signatures.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/test_tagopt.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/test_tool.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/test/test_wheelfile.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/tool/__init__.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/util.py delete mode 100644 virtualenv/lib/python3.5/site-packages/wheel/wininst2wheel.py delete mode 100644 virtualenv/lib/python3.5/site.py delete mode 120000 virtualenv/lib/python3.5/sre_compile.py delete mode 120000 virtualenv/lib/python3.5/sre_constants.py delete mode 120000 virtualenv/lib/python3.5/sre_parse.py delete mode 120000 virtualenv/lib/python3.5/stat.py delete mode 120000 virtualenv/lib/python3.5/struct.py delete mode 120000 virtualenv/lib/python3.5/tarfile.py delete mode 120000 virtualenv/lib/python3.5/tempfile.py delete mode 120000 virtualenv/lib/python3.5/token.py delete mode 120000 virtualenv/lib/python3.5/tokenize.py delete mode 120000 virtualenv/lib/python3.5/types.py delete mode 120000 virtualenv/lib/python3.5/warnings.py delete mode 120000 virtualenv/lib/python3.5/weakref.py delete mode 100644 virtualenv/pip-selfcheck.json diff --git a/.gitignore b/.gitignore index 788b915..bae02c5 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ package.sh testMain.c dist *.egg-info +virtualenv diff --git a/README b/README index 192c53e..5d6012d 100644 --- a/README +++ b/README @@ -1,4 +1,13 @@ p4d is a Python Database API 2.0 compliant driver for the 4D (4th Dimension) database server. As such, usage should be familiar to anyone who has used any python database modules before. This module is based off of a C library provided by 4D, and integrated with Python using CFFI. As such, installation of this module does require CFFI. +v0.9 2016-02-10: + - Fix bug that called .decode() on a str object in python 3 + - Add support for "pyformat" style parameter markers + - Add support for "format" style parameter markers + - Add support for "named" style parameter markers + +v0.8 2015-11-24: + - Changes for python 3 compatibility + v0.7 2015-09-30: - Fix bug with running multiple queries in a row on the same cursor diff --git a/p4d/p4d.py b/p4d/p4d.py index 68e8aa1..1e0c089 100644 --- a/p4d/p4d.py +++ b/p4d/p4d.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import,unicode_literals - import os, sys, binascii from cffi import FFI from cffi.verifier import Verifier @@ -7,7 +5,7 @@ from datetime import datetime, timedelta, time, date from collections import defaultdict import time as timemod -import threading, glob +import threading, glob, re ######################################################################## @@ -244,6 +242,28 @@ def execute(self, query, params=[], describe=True): if self.connection.connected == False: raise InternalError("Database not connected") + # See if we are using named parameters. If so, break them out (we always need qmark style in the end) + if isinstance(params, dict): + new_params = [] + # Parse query string for references to dict entries + regex = re.compile('%\(([^\)]+)\)s') + for key in re.findall(regex, query): + new_params.append(params[key]) # Will raise key error if the query string argument is not in params. + + if not new_params: + # We didn't match anything in the query string for the %()s format markers. Try named (:name) instead + regex = re.compile(':([A-Za-z0-9]+)') + for key in re.findall(regex, query): + new_params.append(params[key]) + + query = re.sub(regex, '?', query) + params = new_params + + # If using "format" parameter markers, just convert all % markers to ?'s + query = re.sub('%[A-Za-z]', '?', query) + query.replace('%%', '%') # Replace double-quotes with single quote + + # if any parameter is a tuple, we need to modify the query string and # make multiple passes through the parameters, breaking out one tuple/list # each time. @@ -443,7 +463,7 @@ def fetchone(self): self.lib4d_sql.fourd_field_to_string(self.result, col, inbuff, strlen) strdata = inbuff[0] - output = str(ffi.buffer(strdata, strlen[0])[:]) + output = ffi.buffer(strdata, strlen[0])[:] if strdata != ffi.NULL: self.lib4d_sql.free(strdata) #must call free explicitly, otherwise we leak. strdata = ffi.NULL diff --git a/setup.py b/setup.py index 423c881..7bbc101 100755 --- a/setup.py +++ b/setup.py @@ -26,9 +26,9 @@ def finalize_options(self): setup( zip_safe=False, name="p4d", - version="0.7", + version="0.9", install_requires=["cffi", ], - setup_requires=['cffi', ], + setup_requires=['cffi', 'python-dateutil' ], packages=find_packages(), # need to include these files to be able to build our shared library package_data={'p4d': ['py_fourd.h'],}, @@ -51,5 +51,4 @@ def finalize_options(self): 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 2'], keywords='datababase drivers DBI 4d' - ) diff --git a/virtualenv/.Python b/virtualenv/.Python deleted file mode 120000 index 34214c3..0000000 --- a/virtualenv/.Python +++ /dev/null @@ -1 +0,0 @@ -/Library/Frameworks/Python.framework/Versions/3.5/Python \ No newline at end of file diff --git a/virtualenv/bin/activate b/virtualenv/bin/activate deleted file mode 100644 index 569af5d..0000000 --- a/virtualenv/bin/activate +++ /dev/null @@ -1,80 +0,0 @@ -# This file must be used with "source bin/activate" *from bash* -# you cannot run it directly - -deactivate () { - unset pydoc - - # reset old environment variables - if [ -n "${_OLD_VIRTUAL_PATH-}" ] ; then - PATH="$_OLD_VIRTUAL_PATH" - export PATH - unset _OLD_VIRTUAL_PATH - fi - if [ -n "${_OLD_VIRTUAL_PYTHONHOME-}" ] ; then - PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME" - export PYTHONHOME - unset _OLD_VIRTUAL_PYTHONHOME - fi - - # This should detect bash and zsh, which have a hash command that must - # be called to get it to forget past commands. Without forgetting - # past commands the $PATH changes we made may not be respected - if [ -n "${BASH-}" -o -n "${ZSH_VERSION-}" ] ; then - hash -r 2>/dev/null - fi - - if [ -n "${_OLD_VIRTUAL_PS1-}" ] ; then - PS1="$_OLD_VIRTUAL_PS1" - export PS1 - unset _OLD_VIRTUAL_PS1 - fi - - unset VIRTUAL_ENV - if [ ! "${1-}" = "nondestructive" ] ; then - # Self destruct! - unset -f deactivate - fi -} - -# unset irrelevant variables -deactivate nondestructive - -VIRTUAL_ENV="/Volumes/Internal10/Development/p4d/virtualenv" -export VIRTUAL_ENV - -_OLD_VIRTUAL_PATH="$PATH" -PATH="$VIRTUAL_ENV/bin:$PATH" -export PATH - -# unset PYTHONHOME if set -# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) -# could use `if (set -u; : $PYTHONHOME) ;` in bash -if [ -n "${PYTHONHOME-}" ] ; then - _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME" - unset PYTHONHOME -fi - -if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then - _OLD_VIRTUAL_PS1="$PS1" - if [ "x" != x ] ; then - PS1="$PS1" - else - if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then - # special case for Aspen magic directories - # see http://www.zetadev.com/software/aspen/ - PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1" - else - PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1" - fi - fi - export PS1 -fi - -alias pydoc="python -m pydoc" - -# This should detect bash and zsh, which have a hash command that must -# be called to get it to forget past commands. Without forgetting -# past commands the $PATH changes we made may not be respected -if [ -n "${BASH-}" -o -n "${ZSH_VERSION-}" ] ; then - hash -r 2>/dev/null -fi diff --git a/virtualenv/bin/activate.csh b/virtualenv/bin/activate.csh deleted file mode 100644 index 1363eed..0000000 --- a/virtualenv/bin/activate.csh +++ /dev/null @@ -1,42 +0,0 @@ -# This file must be used with "source bin/activate.csh" *from csh*. -# You cannot run it directly. -# Created by Davide Di Blasi . - -alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate && unalias pydoc' - -# Unset irrelevant variables. -deactivate nondestructive - -setenv VIRTUAL_ENV "/Volumes/Internal10/Development/p4d/virtualenv" - -set _OLD_VIRTUAL_PATH="$PATH" -setenv PATH "$VIRTUAL_ENV/bin:$PATH" - - - -if ("" != "") then - set env_name = "" -else - if (`basename "$VIRTUAL_ENV"` == "__") then - # special case for Aspen magic directories - # see http://www.zetadev.com/software/aspen/ - set env_name = `basename \`dirname "$VIRTUAL_ENV"\`` - else - set env_name = `basename "$VIRTUAL_ENV"` - endif -endif - -# Could be in a non-interactive environment, -# in which case, $prompt is undefined and we wouldn't -# care about the prompt anyway. -if ( $?prompt ) then - set _OLD_VIRTUAL_PROMPT="$prompt" - set prompt = "[$env_name] $prompt" -endif - -unset env_name - -alias pydoc python -m pydoc - -rehash - diff --git a/virtualenv/bin/activate.fish b/virtualenv/bin/activate.fish deleted file mode 100644 index 452e691..0000000 --- a/virtualenv/bin/activate.fish +++ /dev/null @@ -1,74 +0,0 @@ -# This file must be used with "source bin/activate.fish" *from fish* (http://fishshell.com) -# you cannot run it directly - -function deactivate -d "Exit virtualenv and return to normal shell environment" - # reset old environment variables - if test -n "$_OLD_VIRTUAL_PATH" - set -gx PATH $_OLD_VIRTUAL_PATH - set -e _OLD_VIRTUAL_PATH - end - if test -n "$_OLD_VIRTUAL_PYTHONHOME" - set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME - set -e _OLD_VIRTUAL_PYTHONHOME - end - - if test -n "$_OLD_FISH_PROMPT_OVERRIDE" - # set an empty local fish_function_path, so fish_prompt doesn't automatically reload - set -l fish_function_path - # erase the virtualenv's fish_prompt function, and restore the original - functions -e fish_prompt - functions -c _old_fish_prompt fish_prompt - functions -e _old_fish_prompt - set -e _OLD_FISH_PROMPT_OVERRIDE - end - - set -e VIRTUAL_ENV - if test "$argv[1]" != "nondestructive" - # Self destruct! - functions -e deactivate - end -end - -# unset irrelevant variables -deactivate nondestructive - -set -gx VIRTUAL_ENV "/Volumes/Internal10/Development/p4d/virtualenv" - -set -gx _OLD_VIRTUAL_PATH $PATH -set -gx PATH "$VIRTUAL_ENV/bin" $PATH - -# unset PYTHONHOME if set -if set -q PYTHONHOME - set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME - set -e PYTHONHOME -end - -if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" - # fish uses a function instead of an env var to generate the prompt. - - # copy the current fish_prompt function as the function _old_fish_prompt - functions -c fish_prompt _old_fish_prompt - - # with the original prompt function copied, we can override with our own. - function fish_prompt - # Prompt override? - if test -n "" - printf "%s%s" "" (set_color normal) - _old_fish_prompt - return - end - # ...Otherwise, prepend env - set -l _checkbase (basename "$VIRTUAL_ENV") - if test $_checkbase = "__" - # special case for Aspen magic directories - # see http://www.zetadev.com/software/aspen/ - printf "%s[%s]%s " (set_color -b blue white) (basename (dirname "$VIRTUAL_ENV")) (set_color normal) - _old_fish_prompt - else - printf "%s(%s)%s" (set_color -b blue white) (basename "$VIRTUAL_ENV") (set_color normal) - _old_fish_prompt - end - end - - set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" -end diff --git a/virtualenv/bin/activate_this.py b/virtualenv/bin/activate_this.py deleted file mode 100644 index f18193b..0000000 --- a/virtualenv/bin/activate_this.py +++ /dev/null @@ -1,34 +0,0 @@ -"""By using execfile(this_file, dict(__file__=this_file)) you will -activate this virtualenv environment. - -This can be used when you must use an existing Python interpreter, not -the virtualenv bin/python -""" - -try: - __file__ -except NameError: - raise AssertionError( - "You must run this like execfile('path/to/activate_this.py', dict(__file__='path/to/activate_this.py'))") -import sys -import os - -old_os_path = os.environ.get('PATH', '') -os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + os.pathsep + old_os_path -base = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -if sys.platform == 'win32': - site_packages = os.path.join(base, 'Lib', 'site-packages') -else: - site_packages = os.path.join(base, 'lib', 'python%s' % sys.version[:3], 'site-packages') -prev_sys_path = list(sys.path) -import site -site.addsitedir(site_packages) -sys.real_prefix = sys.prefix -sys.prefix = base -# Move the added items to the front of the path: -new_sys_path = [] -for item in list(sys.path): - if item not in prev_sys_path: - new_sys_path.append(item) - sys.path.remove(item) -sys.path[:0] = new_sys_path diff --git a/virtualenv/bin/easy_install b/virtualenv/bin/easy_install deleted file mode 100755 index f4788c0..0000000 --- a/virtualenv/bin/easy_install +++ /dev/null @@ -1,11 +0,0 @@ -#!/Volumes/Internal10/Development/p4d/virtualenv/bin/python3.5 - -# -*- coding: utf-8 -*- -import re -import sys - -from setuptools.command.easy_install import main - -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/virtualenv/bin/easy_install-3.5 b/virtualenv/bin/easy_install-3.5 deleted file mode 100755 index f4788c0..0000000 --- a/virtualenv/bin/easy_install-3.5 +++ /dev/null @@ -1,11 +0,0 @@ -#!/Volumes/Internal10/Development/p4d/virtualenv/bin/python3.5 - -# -*- coding: utf-8 -*- -import re -import sys - -from setuptools.command.easy_install import main - -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/virtualenv/bin/pip b/virtualenv/bin/pip deleted file mode 100755 index 69d384f..0000000 --- a/virtualenv/bin/pip +++ /dev/null @@ -1,11 +0,0 @@ -#!/Volumes/Internal10/Development/p4d/virtualenv/bin/python3.5 - -# -*- coding: utf-8 -*- -import re -import sys - -from pip import main - -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/virtualenv/bin/pip3 b/virtualenv/bin/pip3 deleted file mode 100755 index 69d384f..0000000 --- a/virtualenv/bin/pip3 +++ /dev/null @@ -1,11 +0,0 @@ -#!/Volumes/Internal10/Development/p4d/virtualenv/bin/python3.5 - -# -*- coding: utf-8 -*- -import re -import sys - -from pip import main - -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/virtualenv/bin/pip3.5 b/virtualenv/bin/pip3.5 deleted file mode 100755 index 69d384f..0000000 --- a/virtualenv/bin/pip3.5 +++ /dev/null @@ -1,11 +0,0 @@ -#!/Volumes/Internal10/Development/p4d/virtualenv/bin/python3.5 - -# -*- coding: utf-8 -*- -import re -import sys - -from pip import main - -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/virtualenv/bin/python b/virtualenv/bin/python deleted file mode 120000 index f549cea..0000000 --- a/virtualenv/bin/python +++ /dev/null @@ -1 +0,0 @@ -python3.5 \ No newline at end of file diff --git a/virtualenv/bin/python3 b/virtualenv/bin/python3 deleted file mode 120000 index f549cea..0000000 --- a/virtualenv/bin/python3 +++ /dev/null @@ -1 +0,0 @@ -python3.5 \ No newline at end of file diff --git a/virtualenv/bin/python3.5 b/virtualenv/bin/python3.5 deleted file mode 100755 index 61d22e5db2355dd9f068eec0df84add4f2eeea96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25384 zcmeHO4Qw366`o5j$&s4aqM;3KfF+#4La8qX2PGj$cZttk3nz6GJ6H{{ob7Y$)V{OU zcO*ukSUo$*_PF4Ribg4-6jcSaQXA1qM5s;kN1W2%v}%P!1!?P`3kfYn5PsTn{l3{< z-}>ytkwR43&QspZdv9jm%zQf+&(6Mi;e+S)3n6BJ=YVGlQGsmHyGY7>unkIE80z&^ zw1E{V1QY@a0fm4IOCWt+pw|G74PYbn^X8$1s|QTuY!*WG+{33#Fp+v zhtZwrOrlchIQGJa4*OpCn1F}JA)kdVpG94yIpQhMAiK}Qc@{YQ8TVrteP(i#8S6Ff zi<$lGdvg2vbceQH>}YbyFcQGfhO#eZPVzBdvk#Q!m-rxlmpM)hqbGJg9~yiFQCBPR z!L{WcRvAV|EERJcA}gIson}K(SK_1C!uwljS=-RMzB#h`4!8KH5PSkYNbYaR*1YW+ z8`jw0@vJ74Ho- zcDI=^b0AcY&BNJ$;IWj}me(*2&D+8<{f|*}MJL!eDMqz-kQoGlzW#|1!h( zbL*~PAUiX2*gt$A{SK6}JU1fn4n{H^WwK zFkgc@)+nVLDMe2V7s`iTK;iI#@}Wb>N9%%e<2>r;9#Z6QVl_CQE31#O+Baa&W!}Ty z#X@Dbq7N0&7b@)fAu80IJ^hK!@@wm0Y&l{1pQ*ns9Vj1q4<&97*_N`b{~7vzlCJ#E zVnV;mM#pFwf+bh)ga1G-^S;wlHnSGHjjSBb4%qgCh4n_}$l{In7(Y8)e(ex+RB)@+ z1T6?m$H?_r?<`?fS~@xuQ_1X##0brrco{Di_OiiA-x{ zx=f}kWg14>wLpq|nHlMNObBu6wL+oLHB9LQB?#iwA1K{N=@*nXQ#wRx9i@GgR#W;u zC2qV=eVfu^N_!w7mxMy)5Kssx1QY@a0fm47ne>Uzn+r$6{Fo=dd>d`}_Kc6$=6oCunc5X$qiJAGyw_M4+fr}F z<6=aZL9cO5tfwd0PIHws8+G#3r7_ta>yfn=+vYW~?gVQsfm(FAK4o^K`)IGlnBrTz zQo8Y@LQ8M0sa;xoGv=pAA)pXY z2q**;0tx|zfI>hapb$_9{J$aaYdij*FO`FQ=VSax055*~)-$mW`RhCb8N1zEoyYx4klL1lZJMTDo;_GRf5bIwvd3+lH z2>mhMpXBPc2CO_W|Flha|6s)N*X%f;E??*!-5Iu{$?=`{9>JL7j{zkl>JwJ#vr;GE-&cNsFA+Ab)4zE3;;nw)mjz4Jvl*S%hsTqip*fYKO!o}+MF z%q5lNTqpGFj&<7m3y!}k+ne;ub#^YA?k+=>Almy^6Bn1gdKnU?UAT^ z{c*mGPj_j$I}SS?f11;Py7xJ_e%!qHyPtI5VPoMzSxY_+p}8&W+-8q^MbKT& z^SB5X_WzT_VmjhHyTHVjm|e=d7p>lYK7_j$94^Pd%_aF*$`=oG_Th)XR0FBzjQ0TFOrM;^xb-H;qx4#ZoQI!98DUmqZA*J;^>;;v*knl z2&Xe}|49fnXKM=iZ=zI39}mhrdQ6rMv085FW3ZvhHe}J^*UNW(2j*zaSj|hPud?I$ z8!Z1Tk-`zZa5%dBO!?3+*(@8~r)O8bSaUY7p&e?x443KOW5&nwGhm72nu9(#4@1_o zvkv0#q@GG=M7E;osi0g06UA+eGBkK#5w<90n%*3fz$0P0kNa+#U zeoJYX(lJVlDeb4Un$nLb$$0(mQj#(JPf(I^{f|Pj_mhmr=X5kMNdwEh5)}~lA7nR1 zpE9?>Wk?sumKY=g_W7=Pymb~`iTO-GzWdh+-_{CWMcJId2uc{=&;E}66WxQ3%Gxl< z8zA#4w$Jd>_2skuycL|8^U&- z$rs}Nj`|HwzQoB_IC-6uU*Y5dC!fN#GARTU0tx|zfI>hapb$_9Cz# zAt8Xsd2jrG)fDmnBkalydqe%*_Z@^N', '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/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/PKG-INFO b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/PKG-INFO deleted file mode 100644 index 7928030..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/PKG-INFO +++ /dev/null @@ -1,31 +0,0 @@ -Metadata-Version: 1.1 -Name: cffi -Version: 1.3.1 -Summary: Foreign Function Interface for Python calling C code. -Home-page: http://cffi.readthedocs.org -Author: Armin Rigo, Maciej Fijalkowski -Author-email: python-cffi@googlegroups.com -License: MIT -Description: - CFFI - ==== - - Foreign Function Interface for Python calling C code. - Please see the `Documentation `_. - - Contact - ------- - - `Mailing list `_ - -Platform: UNKNOWN -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.2 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/SOURCES.txt b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/SOURCES.txt deleted file mode 100644 index fc8fe02..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/SOURCES.txt +++ /dev/null @@ -1,147 +0,0 @@ -AUTHORS -LICENSE -MANIFEST.in -setup.cfg -setup.py -setup_base.py -c/_cffi_backend.c -c/cdlopen.c -c/cffi1_module.c -c/cglob.c -c/commontypes.c -c/ffi_obj.c -c/file_emulator.h -c/lib_obj.c -c/malloc_closure.h -c/minibuffer.h -c/misc_thread.h -c/misc_win32.h -c/parse_c_type.c -c/realize_c_type.c -c/test_c.py -c/wchar_helper.h -c/libffi_msvc/ffi.c -c/libffi_msvc/ffi.h -c/libffi_msvc/ffi_common.h -c/libffi_msvc/fficonfig.h -c/libffi_msvc/ffitarget.h -c/libffi_msvc/prep_cif.c -c/libffi_msvc/types.c -c/libffi_msvc/win32.c -c/libffi_msvc/win64.asm -c/libffi_msvc/win64.obj -cffi/__init__.py -cffi/_cffi_include.h -cffi/api.py -cffi/backend_ctypes.py -cffi/cffi_opcode.py -cffi/commontypes.py -cffi/cparser.py -cffi/ffiplatform.py -cffi/gc_weakref.py -cffi/lock.py -cffi/model.py -cffi/parse_c_type.h -cffi/recompiler.py -cffi/setuptools_ext.py -cffi/vengine_cpy.py -cffi/vengine_gen.py -cffi/verifier.py -cffi.egg-info/PKG-INFO -cffi.egg-info/SOURCES.txt -cffi.egg-info/dependency_links.txt -cffi.egg-info/entry_points.txt -cffi.egg-info/not-zip-safe -cffi.egg-info/requires.txt -cffi.egg-info/top_level.txt -demo/_curses.py -demo/_curses_build.py -demo/_curses_setup.py -demo/api.py -demo/bsdopendirtype.py -demo/bsdopendirtype_build.py -demo/bsdopendirtype_setup.py -demo/btrfs-snap.py -demo/cffi-cocoa.py -demo/fastcsv.py -demo/gmp.py -demo/manual.c -demo/manual2.py -demo/pwuid.py -demo/py.cleanup -demo/pyobj.py -demo/readdir.py -demo/readdir2.py -demo/readdir2_build.py -demo/readdir2_setup.py -demo/readdir_build.py -demo/readdir_ctypes.py -demo/readdir_setup.py -demo/recopendirtype.py -demo/recopendirtype_build.py -demo/setup.py -demo/setup_manual.py -demo/winclipboard.py -demo/xclient.py -doc/Makefile -doc/make.bat -doc/misc/design.rst -doc/misc/grant-cffi-1.0.rst -doc/misc/parse_c_type.rst -doc/source/cdef.rst -doc/source/conf.py -doc/source/index.rst -doc/source/installation.rst -doc/source/overview.rst -doc/source/using.rst -doc/source/whatsnew.rst -testing/__init__.py -testing/support.py -testing/udir.py -testing/cffi0/__init__.py -testing/cffi0/backend_tests.py -testing/cffi0/callback_in_thread.py -testing/cffi0/test_cdata.py -testing/cffi0/test_ctypes.py -testing/cffi0/test_ffi_backend.py -testing/cffi0/test_function.py -testing/cffi0/test_model.py -testing/cffi0/test_ownlib.py -testing/cffi0/test_parsing.py -testing/cffi0/test_platform.py -testing/cffi0/test_unicode_literals.py -testing/cffi0/test_verify.py -testing/cffi0/test_verify2.py -testing/cffi0/test_version.py -testing/cffi0/test_vgen.py -testing/cffi0/test_vgen2.py -testing/cffi0/test_zdistutils.py -testing/cffi0/test_zintegration.py -testing/cffi0/snippets/distutils_module/setup.py -testing/cffi0/snippets/distutils_module/snip_basic_verify.py -testing/cffi0/snippets/distutils_package_1/setup.py -testing/cffi0/snippets/distutils_package_1/snip_basic_verify1/__init__.py -testing/cffi0/snippets/distutils_package_2/setup.py -testing/cffi0/snippets/distutils_package_2/snip_basic_verify2/__init__.py -testing/cffi0/snippets/infrastructure/setup.py -testing/cffi0/snippets/infrastructure/snip_infrastructure/__init__.py -testing/cffi0/snippets/setuptools_module/setup.py -testing/cffi0/snippets/setuptools_module/snip_setuptools_verify.py -testing/cffi0/snippets/setuptools_package_1/setup.py -testing/cffi0/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py -testing/cffi0/snippets/setuptools_package_2/setup.py -testing/cffi0/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py -testing/cffi1/__init__.py -testing/cffi1/test_cffi_binary.py -testing/cffi1/test_commontypes.py -testing/cffi1/test_dlopen.py -testing/cffi1/test_dlopen_unicode_literals.py -testing/cffi1/test_ffi_obj.py -testing/cffi1/test_new_ffi_1.py -testing/cffi1/test_parse_c_type.py -testing/cffi1/test_re_python.py -testing/cffi1/test_realize_c_type.py -testing/cffi1/test_recompiler.py -testing/cffi1/test_unicode_literals.py -testing/cffi1/test_verify1.py -testing/cffi1/test_zdist.py \ No newline at end of file diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/dependency_links.txt b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/entry_points.txt b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/entry_points.txt deleted file mode 100644 index eee7e0f..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[distutils.setup_keywords] -cffi_modules = cffi.setuptools_ext:cffi_modules - diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/native_libs.txt b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/native_libs.txt deleted file mode 100644 index 3d428bb..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/native_libs.txt +++ /dev/null @@ -1 +0,0 @@ -_cffi_backend.cpython-35m-darwin.so diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/not-zip-safe b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/not-zip-safe deleted file mode 100644 index 8b13789..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/not-zip-safe +++ /dev/null @@ -1 +0,0 @@ - diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/requires.txt b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/requires.txt deleted file mode 100644 index dc1c9e1..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/requires.txt +++ /dev/null @@ -1 +0,0 @@ -pycparser diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/top_level.txt b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/top_level.txt deleted file mode 100644 index f645779..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/EGG-INFO/top_level.txt +++ /dev/null @@ -1,2 +0,0 @@ -_cffi_backend -cffi diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/_cffi_backend.cpython-35m-darwin.so b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/_cffi_backend.cpython-35m-darwin.so deleted file mode 100755 index 0b4912c18f1e67202fe8769c7df94af7f6f4df98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 180928 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 dTXWcm+7`8L#csJ=Uq3dbac66(2D>7 diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/_cffi_backend.py b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/_cffi_backend.py deleted file mode 100644 index 929c502..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/_cffi_backend.py +++ /dev/null @@ -1,7 +0,0 @@ -def __bootstrap__(): - global __bootstrap__, __loader__, __file__ - import sys, pkg_resources, imp - __file__ = pkg_resources.resource_filename(__name__, '_cffi_backend.cpython-35m-darwin.so') - __loader__ = None; del __bootstrap__, __loader__ - imp.load_dynamic(__name__,__file__) -__bootstrap__() diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/__init__.py b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/__init__.py deleted file mode 100644 index a7c0678..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -__all__ = ['FFI', 'VerificationError', 'VerificationMissing', 'CDefError', - 'FFIError'] - -from .api import FFI, CDefError, FFIError -from .ffiplatform import VerificationError, VerificationMissing - -__version__ = "1.3.1" -__version_info__ = (1, 3, 1) - -# The verifier module file names are based on the CRC32 of a string that -# contains the following version number. It may be older than __version__ -# if nothing is clearly incompatible. -__version_verifier_modules__ = "0.8.6" diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/_cffi_include.h b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/_cffi_include.h deleted file mode 100644 index 9b32293..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/_cffi_include.h +++ /dev/null @@ -1,229 +0,0 @@ -#define _CFFI_ -#include -#ifdef __cplusplus -extern "C" { -#endif -#include -#include "parse_c_type.h" - -/* this block of #ifs should be kept exactly identical between - c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py - and cffi/_cffi_include.h */ -#if defined(_MSC_VER) -# include /* for alloca() */ -# if _MSC_VER < 1600 /* MSVC < 2010 */ - typedef __int8 int8_t; - typedef __int16 int16_t; - typedef __int32 int32_t; - typedef __int64 int64_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; - typedef unsigned __int64 uint64_t; - typedef __int8 int_least8_t; - typedef __int16 int_least16_t; - typedef __int32 int_least32_t; - typedef __int64 int_least64_t; - typedef unsigned __int8 uint_least8_t; - typedef unsigned __int16 uint_least16_t; - typedef unsigned __int32 uint_least32_t; - typedef unsigned __int64 uint_least64_t; - typedef __int8 int_fast8_t; - typedef __int16 int_fast16_t; - typedef __int32 int_fast32_t; - typedef __int64 int_fast64_t; - typedef unsigned __int8 uint_fast8_t; - typedef unsigned __int16 uint_fast16_t; - typedef unsigned __int32 uint_fast32_t; - typedef unsigned __int64 uint_fast64_t; - typedef __int64 intmax_t; - typedef unsigned __int64 uintmax_t; -# else -# include -# endif -# if _MSC_VER < 1800 /* MSVC < 2013 */ - typedef unsigned char _Bool; -# endif -#else -# include -# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) -# include -# endif -#endif - -#ifdef __GNUC__ -# define _CFFI_UNUSED_FN __attribute__((unused)) -#else -# define _CFFI_UNUSED_FN /* nothing */ -#endif - -/********** CPython-specific section **********/ -#ifndef PYPY_VERSION - - -#if PY_MAJOR_VERSION >= 3 -# define PyInt_FromLong PyLong_FromLong -#endif - -#define _cffi_from_c_double PyFloat_FromDouble -#define _cffi_from_c_float PyFloat_FromDouble -#define _cffi_from_c_long PyInt_FromLong -#define _cffi_from_c_ulong PyLong_FromUnsignedLong -#define _cffi_from_c_longlong PyLong_FromLongLong -#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong - -#define _cffi_to_c_double PyFloat_AsDouble -#define _cffi_to_c_float PyFloat_AsDouble - -#define _cffi_from_c_int(x, type) \ - (((type)-1) > 0 ? /* unsigned */ \ - (sizeof(type) < sizeof(long) ? \ - PyInt_FromLong((long)x) : \ - sizeof(type) == sizeof(long) ? \ - PyLong_FromUnsignedLong((unsigned long)x) : \ - PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ - (sizeof(type) <= sizeof(long) ? \ - PyInt_FromLong((long)x) : \ - PyLong_FromLongLong((long long)x))) - -#define _cffi_to_c_int(o, type) \ - ((type)( \ - sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ - : (type)_cffi_to_c_i8(o)) : \ - sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ - : (type)_cffi_to_c_i16(o)) : \ - sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ - : (type)_cffi_to_c_i32(o)) : \ - sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ - : (type)_cffi_to_c_i64(o)) : \ - (Py_FatalError("unsupported size for type " #type), (type)0))) - -#define _cffi_to_c_i8 \ - ((int(*)(PyObject *))_cffi_exports[1]) -#define _cffi_to_c_u8 \ - ((int(*)(PyObject *))_cffi_exports[2]) -#define _cffi_to_c_i16 \ - ((int(*)(PyObject *))_cffi_exports[3]) -#define _cffi_to_c_u16 \ - ((int(*)(PyObject *))_cffi_exports[4]) -#define _cffi_to_c_i32 \ - ((int(*)(PyObject *))_cffi_exports[5]) -#define _cffi_to_c_u32 \ - ((unsigned int(*)(PyObject *))_cffi_exports[6]) -#define _cffi_to_c_i64 \ - ((long long(*)(PyObject *))_cffi_exports[7]) -#define _cffi_to_c_u64 \ - ((unsigned long long(*)(PyObject *))_cffi_exports[8]) -#define _cffi_to_c_char \ - ((int(*)(PyObject *))_cffi_exports[9]) -#define _cffi_from_c_pointer \ - ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[10]) -#define _cffi_to_c_pointer \ - ((char *(*)(PyObject *, CTypeDescrObject *))_cffi_exports[11]) -#define _cffi_get_struct_layout \ - not used any more -#define _cffi_restore_errno \ - ((void(*)(void))_cffi_exports[13]) -#define _cffi_save_errno \ - ((void(*)(void))_cffi_exports[14]) -#define _cffi_from_c_char \ - ((PyObject *(*)(char))_cffi_exports[15]) -#define _cffi_from_c_deref \ - ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[16]) -#define _cffi_to_c \ - ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[17]) -#define _cffi_from_c_struct \ - ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[18]) -#define _cffi_to_c_wchar_t \ - ((wchar_t(*)(PyObject *))_cffi_exports[19]) -#define _cffi_from_c_wchar_t \ - ((PyObject *(*)(wchar_t))_cffi_exports[20]) -#define _cffi_to_c_long_double \ - ((long double(*)(PyObject *))_cffi_exports[21]) -#define _cffi_to_c__Bool \ - ((_Bool(*)(PyObject *))_cffi_exports[22]) -#define _cffi_prepare_pointer_call_argument \ - ((Py_ssize_t(*)(CTypeDescrObject *, PyObject *, char **))_cffi_exports[23]) -#define _cffi_convert_array_from_object \ - ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24]) -#define _CFFI_NUM_EXPORTS 25 - -typedef struct _ctypedescr CTypeDescrObject; - -static void *_cffi_exports[_CFFI_NUM_EXPORTS]; - -#define _cffi_type(index) ( \ - assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \ - (CTypeDescrObject *)_cffi_types[index]) - -static PyObject *_cffi_init(const char *module_name, Py_ssize_t version, - const struct _cffi_type_context_s *ctx) -{ - PyObject *module, *o_arg, *new_module; - void *raw[] = { - (void *)module_name, - (void *)version, - (void *)_cffi_exports, - (void *)ctx, - }; - - module = PyImport_ImportModule("_cffi_backend"); - if (module == NULL) - goto failure; - - o_arg = PyLong_FromVoidPtr((void *)raw); - if (o_arg == NULL) - goto failure; - - new_module = PyObject_CallMethod( - module, (char *)"_init_cffi_1_0_external_module", (char *)"O", o_arg); - - Py_DECREF(o_arg); - Py_DECREF(module); - return new_module; - - failure: - Py_XDECREF(module); - return NULL; -} - -_CFFI_UNUSED_FN -static PyObject **_cffi_unpack_args(PyObject *args_tuple, Py_ssize_t expected, - const char *fnname) -{ - if (PyTuple_GET_SIZE(args_tuple) != expected) { - PyErr_Format(PyExc_TypeError, - "%.150s() takes exactly %zd arguments (%zd given)", - fnname, expected, PyTuple_GET_SIZE(args_tuple)); - return NULL; - } - return &PyTuple_GET_ITEM(args_tuple, 0); /* pointer to the first item, - the others follow */ -} - -#endif -/********** end CPython-specific section **********/ - - -#define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0])) - -#define _cffi_prim_int(size, sign) \ - ((size) == 1 ? ((sign) ? _CFFI_PRIM_INT8 : _CFFI_PRIM_UINT8) : \ - (size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) : \ - (size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) : \ - (size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : \ - _CFFI__UNKNOWN_PRIM) - -#define _cffi_prim_float(size) \ - ((size) == sizeof(float) ? _CFFI_PRIM_FLOAT : \ - (size) == sizeof(double) ? _CFFI_PRIM_DOUBLE : \ - (size) == sizeof(long double) ? _CFFI__UNKNOWN_LONG_DOUBLE : \ - _CFFI__UNKNOWN_FLOAT_PRIM) - -#define _cffi_check_int(got, got_nonpos, expected) \ - ((got_nonpos) == (expected <= 0) && \ - (got) == (unsigned long long)expected) - -#ifdef __cplusplus -} -#endif diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/api.py b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/api.py deleted file mode 100644 index 0a98e05..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/api.py +++ /dev/null @@ -1,724 +0,0 @@ -import sys, types -from .lock import allocate_lock - -try: - callable -except NameError: - # Python 3.1 - from collections import Callable - callable = lambda x: isinstance(x, Callable) - -try: - basestring -except NameError: - # Python 3.x - basestring = str - - -class FFIError(Exception): - pass - -class CDefError(Exception): - def __str__(self): - try: - line = 'line %d: ' % (self.args[1].coord.line,) - except (AttributeError, TypeError, IndexError): - line = '' - return '%s%s' % (line, self.args[0]) - - -class FFI(object): - r''' - The main top-level class that you instantiate once, or once per module. - - Example usage: - - ffi = FFI() - ffi.cdef(""" - int printf(const char *, ...); - """) - - C = ffi.dlopen(None) # standard library - -or- - C = ffi.verify() # use a C compiler: verify the decl above is right - - C.printf("hello, %s!\n", ffi.new("char[]", "world")) - ''' - - def __init__(self, backend=None): - """Create an FFI instance. The 'backend' argument is used to - select a non-default backend, mostly for tests. - """ - from . import cparser, model - if backend is None: - # You need PyPy (>= 2.0 beta), or a CPython (>= 2.6) with - # _cffi_backend.so compiled. - import _cffi_backend as backend - from . import __version__ - assert backend.__version__ == __version__, \ - "version mismatch, %s != %s" % (backend.__version__, __version__) - # (If you insist you can also try to pass the option - # 'backend=backend_ctypes.CTypesBackend()', but don't - # rely on it! It's probably not going to work well.) - - self._backend = backend - self._lock = allocate_lock() - self._parser = cparser.Parser() - self._cached_btypes = {} - self._parsed_types = types.ModuleType('parsed_types').__dict__ - self._new_types = types.ModuleType('new_types').__dict__ - self._function_caches = [] - self._libraries = [] - self._cdefsources = [] - self._included_ffis = [] - self._windows_unicode = None - if hasattr(backend, 'set_ffi'): - backend.set_ffi(self) - for name in backend.__dict__: - if name.startswith('RTLD_'): - setattr(self, name, getattr(backend, name)) - # - with self._lock: - self.BVoidP = self._get_cached_btype(model.voidp_type) - self.BCharA = self._get_cached_btype(model.char_array_type) - if isinstance(backend, types.ModuleType): - # _cffi_backend: attach these constants to the class - if not hasattr(FFI, 'NULL'): - FFI.NULL = self.cast(self.BVoidP, 0) - FFI.CData, FFI.CType = backend._get_types() - else: - # ctypes backend: attach these constants to the instance - self.NULL = self.cast(self.BVoidP, 0) - self.CData, self.CType = backend._get_types() - - def cdef(self, csource, override=False, packed=False): - """Parse the given C source. This registers all declared functions, - types, and global variables. The functions and global variables can - then be accessed via either 'ffi.dlopen()' or 'ffi.verify()'. - The types can be used in 'ffi.new()' and other functions. - If 'packed' is specified as True, all structs declared inside this - cdef are packed, i.e. laid out without any field alignment at all. - """ - if not isinstance(csource, str): # unicode, on Python 2 - if not isinstance(csource, basestring): - raise TypeError("cdef() argument must be a string") - csource = csource.encode('ascii') - with self._lock: - self._parser.parse(csource, override=override, packed=packed) - self._cdefsources.append(csource) - if override: - for cache in self._function_caches: - cache.clear() - finishlist = self._parser._recomplete - if finishlist: - self._parser._recomplete = [] - for tp in finishlist: - tp.finish_backend_type(self, finishlist) - - def dlopen(self, name, flags=0): - """Load and return a dynamic library identified by 'name'. - The standard C library can be loaded by passing None. - Note that functions and types declared by 'ffi.cdef()' are not - linked to a particular library, just like C headers; in the - library we only look for the actual (untyped) symbols. - """ - assert isinstance(name, basestring) or name is None - with self._lock: - lib, function_cache = _make_ffi_library(self, name, flags) - self._function_caches.append(function_cache) - self._libraries.append(lib) - return lib - - def _typeof_locked(self, cdecl): - # call me with the lock! - key = cdecl - if key in self._parsed_types: - return self._parsed_types[key] - # - if not isinstance(cdecl, str): # unicode, on Python 2 - cdecl = cdecl.encode('ascii') - # - type = self._parser.parse_type(cdecl) - really_a_function_type = type.is_raw_function - if really_a_function_type: - type = type.as_function_pointer() - btype = self._get_cached_btype(type) - result = btype, really_a_function_type - self._parsed_types[key] = result - return result - - def _typeof(self, cdecl, consider_function_as_funcptr=False): - # string -> ctype object - try: - result = self._parsed_types[cdecl] - except KeyError: - with self._lock: - result = self._typeof_locked(cdecl) - # - btype, really_a_function_type = result - if really_a_function_type and not consider_function_as_funcptr: - raise CDefError("the type %r is a function type, not a " - "pointer-to-function type" % (cdecl,)) - return btype - - def typeof(self, cdecl): - """Parse the C type given as a string and return the - corresponding object. - It can also be used on 'cdata' instance to get its C type. - """ - if isinstance(cdecl, basestring): - return self._typeof(cdecl) - if isinstance(cdecl, self.CData): - return self._backend.typeof(cdecl) - if isinstance(cdecl, types.BuiltinFunctionType): - res = _builtin_function_type(cdecl) - if res is not None: - return res - if (isinstance(cdecl, types.FunctionType) - and hasattr(cdecl, '_cffi_base_type')): - with self._lock: - return self._get_cached_btype(cdecl._cffi_base_type) - raise TypeError(type(cdecl)) - - def sizeof(self, cdecl): - """Return the size in bytes of the argument. It can be a - string naming a C type, or a 'cdata' instance. - """ - if isinstance(cdecl, basestring): - BType = self._typeof(cdecl) - return self._backend.sizeof(BType) - else: - return self._backend.sizeof(cdecl) - - def alignof(self, cdecl): - """Return the natural alignment size in bytes of the C type - given as a string. - """ - if isinstance(cdecl, basestring): - cdecl = self._typeof(cdecl) - return self._backend.alignof(cdecl) - - def offsetof(self, cdecl, *fields_or_indexes): - """Return the offset of the named field inside the given - structure or array, which must be given as a C type name. - You can give several field names in case of nested structures. - You can also give numeric values which correspond to array - items, in case of an array type. - """ - if isinstance(cdecl, basestring): - cdecl = self._typeof(cdecl) - return self._typeoffsetof(cdecl, *fields_or_indexes)[1] - - def new(self, cdecl, init=None): - """Allocate an instance according to the specified C type and - return a pointer to it. The specified C type must be either a - pointer or an array: ``new('X *')`` allocates an X and returns - a pointer to it, whereas ``new('X[n]')`` allocates an array of - n X'es and returns an array referencing it (which works - mostly like a pointer, like in C). You can also use - ``new('X[]', n)`` to allocate an array of a non-constant - length n. - - The memory is initialized following the rules of declaring a - global variable in C: by default it is zero-initialized, but - an explicit initializer can be given which can be used to - fill all or part of the memory. - - When the returned object goes out of scope, the memory - is freed. In other words the returned object has - ownership of the value of type 'cdecl' that it points to. This - means that the raw data can be used as long as this object is - kept alive, but must not be used for a longer time. Be careful - about that when copying the pointer to the memory somewhere - else, e.g. into another structure. - """ - if isinstance(cdecl, basestring): - cdecl = self._typeof(cdecl) - return self._backend.newp(cdecl, init) - - def new_allocator(self, alloc=None, free=None, - should_clear_after_alloc=True): - """Return a new allocator, i.e. a function that behaves like ffi.new() - but uses the provided low-level 'alloc' and 'free' functions. - - 'alloc' is called with the size as argument. If it returns NULL, a - MemoryError is raised. 'free' is called with the result of 'alloc' - as argument. Both can be either Python function or directly C - functions. If 'free' is None, then no free function is called. - If both 'alloc' and 'free' are None, the default is used. - - If 'should_clear_after_alloc' is set to False, then the memory - returned by 'alloc' is assumed to be already cleared (or you are - fine with garbage); otherwise CFFI will clear it. - """ - compiled_ffi = self._backend.FFI() - allocator = compiled_ffi.new_allocator(alloc, free, - should_clear_after_alloc) - def allocate(cdecl, init=None): - if isinstance(cdecl, basestring): - cdecl = self._typeof(cdecl) - return allocator(cdecl, init) - return allocate - - def cast(self, cdecl, source): - """Similar to a C cast: returns an instance of the named C - type initialized with the given 'source'. The source is - casted between integers or pointers of any type. - """ - if isinstance(cdecl, basestring): - cdecl = self._typeof(cdecl) - return self._backend.cast(cdecl, source) - - def string(self, cdata, maxlen=-1): - """Return a Python string (or unicode string) from the 'cdata'. - If 'cdata' is a pointer or array of characters or bytes, returns - the null-terminated string. The returned string extends until - the first null character, or at most 'maxlen' characters. If - 'cdata' is an array then 'maxlen' defaults to its length. - - If 'cdata' is a pointer or array of wchar_t, returns a unicode - string following the same rules. - - If 'cdata' is a single character or byte or a wchar_t, returns - it as a string or unicode string. - - If 'cdata' is an enum, returns the value of the enumerator as a - string, or 'NUMBER' if the value is out of range. - """ - return self._backend.string(cdata, maxlen) - - def buffer(self, cdata, size=-1): - """Return a read-write buffer object that references the raw C data - pointed to by the given 'cdata'. The 'cdata' must be a pointer or - an array. Can be passed to functions expecting a buffer, or directly - manipulated with: - - buf[:] get a copy of it in a regular string, or - buf[idx] as a single character - buf[:] = ... - buf[idx] = ... change the content - """ - return self._backend.buffer(cdata, size) - - def from_buffer(self, python_buffer): - """Return a that points to the data of the - given Python object, which must support the buffer interface. - Note that this is not meant to be used on the built-in types str, - unicode, or bytearray (you can build 'char[]' arrays explicitly) - but only on objects containing large quantities of raw data - in some other format, like 'array.array' or numpy arrays. - """ - return self._backend.from_buffer(self.BCharA, python_buffer) - - def memmove(self, dest, src, n): - """ffi.memmove(dest, src, n) copies n bytes of memory from src to dest. - - Like the C function memmove(), the memory areas may overlap; - apart from that it behaves like the C function memcpy(). - - 'src' can be any cdata ptr or array, or any Python buffer object. - 'dest' can be any cdata ptr or array, or a writable Python buffer - object. The size to copy, 'n', is always measured in bytes. - - Unlike other methods, this one supports all Python buffer including - byte strings and bytearrays---but it still does not support - non-contiguous buffers. - """ - return self._backend.memmove(dest, src, n) - - def callback(self, cdecl, python_callable=None, error=None, onerror=None): - """Return a callback object or a decorator making such a - callback object. 'cdecl' must name a C function pointer type. - The callback invokes the specified 'python_callable' (which may - be provided either directly or via a decorator). Important: the - callback object must be manually kept alive for as long as the - callback may be invoked from the C level. - """ - def callback_decorator_wrap(python_callable): - if not callable(python_callable): - raise TypeError("the 'python_callable' argument " - "is not callable") - return self._backend.callback(cdecl, python_callable, - error, onerror) - if isinstance(cdecl, basestring): - cdecl = self._typeof(cdecl, consider_function_as_funcptr=True) - if python_callable is None: - return callback_decorator_wrap # decorator mode - else: - return callback_decorator_wrap(python_callable) # direct mode - - def getctype(self, cdecl, replace_with=''): - """Return a string giving the C type 'cdecl', which may be itself - a string or a object. If 'replace_with' is given, it gives - extra text to append (or insert for more complicated C types), like - a variable name, or '*' to get actually the C type 'pointer-to-cdecl'. - """ - if isinstance(cdecl, basestring): - cdecl = self._typeof(cdecl) - replace_with = replace_with.strip() - if (replace_with.startswith('*') - and '&[' in self._backend.getcname(cdecl, '&')): - replace_with = '(%s)' % replace_with - elif replace_with and not replace_with[0] in '[(': - replace_with = ' ' + replace_with - return self._backend.getcname(cdecl, replace_with) - - def gc(self, cdata, destructor): - """Return a new cdata object that points to the same - data. Later, when this new cdata object is garbage-collected, - 'destructor(old_cdata_object)' will be called. - """ - try: - gcp = self._backend.gcp - except AttributeError: - pass - else: - return gcp(cdata, destructor) - # - with self._lock: - try: - gc_weakrefs = self.gc_weakrefs - except AttributeError: - from .gc_weakref import GcWeakrefs - gc_weakrefs = self.gc_weakrefs = GcWeakrefs(self) - return gc_weakrefs.build(cdata, destructor) - - def _get_cached_btype(self, type): - assert self._lock.acquire(False) is False - # call me with the lock! - try: - BType = self._cached_btypes[type] - except KeyError: - finishlist = [] - BType = type.get_cached_btype(self, finishlist) - for type in finishlist: - type.finish_backend_type(self, finishlist) - return BType - - def verify(self, source='', tmpdir=None, **kwargs): - """Verify that the current ffi signatures compile on this - machine, and return a dynamic library object. The dynamic - library can be used to call functions and access global - variables declared in this 'ffi'. The library is compiled - by the C compiler: it gives you C-level API compatibility - (including calling macros). This is unlike 'ffi.dlopen()', - which requires binary compatibility in the signatures. - """ - from .verifier import Verifier, _caller_dir_pycache - # - # If set_unicode(True) was called, insert the UNICODE and - # _UNICODE macro declarations - if self._windows_unicode: - self._apply_windows_unicode(kwargs) - # - # Set the tmpdir here, and not in Verifier.__init__: it picks - # up the caller's directory, which we want to be the caller of - # ffi.verify(), as opposed to the caller of Veritier(). - tmpdir = tmpdir or _caller_dir_pycache() - # - # Make a Verifier() and use it to load the library. - self.verifier = Verifier(self, source, tmpdir, **kwargs) - lib = self.verifier.load_library() - # - # Save the loaded library for keep-alive purposes, even - # if the caller doesn't keep it alive itself (it should). - self._libraries.append(lib) - return lib - - def _get_errno(self): - return self._backend.get_errno() - def _set_errno(self, errno): - self._backend.set_errno(errno) - errno = property(_get_errno, _set_errno, None, - "the value of 'errno' from/to the C calls") - - def getwinerror(self, code=-1): - return self._backend.getwinerror(code) - - def _pointer_to(self, ctype): - from . import model - with self._lock: - return model.pointer_cache(self, ctype) - - def addressof(self, cdata, *fields_or_indexes): - """Return the address of a . - If 'fields_or_indexes' are given, returns the address of that - field or array item in the structure or array, recursively in - case of nested structures. - """ - ctype = self._backend.typeof(cdata) - if fields_or_indexes: - ctype, offset = self._typeoffsetof(ctype, *fields_or_indexes) - else: - if ctype.kind == "pointer": - raise TypeError("addressof(pointer)") - offset = 0 - ctypeptr = self._pointer_to(ctype) - return self._backend.rawaddressof(ctypeptr, cdata, offset) - - def _typeoffsetof(self, ctype, field_or_index, *fields_or_indexes): - ctype, offset = self._backend.typeoffsetof(ctype, field_or_index) - for field1 in fields_or_indexes: - ctype, offset1 = self._backend.typeoffsetof(ctype, field1, 1) - offset += offset1 - return ctype, offset - - def include(self, ffi_to_include): - """Includes the typedefs, structs, unions and enums defined - in another FFI instance. Usage is similar to a #include in C, - where a part of the program might include types defined in - another part for its own usage. Note that the include() - method has no effect on functions, constants and global - variables, which must anyway be accessed directly from the - lib object returned by the original FFI instance. - """ - if not isinstance(ffi_to_include, FFI): - raise TypeError("ffi.include() expects an argument that is also of" - " type cffi.FFI, not %r" % ( - type(ffi_to_include).__name__,)) - if ffi_to_include is self: - raise ValueError("self.include(self)") - with ffi_to_include._lock: - with self._lock: - self._parser.include(ffi_to_include._parser) - self._cdefsources.append('[') - self._cdefsources.extend(ffi_to_include._cdefsources) - self._cdefsources.append(']') - self._included_ffis.append(ffi_to_include) - - def new_handle(self, x): - return self._backend.newp_handle(self.BVoidP, x) - - def from_handle(self, x): - return self._backend.from_handle(x) - - def set_unicode(self, enabled_flag): - """Windows: if 'enabled_flag' is True, enable the UNICODE and - _UNICODE defines in C, and declare the types like TCHAR and LPTCSTR - to be (pointers to) wchar_t. If 'enabled_flag' is False, - declare these types to be (pointers to) plain 8-bit characters. - This is mostly for backward compatibility; you usually want True. - """ - if self._windows_unicode is not None: - raise ValueError("set_unicode() can only be called once") - enabled_flag = bool(enabled_flag) - if enabled_flag: - self.cdef("typedef wchar_t TBYTE;" - "typedef wchar_t TCHAR;" - "typedef const wchar_t *LPCTSTR;" - "typedef const wchar_t *PCTSTR;" - "typedef wchar_t *LPTSTR;" - "typedef wchar_t *PTSTR;" - "typedef TBYTE *PTBYTE;" - "typedef TCHAR *PTCHAR;") - else: - self.cdef("typedef char TBYTE;" - "typedef char TCHAR;" - "typedef const char *LPCTSTR;" - "typedef const char *PCTSTR;" - "typedef char *LPTSTR;" - "typedef char *PTSTR;" - "typedef TBYTE *PTBYTE;" - "typedef TCHAR *PTCHAR;") - self._windows_unicode = enabled_flag - - def _apply_windows_unicode(self, kwds): - defmacros = kwds.get('define_macros', ()) - if not isinstance(defmacros, (list, tuple)): - raise TypeError("'define_macros' must be a list or tuple") - defmacros = list(defmacros) + [('UNICODE', '1'), - ('_UNICODE', '1')] - kwds['define_macros'] = defmacros - - def set_source(self, module_name, source, source_extension='.c', **kwds): - if hasattr(self, '_assigned_source'): - raise ValueError("set_source() cannot be called several times " - "per ffi object") - if not isinstance(module_name, basestring): - raise TypeError("'module_name' must be a string") - self._assigned_source = (str(module_name), source, - source_extension, kwds) - - def distutils_extension(self, tmpdir='build', verbose=True): - from distutils.dir_util import mkpath - from .recompiler import recompile - # - if not hasattr(self, '_assigned_source'): - if hasattr(self, 'verifier'): # fallback, 'tmpdir' ignored - return self.verifier.get_extension() - raise ValueError("set_source() must be called before" - " distutils_extension()") - module_name, source, source_extension, kwds = self._assigned_source - if source is None: - raise TypeError("distutils_extension() is only for C extension " - "modules, not for dlopen()-style pure Python " - "modules") - mkpath(tmpdir) - ext, updated = recompile(self, module_name, - source, tmpdir=tmpdir, extradir=tmpdir, - source_extension=source_extension, - call_c_compiler=False, **kwds) - if verbose: - if updated: - sys.stderr.write("regenerated: %r\n" % (ext.sources[0],)) - else: - sys.stderr.write("not modified: %r\n" % (ext.sources[0],)) - return ext - - def emit_c_code(self, filename): - from .recompiler import recompile - # - if not hasattr(self, '_assigned_source'): - raise ValueError("set_source() must be called before emit_c_code()") - module_name, source, source_extension, kwds = self._assigned_source - if source is None: - raise TypeError("emit_c_code() is only for C extension modules, " - "not for dlopen()-style pure Python modules") - recompile(self, module_name, source, - c_file=filename, call_c_compiler=False, **kwds) - - def emit_python_code(self, filename): - from .recompiler import recompile - # - if not hasattr(self, '_assigned_source'): - raise ValueError("set_source() must be called before emit_c_code()") - module_name, source, source_extension, kwds = self._assigned_source - if source is not None: - raise TypeError("emit_python_code() is only for dlopen()-style " - "pure Python modules, not for C extension modules") - recompile(self, module_name, source, - c_file=filename, call_c_compiler=False, **kwds) - - def compile(self, tmpdir='.'): - from .recompiler import recompile - # - if not hasattr(self, '_assigned_source'): - raise ValueError("set_source() must be called before compile()") - module_name, source, source_extension, kwds = self._assigned_source - return recompile(self, module_name, source, tmpdir=tmpdir, - source_extension=source_extension, **kwds) - - -def _load_backend_lib(backend, name, flags): - if name is None: - if sys.platform != "win32": - return backend.load_library(None, flags) - name = "c" # Windows: load_library(None) fails, but this works - # (backward compatibility hack only) - try: - if '.' not in name and '/' not in name: - raise OSError("library not found: %r" % (name,)) - return backend.load_library(name, flags) - except OSError: - import ctypes.util - path = ctypes.util.find_library(name) - if path is None: - raise # propagate the original OSError - return backend.load_library(path, flags) - -def _make_ffi_library(ffi, libname, flags): - import os - backend = ffi._backend - backendlib = _load_backend_lib(backend, libname, flags) - copied_enums = [] - # - def make_accessor_locked(name): - key = 'function ' + name - if key in ffi._parser._declarations: - tp, _ = ffi._parser._declarations[key] - BType = ffi._get_cached_btype(tp) - try: - value = backendlib.load_function(BType, name) - except KeyError as e: - raise AttributeError('%s: %s' % (name, e)) - library.__dict__[name] = value - return - # - key = 'variable ' + name - if key in ffi._parser._declarations: - tp, _ = ffi._parser._declarations[key] - BType = ffi._get_cached_btype(tp) - read_variable = backendlib.read_variable - write_variable = backendlib.write_variable - setattr(FFILibrary, name, property( - lambda self: read_variable(BType, name), - lambda self, value: write_variable(BType, name, value))) - return - # - if not copied_enums: - from . import model - error = None - for key, (tp, _) in ffi._parser._declarations.items(): - if not isinstance(tp, model.EnumType): - continue - try: - tp.check_not_partial() - except Exception as e: - error = e - continue - for enumname, enumval in zip(tp.enumerators, tp.enumvalues): - if enumname not in library.__dict__: - library.__dict__[enumname] = enumval - if error is not None: - if name in library.__dict__: - return # ignore error, about a different enum - raise error - - for key, val in ffi._parser._int_constants.items(): - if key not in library.__dict__: - library.__dict__[key] = val - - copied_enums.append(True) - if name in library.__dict__: - return - # - key = 'constant ' + name - if key in ffi._parser._declarations: - raise NotImplementedError("fetching a non-integer constant " - "after dlopen()") - # - raise AttributeError(name) - # - def make_accessor(name): - with ffi._lock: - if name in library.__dict__ or name in FFILibrary.__dict__: - return # added by another thread while waiting for the lock - make_accessor_locked(name) - # - class FFILibrary(object): - def __getattr__(self, name): - make_accessor(name) - return getattr(self, name) - def __setattr__(self, name, value): - try: - property = getattr(self.__class__, name) - except AttributeError: - make_accessor(name) - setattr(self, name, value) - else: - property.__set__(self, value) - # - if libname is not None: - try: - if not isinstance(libname, str): # unicode, on Python 2 - libname = libname.encode('utf-8') - FFILibrary.__name__ = 'FFILibrary_%s' % libname - except UnicodeError: - pass - library = FFILibrary() - return library, library.__dict__ - -def _builtin_function_type(func): - # a hack to make at least ffi.typeof(builtin_function) work, - # if the builtin function was obtained by 'vengine_cpy'. - import sys - try: - module = sys.modules[func.__module__] - ffi = module._cffi_original_ffi - types_of_builtin_funcs = module._cffi_types_of_builtin_funcs - tp = types_of_builtin_funcs[func] - except (KeyError, AttributeError, TypeError): - return None - else: - with ffi._lock: - return ffi._get_cached_btype(tp) diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/backend_ctypes.py b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/backend_ctypes.py deleted file mode 100644 index b061cda..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/backend_ctypes.py +++ /dev/null @@ -1,1068 +0,0 @@ -import ctypes, ctypes.util, operator, sys -from . import model - -if sys.version_info < (3,): - bytechr = chr -else: - unicode = str - long = int - xrange = range - bytechr = lambda num: bytes([num]) - -class CTypesType(type): - pass - -class CTypesData(object): - __metaclass__ = CTypesType - __slots__ = ['__weakref__'] - __name__ = '' - - def __init__(self, *args): - raise TypeError("cannot instantiate %r" % (self.__class__,)) - - @classmethod - def _newp(cls, init): - raise TypeError("expected a pointer or array ctype, got '%s'" - % (cls._get_c_name(),)) - - @staticmethod - def _to_ctypes(value): - raise TypeError - - @classmethod - def _arg_to_ctypes(cls, *value): - try: - ctype = cls._ctype - except AttributeError: - raise TypeError("cannot create an instance of %r" % (cls,)) - if value: - res = cls._to_ctypes(*value) - if not isinstance(res, ctype): - res = cls._ctype(res) - else: - res = cls._ctype() - return res - - @classmethod - def _create_ctype_obj(cls, init): - if init is None: - return cls._arg_to_ctypes() - else: - return cls._arg_to_ctypes(init) - - @staticmethod - def _from_ctypes(ctypes_value): - raise TypeError - - @classmethod - def _get_c_name(cls, replace_with=''): - return cls._reftypename.replace(' &', replace_with) - - @classmethod - def _fix_class(cls): - cls.__name__ = 'CData<%s>' % (cls._get_c_name(),) - cls.__qualname__ = 'CData<%s>' % (cls._get_c_name(),) - cls.__module__ = 'ffi' - - def _get_own_repr(self): - raise NotImplementedError - - def _addr_repr(self, address): - if address == 0: - return 'NULL' - else: - if address < 0: - address += 1 << (8*ctypes.sizeof(ctypes.c_void_p)) - return '0x%x' % address - - def __repr__(self, c_name=None): - own = self._get_own_repr() - return '' % (c_name or self._get_c_name(), own) - - def _convert_to_address(self, BClass): - if BClass is None: - raise TypeError("cannot convert %r to an address" % ( - self._get_c_name(),)) - else: - raise TypeError("cannot convert %r to %r" % ( - self._get_c_name(), BClass._get_c_name())) - - @classmethod - def _get_size(cls): - return ctypes.sizeof(cls._ctype) - - def _get_size_of_instance(self): - return ctypes.sizeof(self._ctype) - - @classmethod - def _cast_from(cls, source): - raise TypeError("cannot cast to %r" % (cls._get_c_name(),)) - - def _cast_to_integer(self): - return self._convert_to_address(None) - - @classmethod - def _alignment(cls): - return ctypes.alignment(cls._ctype) - - def __iter__(self): - raise TypeError("cdata %r does not support iteration" % ( - self._get_c_name()),) - - def _make_cmp(name): - cmpfunc = getattr(operator, name) - def cmp(self, other): - if isinstance(other, CTypesData): - return cmpfunc(self._convert_to_address(None), - other._convert_to_address(None)) - else: - return NotImplemented - cmp.func_name = name - return cmp - - __eq__ = _make_cmp('__eq__') - __ne__ = _make_cmp('__ne__') - __lt__ = _make_cmp('__lt__') - __le__ = _make_cmp('__le__') - __gt__ = _make_cmp('__gt__') - __ge__ = _make_cmp('__ge__') - - def __hash__(self): - return hash(type(self)) ^ hash(self._convert_to_address(None)) - - def _to_string(self, maxlen): - raise TypeError("string(): %r" % (self,)) - - -class CTypesGenericPrimitive(CTypesData): - __slots__ = [] - - def __eq__(self, other): - return self is other - - def __ne__(self, other): - return self is not other - - def __hash__(self): - return object.__hash__(self) - - def _get_own_repr(self): - return repr(self._from_ctypes(self._value)) - - -class CTypesGenericArray(CTypesData): - __slots__ = [] - - @classmethod - def _newp(cls, init): - return cls(init) - - def __iter__(self): - for i in xrange(len(self)): - yield self[i] - - def _get_own_repr(self): - return self._addr_repr(ctypes.addressof(self._blob)) - - -class CTypesGenericPtr(CTypesData): - __slots__ = ['_address', '_as_ctype_ptr'] - _automatic_casts = False - kind = "pointer" - - @classmethod - def _newp(cls, init): - return cls(init) - - @classmethod - def _cast_from(cls, source): - if source is None: - address = 0 - elif isinstance(source, CTypesData): - address = source._cast_to_integer() - elif isinstance(source, (int, long)): - address = source - else: - raise TypeError("bad type for cast to %r: %r" % - (cls, type(source).__name__)) - return cls._new_pointer_at(address) - - @classmethod - def _new_pointer_at(cls, address): - self = cls.__new__(cls) - self._address = address - self._as_ctype_ptr = ctypes.cast(address, cls._ctype) - return self - - def _get_own_repr(self): - try: - return self._addr_repr(self._address) - except AttributeError: - return '???' - - def _cast_to_integer(self): - return self._address - - def __nonzero__(self): - return bool(self._address) - - def __bool__(self): - return bool(self._address) - - @classmethod - def _to_ctypes(cls, value): - if not isinstance(value, CTypesData): - raise TypeError("unexpected %s object" % type(value).__name__) - address = value._convert_to_address(cls) - return ctypes.cast(address, cls._ctype) - - @classmethod - def _from_ctypes(cls, ctypes_ptr): - address = ctypes.cast(ctypes_ptr, ctypes.c_void_p).value or 0 - return cls._new_pointer_at(address) - - @classmethod - def _initialize(cls, ctypes_ptr, value): - if value: - ctypes_ptr.contents = cls._to_ctypes(value).contents - - def _convert_to_address(self, BClass): - if (BClass in (self.__class__, None) or BClass._automatic_casts - or self._automatic_casts): - return self._address - else: - return CTypesData._convert_to_address(self, BClass) - - -class CTypesBaseStructOrUnion(CTypesData): - __slots__ = ['_blob'] - - @classmethod - def _create_ctype_obj(cls, init): - # may be overridden - raise TypeError("cannot instantiate opaque type %s" % (cls,)) - - def _get_own_repr(self): - return self._addr_repr(ctypes.addressof(self._blob)) - - @classmethod - def _offsetof(cls, fieldname): - return getattr(cls._ctype, fieldname).offset - - def _convert_to_address(self, BClass): - if getattr(BClass, '_BItem', None) is self.__class__: - return ctypes.addressof(self._blob) - else: - return CTypesData._convert_to_address(self, BClass) - - @classmethod - def _from_ctypes(cls, ctypes_struct_or_union): - self = cls.__new__(cls) - self._blob = ctypes_struct_or_union - return self - - @classmethod - def _to_ctypes(cls, value): - return value._blob - - def __repr__(self, c_name=None): - return CTypesData.__repr__(self, c_name or self._get_c_name(' &')) - - -class CTypesBackend(object): - - PRIMITIVE_TYPES = { - 'char': ctypes.c_char, - 'short': ctypes.c_short, - 'int': ctypes.c_int, - 'long': ctypes.c_long, - 'long long': ctypes.c_longlong, - 'signed char': ctypes.c_byte, - 'unsigned char': ctypes.c_ubyte, - 'unsigned short': ctypes.c_ushort, - 'unsigned int': ctypes.c_uint, - 'unsigned long': ctypes.c_ulong, - 'unsigned long long': ctypes.c_ulonglong, - 'float': ctypes.c_float, - 'double': ctypes.c_double, - '_Bool': ctypes.c_bool, - } - - for _name in ['unsigned long long', 'unsigned long', - 'unsigned int', 'unsigned short', 'unsigned char']: - _size = ctypes.sizeof(PRIMITIVE_TYPES[_name]) - PRIMITIVE_TYPES['uint%d_t' % (8*_size)] = PRIMITIVE_TYPES[_name] - if _size == ctypes.sizeof(ctypes.c_void_p): - PRIMITIVE_TYPES['uintptr_t'] = PRIMITIVE_TYPES[_name] - if _size == ctypes.sizeof(ctypes.c_size_t): - PRIMITIVE_TYPES['size_t'] = PRIMITIVE_TYPES[_name] - - for _name in ['long long', 'long', 'int', 'short', 'signed char']: - _size = ctypes.sizeof(PRIMITIVE_TYPES[_name]) - PRIMITIVE_TYPES['int%d_t' % (8*_size)] = PRIMITIVE_TYPES[_name] - if _size == ctypes.sizeof(ctypes.c_void_p): - PRIMITIVE_TYPES['intptr_t'] = PRIMITIVE_TYPES[_name] - PRIMITIVE_TYPES['ptrdiff_t'] = PRIMITIVE_TYPES[_name] - if _size == ctypes.sizeof(ctypes.c_size_t): - PRIMITIVE_TYPES['ssize_t'] = PRIMITIVE_TYPES[_name] - - - def __init__(self): - self.RTLD_LAZY = 0 # not supported anyway by ctypes - self.RTLD_NOW = 0 - self.RTLD_GLOBAL = ctypes.RTLD_GLOBAL - self.RTLD_LOCAL = ctypes.RTLD_LOCAL - - def set_ffi(self, ffi): - self.ffi = ffi - - def _get_types(self): - return CTypesData, CTypesType - - def load_library(self, path, flags=0): - cdll = ctypes.CDLL(path, flags) - return CTypesLibrary(self, cdll) - - def new_void_type(self): - class CTypesVoid(CTypesData): - __slots__ = [] - _reftypename = 'void &' - @staticmethod - def _from_ctypes(novalue): - return None - @staticmethod - def _to_ctypes(novalue): - if novalue is not None: - raise TypeError("None expected, got %s object" % - (type(novalue).__name__,)) - return None - CTypesVoid._fix_class() - return CTypesVoid - - def new_primitive_type(self, name): - if name == 'wchar_t': - raise NotImplementedError(name) - ctype = self.PRIMITIVE_TYPES[name] - if name == 'char': - kind = 'char' - elif name in ('float', 'double'): - kind = 'float' - else: - if name in ('signed char', 'unsigned char'): - kind = 'byte' - elif name == '_Bool': - kind = 'bool' - else: - kind = 'int' - is_signed = (ctype(-1).value == -1) - # - def _cast_source_to_int(source): - if isinstance(source, (int, long, float)): - source = int(source) - elif isinstance(source, CTypesData): - source = source._cast_to_integer() - elif isinstance(source, bytes): - source = ord(source) - elif source is None: - source = 0 - else: - raise TypeError("bad type for cast to %r: %r" % - (CTypesPrimitive, type(source).__name__)) - return source - # - kind1 = kind - class CTypesPrimitive(CTypesGenericPrimitive): - __slots__ = ['_value'] - _ctype = ctype - _reftypename = '%s &' % name - kind = kind1 - - def __init__(self, value): - self._value = value - - @staticmethod - def _create_ctype_obj(init): - if init is None: - return ctype() - return ctype(CTypesPrimitive._to_ctypes(init)) - - if kind == 'int' or kind == 'byte': - @classmethod - def _cast_from(cls, source): - source = _cast_source_to_int(source) - source = ctype(source).value # cast within range - return cls(source) - def __int__(self): - return self._value - - if kind == 'bool': - @classmethod - def _cast_from(cls, source): - if not isinstance(source, (int, long, float)): - source = _cast_source_to_int(source) - return cls(bool(source)) - def __int__(self): - return self._value - - if kind == 'char': - @classmethod - def _cast_from(cls, source): - source = _cast_source_to_int(source) - source = bytechr(source & 0xFF) - return cls(source) - def __int__(self): - return ord(self._value) - - if kind == 'float': - @classmethod - def _cast_from(cls, source): - if isinstance(source, float): - pass - elif isinstance(source, CTypesGenericPrimitive): - if hasattr(source, '__float__'): - source = float(source) - else: - source = int(source) - else: - source = _cast_source_to_int(source) - source = ctype(source).value # fix precision - return cls(source) - def __int__(self): - return int(self._value) - def __float__(self): - return self._value - - _cast_to_integer = __int__ - - if kind == 'int' or kind == 'byte' or kind == 'bool': - @staticmethod - def _to_ctypes(x): - if not isinstance(x, (int, long)): - if isinstance(x, CTypesData): - x = int(x) - else: - raise TypeError("integer expected, got %s" % - type(x).__name__) - if ctype(x).value != x: - if not is_signed and x < 0: - raise OverflowError("%s: negative integer" % name) - else: - raise OverflowError("%s: integer out of bounds" - % name) - return x - - if kind == 'char': - @staticmethod - def _to_ctypes(x): - if isinstance(x, bytes) and len(x) == 1: - return x - if isinstance(x, CTypesPrimitive): # > - return x._value - raise TypeError("character expected, got %s" % - type(x).__name__) - - if kind == 'float': - @staticmethod - def _to_ctypes(x): - if not isinstance(x, (int, long, float, CTypesData)): - raise TypeError("float expected, got %s" % - type(x).__name__) - return ctype(x).value - - @staticmethod - def _from_ctypes(value): - return getattr(value, 'value', value) - - @staticmethod - def _initialize(blob, init): - blob.value = CTypesPrimitive._to_ctypes(init) - - if kind == 'char': - def _to_string(self, maxlen): - return self._value - if kind == 'byte': - def _to_string(self, maxlen): - return chr(self._value & 0xff) - # - CTypesPrimitive._fix_class() - return CTypesPrimitive - - def new_pointer_type(self, BItem): - getbtype = self.ffi._get_cached_btype - if BItem is getbtype(model.PrimitiveType('char')): - kind = 'charp' - elif BItem in (getbtype(model.PrimitiveType('signed char')), - getbtype(model.PrimitiveType('unsigned char'))): - kind = 'bytep' - elif BItem is getbtype(model.void_type): - kind = 'voidp' - else: - kind = 'generic' - # - class CTypesPtr(CTypesGenericPtr): - __slots__ = ['_own'] - if kind == 'charp': - __slots__ += ['__as_strbuf'] - _BItem = BItem - if hasattr(BItem, '_ctype'): - _ctype = ctypes.POINTER(BItem._ctype) - _bitem_size = ctypes.sizeof(BItem._ctype) - else: - _ctype = ctypes.c_void_p - if issubclass(BItem, CTypesGenericArray): - _reftypename = BItem._get_c_name('(* &)') - else: - _reftypename = BItem._get_c_name(' * &') - - def __init__(self, init): - ctypeobj = BItem._create_ctype_obj(init) - if kind == 'charp': - self.__as_strbuf = ctypes.create_string_buffer( - ctypeobj.value + b'\x00') - self._as_ctype_ptr = ctypes.cast( - self.__as_strbuf, self._ctype) - else: - self._as_ctype_ptr = ctypes.pointer(ctypeobj) - self._address = ctypes.cast(self._as_ctype_ptr, - ctypes.c_void_p).value - self._own = True - - def __add__(self, other): - if isinstance(other, (int, long)): - return self._new_pointer_at(self._address + - other * self._bitem_size) - else: - return NotImplemented - - def __sub__(self, other): - if isinstance(other, (int, long)): - return self._new_pointer_at(self._address - - other * self._bitem_size) - elif type(self) is type(other): - return (self._address - other._address) // self._bitem_size - else: - return NotImplemented - - def __getitem__(self, index): - if getattr(self, '_own', False) and index != 0: - raise IndexError - return BItem._from_ctypes(self._as_ctype_ptr[index]) - - def __setitem__(self, index, value): - self._as_ctype_ptr[index] = BItem._to_ctypes(value) - - if kind == 'charp' or kind == 'voidp': - @classmethod - def _arg_to_ctypes(cls, *value): - if value and isinstance(value[0], bytes): - return ctypes.c_char_p(value[0]) - else: - return super(CTypesPtr, cls)._arg_to_ctypes(*value) - - if kind == 'charp' or kind == 'bytep': - def _to_string(self, maxlen): - if maxlen < 0: - maxlen = sys.maxsize - p = ctypes.cast(self._as_ctype_ptr, - ctypes.POINTER(ctypes.c_char)) - n = 0 - while n < maxlen and p[n] != b'\x00': - n += 1 - return b''.join([p[i] for i in range(n)]) - - def _get_own_repr(self): - if getattr(self, '_own', False): - return 'owning %d bytes' % ( - ctypes.sizeof(self._as_ctype_ptr.contents),) - return super(CTypesPtr, self)._get_own_repr() - # - if (BItem is self.ffi._get_cached_btype(model.void_type) or - BItem is self.ffi._get_cached_btype(model.PrimitiveType('char'))): - CTypesPtr._automatic_casts = True - # - CTypesPtr._fix_class() - return CTypesPtr - - def new_array_type(self, CTypesPtr, length): - if length is None: - brackets = ' &[]' - else: - brackets = ' &[%d]' % length - BItem = CTypesPtr._BItem - getbtype = self.ffi._get_cached_btype - if BItem is getbtype(model.PrimitiveType('char')): - kind = 'char' - elif BItem in (getbtype(model.PrimitiveType('signed char')), - getbtype(model.PrimitiveType('unsigned char'))): - kind = 'byte' - else: - kind = 'generic' - # - class CTypesArray(CTypesGenericArray): - __slots__ = ['_blob', '_own'] - if length is not None: - _ctype = BItem._ctype * length - else: - __slots__.append('_ctype') - _reftypename = BItem._get_c_name(brackets) - _declared_length = length - _CTPtr = CTypesPtr - - def __init__(self, init): - if length is None: - if isinstance(init, (int, long)): - len1 = init - init = None - elif kind == 'char' and isinstance(init, bytes): - len1 = len(init) + 1 # extra null - else: - init = tuple(init) - len1 = len(init) - self._ctype = BItem._ctype * len1 - self._blob = self._ctype() - self._own = True - if init is not None: - self._initialize(self._blob, init) - - @staticmethod - def _initialize(blob, init): - if isinstance(init, bytes): - init = [init[i:i+1] for i in range(len(init))] - else: - init = tuple(init) - if len(init) > len(blob): - raise IndexError("too many initializers") - addr = ctypes.cast(blob, ctypes.c_void_p).value - PTR = ctypes.POINTER(BItem._ctype) - itemsize = ctypes.sizeof(BItem._ctype) - for i, value in enumerate(init): - p = ctypes.cast(addr + i * itemsize, PTR) - BItem._initialize(p.contents, value) - - def __len__(self): - return len(self._blob) - - def __getitem__(self, index): - if not (0 <= index < len(self._blob)): - raise IndexError - return BItem._from_ctypes(self._blob[index]) - - def __setitem__(self, index, value): - if not (0 <= index < len(self._blob)): - raise IndexError - self._blob[index] = BItem._to_ctypes(value) - - if kind == 'char' or kind == 'byte': - def _to_string(self, maxlen): - if maxlen < 0: - maxlen = len(self._blob) - p = ctypes.cast(self._blob, - ctypes.POINTER(ctypes.c_char)) - n = 0 - while n < maxlen and p[n] != b'\x00': - n += 1 - return b''.join([p[i] for i in range(n)]) - - def _get_own_repr(self): - if getattr(self, '_own', False): - return 'owning %d bytes' % (ctypes.sizeof(self._blob),) - return super(CTypesArray, self)._get_own_repr() - - def _convert_to_address(self, BClass): - if BClass in (CTypesPtr, None) or BClass._automatic_casts: - return ctypes.addressof(self._blob) - else: - return CTypesData._convert_to_address(self, BClass) - - @staticmethod - def _from_ctypes(ctypes_array): - self = CTypesArray.__new__(CTypesArray) - self._blob = ctypes_array - return self - - @staticmethod - def _arg_to_ctypes(value): - return CTypesPtr._arg_to_ctypes(value) - - def __add__(self, other): - if isinstance(other, (int, long)): - return CTypesPtr._new_pointer_at( - ctypes.addressof(self._blob) + - other * ctypes.sizeof(BItem._ctype)) - else: - return NotImplemented - - @classmethod - def _cast_from(cls, source): - raise NotImplementedError("casting to %r" % ( - cls._get_c_name(),)) - # - CTypesArray._fix_class() - return CTypesArray - - def _new_struct_or_union(self, kind, name, base_ctypes_class): - # - class struct_or_union(base_ctypes_class): - pass - struct_or_union.__name__ = '%s_%s' % (kind, name) - kind1 = kind - # - class CTypesStructOrUnion(CTypesBaseStructOrUnion): - __slots__ = ['_blob'] - _ctype = struct_or_union - _reftypename = '%s &' % (name,) - _kind = kind = kind1 - # - CTypesStructOrUnion._fix_class() - return CTypesStructOrUnion - - def new_struct_type(self, name): - return self._new_struct_or_union('struct', name, ctypes.Structure) - - def new_union_type(self, name): - return self._new_struct_or_union('union', name, ctypes.Union) - - def complete_struct_or_union(self, CTypesStructOrUnion, fields, tp, - totalsize=-1, totalalignment=-1, sflags=0): - if totalsize >= 0 or totalalignment >= 0: - raise NotImplementedError("the ctypes backend of CFFI does not support " - "structures completed by verify(); please " - "compile and install the _cffi_backend module.") - struct_or_union = CTypesStructOrUnion._ctype - fnames = [fname for (fname, BField, bitsize) in fields] - btypes = [BField for (fname, BField, bitsize) in fields] - bitfields = [bitsize for (fname, BField, bitsize) in fields] - # - bfield_types = {} - cfields = [] - for (fname, BField, bitsize) in fields: - if bitsize < 0: - cfields.append((fname, BField._ctype)) - bfield_types[fname] = BField - else: - cfields.append((fname, BField._ctype, bitsize)) - bfield_types[fname] = Ellipsis - if sflags & 8: - struct_or_union._pack_ = 1 - struct_or_union._fields_ = cfields - CTypesStructOrUnion._bfield_types = bfield_types - # - @staticmethod - def _create_ctype_obj(init): - result = struct_or_union() - if init is not None: - initialize(result, init) - return result - CTypesStructOrUnion._create_ctype_obj = _create_ctype_obj - # - def initialize(blob, init): - if is_union: - if len(init) > 1: - raise ValueError("union initializer: %d items given, but " - "only one supported (use a dict if needed)" - % (len(init),)) - if not isinstance(init, dict): - if isinstance(init, (bytes, unicode)): - raise TypeError("union initializer: got a str") - init = tuple(init) - if len(init) > len(fnames): - raise ValueError("too many values for %s initializer" % - CTypesStructOrUnion._get_c_name()) - init = dict(zip(fnames, init)) - addr = ctypes.addressof(blob) - for fname, value in init.items(): - BField, bitsize = name2fieldtype[fname] - assert bitsize < 0, \ - "not implemented: initializer with bit fields" - offset = CTypesStructOrUnion._offsetof(fname) - PTR = ctypes.POINTER(BField._ctype) - p = ctypes.cast(addr + offset, PTR) - BField._initialize(p.contents, value) - is_union = CTypesStructOrUnion._kind == 'union' - name2fieldtype = dict(zip(fnames, zip(btypes, bitfields))) - # - for fname, BField, bitsize in fields: - if fname == '': - raise NotImplementedError("nested anonymous structs/unions") - if hasattr(CTypesStructOrUnion, fname): - raise ValueError("the field name %r conflicts in " - "the ctypes backend" % fname) - if bitsize < 0: - def getter(self, fname=fname, BField=BField, - offset=CTypesStructOrUnion._offsetof(fname), - PTR=ctypes.POINTER(BField._ctype)): - addr = ctypes.addressof(self._blob) - p = ctypes.cast(addr + offset, PTR) - return BField._from_ctypes(p.contents) - def setter(self, value, fname=fname, BField=BField): - setattr(self._blob, fname, BField._to_ctypes(value)) - # - if issubclass(BField, CTypesGenericArray): - setter = None - if BField._declared_length == 0: - def getter(self, fname=fname, BFieldPtr=BField._CTPtr, - offset=CTypesStructOrUnion._offsetof(fname), - PTR=ctypes.POINTER(BField._ctype)): - addr = ctypes.addressof(self._blob) - p = ctypes.cast(addr + offset, PTR) - return BFieldPtr._from_ctypes(p) - # - else: - def getter(self, fname=fname, BField=BField): - return BField._from_ctypes(getattr(self._blob, fname)) - def setter(self, value, fname=fname, BField=BField): - # xxx obscure workaround - value = BField._to_ctypes(value) - oldvalue = getattr(self._blob, fname) - setattr(self._blob, fname, value) - if value != getattr(self._blob, fname): - setattr(self._blob, fname, oldvalue) - raise OverflowError("value too large for bitfield") - setattr(CTypesStructOrUnion, fname, property(getter, setter)) - # - CTypesPtr = self.ffi._get_cached_btype(model.PointerType(tp)) - for fname in fnames: - if hasattr(CTypesPtr, fname): - raise ValueError("the field name %r conflicts in " - "the ctypes backend" % fname) - def getter(self, fname=fname): - return getattr(self[0], fname) - def setter(self, value, fname=fname): - setattr(self[0], fname, value) - setattr(CTypesPtr, fname, property(getter, setter)) - - def new_function_type(self, BArgs, BResult, has_varargs): - nameargs = [BArg._get_c_name() for BArg in BArgs] - if has_varargs: - nameargs.append('...') - nameargs = ', '.join(nameargs) - # - class CTypesFunctionPtr(CTypesGenericPtr): - __slots__ = ['_own_callback', '_name'] - _ctype = ctypes.CFUNCTYPE(getattr(BResult, '_ctype', None), - *[BArg._ctype for BArg in BArgs], - use_errno=True) - _reftypename = BResult._get_c_name('(* &)(%s)' % (nameargs,)) - - def __init__(self, init, error=None): - # create a callback to the Python callable init() - import traceback - assert not has_varargs, "varargs not supported for callbacks" - if getattr(BResult, '_ctype', None) is not None: - error = BResult._from_ctypes( - BResult._create_ctype_obj(error)) - else: - error = None - def callback(*args): - args2 = [] - for arg, BArg in zip(args, BArgs): - args2.append(BArg._from_ctypes(arg)) - try: - res2 = init(*args2) - res2 = BResult._to_ctypes(res2) - except: - traceback.print_exc() - res2 = error - if issubclass(BResult, CTypesGenericPtr): - if res2: - res2 = ctypes.cast(res2, ctypes.c_void_p).value - # .value: http://bugs.python.org/issue1574593 - else: - res2 = None - #print repr(res2) - return res2 - if issubclass(BResult, CTypesGenericPtr): - # The only pointers callbacks can return are void*s: - # http://bugs.python.org/issue5710 - callback_ctype = ctypes.CFUNCTYPE( - ctypes.c_void_p, - *[BArg._ctype for BArg in BArgs], - use_errno=True) - else: - callback_ctype = CTypesFunctionPtr._ctype - self._as_ctype_ptr = callback_ctype(callback) - self._address = ctypes.cast(self._as_ctype_ptr, - ctypes.c_void_p).value - self._own_callback = init - - @staticmethod - def _initialize(ctypes_ptr, value): - if value: - raise NotImplementedError("ctypes backend: not supported: " - "initializers for function pointers") - - def __repr__(self): - c_name = getattr(self, '_name', None) - if c_name: - i = self._reftypename.index('(* &)') - if self._reftypename[i-1] not in ' )*': - c_name = ' ' + c_name - c_name = self._reftypename.replace('(* &)', c_name) - return CTypesData.__repr__(self, c_name) - - def _get_own_repr(self): - if getattr(self, '_own_callback', None) is not None: - return 'calling %r' % (self._own_callback,) - return super(CTypesFunctionPtr, self)._get_own_repr() - - def __call__(self, *args): - if has_varargs: - assert len(args) >= len(BArgs) - extraargs = args[len(BArgs):] - args = args[:len(BArgs)] - else: - assert len(args) == len(BArgs) - ctypes_args = [] - for arg, BArg in zip(args, BArgs): - ctypes_args.append(BArg._arg_to_ctypes(arg)) - if has_varargs: - for i, arg in enumerate(extraargs): - if arg is None: - ctypes_args.append(ctypes.c_void_p(0)) # NULL - continue - if not isinstance(arg, CTypesData): - raise TypeError( - "argument %d passed in the variadic part " - "needs to be a cdata object (got %s)" % - (1 + len(BArgs) + i, type(arg).__name__)) - ctypes_args.append(arg._arg_to_ctypes(arg)) - result = self._as_ctype_ptr(*ctypes_args) - return BResult._from_ctypes(result) - # - CTypesFunctionPtr._fix_class() - return CTypesFunctionPtr - - def new_enum_type(self, name, enumerators, enumvalues, CTypesInt): - assert isinstance(name, str) - reverse_mapping = dict(zip(reversed(enumvalues), - reversed(enumerators))) - # - class CTypesEnum(CTypesInt): - __slots__ = [] - _reftypename = '%s &' % name - - def _get_own_repr(self): - value = self._value - try: - return '%d: %s' % (value, reverse_mapping[value]) - except KeyError: - return str(value) - - def _to_string(self, maxlen): - value = self._value - try: - return reverse_mapping[value] - except KeyError: - return str(value) - # - CTypesEnum._fix_class() - return CTypesEnum - - def get_errno(self): - return ctypes.get_errno() - - def set_errno(self, value): - ctypes.set_errno(value) - - def string(self, b, maxlen=-1): - return b._to_string(maxlen) - - def buffer(self, bptr, size=-1): - raise NotImplementedError("buffer() with ctypes backend") - - def sizeof(self, cdata_or_BType): - if isinstance(cdata_or_BType, CTypesData): - return cdata_or_BType._get_size_of_instance() - else: - assert issubclass(cdata_or_BType, CTypesData) - return cdata_or_BType._get_size() - - def alignof(self, BType): - assert issubclass(BType, CTypesData) - return BType._alignment() - - def newp(self, BType, source): - if not issubclass(BType, CTypesData): - raise TypeError - return BType._newp(source) - - def cast(self, BType, source): - return BType._cast_from(source) - - def callback(self, BType, source, error, onerror): - assert onerror is None # XXX not implemented - return BType(source, error) - - typeof = type - - def getcname(self, BType, replace_with): - return BType._get_c_name(replace_with) - - def typeoffsetof(self, BType, fieldname, num=0): - if isinstance(fieldname, str): - if num == 0 and issubclass(BType, CTypesGenericPtr): - BType = BType._BItem - if not issubclass(BType, CTypesBaseStructOrUnion): - raise TypeError("expected a struct or union ctype") - BField = BType._bfield_types[fieldname] - if BField is Ellipsis: - raise TypeError("not supported for bitfields") - return (BField, BType._offsetof(fieldname)) - elif isinstance(fieldname, (int, long)): - if issubclass(BType, CTypesGenericArray): - BType = BType._CTPtr - if not issubclass(BType, CTypesGenericPtr): - raise TypeError("expected an array or ptr ctype") - BItem = BType._BItem - offset = BItem._get_size() * fieldname - if offset > sys.maxsize: - raise OverflowError - return (BItem, offset) - else: - raise TypeError(type(fieldname)) - - def rawaddressof(self, BTypePtr, cdata, offset=None): - if isinstance(cdata, CTypesBaseStructOrUnion): - ptr = ctypes.pointer(type(cdata)._to_ctypes(cdata)) - elif isinstance(cdata, CTypesGenericPtr): - if offset is None or not issubclass(type(cdata)._BItem, - CTypesBaseStructOrUnion): - raise TypeError("unexpected cdata type") - ptr = type(cdata)._to_ctypes(cdata) - elif isinstance(cdata, CTypesGenericArray): - ptr = type(cdata)._to_ctypes(cdata) - else: - raise TypeError("expected a ") - if offset: - ptr = ctypes.cast( - ctypes.c_void_p( - ctypes.cast(ptr, ctypes.c_void_p).value + offset), - type(ptr)) - return BTypePtr._from_ctypes(ptr) - - -class CTypesLibrary(object): - - def __init__(self, backend, cdll): - self.backend = backend - self.cdll = cdll - - def load_function(self, BType, name): - c_func = getattr(self.cdll, name) - funcobj = BType._from_ctypes(c_func) - funcobj._name = name - return funcobj - - def read_variable(self, BType, name): - try: - ctypes_obj = BType._ctype.in_dll(self.cdll, name) - except AttributeError as e: - raise NotImplementedError(e) - return BType._from_ctypes(ctypes_obj) - - def write_variable(self, BType, name, value): - new_ctypes_obj = BType._to_ctypes(value) - ctypes_obj = BType._ctype.in_dll(self.cdll, name) - ctypes.memmove(ctypes.addressof(ctypes_obj), - ctypes.addressof(new_ctypes_obj), - ctypes.sizeof(BType._ctype)) diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/cffi_opcode.py b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/cffi_opcode.py deleted file mode 100644 index 0da15a5..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/cffi_opcode.py +++ /dev/null @@ -1,178 +0,0 @@ - -class CffiOp(object): - def __init__(self, op, arg): - self.op = op - self.arg = arg - - def as_c_expr(self): - if self.op is None: - assert isinstance(self.arg, str) - return '(_cffi_opcode_t)(%s)' % (self.arg,) - classname = CLASS_NAME[self.op] - return '_CFFI_OP(_CFFI_OP_%s, %s)' % (classname, self.arg) - - def as_python_bytes(self): - if self.op is None and self.arg.isdigit(): - value = int(self.arg) # non-negative: '-' not in self.arg - if value >= 2**31: - raise OverflowError("cannot emit %r: limited to 2**31-1" - % (self.arg,)) - return format_four_bytes(value) - if isinstance(self.arg, str): - from .ffiplatform import VerificationError - raise VerificationError("cannot emit to Python: %r" % (self.arg,)) - return format_four_bytes((self.arg << 8) | self.op) - - def __str__(self): - classname = CLASS_NAME.get(self.op, self.op) - return '(%s %s)' % (classname, self.arg) - -def format_four_bytes(num): - return '\\x%02X\\x%02X\\x%02X\\x%02X' % ( - (num >> 24) & 0xFF, - (num >> 16) & 0xFF, - (num >> 8) & 0xFF, - (num ) & 0xFF) - -OP_PRIMITIVE = 1 -OP_POINTER = 3 -OP_ARRAY = 5 -OP_OPEN_ARRAY = 7 -OP_STRUCT_UNION = 9 -OP_ENUM = 11 -OP_FUNCTION = 13 -OP_FUNCTION_END = 15 -OP_NOOP = 17 -OP_BITFIELD = 19 -OP_TYPENAME = 21 -OP_CPYTHON_BLTN_V = 23 # varargs -OP_CPYTHON_BLTN_N = 25 # noargs -OP_CPYTHON_BLTN_O = 27 # O (i.e. a single arg) -OP_CONSTANT = 29 -OP_CONSTANT_INT = 31 -OP_GLOBAL_VAR = 33 -OP_DLOPEN_FUNC = 35 -OP_DLOPEN_CONST = 37 -OP_GLOBAL_VAR_F = 39 - -PRIM_VOID = 0 -PRIM_BOOL = 1 -PRIM_CHAR = 2 -PRIM_SCHAR = 3 -PRIM_UCHAR = 4 -PRIM_SHORT = 5 -PRIM_USHORT = 6 -PRIM_INT = 7 -PRIM_UINT = 8 -PRIM_LONG = 9 -PRIM_ULONG = 10 -PRIM_LONGLONG = 11 -PRIM_ULONGLONG = 12 -PRIM_FLOAT = 13 -PRIM_DOUBLE = 14 -PRIM_LONGDOUBLE = 15 - -PRIM_WCHAR = 16 -PRIM_INT8 = 17 -PRIM_UINT8 = 18 -PRIM_INT16 = 19 -PRIM_UINT16 = 20 -PRIM_INT32 = 21 -PRIM_UINT32 = 22 -PRIM_INT64 = 23 -PRIM_UINT64 = 24 -PRIM_INTPTR = 25 -PRIM_UINTPTR = 26 -PRIM_PTRDIFF = 27 -PRIM_SIZE = 28 -PRIM_SSIZE = 29 -PRIM_INT_LEAST8 = 30 -PRIM_UINT_LEAST8 = 31 -PRIM_INT_LEAST16 = 32 -PRIM_UINT_LEAST16 = 33 -PRIM_INT_LEAST32 = 34 -PRIM_UINT_LEAST32 = 35 -PRIM_INT_LEAST64 = 36 -PRIM_UINT_LEAST64 = 37 -PRIM_INT_FAST8 = 38 -PRIM_UINT_FAST8 = 39 -PRIM_INT_FAST16 = 40 -PRIM_UINT_FAST16 = 41 -PRIM_INT_FAST32 = 42 -PRIM_UINT_FAST32 = 43 -PRIM_INT_FAST64 = 44 -PRIM_UINT_FAST64 = 45 -PRIM_INTMAX = 46 -PRIM_UINTMAX = 47 - -_NUM_PRIM = 48 -_UNKNOWN_PRIM = -1 -_UNKNOWN_FLOAT_PRIM = -2 -_UNKNOWN_LONG_DOUBLE = -3 - -_IO_FILE_STRUCT = -1 - -PRIMITIVE_TO_INDEX = { - 'char': PRIM_CHAR, - 'short': PRIM_SHORT, - 'int': PRIM_INT, - 'long': PRIM_LONG, - 'long long': PRIM_LONGLONG, - 'signed char': PRIM_SCHAR, - 'unsigned char': PRIM_UCHAR, - 'unsigned short': PRIM_USHORT, - 'unsigned int': PRIM_UINT, - 'unsigned long': PRIM_ULONG, - 'unsigned long long': PRIM_ULONGLONG, - 'float': PRIM_FLOAT, - 'double': PRIM_DOUBLE, - 'long double': PRIM_LONGDOUBLE, - '_Bool': PRIM_BOOL, - 'wchar_t': PRIM_WCHAR, - 'int8_t': PRIM_INT8, - 'uint8_t': PRIM_UINT8, - 'int16_t': PRIM_INT16, - 'uint16_t': PRIM_UINT16, - 'int32_t': PRIM_INT32, - 'uint32_t': PRIM_UINT32, - 'int64_t': PRIM_INT64, - 'uint64_t': PRIM_UINT64, - 'intptr_t': PRIM_INTPTR, - 'uintptr_t': PRIM_UINTPTR, - 'ptrdiff_t': PRIM_PTRDIFF, - 'size_t': PRIM_SIZE, - 'ssize_t': PRIM_SSIZE, - 'int_least8_t': PRIM_INT_LEAST8, - 'uint_least8_t': PRIM_UINT_LEAST8, - 'int_least16_t': PRIM_INT_LEAST16, - 'uint_least16_t': PRIM_UINT_LEAST16, - 'int_least32_t': PRIM_INT_LEAST32, - 'uint_least32_t': PRIM_UINT_LEAST32, - 'int_least64_t': PRIM_INT_LEAST64, - 'uint_least64_t': PRIM_UINT_LEAST64, - 'int_fast8_t': PRIM_INT_FAST8, - 'uint_fast8_t': PRIM_UINT_FAST8, - 'int_fast16_t': PRIM_INT_FAST16, - 'uint_fast16_t': PRIM_UINT_FAST16, - 'int_fast32_t': PRIM_INT_FAST32, - 'uint_fast32_t': PRIM_UINT_FAST32, - 'int_fast64_t': PRIM_INT_FAST64, - 'uint_fast64_t': PRIM_UINT_FAST64, - 'intmax_t': PRIM_INTMAX, - 'uintmax_t': PRIM_UINTMAX, - } - -F_UNION = 0x01 -F_CHECK_FIELDS = 0x02 -F_PACKED = 0x04 -F_EXTERNAL = 0x08 -F_OPAQUE = 0x10 - -G_FLAGS = dict([('_CFFI_' + _key, globals()[_key]) - for _key in ['F_UNION', 'F_CHECK_FIELDS', 'F_PACKED', - 'F_EXTERNAL', 'F_OPAQUE']]) - -CLASS_NAME = {} -for _name, _value in list(globals().items()): - if _name.startswith('OP_') and isinstance(_value, int): - CLASS_NAME[_value] = _name[3:] diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/commontypes.py b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/commontypes.py deleted file mode 100644 index 3d11aae..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/commontypes.py +++ /dev/null @@ -1,76 +0,0 @@ -import sys -from . import api, model - - -COMMON_TYPES = {} - -try: - # fetch "bool" and all simple Windows types - from _cffi_backend import _get_common_types - _get_common_types(COMMON_TYPES) -except ImportError: - pass - -COMMON_TYPES['FILE'] = model.unknown_type('FILE', '_IO_FILE') -COMMON_TYPES['bool'] = '_Bool' # in case we got ImportError above - -for _type in model.PrimitiveType.ALL_PRIMITIVE_TYPES: - if _type.endswith('_t'): - COMMON_TYPES[_type] = _type -del _type - -_CACHE = {} - -def resolve_common_type(parser, commontype): - try: - return _CACHE[commontype] - except KeyError: - cdecl = COMMON_TYPES.get(commontype, commontype) - if not isinstance(cdecl, str): - result, quals = cdecl, 0 # cdecl is already a BaseType - elif cdecl in model.PrimitiveType.ALL_PRIMITIVE_TYPES: - result, quals = model.PrimitiveType(cdecl), 0 - elif cdecl == 'set-unicode-needed': - raise api.FFIError("The Windows type %r is only available after " - "you call ffi.set_unicode()" % (commontype,)) - else: - if commontype == cdecl: - raise api.FFIError("Unsupported type: %r. Please file a bug " - "if you think it should be." % (commontype,)) - result, quals = parser.parse_type_and_quals(cdecl) # recursive - - assert isinstance(result, model.BaseTypeByIdentity) - _CACHE[commontype] = result, quals - return result, quals - - -# ____________________________________________________________ -# extra types for Windows (most of them are in commontypes.c) - - -def win_common_types(): - return { - "UNICODE_STRING": model.StructType( - "_UNICODE_STRING", - ["Length", - "MaximumLength", - "Buffer"], - [model.PrimitiveType("unsigned short"), - model.PrimitiveType("unsigned short"), - model.PointerType(model.PrimitiveType("wchar_t"))], - [-1, -1, -1]), - "PUNICODE_STRING": "UNICODE_STRING *", - "PCUNICODE_STRING": "const UNICODE_STRING *", - - "TBYTE": "set-unicode-needed", - "TCHAR": "set-unicode-needed", - "LPCTSTR": "set-unicode-needed", - "PCTSTR": "set-unicode-needed", - "LPTSTR": "set-unicode-needed", - "PTSTR": "set-unicode-needed", - "PTBYTE": "set-unicode-needed", - "PTCHAR": "set-unicode-needed", - } - -if sys.platform == 'win32': - COMMON_TYPES.update(win_common_types()) diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/cparser.py b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/cparser.py deleted file mode 100644 index b3b07d7..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/cparser.py +++ /dev/null @@ -1,772 +0,0 @@ -from . import api, model -from .commontypes import COMMON_TYPES, resolve_common_type -try: - from . import _pycparser as pycparser -except ImportError: - import pycparser -import weakref, re, sys - -try: - if sys.version_info < (3,): - import thread as _thread - else: - import _thread - lock = _thread.allocate_lock() -except ImportError: - lock = None - -_r_comment = re.compile(r"/\*.*?\*/|//([^\n\\]|\\.)*?$", - re.DOTALL | re.MULTILINE) -_r_define = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)" - r"\b((?:[^\n\\]|\\.)*?)$", - re.DOTALL | re.MULTILINE) -_r_partial_enum = re.compile(r"=\s*\.\.\.\s*[,}]|\.\.\.\s*\}") -_r_enum_dotdotdot = re.compile(r"__dotdotdot\d+__$") -_r_partial_array = re.compile(r"\[\s*\.\.\.\s*\]") -_r_words = re.compile(r"\w+|\S") -_parser_cache = None -_r_int_literal = re.compile(r"-?0?x?[0-9a-f]+[lu]*$", re.IGNORECASE) -_r_stdcall1 = re.compile(r"\b(__stdcall|WINAPI)\b") -_r_stdcall2 = re.compile(r"[(]\s*(__stdcall|WINAPI)\b") -_r_cdecl = re.compile(r"\b__cdecl\b") -_r_star_const_space = re.compile( # matches "* const " - r"[*]\s*((const|volatile|restrict)\b\s*)+") - -def _get_parser(): - global _parser_cache - if _parser_cache is None: - _parser_cache = pycparser.CParser() - return _parser_cache - -def _workaround_for_old_pycparser(csource): - # Workaround for a pycparser issue (fixed between pycparser 2.10 and - # 2.14): "char*const***" gives us a wrong syntax tree, the same as - # for "char***(*const)". This means we can't tell the difference - # afterwards. But "char(*const(***))" gives us the right syntax - # tree. The issue only occurs if there are several stars in - # sequence with no parenthesis inbetween, just possibly qualifiers. - # Attempt to fix it by adding some parentheses in the source: each - # time we see "* const" or "* const *", we add an opening - # parenthesis before each star---the hard part is figuring out where - # to close them. - parts = [] - while True: - match = _r_star_const_space.search(csource) - if not match: - break - #print repr(''.join(parts)+csource), '=>', - parts.append(csource[:match.start()]) - parts.append('('); closing = ')' - parts.append(match.group()) # e.g. "* const " - endpos = match.end() - if csource.startswith('*', endpos): - parts.append('('); closing += ')' - level = 0 - i = endpos - while i < len(csource): - c = csource[i] - if c == '(': - level += 1 - elif c == ')': - if level == 0: - break - level -= 1 - elif c in ',;=': - if level == 0: - break - i += 1 - csource = csource[endpos:i] + closing + csource[i:] - #print repr(''.join(parts)+csource) - parts.append(csource) - return ''.join(parts) - -def _preprocess(csource): - # Remove comments. NOTE: this only work because the cdef() section - # should not contain any string literal! - csource = _r_comment.sub(' ', csource) - # Remove the "#define FOO x" lines - macros = {} - for match in _r_define.finditer(csource): - macroname, macrovalue = match.groups() - macrovalue = macrovalue.replace('\\\n', '').strip() - macros[macroname] = macrovalue - csource = _r_define.sub('', csource) - # - if pycparser.__version__ < '2.14': - csource = _workaround_for_old_pycparser(csource) - # - # BIG HACK: replace WINAPI or __stdcall with "volatile const". - # It doesn't make sense for the return type of a function to be - # "volatile volatile const", so we abuse it to detect __stdcall... - # Hack number 2 is that "int(volatile *fptr)();" is not valid C - # syntax, so we place the "volatile" before the opening parenthesis. - csource = _r_stdcall2.sub(' volatile volatile const(', csource) - csource = _r_stdcall1.sub(' volatile volatile const ', csource) - csource = _r_cdecl.sub(' ', csource) - # Replace "[...]" with "[__dotdotdotarray__]" - csource = _r_partial_array.sub('[__dotdotdotarray__]', csource) - # Replace "...}" with "__dotdotdotNUM__}". This construction should - # occur only at the end of enums; at the end of structs we have "...;}" - # and at the end of vararg functions "...);". Also replace "=...[,}]" - # with ",__dotdotdotNUM__[,}]": this occurs in the enums too, when - # giving an unknown value. - matches = list(_r_partial_enum.finditer(csource)) - for number, match in enumerate(reversed(matches)): - p = match.start() - if csource[p] == '=': - p2 = csource.find('...', p, match.end()) - assert p2 > p - csource = '%s,__dotdotdot%d__ %s' % (csource[:p], number, - csource[p2+3:]) - else: - assert csource[p:p+3] == '...' - csource = '%s __dotdotdot%d__ %s' % (csource[:p], number, - csource[p+3:]) - # Replace all remaining "..." with the same name, "__dotdotdot__", - # which is declared with a typedef for the purpose of C parsing. - return csource.replace('...', ' __dotdotdot__ '), macros - -def _common_type_names(csource): - # Look in the source for what looks like usages of types from the - # list of common types. A "usage" is approximated here as the - # appearance of the word, minus a "definition" of the type, which - # is the last word in a "typedef" statement. Approximative only - # but should be fine for all the common types. - look_for_words = set(COMMON_TYPES) - look_for_words.add(';') - look_for_words.add(',') - look_for_words.add('(') - look_for_words.add(')') - look_for_words.add('typedef') - words_used = set() - is_typedef = False - paren = 0 - previous_word = '' - for word in _r_words.findall(csource): - if word in look_for_words: - if word == ';': - if is_typedef: - words_used.discard(previous_word) - look_for_words.discard(previous_word) - is_typedef = False - elif word == 'typedef': - is_typedef = True - paren = 0 - elif word == '(': - paren += 1 - elif word == ')': - paren -= 1 - elif word == ',': - if is_typedef and paren == 0: - words_used.discard(previous_word) - look_for_words.discard(previous_word) - else: # word in COMMON_TYPES - words_used.add(word) - previous_word = word - return words_used - - -class Parser(object): - - def __init__(self): - self._declarations = {} - self._included_declarations = set() - self._anonymous_counter = 0 - self._structnode2type = weakref.WeakKeyDictionary() - self._override = False - self._packed = False - self._int_constants = {} - self._recomplete = [] - self._uses_new_feature = None - - def _parse(self, csource): - csource, macros = _preprocess(csource) - # XXX: for more efficiency we would need to poke into the - # internals of CParser... the following registers the - # typedefs, because their presence or absence influences the - # parsing itself (but what they are typedef'ed to plays no role) - ctn = _common_type_names(csource) - typenames = [] - for name in sorted(self._declarations): - if name.startswith('typedef '): - name = name[8:] - typenames.append(name) - ctn.discard(name) - typenames += sorted(ctn) - # - csourcelines = ['typedef int %s;' % typename for typename in typenames] - csourcelines.append('typedef int __dotdotdot__;') - csourcelines.append(csource) - csource = '\n'.join(csourcelines) - if lock is not None: - lock.acquire() # pycparser is not thread-safe... - try: - ast = _get_parser().parse(csource) - except pycparser.c_parser.ParseError as e: - self.convert_pycparser_error(e, csource) - finally: - if lock is not None: - lock.release() - # csource will be used to find buggy source text - return ast, macros, csource - - def _convert_pycparser_error(self, e, csource): - # xxx look for ":NUM:" at the start of str(e) and try to interpret - # it as a line number - line = None - msg = str(e) - if msg.startswith(':') and ':' in msg[1:]: - linenum = msg[1:msg.find(':',1)] - if linenum.isdigit(): - linenum = int(linenum, 10) - csourcelines = csource.splitlines() - if 1 <= linenum <= len(csourcelines): - line = csourcelines[linenum-1] - return line - - def convert_pycparser_error(self, e, csource): - line = self._convert_pycparser_error(e, csource) - - msg = str(e) - if line: - msg = 'cannot parse "%s"\n%s' % (line.strip(), msg) - else: - msg = 'parse error\n%s' % (msg,) - raise api.CDefError(msg) - - def parse(self, csource, override=False, packed=False): - prev_override = self._override - prev_packed = self._packed - try: - self._override = override - self._packed = packed - self._internal_parse(csource) - finally: - self._override = prev_override - self._packed = prev_packed - - def _internal_parse(self, csource): - ast, macros, csource = self._parse(csource) - # add the macros - self._process_macros(macros) - # find the first "__dotdotdot__" and use that as a separator - # between the repeated typedefs and the real csource - iterator = iter(ast.ext) - for decl in iterator: - if decl.name == '__dotdotdot__': - break - # - try: - for decl in iterator: - if isinstance(decl, pycparser.c_ast.Decl): - self._parse_decl(decl) - elif isinstance(decl, pycparser.c_ast.Typedef): - if not decl.name: - raise api.CDefError("typedef does not declare any name", - decl) - quals = 0 - if (isinstance(decl.type.type, pycparser.c_ast.IdentifierType) - and decl.type.type.names[-1] == '__dotdotdot__'): - realtype = self._get_unknown_type(decl) - elif (isinstance(decl.type, pycparser.c_ast.PtrDecl) and - isinstance(decl.type.type, pycparser.c_ast.TypeDecl) and - isinstance(decl.type.type.type, - pycparser.c_ast.IdentifierType) and - decl.type.type.type.names == ['__dotdotdot__']): - realtype = model.unknown_ptr_type(decl.name) - else: - realtype, quals = self._get_type_and_quals( - decl.type, name=decl.name) - self._declare('typedef ' + decl.name, realtype, quals=quals) - else: - raise api.CDefError("unrecognized construct", decl) - except api.FFIError as e: - msg = self._convert_pycparser_error(e, csource) - if msg: - e.args = (e.args[0] + "\n *** Err: %s" % msg,) - raise - - def _add_constants(self, key, val): - if key in self._int_constants: - if self._int_constants[key] == val: - return # ignore identical double declarations - raise api.FFIError( - "multiple declarations of constant: %s" % (key,)) - self._int_constants[key] = val - - def _add_integer_constant(self, name, int_str): - int_str = int_str.lower().rstrip("ul") - neg = int_str.startswith('-') - if neg: - int_str = int_str[1:] - # "010" is not valid oct in py3 - if (int_str.startswith("0") and int_str != '0' - and not int_str.startswith("0x")): - int_str = "0o" + int_str[1:] - pyvalue = int(int_str, 0) - if neg: - pyvalue = -pyvalue - self._add_constants(name, pyvalue) - self._declare('macro ' + name, pyvalue) - - def _process_macros(self, macros): - for key, value in macros.items(): - value = value.strip() - if _r_int_literal.match(value): - self._add_integer_constant(key, value) - elif value == '...': - self._declare('macro ' + key, value) - else: - raise api.CDefError( - 'only supports one of the following syntax:\n' - ' #define %s ... (literally dot-dot-dot)\n' - ' #define %s NUMBER (with NUMBER an integer' - ' constant, decimal/hex/octal)\n' - 'got:\n' - ' #define %s %s' - % (key, key, key, value)) - - def _parse_decl(self, decl): - node = decl.type - if isinstance(node, pycparser.c_ast.FuncDecl): - tp, quals = self._get_type_and_quals(node, name=decl.name) - assert isinstance(tp, model.RawFunctionType) - tp = self._get_type_pointer(tp, quals) - self._declare('function ' + decl.name, tp) - else: - if isinstance(node, pycparser.c_ast.Struct): - self._get_struct_union_enum_type('struct', node) - elif isinstance(node, pycparser.c_ast.Union): - self._get_struct_union_enum_type('union', node) - elif isinstance(node, pycparser.c_ast.Enum): - self._get_struct_union_enum_type('enum', node) - elif not decl.name: - raise api.CDefError("construct does not declare any variable", - decl) - # - if decl.name: - tp, quals = self._get_type_and_quals(node, - partial_length_ok=True) - if tp.is_raw_function: - tp = self._get_type_pointer(tp, quals) - self._declare('function ' + decl.name, tp) - elif (tp.is_integer_type() and - hasattr(decl, 'init') and - hasattr(decl.init, 'value') and - _r_int_literal.match(decl.init.value)): - self._add_integer_constant(decl.name, decl.init.value) - elif (tp.is_integer_type() and - isinstance(decl.init, pycparser.c_ast.UnaryOp) and - decl.init.op == '-' and - hasattr(decl.init.expr, 'value') and - _r_int_literal.match(decl.init.expr.value)): - self._add_integer_constant(decl.name, - '-' + decl.init.expr.value) - elif (quals & model.Q_CONST) and not tp.is_array_type: - self._declare('constant ' + decl.name, tp, quals=quals) - else: - self._declare('variable ' + decl.name, tp, quals=quals) - - def parse_type(self, cdecl): - return self.parse_type_and_quals(cdecl)[0] - - def parse_type_and_quals(self, cdecl): - ast, macros = self._parse('void __dummy(\n%s\n);' % cdecl)[:2] - assert not macros - exprnode = ast.ext[-1].type.args.params[0] - if isinstance(exprnode, pycparser.c_ast.ID): - raise api.CDefError("unknown identifier '%s'" % (exprnode.name,)) - return self._get_type_and_quals(exprnode.type) - - def _declare(self, name, obj, included=False, quals=0): - if name in self._declarations: - prevobj, prevquals = self._declarations[name] - if prevobj is obj and prevquals == quals: - return - if not self._override: - raise api.FFIError( - "multiple declarations of %s (for interactive usage, " - "try cdef(xx, override=True))" % (name,)) - assert '__dotdotdot__' not in name.split() - self._declarations[name] = (obj, quals) - if included: - self._included_declarations.add(obj) - - def _extract_quals(self, type): - quals = 0 - if isinstance(type, (pycparser.c_ast.TypeDecl, - pycparser.c_ast.PtrDecl)): - if 'const' in type.quals: - quals |= model.Q_CONST - if 'volatile' in type.quals: - quals |= model.Q_VOLATILE - if 'restrict' in type.quals: - quals |= model.Q_RESTRICT - return quals - - def _get_type_pointer(self, type, quals, declname=None): - if isinstance(type, model.RawFunctionType): - return type.as_function_pointer() - if (isinstance(type, model.StructOrUnionOrEnum) and - type.name.startswith('$') and type.name[1:].isdigit() and - type.forcename is None and declname is not None): - return model.NamedPointerType(type, declname, quals) - return model.PointerType(type, quals) - - def _get_type_and_quals(self, typenode, name=None, partial_length_ok=False): - # first, dereference typedefs, if we have it already parsed, we're good - if (isinstance(typenode, pycparser.c_ast.TypeDecl) and - isinstance(typenode.type, pycparser.c_ast.IdentifierType) and - len(typenode.type.names) == 1 and - ('typedef ' + typenode.type.names[0]) in self._declarations): - tp, quals = self._declarations['typedef ' + typenode.type.names[0]] - quals |= self._extract_quals(typenode) - return tp, quals - # - if isinstance(typenode, pycparser.c_ast.ArrayDecl): - # array type - if typenode.dim is None: - length = None - else: - length = self._parse_constant( - typenode.dim, partial_length_ok=partial_length_ok) - tp, quals = self._get_type_and_quals(typenode.type, - partial_length_ok=partial_length_ok) - return model.ArrayType(tp, length), quals - # - if isinstance(typenode, pycparser.c_ast.PtrDecl): - # pointer type - itemtype, itemquals = self._get_type_and_quals(typenode.type) - tp = self._get_type_pointer(itemtype, itemquals, declname=name) - quals = self._extract_quals(typenode) - return tp, quals - # - if isinstance(typenode, pycparser.c_ast.TypeDecl): - quals = self._extract_quals(typenode) - type = typenode.type - if isinstance(type, pycparser.c_ast.IdentifierType): - # assume a primitive type. get it from .names, but reduce - # synonyms to a single chosen combination - names = list(type.names) - if names != ['signed', 'char']: # keep this unmodified - prefixes = {} - while names: - name = names[0] - if name in ('short', 'long', 'signed', 'unsigned'): - prefixes[name] = prefixes.get(name, 0) + 1 - del names[0] - else: - break - # ignore the 'signed' prefix below, and reorder the others - newnames = [] - for prefix in ('unsigned', 'short', 'long'): - for i in range(prefixes.get(prefix, 0)): - newnames.append(prefix) - if not names: - names = ['int'] # implicitly - if names == ['int']: # but kill it if 'short' or 'long' - if 'short' in prefixes or 'long' in prefixes: - names = [] - names = newnames + names - ident = ' '.join(names) - if ident == 'void': - return model.void_type, quals - if ident == '__dotdotdot__': - raise api.FFIError(':%d: bad usage of "..."' % - typenode.coord.line) - tp0, quals0 = resolve_common_type(self, ident) - return tp0, (quals | quals0) - # - if isinstance(type, pycparser.c_ast.Struct): - # 'struct foobar' - tp = self._get_struct_union_enum_type('struct', type, name) - return tp, quals - # - if isinstance(type, pycparser.c_ast.Union): - # 'union foobar' - tp = self._get_struct_union_enum_type('union', type, name) - return tp, quals - # - if isinstance(type, pycparser.c_ast.Enum): - # 'enum foobar' - tp = self._get_struct_union_enum_type('enum', type, name) - return tp, quals - # - if isinstance(typenode, pycparser.c_ast.FuncDecl): - # a function type - return self._parse_function_type(typenode, name), 0 - # - # nested anonymous structs or unions end up here - if isinstance(typenode, pycparser.c_ast.Struct): - return self._get_struct_union_enum_type('struct', typenode, name, - nested=True), 0 - if isinstance(typenode, pycparser.c_ast.Union): - return self._get_struct_union_enum_type('union', typenode, name, - nested=True), 0 - # - raise api.FFIError(":%d: bad or unsupported type declaration" % - typenode.coord.line) - - def _parse_function_type(self, typenode, funcname=None): - params = list(getattr(typenode.args, 'params', [])) - for i, arg in enumerate(params): - if not hasattr(arg, 'type'): - raise api.CDefError("%s arg %d: unknown type '%s'" - " (if you meant to use the old C syntax of giving" - " untyped arguments, it is not supported)" - % (funcname or 'in expression', i + 1, - getattr(arg, 'name', '?'))) - ellipsis = ( - len(params) > 0 and - isinstance(params[-1].type, pycparser.c_ast.TypeDecl) and - isinstance(params[-1].type.type, - pycparser.c_ast.IdentifierType) and - params[-1].type.type.names == ['__dotdotdot__']) - if ellipsis: - params.pop() - if not params: - raise api.CDefError( - "%s: a function with only '(...)' as argument" - " is not correct C" % (funcname or 'in expression')) - args = [self._as_func_arg(*self._get_type_and_quals(argdeclnode.type)) - for argdeclnode in params] - if not ellipsis and args == [model.void_type]: - args = [] - result, quals = self._get_type_and_quals(typenode.type) - # the 'quals' on the result type are ignored. HACK: we absure them - # to detect __stdcall functions: we textually replace "__stdcall" - # with "volatile volatile const" above. - abi = None - if hasattr(typenode.type, 'quals'): # else, probable syntax error anyway - if typenode.type.quals[-3:] == ['volatile', 'volatile', 'const']: - abi = '__stdcall' - return model.RawFunctionType(tuple(args), result, ellipsis, abi) - - def _as_func_arg(self, type, quals): - if isinstance(type, model.ArrayType): - return model.PointerType(type.item, quals) - elif isinstance(type, model.RawFunctionType): - return type.as_function_pointer() - else: - return type - - def _get_struct_union_enum_type(self, kind, type, name=None, nested=False): - # First, a level of caching on the exact 'type' node of the AST. - # This is obscure, but needed because pycparser "unrolls" declarations - # such as "typedef struct { } foo_t, *foo_p" and we end up with - # an AST that is not a tree, but a DAG, with the "type" node of the - # two branches foo_t and foo_p of the trees being the same node. - # It's a bit silly but detecting "DAG-ness" in the AST tree seems - # to be the only way to distinguish this case from two independent - # structs. See test_struct_with_two_usages. - try: - return self._structnode2type[type] - except KeyError: - pass - # - # Note that this must handle parsing "struct foo" any number of - # times and always return the same StructType object. Additionally, - # one of these times (not necessarily the first), the fields of - # the struct can be specified with "struct foo { ...fields... }". - # If no name is given, then we have to create a new anonymous struct - # with no caching; in this case, the fields are either specified - # right now or never. - # - force_name = name - name = type.name - # - # get the type or create it if needed - if name is None: - # 'force_name' is used to guess a more readable name for - # anonymous structs, for the common case "typedef struct { } foo". - if force_name is not None: - explicit_name = '$%s' % force_name - else: - self._anonymous_counter += 1 - explicit_name = '$%d' % self._anonymous_counter - tp = None - else: - explicit_name = name - key = '%s %s' % (kind, name) - tp, _ = self._declarations.get(key, (None, None)) - # - if tp is None: - if kind == 'struct': - tp = model.StructType(explicit_name, None, None, None) - elif kind == 'union': - tp = model.UnionType(explicit_name, None, None, None) - elif kind == 'enum': - if explicit_name == '__dotdotdot__': - raise CDefError("Enums cannot be declared with ...") - tp = self._build_enum_type(explicit_name, type.values) - else: - raise AssertionError("kind = %r" % (kind,)) - if name is not None: - self._declare(key, tp) - else: - if kind == 'enum' and type.values is not None: - raise NotImplementedError( - "enum %s: the '{}' declaration should appear on the first " - "time the enum is mentioned, not later" % explicit_name) - if not tp.forcename: - tp.force_the_name(force_name) - if tp.forcename and '$' in tp.name: - self._declare('anonymous %s' % tp.forcename, tp) - # - self._structnode2type[type] = tp - # - # enums: done here - if kind == 'enum': - return tp - # - # is there a 'type.decls'? If yes, then this is the place in the - # C sources that declare the fields. If no, then just return the - # existing type, possibly still incomplete. - if type.decls is None: - return tp - # - if tp.fldnames is not None: - raise api.CDefError("duplicate declaration of struct %s" % name) - fldnames = [] - fldtypes = [] - fldbitsize = [] - fldquals = [] - for decl in type.decls: - if (isinstance(decl.type, pycparser.c_ast.IdentifierType) and - ''.join(decl.type.names) == '__dotdotdot__'): - # XXX pycparser is inconsistent: 'names' should be a list - # of strings, but is sometimes just one string. Use - # str.join() as a way to cope with both. - self._make_partial(tp, nested) - continue - if decl.bitsize is None: - bitsize = -1 - else: - bitsize = self._parse_constant(decl.bitsize) - self._partial_length = False - type, fqual = self._get_type_and_quals(decl.type, - partial_length_ok=True) - if self._partial_length: - self._make_partial(tp, nested) - if isinstance(type, model.StructType) and type.partial: - self._make_partial(tp, nested) - fldnames.append(decl.name or '') - fldtypes.append(type) - fldbitsize.append(bitsize) - fldquals.append(fqual) - tp.fldnames = tuple(fldnames) - tp.fldtypes = tuple(fldtypes) - tp.fldbitsize = tuple(fldbitsize) - tp.fldquals = tuple(fldquals) - if fldbitsize != [-1] * len(fldbitsize): - if isinstance(tp, model.StructType) and tp.partial: - raise NotImplementedError("%s: using both bitfields and '...;'" - % (tp,)) - tp.packed = self._packed - if tp.completed: # must be re-completed: it is not opaque any more - tp.completed = 0 - self._recomplete.append(tp) - return tp - - def _make_partial(self, tp, nested): - if not isinstance(tp, model.StructOrUnion): - raise api.CDefError("%s cannot be partial" % (tp,)) - if not tp.has_c_name() and not nested: - raise NotImplementedError("%s is partial but has no C name" %(tp,)) - tp.partial = True - - def _parse_constant(self, exprnode, partial_length_ok=False): - # for now, limited to expressions that are an immediate number - # or positive/negative number - if isinstance(exprnode, pycparser.c_ast.Constant): - s = exprnode.value - if s.startswith('0'): - if s.startswith('0x') or s.startswith('0X'): - return int(s, 16) - return int(s, 8) - elif '1' <= s[0] <= '9': - return int(s, 10) - elif s[0] == "'" and s[-1] == "'" and ( - len(s) == 3 or (len(s) == 4 and s[1] == "\\")): - return ord(s[-2]) - else: - raise api.CDefError("invalid constant %r" % (s,)) - # - if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and - exprnode.op == '+'): - return self._parse_constant(exprnode.expr) - # - if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and - exprnode.op == '-'): - return -self._parse_constant(exprnode.expr) - # load previously defined int constant - if (isinstance(exprnode, pycparser.c_ast.ID) and - exprnode.name in self._int_constants): - return self._int_constants[exprnode.name] - # - if partial_length_ok: - if (isinstance(exprnode, pycparser.c_ast.ID) and - exprnode.name == '__dotdotdotarray__'): - self._partial_length = True - return '...' - # - raise api.FFIError(":%d: unsupported expression: expected a " - "simple numeric constant" % exprnode.coord.line) - - def _build_enum_type(self, explicit_name, decls): - if decls is not None: - partial = False - enumerators = [] - enumvalues = [] - nextenumvalue = 0 - for enum in decls.enumerators: - if _r_enum_dotdotdot.match(enum.name): - partial = True - continue - if enum.value is not None: - nextenumvalue = self._parse_constant(enum.value) - enumerators.append(enum.name) - enumvalues.append(nextenumvalue) - self._add_constants(enum.name, nextenumvalue) - nextenumvalue += 1 - enumerators = tuple(enumerators) - enumvalues = tuple(enumvalues) - tp = model.EnumType(explicit_name, enumerators, enumvalues) - tp.partial = partial - else: # opaque enum - tp = model.EnumType(explicit_name, (), ()) - return tp - - def include(self, other): - for name, (tp, quals) in other._declarations.items(): - if name.startswith('anonymous $enum_$'): - continue # fix for test_anonymous_enum_include - kind = name.split(' ', 1)[0] - if kind in ('struct', 'union', 'enum', 'anonymous', 'typedef'): - self._declare(name, tp, included=True, quals=quals) - for k, v in other._int_constants.items(): - self._add_constants(k, v) - - def _get_unknown_type(self, decl): - typenames = decl.type.type.names - assert typenames[-1] == '__dotdotdot__' - if len(typenames) == 1: - return model.unknown_type(decl.name) - - if (typenames[:-1] == ['float'] or - typenames[:-1] == ['double']): - # not for 'long double' so far - result = model.UnknownFloatType(decl.name) - else: - for t in typenames[:-1]: - if t not in ['int', 'short', 'long', 'signed', - 'unsigned', 'char']: - raise api.FFIError(':%d: bad usage of "..."' % - decl.coord.line) - result = model.UnknownIntegerType(decl.name) - - if self._uses_new_feature is None: - self._uses_new_feature = "'typedef %s... %s'" % ( - ' '.join(typenames[:-1]), decl.name) - - return result diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/ffiplatform.py b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/ffiplatform.py deleted file mode 100644 index 62ca4f1..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/ffiplatform.py +++ /dev/null @@ -1,115 +0,0 @@ -import sys, os - - -class VerificationError(Exception): - """ An error raised when verification fails - """ - -class VerificationMissing(Exception): - """ An error raised when incomplete structures are passed into - cdef, but no verification has been done - """ - - -LIST_OF_FILE_NAMES = ['sources', 'include_dirs', 'library_dirs', - 'extra_objects', 'depends'] - -def get_extension(srcfilename, modname, sources=(), **kwds): - from distutils.core import Extension - allsources = [srcfilename] - allsources.extend(sources) - return Extension(name=modname, sources=allsources, **kwds) - -def compile(tmpdir, ext): - """Compile a C extension module using distutils.""" - - saved_environ = os.environ.copy() - try: - outputfilename = _build(tmpdir, ext) - outputfilename = os.path.abspath(outputfilename) - finally: - # workaround for a distutils bugs where some env vars can - # become longer and longer every time it is used - for key, value in saved_environ.items(): - if os.environ.get(key) != value: - os.environ[key] = value - return outputfilename - -def _build(tmpdir, ext): - # XXX compact but horrible :-( - from distutils.core import Distribution - import distutils.errors - # - dist = Distribution({'ext_modules': [ext]}) - dist.parse_config_files() - options = dist.get_option_dict('build_ext') - options['force'] = ('ffiplatform', True) - options['build_lib'] = ('ffiplatform', tmpdir) - options['build_temp'] = ('ffiplatform', tmpdir) - # - try: - dist.run_command('build_ext') - except (distutils.errors.CompileError, - distutils.errors.LinkError) as e: - raise VerificationError('%s: %s' % (e.__class__.__name__, e)) - # - cmd_obj = dist.get_command_obj('build_ext') - [soname] = cmd_obj.get_outputs() - return soname - -try: - from os.path import samefile -except ImportError: - def samefile(f1, f2): - return os.path.abspath(f1) == os.path.abspath(f2) - -def maybe_relative_path(path): - if not os.path.isabs(path): - return path # already relative - dir = path - names = [] - while True: - prevdir = dir - dir, name = os.path.split(prevdir) - if dir == prevdir or not dir: - return path # failed to make it relative - names.append(name) - try: - if samefile(dir, os.curdir): - names.reverse() - return os.path.join(*names) - except OSError: - pass - -# ____________________________________________________________ - -try: - int_or_long = (int, long) - import cStringIO -except NameError: - int_or_long = int # Python 3 - import io as cStringIO - -def _flatten(x, f): - if isinstance(x, str): - f.write('%ds%s' % (len(x), x)) - elif isinstance(x, dict): - keys = sorted(x.keys()) - f.write('%dd' % len(keys)) - for key in keys: - _flatten(key, f) - _flatten(x[key], f) - elif isinstance(x, (list, tuple)): - f.write('%dl' % len(x)) - for value in x: - _flatten(value, f) - elif isinstance(x, int_or_long): - f.write('%di' % (x,)) - else: - raise TypeError( - "the keywords to verify() contains unsupported object %r" % (x,)) - -def flatten(x): - f = cStringIO.StringIO() - _flatten(x, f) - return f.getvalue() diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/gc_weakref.py b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/gc_weakref.py deleted file mode 100644 index d0ffb23..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/gc_weakref.py +++ /dev/null @@ -1,22 +0,0 @@ -from weakref import ref - - -class GcWeakrefs(object): - def __init__(self, ffi): - self.ffi = ffi - self.data = {} - - def build(self, cdata, destructor): - # make a new cdata of the same type as the original one - new_cdata = self.ffi.cast(self.ffi._backend.typeof(cdata), cdata) - # - def remove(key): - # careful, this function is not protected by any lock - old_key = self.data.pop(index) - assert old_key is key - destructor(cdata) - # - key = ref(new_cdata, remove) - index = object() - self.data[index] = key - return new_cdata diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/lock.py b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/lock.py deleted file mode 100644 index db91b71..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/lock.py +++ /dev/null @@ -1,30 +0,0 @@ -import sys - -if sys.version_info < (3,): - try: - from thread import allocate_lock - except ImportError: - from dummy_thread import allocate_lock -else: - try: - from _thread import allocate_lock - except ImportError: - from _dummy_thread import allocate_lock - - -##import sys -##l1 = allocate_lock - -##class allocate_lock(object): -## def __init__(self): -## self._real = l1() -## def __enter__(self): -## for i in range(4, 0, -1): -## print sys._getframe(i).f_code -## print -## return self._real.__enter__() -## def __exit__(self, *args): -## return self._real.__exit__(*args) -## def acquire(self, f): -## assert f is False -## return self._real.acquire(f) diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/model.py b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/model.py deleted file mode 100644 index 5783034..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/model.py +++ /dev/null @@ -1,602 +0,0 @@ -import types, sys -import weakref - -from .lock import allocate_lock - - -# type qualifiers -Q_CONST = 0x01 -Q_RESTRICT = 0x02 -Q_VOLATILE = 0x04 - -def qualify(quals, replace_with): - if quals & Q_CONST: - replace_with = ' const ' + replace_with.lstrip() - if quals & Q_VOLATILE: - replace_with = ' volatile ' + replace_with.lstrip() - if quals & Q_RESTRICT: - # It seems that __restrict is supported by gcc and msvc. - # If you hit some different compiler, add a #define in - # _cffi_include.h for it (and in its copies, documented there) - replace_with = ' __restrict ' + replace_with.lstrip() - return replace_with - - -class BaseTypeByIdentity(object): - is_array_type = False - is_raw_function = False - - def get_c_name(self, replace_with='', context='a C file', quals=0): - result = self.c_name_with_marker - assert result.count('&') == 1 - # some logic duplication with ffi.getctype()... :-( - replace_with = replace_with.strip() - if replace_with: - if replace_with.startswith('*') and '&[' in result: - replace_with = '(%s)' % replace_with - elif not replace_with[0] in '[(': - replace_with = ' ' + replace_with - replace_with = qualify(quals, replace_with) - result = result.replace('&', replace_with) - if '$' in result: - from .ffiplatform import VerificationError - raise VerificationError( - "cannot generate '%s' in %s: unknown type name" - % (self._get_c_name(), context)) - return result - - def _get_c_name(self): - return self.c_name_with_marker.replace('&', '') - - def has_c_name(self): - return '$' not in self._get_c_name() - - def is_integer_type(self): - return False - - def get_cached_btype(self, ffi, finishlist, can_delay=False): - try: - BType = ffi._cached_btypes[self] - except KeyError: - BType = self.build_backend_type(ffi, finishlist) - BType2 = ffi._cached_btypes.setdefault(self, BType) - assert BType2 is BType - return BType - - def __repr__(self): - return '<%s>' % (self._get_c_name(),) - - def _get_items(self): - return [(name, getattr(self, name)) for name in self._attrs_] - - -class BaseType(BaseTypeByIdentity): - - def __eq__(self, other): - return (self.__class__ == other.__class__ and - self._get_items() == other._get_items()) - - def __ne__(self, other): - return not self == other - - def __hash__(self): - return hash((self.__class__, tuple(self._get_items()))) - - -class VoidType(BaseType): - _attrs_ = () - - def __init__(self): - self.c_name_with_marker = 'void&' - - def build_backend_type(self, ffi, finishlist): - return global_cache(self, ffi, 'new_void_type') - -void_type = VoidType() - - -class BasePrimitiveType(BaseType): - pass - - -class PrimitiveType(BasePrimitiveType): - _attrs_ = ('name',) - - ALL_PRIMITIVE_TYPES = { - 'char': 'c', - 'short': 'i', - 'int': 'i', - 'long': 'i', - 'long long': 'i', - 'signed char': 'i', - 'unsigned char': 'i', - 'unsigned short': 'i', - 'unsigned int': 'i', - 'unsigned long': 'i', - 'unsigned long long': 'i', - 'float': 'f', - 'double': 'f', - 'long double': 'f', - '_Bool': 'i', - # the following types are not primitive in the C sense - 'wchar_t': 'c', - 'int8_t': 'i', - 'uint8_t': 'i', - 'int16_t': 'i', - 'uint16_t': 'i', - 'int32_t': 'i', - 'uint32_t': 'i', - 'int64_t': 'i', - 'uint64_t': 'i', - 'int_least8_t': 'i', - 'uint_least8_t': 'i', - 'int_least16_t': 'i', - 'uint_least16_t': 'i', - 'int_least32_t': 'i', - 'uint_least32_t': 'i', - 'int_least64_t': 'i', - 'uint_least64_t': 'i', - 'int_fast8_t': 'i', - 'uint_fast8_t': 'i', - 'int_fast16_t': 'i', - 'uint_fast16_t': 'i', - 'int_fast32_t': 'i', - 'uint_fast32_t': 'i', - 'int_fast64_t': 'i', - 'uint_fast64_t': 'i', - 'intptr_t': 'i', - 'uintptr_t': 'i', - 'intmax_t': 'i', - 'uintmax_t': 'i', - 'ptrdiff_t': 'i', - 'size_t': 'i', - 'ssize_t': 'i', - } - - def __init__(self, name): - assert name in self.ALL_PRIMITIVE_TYPES - self.name = name - self.c_name_with_marker = name + '&' - - def is_char_type(self): - return self.ALL_PRIMITIVE_TYPES[self.name] == 'c' - def is_integer_type(self): - return self.ALL_PRIMITIVE_TYPES[self.name] == 'i' - def is_float_type(self): - return self.ALL_PRIMITIVE_TYPES[self.name] == 'f' - - def build_backend_type(self, ffi, finishlist): - return global_cache(self, ffi, 'new_primitive_type', self.name) - - -class UnknownIntegerType(BasePrimitiveType): - _attrs_ = ('name',) - - def __init__(self, name): - self.name = name - self.c_name_with_marker = name + '&' - - def is_integer_type(self): - return True - - def build_backend_type(self, ffi, finishlist): - raise NotImplementedError("integer type '%s' can only be used after " - "compilation" % self.name) - -class UnknownFloatType(BasePrimitiveType): - _attrs_ = ('name', ) - - def __init__(self, name): - self.name = name - self.c_name_with_marker = name + '&' - - def build_backend_type(self, ffi, finishlist): - raise NotImplementedError("float type '%s' can only be used after " - "compilation" % self.name) - - -class BaseFunctionType(BaseType): - _attrs_ = ('args', 'result', 'ellipsis', 'abi') - - def __init__(self, args, result, ellipsis, abi=None): - self.args = args - self.result = result - self.ellipsis = ellipsis - self.abi = abi - # - reprargs = [arg._get_c_name() for arg in self.args] - if self.ellipsis: - reprargs.append('...') - reprargs = reprargs or ['void'] - replace_with = self._base_pattern % (', '.join(reprargs),) - if abi is not None: - replace_with = replace_with[:1] + abi + ' ' + replace_with[1:] - self.c_name_with_marker = ( - self.result.c_name_with_marker.replace('&', replace_with)) - - -class RawFunctionType(BaseFunctionType): - # Corresponds to a C type like 'int(int)', which is the C type of - # a function, but not a pointer-to-function. The backend has no - # notion of such a type; it's used temporarily by parsing. - _base_pattern = '(&)(%s)' - is_raw_function = True - - def build_backend_type(self, ffi, finishlist): - from . import api - raise api.CDefError("cannot render the type %r: it is a function " - "type, not a pointer-to-function type" % (self,)) - - def as_function_pointer(self): - return FunctionPtrType(self.args, self.result, self.ellipsis, self.abi) - - -class FunctionPtrType(BaseFunctionType): - _base_pattern = '(*&)(%s)' - - def build_backend_type(self, ffi, finishlist): - result = self.result.get_cached_btype(ffi, finishlist) - args = [] - for tp in self.args: - args.append(tp.get_cached_btype(ffi, finishlist)) - abi_args = () - if self.abi == "__stdcall": - if not self.ellipsis: # __stdcall ignored for variadic funcs - try: - abi_args = (ffi._backend.FFI_STDCALL,) - except AttributeError: - pass - return global_cache(self, ffi, 'new_function_type', - tuple(args), result, self.ellipsis, *abi_args) - - def as_raw_function(self): - return RawFunctionType(self.args, self.result, self.ellipsis, self.abi) - - -class PointerType(BaseType): - _attrs_ = ('totype', 'quals') - - def __init__(self, totype, quals=0): - self.totype = totype - self.quals = quals - extra = qualify(quals, " *&") - if totype.is_array_type: - extra = "(%s)" % (extra.lstrip(),) - self.c_name_with_marker = totype.c_name_with_marker.replace('&', extra) - - def build_backend_type(self, ffi, finishlist): - BItem = self.totype.get_cached_btype(ffi, finishlist, can_delay=True) - return global_cache(self, ffi, 'new_pointer_type', BItem) - -voidp_type = PointerType(void_type) - -def ConstPointerType(totype): - return PointerType(totype, Q_CONST) - -const_voidp_type = ConstPointerType(void_type) - - -class NamedPointerType(PointerType): - _attrs_ = ('totype', 'name') - - def __init__(self, totype, name, quals=0): - PointerType.__init__(self, totype, quals) - self.name = name - self.c_name_with_marker = name + '&' - - -class ArrayType(BaseType): - _attrs_ = ('item', 'length') - is_array_type = True - - def __init__(self, item, length): - self.item = item - self.length = length - # - if length is None: - brackets = '&[]' - elif length == '...': - brackets = '&[/*...*/]' - else: - brackets = '&[%s]' % length - self.c_name_with_marker = ( - self.item.c_name_with_marker.replace('&', brackets)) - - def resolve_length(self, newlength): - return ArrayType(self.item, newlength) - - def build_backend_type(self, ffi, finishlist): - if self.length == '...': - from . import api - raise api.CDefError("cannot render the type %r: unknown length" % - (self,)) - self.item.get_cached_btype(ffi, finishlist) # force the item BType - BPtrItem = PointerType(self.item).get_cached_btype(ffi, finishlist) - return global_cache(self, ffi, 'new_array_type', BPtrItem, self.length) - -char_array_type = ArrayType(PrimitiveType('char'), None) - - -class StructOrUnionOrEnum(BaseTypeByIdentity): - _attrs_ = ('name',) - forcename = None - - def build_c_name_with_marker(self): - name = self.forcename or '%s %s' % (self.kind, self.name) - self.c_name_with_marker = name + '&' - - def force_the_name(self, forcename): - self.forcename = forcename - self.build_c_name_with_marker() - - def get_official_name(self): - assert self.c_name_with_marker.endswith('&') - return self.c_name_with_marker[:-1] - - -class StructOrUnion(StructOrUnionOrEnum): - fixedlayout = None - completed = 0 - partial = False - packed = False - - def __init__(self, name, fldnames, fldtypes, fldbitsize, fldquals=None): - self.name = name - self.fldnames = fldnames - self.fldtypes = fldtypes - self.fldbitsize = fldbitsize - self.fldquals = fldquals - self.build_c_name_with_marker() - - def has_anonymous_struct_fields(self): - if self.fldtypes is None: - return False - for name, type in zip(self.fldnames, self.fldtypes): - if name == '' and isinstance(type, StructOrUnion): - return True - return False - - def enumfields(self): - fldquals = self.fldquals - if fldquals is None: - fldquals = (0,) * len(self.fldnames) - for name, type, bitsize, quals in zip(self.fldnames, self.fldtypes, - self.fldbitsize, fldquals): - if name == '' and isinstance(type, StructOrUnion): - # nested anonymous struct/union - for result in type.enumfields(): - yield result - else: - yield (name, type, bitsize, quals) - - def force_flatten(self): - # force the struct or union to have a declaration that lists - # directly all fields returned by enumfields(), flattening - # nested anonymous structs/unions. - names = [] - types = [] - bitsizes = [] - fldquals = [] - for name, type, bitsize, quals in self.enumfields(): - names.append(name) - types.append(type) - bitsizes.append(bitsize) - fldquals.append(quals) - self.fldnames = tuple(names) - self.fldtypes = tuple(types) - self.fldbitsize = tuple(bitsizes) - self.fldquals = tuple(fldquals) - - def get_cached_btype(self, ffi, finishlist, can_delay=False): - BType = StructOrUnionOrEnum.get_cached_btype(self, ffi, finishlist, - can_delay) - if not can_delay: - self.finish_backend_type(ffi, finishlist) - return BType - - def finish_backend_type(self, ffi, finishlist): - if self.completed: - if self.completed != 2: - raise NotImplementedError("recursive structure declaration " - "for '%s'" % (self.name,)) - return - BType = ffi._cached_btypes[self] - # - self.completed = 1 - # - if self.fldtypes is None: - pass # not completing it: it's an opaque struct - # - elif self.fixedlayout is None: - fldtypes = [tp.get_cached_btype(ffi, finishlist) - for tp in self.fldtypes] - lst = list(zip(self.fldnames, fldtypes, self.fldbitsize)) - sflags = 0 - if self.packed: - sflags = 8 # SF_PACKED - ffi._backend.complete_struct_or_union(BType, lst, self, - -1, -1, sflags) - # - else: - fldtypes = [] - fieldofs, fieldsize, totalsize, totalalignment = self.fixedlayout - for i in range(len(self.fldnames)): - fsize = fieldsize[i] - ftype = self.fldtypes[i] - # - if isinstance(ftype, ArrayType) and ftype.length == '...': - # fix the length to match the total size - BItemType = ftype.item.get_cached_btype(ffi, finishlist) - nlen, nrest = divmod(fsize, ffi.sizeof(BItemType)) - if nrest != 0: - self._verification_error( - "field '%s.%s' has a bogus size?" % ( - self.name, self.fldnames[i] or '{}')) - ftype = ftype.resolve_length(nlen) - self.fldtypes = (self.fldtypes[:i] + (ftype,) + - self.fldtypes[i+1:]) - # - BFieldType = ftype.get_cached_btype(ffi, finishlist) - if isinstance(ftype, ArrayType) and ftype.length is None: - assert fsize == 0 - else: - bitemsize = ffi.sizeof(BFieldType) - if bitemsize != fsize: - self._verification_error( - "field '%s.%s' is declared as %d bytes, but is " - "really %d bytes" % (self.name, - self.fldnames[i] or '{}', - bitemsize, fsize)) - fldtypes.append(BFieldType) - # - lst = list(zip(self.fldnames, fldtypes, self.fldbitsize, fieldofs)) - ffi._backend.complete_struct_or_union(BType, lst, self, - totalsize, totalalignment) - self.completed = 2 - - def _verification_error(self, msg): - from .ffiplatform import VerificationError - raise VerificationError(msg) - - def check_not_partial(self): - if self.partial and self.fixedlayout is None: - from . import ffiplatform - raise ffiplatform.VerificationMissing(self._get_c_name()) - - def build_backend_type(self, ffi, finishlist): - self.check_not_partial() - finishlist.append(self) - # - return global_cache(self, ffi, 'new_%s_type' % self.kind, - self.get_official_name(), key=self) - - -class StructType(StructOrUnion): - kind = 'struct' - - -class UnionType(StructOrUnion): - kind = 'union' - - -class EnumType(StructOrUnionOrEnum): - kind = 'enum' - partial = False - partial_resolved = False - - def __init__(self, name, enumerators, enumvalues, baseinttype=None): - self.name = name - self.enumerators = enumerators - self.enumvalues = enumvalues - self.baseinttype = baseinttype - self.build_c_name_with_marker() - - def force_the_name(self, forcename): - StructOrUnionOrEnum.force_the_name(self, forcename) - if self.forcename is None: - name = self.get_official_name() - self.forcename = '$' + name.replace(' ', '_') - - def check_not_partial(self): - if self.partial and not self.partial_resolved: - from . import ffiplatform - raise ffiplatform.VerificationMissing(self._get_c_name()) - - def build_backend_type(self, ffi, finishlist): - self.check_not_partial() - base_btype = self.build_baseinttype(ffi, finishlist) - return global_cache(self, ffi, 'new_enum_type', - self.get_official_name(), - self.enumerators, self.enumvalues, - base_btype, key=self) - - def build_baseinttype(self, ffi, finishlist): - if self.baseinttype is not None: - return self.baseinttype.get_cached_btype(ffi, finishlist) - # - from . import api - if self.enumvalues: - smallest_value = min(self.enumvalues) - largest_value = max(self.enumvalues) - else: - import warnings - warnings.warn("%r has no values explicitly defined; next version " - "will refuse to guess which integer type it is " - "meant to be (unsigned/signed, int/long)" - % self._get_c_name()) - smallest_value = largest_value = 0 - if smallest_value < 0: # needs a signed type - sign = 1 - candidate1 = PrimitiveType("int") - candidate2 = PrimitiveType("long") - else: - sign = 0 - candidate1 = PrimitiveType("unsigned int") - candidate2 = PrimitiveType("unsigned long") - btype1 = candidate1.get_cached_btype(ffi, finishlist) - btype2 = candidate2.get_cached_btype(ffi, finishlist) - size1 = ffi.sizeof(btype1) - size2 = ffi.sizeof(btype2) - if (smallest_value >= ((-1) << (8*size1-1)) and - largest_value < (1 << (8*size1-sign))): - return btype1 - if (smallest_value >= ((-1) << (8*size2-1)) and - largest_value < (1 << (8*size2-sign))): - return btype2 - raise api.CDefError("%s values don't all fit into either 'long' " - "or 'unsigned long'" % self._get_c_name()) - -def unknown_type(name, structname=None): - if structname is None: - structname = '$%s' % name - tp = StructType(structname, None, None, None) - tp.force_the_name(name) - tp.origin = "unknown_type" - return tp - -def unknown_ptr_type(name, structname=None): - if structname is None: - structname = '$$%s' % name - tp = StructType(structname, None, None, None) - return NamedPointerType(tp, name) - - -global_lock = allocate_lock() - -def global_cache(srctype, ffi, funcname, *args, **kwds): - key = kwds.pop('key', (funcname, args)) - assert not kwds - try: - return ffi._backend.__typecache[key] - except KeyError: - pass - except AttributeError: - # initialize the __typecache attribute, either at the module level - # if ffi._backend is a module, or at the class level if ffi._backend - # is some instance. - if isinstance(ffi._backend, types.ModuleType): - ffi._backend.__typecache = weakref.WeakValueDictionary() - else: - type(ffi._backend).__typecache = weakref.WeakValueDictionary() - try: - res = getattr(ffi._backend, funcname)(*args) - except NotImplementedError as e: - raise NotImplementedError("%s: %r: %s" % (funcname, srctype, e)) - # note that setdefault() on WeakValueDictionary is not atomic - # and contains a rare bug (http://bugs.python.org/issue19542); - # we have to use a lock and do it ourselves - cache = ffi._backend.__typecache - with global_lock: - res1 = cache.get(key) - if res1 is None: - cache[key] = res - return res - else: - return res1 - -def pointer_cache(ffi, BType): - return global_cache('?', ffi, 'new_pointer_type', BType) - -def attach_exception_info(e, name): - if e.args and type(e.args[0]) is str: - e.args = ('%s: %s' % (name, e.args[0]),) + e.args[1:] diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/parse_c_type.h b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/parse_c_type.h deleted file mode 100644 index 693ea9b..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/parse_c_type.h +++ /dev/null @@ -1,169 +0,0 @@ - -/* See doc/misc/parse_c_type.rst in the source of CFFI for more information */ - -typedef void *_cffi_opcode_t; - -#define _CFFI_OP(opcode, arg) (_cffi_opcode_t)(opcode | (((uintptr_t)(arg)) << 8)) -#define _CFFI_GETOP(cffi_opcode) ((unsigned char)(uintptr_t)cffi_opcode) -#define _CFFI_GETARG(cffi_opcode) (((intptr_t)cffi_opcode) >> 8) - -#define _CFFI_OP_PRIMITIVE 1 -#define _CFFI_OP_POINTER 3 -#define _CFFI_OP_ARRAY 5 -#define _CFFI_OP_OPEN_ARRAY 7 -#define _CFFI_OP_STRUCT_UNION 9 -#define _CFFI_OP_ENUM 11 -#define _CFFI_OP_FUNCTION 13 -#define _CFFI_OP_FUNCTION_END 15 -#define _CFFI_OP_NOOP 17 -#define _CFFI_OP_BITFIELD 19 -#define _CFFI_OP_TYPENAME 21 -#define _CFFI_OP_CPYTHON_BLTN_V 23 // varargs -#define _CFFI_OP_CPYTHON_BLTN_N 25 // noargs -#define _CFFI_OP_CPYTHON_BLTN_O 27 // O (i.e. a single arg) -#define _CFFI_OP_CONSTANT 29 -#define _CFFI_OP_CONSTANT_INT 31 -#define _CFFI_OP_GLOBAL_VAR 33 -#define _CFFI_OP_DLOPEN_FUNC 35 -#define _CFFI_OP_DLOPEN_CONST 37 -#define _CFFI_OP_GLOBAL_VAR_F 39 - -#define _CFFI_PRIM_VOID 0 -#define _CFFI_PRIM_BOOL 1 -#define _CFFI_PRIM_CHAR 2 -#define _CFFI_PRIM_SCHAR 3 -#define _CFFI_PRIM_UCHAR 4 -#define _CFFI_PRIM_SHORT 5 -#define _CFFI_PRIM_USHORT 6 -#define _CFFI_PRIM_INT 7 -#define _CFFI_PRIM_UINT 8 -#define _CFFI_PRIM_LONG 9 -#define _CFFI_PRIM_ULONG 10 -#define _CFFI_PRIM_LONGLONG 11 -#define _CFFI_PRIM_ULONGLONG 12 -#define _CFFI_PRIM_FLOAT 13 -#define _CFFI_PRIM_DOUBLE 14 -#define _CFFI_PRIM_LONGDOUBLE 15 - -#define _CFFI_PRIM_WCHAR 16 -#define _CFFI_PRIM_INT8 17 -#define _CFFI_PRIM_UINT8 18 -#define _CFFI_PRIM_INT16 19 -#define _CFFI_PRIM_UINT16 20 -#define _CFFI_PRIM_INT32 21 -#define _CFFI_PRIM_UINT32 22 -#define _CFFI_PRIM_INT64 23 -#define _CFFI_PRIM_UINT64 24 -#define _CFFI_PRIM_INTPTR 25 -#define _CFFI_PRIM_UINTPTR 26 -#define _CFFI_PRIM_PTRDIFF 27 -#define _CFFI_PRIM_SIZE 28 -#define _CFFI_PRIM_SSIZE 29 -#define _CFFI_PRIM_INT_LEAST8 30 -#define _CFFI_PRIM_UINT_LEAST8 31 -#define _CFFI_PRIM_INT_LEAST16 32 -#define _CFFI_PRIM_UINT_LEAST16 33 -#define _CFFI_PRIM_INT_LEAST32 34 -#define _CFFI_PRIM_UINT_LEAST32 35 -#define _CFFI_PRIM_INT_LEAST64 36 -#define _CFFI_PRIM_UINT_LEAST64 37 -#define _CFFI_PRIM_INT_FAST8 38 -#define _CFFI_PRIM_UINT_FAST8 39 -#define _CFFI_PRIM_INT_FAST16 40 -#define _CFFI_PRIM_UINT_FAST16 41 -#define _CFFI_PRIM_INT_FAST32 42 -#define _CFFI_PRIM_UINT_FAST32 43 -#define _CFFI_PRIM_INT_FAST64 44 -#define _CFFI_PRIM_UINT_FAST64 45 -#define _CFFI_PRIM_INTMAX 46 -#define _CFFI_PRIM_UINTMAX 47 - -#define _CFFI__NUM_PRIM 48 -#define _CFFI__UNKNOWN_PRIM (-1) -#define _CFFI__UNKNOWN_FLOAT_PRIM (-2) -#define _CFFI__UNKNOWN_LONG_DOUBLE (-3) - -#define _CFFI__IO_FILE_STRUCT (-1) - - -struct _cffi_global_s { - const char *name; - void *address; - _cffi_opcode_t type_op; - void *size_or_direct_fn; // OP_GLOBAL_VAR: size, or 0 if unknown - // OP_CPYTHON_BLTN_*: addr of direct function -}; - -struct _cffi_getconst_s { - unsigned long long value; - const struct _cffi_type_context_s *ctx; - int gindex; -}; - -struct _cffi_struct_union_s { - const char *name; - int type_index; // -> _cffi_types, on a OP_STRUCT_UNION - int flags; // _CFFI_F_* flags below - size_t size; - int alignment; - int first_field_index; // -> _cffi_fields array - int num_fields; -}; -#define _CFFI_F_UNION 0x01 // is a union, not a struct -#define _CFFI_F_CHECK_FIELDS 0x02 // complain if fields are not in the - // "standard layout" or if some are missing -#define _CFFI_F_PACKED 0x04 // for CHECK_FIELDS, assume a packed struct -#define _CFFI_F_EXTERNAL 0x08 // in some other ffi.include() -#define _CFFI_F_OPAQUE 0x10 // opaque - -struct _cffi_field_s { - const char *name; - size_t field_offset; - size_t field_size; - _cffi_opcode_t field_type_op; -}; - -struct _cffi_enum_s { - const char *name; - int type_index; // -> _cffi_types, on a OP_ENUM - int type_prim; // _CFFI_PRIM_xxx - const char *enumerators; // comma-delimited string -}; - -struct _cffi_typename_s { - const char *name; - int type_index; /* if opaque, points to a possibly artificial - OP_STRUCT which is itself opaque */ -}; - -struct _cffi_type_context_s { - _cffi_opcode_t *types; - const struct _cffi_global_s *globals; - const struct _cffi_field_s *fields; - const struct _cffi_struct_union_s *struct_unions; - const struct _cffi_enum_s *enums; - const struct _cffi_typename_s *typenames; - int num_globals; - int num_struct_unions; - int num_enums; - int num_typenames; - const char *const *includes; - int num_types; - int flags; /* future extension */ -}; - -struct _cffi_parse_info_s { - const struct _cffi_type_context_s *ctx; - _cffi_opcode_t *output; - unsigned int output_size; - size_t error_location; - const char *error_message; -}; - -#ifdef _CFFI_INTERNAL -static int parse_c_type(struct _cffi_parse_info_s *info, const char *input); -static int search_in_globals(const struct _cffi_type_context_s *ctx, - const char *search, size_t search_len); -static int search_in_struct_unions(const struct _cffi_type_context_s *ctx, - const char *search, size_t search_len); -#endif diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/recompiler.py b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/recompiler.py deleted file mode 100644 index 56b9efb..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/recompiler.py +++ /dev/null @@ -1,1290 +0,0 @@ -import os, sys, io -from . import ffiplatform, model -from .cffi_opcode import * - -VERSION = "0x2601" - - -class GlobalExpr: - def __init__(self, name, address, type_op, size=0, check_value=0): - self.name = name - self.address = address - self.type_op = type_op - self.size = size - self.check_value = check_value - - def as_c_expr(self): - return ' { "%s", (void *)%s, %s, (void *)%s },' % ( - self.name, self.address, self.type_op.as_c_expr(), self.size) - - def as_python_expr(self): - return "b'%s%s',%d" % (self.type_op.as_python_bytes(), self.name, - self.check_value) - -class FieldExpr: - def __init__(self, name, field_offset, field_size, fbitsize, field_type_op): - self.name = name - self.field_offset = field_offset - self.field_size = field_size - self.fbitsize = fbitsize - self.field_type_op = field_type_op - - def as_c_expr(self): - spaces = " " * len(self.name) - return (' { "%s", %s,\n' % (self.name, self.field_offset) + - ' %s %s,\n' % (spaces, self.field_size) + - ' %s %s },' % (spaces, self.field_type_op.as_c_expr())) - - def as_python_expr(self): - raise NotImplementedError - - def as_field_python_expr(self): - if self.field_type_op.op == OP_NOOP: - size_expr = '' - elif self.field_type_op.op == OP_BITFIELD: - size_expr = format_four_bytes(self.fbitsize) - else: - raise NotImplementedError - return "b'%s%s%s'" % (self.field_type_op.as_python_bytes(), - size_expr, - self.name) - -class StructUnionExpr: - def __init__(self, name, type_index, flags, size, alignment, comment, - first_field_index, c_fields): - self.name = name - self.type_index = type_index - self.flags = flags - self.size = size - self.alignment = alignment - self.comment = comment - self.first_field_index = first_field_index - self.c_fields = c_fields - - def as_c_expr(self): - return (' { "%s", %d, %s,' % (self.name, self.type_index, self.flags) - + '\n %s, %s, ' % (self.size, self.alignment) - + '%d, %d ' % (self.first_field_index, len(self.c_fields)) - + ('/* %s */ ' % self.comment if self.comment else '') - + '},') - - def as_python_expr(self): - flags = eval(self.flags, G_FLAGS) - fields_expr = [c_field.as_field_python_expr() - for c_field in self.c_fields] - return "(b'%s%s%s',%s)" % ( - format_four_bytes(self.type_index), - format_four_bytes(flags), - self.name, - ','.join(fields_expr)) - -class EnumExpr: - def __init__(self, name, type_index, size, signed, allenums): - self.name = name - self.type_index = type_index - self.size = size - self.signed = signed - self.allenums = allenums - - def as_c_expr(self): - return (' { "%s", %d, _cffi_prim_int(%s, %s),\n' - ' "%s" },' % (self.name, self.type_index, - self.size, self.signed, self.allenums)) - - def as_python_expr(self): - prim_index = { - (1, 0): PRIM_UINT8, (1, 1): PRIM_INT8, - (2, 0): PRIM_UINT16, (2, 1): PRIM_INT16, - (4, 0): PRIM_UINT32, (4, 1): PRIM_INT32, - (8, 0): PRIM_UINT64, (8, 1): PRIM_INT64, - }[self.size, self.signed] - return "b'%s%s%s\\x00%s'" % (format_four_bytes(self.type_index), - format_four_bytes(prim_index), - self.name, self.allenums) - -class TypenameExpr: - def __init__(self, name, type_index): - self.name = name - self.type_index = type_index - - def as_c_expr(self): - return ' { "%s", %d },' % (self.name, self.type_index) - - def as_python_expr(self): - return "b'%s%s'" % (format_four_bytes(self.type_index), self.name) - - -# ____________________________________________________________ - - -class Recompiler: - - def __init__(self, ffi, module_name, target_is_python=False): - self.ffi = ffi - self.module_name = module_name - self.target_is_python = target_is_python - - def collect_type_table(self): - self._typesdict = {} - self._generate("collecttype") - # - all_decls = sorted(self._typesdict, key=str) - # - # prepare all FUNCTION bytecode sequences first - self.cffi_types = [] - for tp in all_decls: - if tp.is_raw_function: - assert self._typesdict[tp] is None - self._typesdict[tp] = len(self.cffi_types) - self.cffi_types.append(tp) # placeholder - for tp1 in tp.args: - assert isinstance(tp1, (model.VoidType, - model.BasePrimitiveType, - model.PointerType, - model.StructOrUnionOrEnum, - model.FunctionPtrType)) - if self._typesdict[tp1] is None: - self._typesdict[tp1] = len(self.cffi_types) - self.cffi_types.append(tp1) # placeholder - self.cffi_types.append('END') # placeholder - # - # prepare all OTHER bytecode sequences - for tp in all_decls: - if not tp.is_raw_function and self._typesdict[tp] is None: - self._typesdict[tp] = len(self.cffi_types) - self.cffi_types.append(tp) # placeholder - if tp.is_array_type and tp.length is not None: - self.cffi_types.append('LEN') # placeholder - assert None not in self._typesdict.values() - # - # collect all structs and unions and enums - self._struct_unions = {} - self._enums = {} - for tp in all_decls: - if isinstance(tp, model.StructOrUnion): - self._struct_unions[tp] = None - elif isinstance(tp, model.EnumType): - self._enums[tp] = None - for i, tp in enumerate(sorted(self._struct_unions, - key=lambda tp: tp.name)): - self._struct_unions[tp] = i - for i, tp in enumerate(sorted(self._enums, - key=lambda tp: tp.name)): - self._enums[tp] = i - # - # emit all bytecode sequences now - for tp in all_decls: - method = getattr(self, '_emit_bytecode_' + tp.__class__.__name__) - method(tp, self._typesdict[tp]) - # - # consistency check - for op in self.cffi_types: - assert isinstance(op, CffiOp) - self.cffi_types = tuple(self.cffi_types) # don't change any more - - def _do_collect_type(self, tp): - if not isinstance(tp, model.BaseTypeByIdentity): - if isinstance(tp, tuple): - for x in tp: - self._do_collect_type(x) - return - if tp not in self._typesdict: - self._typesdict[tp] = None - if isinstance(tp, model.FunctionPtrType): - self._do_collect_type(tp.as_raw_function()) - elif isinstance(tp, model.StructOrUnion): - if tp.fldtypes is not None and ( - tp not in self.ffi._parser._included_declarations): - for name1, tp1, _, _ in tp.enumfields(): - self._do_collect_type(self._field_type(tp, name1, tp1)) - else: - for _, x in tp._get_items(): - self._do_collect_type(x) - - def _generate(self, step_name): - lst = self.ffi._parser._declarations.items() - for name, (tp, quals) in sorted(lst): - kind, realname = name.split(' ', 1) - try: - method = getattr(self, '_generate_cpy_%s_%s' % (kind, - step_name)) - except AttributeError: - raise ffiplatform.VerificationError( - "not implemented in recompile(): %r" % name) - try: - self._current_quals = quals - method(tp, realname) - except Exception as e: - model.attach_exception_info(e, name) - raise - - # ---------- - - ALL_STEPS = ["global", "field", "struct_union", "enum", "typename"] - - def collect_step_tables(self): - # collect the declarations for '_cffi_globals', '_cffi_typenames', etc. - self._lsts = {} - for step_name in self.ALL_STEPS: - self._lsts[step_name] = [] - self._seen_struct_unions = set() - self._generate("ctx") - self._add_missing_struct_unions() - # - for step_name in self.ALL_STEPS: - lst = self._lsts[step_name] - if step_name != "field": - lst.sort(key=lambda entry: entry.name) - self._lsts[step_name] = tuple(lst) # don't change any more - # - # check for a possible internal inconsistency: _cffi_struct_unions - # should have been generated with exactly self._struct_unions - lst = self._lsts["struct_union"] - for tp, i in self._struct_unions.items(): - assert i < len(lst) - assert lst[i].name == tp.name - assert len(lst) == len(self._struct_unions) - # same with enums - lst = self._lsts["enum"] - for tp, i in self._enums.items(): - assert i < len(lst) - assert lst[i].name == tp.name - assert len(lst) == len(self._enums) - - # ---------- - - def _prnt(self, what=''): - self._f.write(what + '\n') - - def write_source_to_f(self, f, preamble): - if self.target_is_python: - assert preamble is None - self.write_py_source_to_f(f) - else: - assert preamble is not None - self.write_c_source_to_f(f, preamble) - - def _rel_readlines(self, filename): - g = open(os.path.join(os.path.dirname(__file__), filename), 'r') - lines = g.readlines() - g.close() - return lines - - def write_c_source_to_f(self, f, preamble): - self._f = f - prnt = self._prnt - # - # first the '#include' (actually done by inlining the file's content) - lines = self._rel_readlines('_cffi_include.h') - i = lines.index('#include "parse_c_type.h"\n') - lines[i:i+1] = self._rel_readlines('parse_c_type.h') - prnt(''.join(lines)) - # - # then paste the C source given by the user, verbatim. - prnt('/************************************************************/') - prnt() - prnt(preamble) - prnt() - prnt('/************************************************************/') - prnt() - # - # the declaration of '_cffi_types' - prnt('static void *_cffi_types[] = {') - typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()]) - for i, op in enumerate(self.cffi_types): - comment = '' - if i in typeindex2type: - comment = ' // ' + typeindex2type[i]._get_c_name() - prnt('/* %2d */ %s,%s' % (i, op.as_c_expr(), comment)) - if not self.cffi_types: - prnt(' 0') - prnt('};') - prnt() - # - # call generate_cpy_xxx_decl(), for every xxx found from - # ffi._parser._declarations. This generates all the functions. - self._seen_constants = set() - self._generate("decl") - # - # the declaration of '_cffi_globals' and '_cffi_typenames' - nums = {} - for step_name in self.ALL_STEPS: - lst = self._lsts[step_name] - nums[step_name] = len(lst) - if nums[step_name] > 0: - prnt('static const struct _cffi_%s_s _cffi_%ss[] = {' % ( - step_name, step_name)) - for entry in lst: - prnt(entry.as_c_expr()) - prnt('};') - prnt() - # - # the declaration of '_cffi_includes' - if self.ffi._included_ffis: - prnt('static const char * const _cffi_includes[] = {') - for ffi_to_include in self.ffi._included_ffis: - try: - included_module_name, included_source = ( - ffi_to_include._assigned_source[:2]) - except AttributeError: - raise ffiplatform.VerificationError( - "ffi object %r includes %r, but the latter has not " - "been prepared with set_source()" % ( - self.ffi, ffi_to_include,)) - if included_source is None: - raise ffiplatform.VerificationError( - "not implemented yet: ffi.include() of a Python-based " - "ffi inside a C-based ffi") - prnt(' "%s",' % (included_module_name,)) - prnt(' NULL') - prnt('};') - prnt() - # - # the declaration of '_cffi_type_context' - prnt('static const struct _cffi_type_context_s _cffi_type_context = {') - prnt(' _cffi_types,') - for step_name in self.ALL_STEPS: - if nums[step_name] > 0: - prnt(' _cffi_%ss,' % step_name) - else: - prnt(' NULL, /* no %ss */' % step_name) - for step_name in self.ALL_STEPS: - if step_name != "field": - prnt(' %d, /* num_%ss */' % (nums[step_name], step_name)) - if self.ffi._included_ffis: - prnt(' _cffi_includes,') - else: - prnt(' NULL, /* no includes */') - prnt(' %d, /* num_types */' % (len(self.cffi_types),)) - prnt(' 0, /* flags */') - prnt('};') - prnt() - # - # the init function - base_module_name = self.module_name.split('.')[-1] - prnt('#ifdef PYPY_VERSION') - prnt('PyMODINIT_FUNC') - prnt('_cffi_pypyinit_%s(const void *p[])' % (base_module_name,)) - prnt('{') - prnt(' p[0] = (const void *)%s;' % VERSION) - prnt(' p[1] = &_cffi_type_context;') - prnt('}') - # on Windows, distutils insists on putting init_cffi_xyz in - # 'export_symbols', so instead of fighting it, just give up and - # give it one - prnt('# ifdef _MSC_VER') - prnt(' PyMODINIT_FUNC') - prnt('# if PY_MAJOR_VERSION >= 3') - prnt(' PyInit_%s(void) { return NULL; }' % (base_module_name,)) - prnt('# else') - prnt(' init%s(void) { }' % (base_module_name,)) - prnt('# endif') - prnt('# endif') - prnt('#elif PY_MAJOR_VERSION >= 3') - prnt('PyMODINIT_FUNC') - prnt('PyInit_%s(void)' % (base_module_name,)) - prnt('{') - prnt(' return _cffi_init("%s", %s, &_cffi_type_context);' % ( - self.module_name, VERSION)) - prnt('}') - prnt('#else') - prnt('PyMODINIT_FUNC') - prnt('init%s(void)' % (base_module_name,)) - prnt('{') - prnt(' _cffi_init("%s", %s, &_cffi_type_context);' % ( - self.module_name, VERSION)) - prnt('}') - prnt('#endif') - - def _to_py(self, x): - if isinstance(x, str): - return "b'%s'" % (x,) - if isinstance(x, (list, tuple)): - rep = [self._to_py(item) for item in x] - if len(rep) == 1: - rep.append('') - return "(%s)" % (','.join(rep),) - return x.as_python_expr() # Py2: unicode unexpected; Py3: bytes unexp. - - def write_py_source_to_f(self, f): - self._f = f - prnt = self._prnt - # - # header - prnt("# auto-generated file") - prnt("import _cffi_backend") - # - # the 'import' of the included ffis - num_includes = len(self.ffi._included_ffis or ()) - for i in range(num_includes): - ffi_to_include = self.ffi._included_ffis[i] - try: - included_module_name, included_source = ( - ffi_to_include._assigned_source[:2]) - except AttributeError: - raise ffiplatform.VerificationError( - "ffi object %r includes %r, but the latter has not " - "been prepared with set_source()" % ( - self.ffi, ffi_to_include,)) - if included_source is not None: - raise ffiplatform.VerificationError( - "not implemented yet: ffi.include() of a C-based " - "ffi inside a Python-based ffi") - prnt('from %s import ffi as _ffi%d' % (included_module_name, i)) - prnt() - prnt("ffi = _cffi_backend.FFI('%s'," % (self.module_name,)) - prnt(" _version = %s," % (VERSION,)) - # - # the '_types' keyword argument - self.cffi_types = tuple(self.cffi_types) # don't change any more - types_lst = [op.as_python_bytes() for op in self.cffi_types] - prnt(' _types = %s,' % (self._to_py(''.join(types_lst)),)) - typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()]) - # - # the keyword arguments from ALL_STEPS - for step_name in self.ALL_STEPS: - lst = self._lsts[step_name] - if len(lst) > 0 and step_name != "field": - prnt(' _%ss = %s,' % (step_name, self._to_py(lst))) - # - # the '_includes' keyword argument - if num_includes > 0: - prnt(' _includes = (%s,),' % ( - ', '.join(['_ffi%d' % i for i in range(num_includes)]),)) - # - # the footer - prnt(')') - - # ---------- - - def _gettypenum(self, type): - # a KeyError here is a bug. please report it! :-) - return self._typesdict[type] - - def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode): - extraarg = '' - if isinstance(tp, model.BasePrimitiveType): - if tp.is_integer_type() and tp.name != '_Bool': - converter = '_cffi_to_c_int' - extraarg = ', %s' % tp.name - elif isinstance(tp, model.UnknownFloatType): - # don't check with is_float_type(): it may be a 'long - # double' here, and _cffi_to_c_double would loose precision - converter = '(%s)_cffi_to_c_double' % (tp.get_c_name(''),) - else: - converter = '(%s)_cffi_to_c_%s' % (tp.get_c_name(''), - tp.name.replace(' ', '_')) - errvalue = '-1' - # - elif isinstance(tp, model.PointerType): - self._convert_funcarg_to_c_ptr_or_array(tp, fromvar, - tovar, errcode) - return - # - elif isinstance(tp, (model.StructOrUnion, model.EnumType)): - # a struct (not a struct pointer) as a function argument - self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)' - % (tovar, self._gettypenum(tp), fromvar)) - self._prnt(' %s;' % errcode) - return - # - elif isinstance(tp, model.FunctionPtrType): - converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('') - extraarg = ', _cffi_type(%d)' % self._gettypenum(tp) - errvalue = 'NULL' - # - else: - raise NotImplementedError(tp) - # - self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg)) - self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % ( - tovar, tp.get_c_name(''), errvalue)) - self._prnt(' %s;' % errcode) - - def _extra_local_variables(self, tp, localvars): - if isinstance(tp, model.PointerType): - localvars.add('Py_ssize_t datasize') - - def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): - self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') - self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( - self._gettypenum(tp), fromvar, tovar)) - self._prnt(' if (datasize != 0) {') - self._prnt(' if (datasize < 0)') - self._prnt(' %s;' % errcode) - self._prnt(' %s = (%s)alloca((size_t)datasize);' % ( - tovar, tp.get_c_name(''))) - self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,)) - self._prnt(' if (_cffi_convert_array_from_object(' - '(char *)%s, _cffi_type(%d), %s) < 0)' % ( - tovar, self._gettypenum(tp), fromvar)) - self._prnt(' %s;' % errcode) - self._prnt(' }') - - def _convert_expr_from_c(self, tp, var, context): - if isinstance(tp, model.BasePrimitiveType): - if tp.is_integer_type(): - return '_cffi_from_c_int(%s, %s)' % (var, tp.name) - elif isinstance(tp, model.UnknownFloatType): - return '_cffi_from_c_double(%s)' % (var,) - elif tp.name != 'long double': - return '_cffi_from_c_%s(%s)' % (tp.name.replace(' ', '_'), var) - else: - return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - elif isinstance(tp, (model.PointerType, model.FunctionPtrType)): - return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - elif isinstance(tp, model.ArrayType): - return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( - var, self._gettypenum(model.PointerType(tp.item))) - elif isinstance(tp, model.StructType): - if tp.fldnames is None: - raise TypeError("'%s' is used as %s, but is opaque" % ( - tp._get_c_name(), context)) - return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - elif isinstance(tp, model.EnumType): - return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - else: - raise NotImplementedError(tp) - - # ---------- - # typedefs - - def _generate_cpy_typedef_collecttype(self, tp, name): - self._do_collect_type(tp) - - def _generate_cpy_typedef_decl(self, tp, name): - pass - - def _typedef_ctx(self, tp, name): - type_index = self._typesdict[tp] - self._lsts["typename"].append(TypenameExpr(name, type_index)) - - def _generate_cpy_typedef_ctx(self, tp, name): - self._typedef_ctx(tp, name) - if getattr(tp, "origin", None) == "unknown_type": - self._struct_ctx(tp, tp.name, approxname=None) - elif isinstance(tp, model.NamedPointerType): - self._struct_ctx(tp.totype, tp.totype.name, approxname=tp.name, - named_ptr=tp) - - # ---------- - # function declarations - - def _generate_cpy_function_collecttype(self, tp, name): - self._do_collect_type(tp.as_raw_function()) - if tp.ellipsis and not self.target_is_python: - self._do_collect_type(tp) - - def _generate_cpy_function_decl(self, tp, name): - assert not self.target_is_python - assert isinstance(tp, model.FunctionPtrType) - if tp.ellipsis: - # cannot support vararg functions better than this: check for its - # exact type (including the fixed arguments), and build it as a - # constant function pointer (no CPython wrapper) - self._generate_cpy_constant_decl(tp, name) - return - prnt = self._prnt - numargs = len(tp.args) - if numargs == 0: - argname = 'noarg' - elif numargs == 1: - argname = 'arg0' - else: - argname = 'args' - # - # ------------------------------ - # the 'd' version of the function, only for addressof(lib, 'func') - arguments = [] - call_arguments = [] - context = 'argument of %s' % name - for i, type in enumerate(tp.args): - arguments.append(type.get_c_name(' x%d' % i, context)) - call_arguments.append('x%d' % i) - repr_arguments = ', '.join(arguments) - repr_arguments = repr_arguments or 'void' - if tp.abi: - abi = tp.abi + ' ' - else: - abi = '' - name_and_arguments = '%s_cffi_d_%s(%s)' % (abi, name, repr_arguments) - prnt('static %s' % (tp.result.get_c_name(name_and_arguments),)) - prnt('{') - call_arguments = ', '.join(call_arguments) - result_code = 'return ' - if isinstance(tp.result, model.VoidType): - result_code = '' - prnt(' %s%s(%s);' % (result_code, name, call_arguments)) - prnt('}') - # - prnt('#ifndef PYPY_VERSION') # ------------------------------ - # - prnt('static PyObject *') - prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname)) - prnt('{') - # - context = 'argument of %s' % name - for i, type in enumerate(tp.args): - arg = type.get_c_name(' x%d' % i, context) - prnt(' %s;' % arg) - # - localvars = set() - for type in tp.args: - self._extra_local_variables(type, localvars) - for decl in localvars: - prnt(' %s;' % (decl,)) - # - if not isinstance(tp.result, model.VoidType): - result_code = 'result = ' - context = 'result of %s' % name - result_decl = ' %s;' % tp.result.get_c_name(' result', context) - prnt(result_decl) - else: - result_decl = None - result_code = '' - # - if len(tp.args) > 1: - rng = range(len(tp.args)) - for i in rng: - prnt(' PyObject *arg%d;' % i) - prnt(' PyObject **aa;') - prnt() - prnt(' aa = _cffi_unpack_args(args, %d, "%s");' % (len(rng), name)) - prnt(' if (aa == NULL)') - prnt(' return NULL;') - for i in rng: - prnt(' arg%d = aa[%d];' % (i, i)) - prnt() - # - for i, type in enumerate(tp.args): - self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i, - 'return NULL') - prnt() - # - prnt(' Py_BEGIN_ALLOW_THREADS') - prnt(' _cffi_restore_errno();') - call_arguments = ['x%d' % i for i in range(len(tp.args))] - call_arguments = ', '.join(call_arguments) - prnt(' { %s%s(%s); }' % (result_code, name, call_arguments)) - prnt(' _cffi_save_errno();') - prnt(' Py_END_ALLOW_THREADS') - prnt() - # - prnt(' (void)self; /* unused */') - if numargs == 0: - prnt(' (void)noarg; /* unused */') - if result_code: - prnt(' return %s;' % - self._convert_expr_from_c(tp.result, 'result', 'result type')) - else: - prnt(' Py_INCREF(Py_None);') - prnt(' return Py_None;') - prnt('}') - # - prnt('#else') # ------------------------------ - # - # the PyPy version: need to replace struct/union arguments with - # pointers, and if the result is a struct/union, insert a first - # arg that is a pointer to the result. - difference = False - arguments = [] - call_arguments = [] - context = 'argument of %s' % name - for i, type in enumerate(tp.args): - indirection = '' - if isinstance(type, model.StructOrUnion): - indirection = '*' - difference = True - arg = type.get_c_name(' %sx%d' % (indirection, i), context) - arguments.append(arg) - call_arguments.append('%sx%d' % (indirection, i)) - tp_result = tp.result - if isinstance(tp_result, model.StructOrUnion): - context = 'result of %s' % name - arg = tp_result.get_c_name(' *result', context) - arguments.insert(0, arg) - tp_result = model.void_type - result_decl = None - result_code = '*result = ' - difference = True - if difference: - repr_arguments = ', '.join(arguments) - repr_arguments = repr_arguments or 'void' - name_and_arguments = '%s_cffi_f_%s(%s)' % (abi, name, - repr_arguments) - prnt('static %s' % (tp_result.get_c_name(name_and_arguments),)) - prnt('{') - if result_decl: - prnt(result_decl) - call_arguments = ', '.join(call_arguments) - prnt(' { %s%s(%s); }' % (result_code, name, call_arguments)) - if result_decl: - prnt(' return result;') - prnt('}') - else: - prnt('# define _cffi_f_%s _cffi_d_%s' % (name, name)) - # - prnt('#endif') # ------------------------------ - prnt() - - def _generate_cpy_function_ctx(self, tp, name): - if tp.ellipsis and not self.target_is_python: - self._generate_cpy_constant_ctx(tp, name) - return - type_index = self._typesdict[tp.as_raw_function()] - numargs = len(tp.args) - if self.target_is_python: - meth_kind = OP_DLOPEN_FUNC - elif numargs == 0: - meth_kind = OP_CPYTHON_BLTN_N # 'METH_NOARGS' - elif numargs == 1: - meth_kind = OP_CPYTHON_BLTN_O # 'METH_O' - else: - meth_kind = OP_CPYTHON_BLTN_V # 'METH_VARARGS' - self._lsts["global"].append( - GlobalExpr(name, '_cffi_f_%s' % name, - CffiOp(meth_kind, type_index), - size='_cffi_d_%s' % name)) - - # ---------- - # named structs or unions - - def _field_type(self, tp_struct, field_name, tp_field): - if isinstance(tp_field, model.ArrayType): - actual_length = tp_field.length - if actual_length == '...': - ptr_struct_name = tp_struct.get_c_name('*') - actual_length = '_cffi_array_len(((%s)0)->%s)' % ( - ptr_struct_name, field_name) - tp_item = self._field_type(tp_struct, '%s[0]' % field_name, - tp_field.item) - tp_field = model.ArrayType(tp_item, actual_length) - return tp_field - - def _struct_collecttype(self, tp): - self._do_collect_type(tp) - - def _struct_decl(self, tp, cname, approxname): - if tp.fldtypes is None: - return - prnt = self._prnt - checkfuncname = '_cffi_checkfld_%s' % (approxname,) - prnt('_CFFI_UNUSED_FN') - prnt('static void %s(%s *p)' % (checkfuncname, cname)) - prnt('{') - prnt(' /* only to generate compile-time warnings or errors */') - prnt(' (void)p;') - for fname, ftype, fbitsize, fqual in tp.enumfields(): - try: - if ftype.is_integer_type() or fbitsize >= 0: - # accept all integers, but complain on float or double - prnt(" (void)((p->%s) << 1); /* check that '%s.%s' is " - "an integer */" % (fname, cname, fname)) - continue - # only accept exactly the type declared, except that '[]' - # is interpreted as a '*' and so will match any array length. - # (It would also match '*', but that's harder to detect...) - while (isinstance(ftype, model.ArrayType) - and (ftype.length is None or ftype.length == '...')): - ftype = ftype.item - fname = fname + '[0]' - prnt(' { %s = &p->%s; (void)tmp; }' % ( - ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual), - fname)) - except ffiplatform.VerificationError as e: - prnt(' /* %s */' % str(e)) # cannot verify it, ignore - prnt('}') - prnt('struct _cffi_align_%s { char x; %s y; };' % (approxname, cname)) - prnt() - - def _struct_ctx(self, tp, cname, approxname, named_ptr=None): - type_index = self._typesdict[tp] - reason_for_not_expanding = None - flags = [] - if isinstance(tp, model.UnionType): - flags.append("_CFFI_F_UNION") - if tp.fldtypes is None: - flags.append("_CFFI_F_OPAQUE") - reason_for_not_expanding = "opaque" - if (tp not in self.ffi._parser._included_declarations and - (named_ptr is None or - named_ptr not in self.ffi._parser._included_declarations)): - if tp.fldtypes is None: - pass # opaque - elif tp.partial or tp.has_anonymous_struct_fields(): - pass # field layout obtained silently from the C compiler - else: - flags.append("_CFFI_F_CHECK_FIELDS") - if tp.packed: - flags.append("_CFFI_F_PACKED") - else: - flags.append("_CFFI_F_EXTERNAL") - reason_for_not_expanding = "external" - flags = '|'.join(flags) or '0' - c_fields = [] - if reason_for_not_expanding is None: - enumfields = list(tp.enumfields()) - for fldname, fldtype, fbitsize, fqual in enumfields: - fldtype = self._field_type(tp, fldname, fldtype) - # cname is None for _add_missing_struct_unions() only - op = OP_NOOP - if fbitsize >= 0: - op = OP_BITFIELD - size = '%d /* bits */' % fbitsize - elif cname is None or ( - isinstance(fldtype, model.ArrayType) and - fldtype.length is None): - size = '(size_t)-1' - else: - size = 'sizeof(((%s)0)->%s)' % ( - tp.get_c_name('*') if named_ptr is None - else named_ptr.name, - fldname) - if cname is None or fbitsize >= 0: - offset = '(size_t)-1' - elif named_ptr is not None: - offset = '((char *)&((%s)0)->%s) - (char *)0' % ( - named_ptr.name, fldname) - else: - offset = 'offsetof(%s, %s)' % (tp.get_c_name(''), fldname) - c_fields.append( - FieldExpr(fldname, offset, size, fbitsize, - CffiOp(op, self._typesdict[fldtype]))) - first_field_index = len(self._lsts["field"]) - self._lsts["field"].extend(c_fields) - # - if cname is None: # unknown name, for _add_missing_struct_unions - size = '(size_t)-2' - align = -2 - comment = "unnamed" - else: - if named_ptr is not None: - size = 'sizeof(*(%s)0)' % (named_ptr.name,) - align = '-1 /* unknown alignment */' - else: - size = 'sizeof(%s)' % (cname,) - align = 'offsetof(struct _cffi_align_%s, y)' % (approxname,) - comment = None - else: - size = '(size_t)-1' - align = -1 - first_field_index = -1 - comment = reason_for_not_expanding - self._lsts["struct_union"].append( - StructUnionExpr(tp.name, type_index, flags, size, align, comment, - first_field_index, c_fields)) - self._seen_struct_unions.add(tp) - - def _add_missing_struct_unions(self): - # not very nice, but some struct declarations might be missing - # because they don't have any known C name. Check that they are - # not partial (we can't complete or verify them!) and emit them - # anonymously. - lst = list(self._struct_unions.items()) - lst.sort(key=lambda tp_order: tp_order[1]) - for tp, order in lst: - if tp not in self._seen_struct_unions: - if tp.partial: - raise NotImplementedError("internal inconsistency: %r is " - "partial but was not seen at " - "this point" % (tp,)) - if tp.name.startswith('$') and tp.name[1:].isdigit(): - approxname = tp.name[1:] - elif tp.name == '_IO_FILE' and tp.forcename == 'FILE': - approxname = 'FILE' - self._typedef_ctx(tp, 'FILE') - else: - raise NotImplementedError("internal inconsistency: %r" % - (tp,)) - self._struct_ctx(tp, None, approxname) - - def _generate_cpy_struct_collecttype(self, tp, name): - self._struct_collecttype(tp) - _generate_cpy_union_collecttype = _generate_cpy_struct_collecttype - - def _struct_names(self, tp): - cname = tp.get_c_name('') - if ' ' in cname: - return cname, cname.replace(' ', '_') - else: - return cname, '_' + cname - - def _generate_cpy_struct_decl(self, tp, name): - self._struct_decl(tp, *self._struct_names(tp)) - _generate_cpy_union_decl = _generate_cpy_struct_decl - - def _generate_cpy_struct_ctx(self, tp, name): - self._struct_ctx(tp, *self._struct_names(tp)) - _generate_cpy_union_ctx = _generate_cpy_struct_ctx - - # ---------- - # 'anonymous' declarations. These are produced for anonymous structs - # or unions; the 'name' is obtained by a typedef. - - def _generate_cpy_anonymous_collecttype(self, tp, name): - if isinstance(tp, model.EnumType): - self._generate_cpy_enum_collecttype(tp, name) - else: - self._struct_collecttype(tp) - - def _generate_cpy_anonymous_decl(self, tp, name): - if isinstance(tp, model.EnumType): - self._generate_cpy_enum_decl(tp) - else: - self._struct_decl(tp, name, 'typedef_' + name) - - def _generate_cpy_anonymous_ctx(self, tp, name): - if isinstance(tp, model.EnumType): - self._enum_ctx(tp, name) - else: - self._struct_ctx(tp, name, 'typedef_' + name) - - # ---------- - # constants, declared with "static const ..." - - def _generate_cpy_const(self, is_int, name, tp=None, category='const', - check_value=None): - if (category, name) in self._seen_constants: - raise ffiplatform.VerificationError( - "duplicate declaration of %s '%s'" % (category, name)) - self._seen_constants.add((category, name)) - # - prnt = self._prnt - funcname = '_cffi_%s_%s' % (category, name) - if is_int: - prnt('static int %s(unsigned long long *o)' % funcname) - prnt('{') - prnt(' int n = (%s) <= 0;' % (name,)) - prnt(' *o = (unsigned long long)((%s) << 0);' - ' /* check that %s is an integer */' % (name, name)) - if check_value is not None: - if check_value > 0: - check_value = '%dU' % (check_value,) - prnt(' if (!_cffi_check_int(*o, n, %s))' % (check_value,)) - prnt(' n |= 2;') - prnt(' return n;') - prnt('}') - else: - assert check_value is None - prnt('static void %s(char *o)' % funcname) - prnt('{') - prnt(' *(%s)o = %s;' % (tp.get_c_name('*'), name)) - prnt('}') - prnt() - - def _generate_cpy_constant_collecttype(self, tp, name): - is_int = tp.is_integer_type() - if not is_int or self.target_is_python: - self._do_collect_type(tp) - - def _generate_cpy_constant_decl(self, tp, name): - is_int = tp.is_integer_type() - self._generate_cpy_const(is_int, name, tp) - - def _generate_cpy_constant_ctx(self, tp, name): - if not self.target_is_python and tp.is_integer_type(): - type_op = CffiOp(OP_CONSTANT_INT, -1) - else: - if self.target_is_python: - const_kind = OP_DLOPEN_CONST - else: - const_kind = OP_CONSTANT - type_index = self._typesdict[tp] - type_op = CffiOp(const_kind, type_index) - self._lsts["global"].append( - GlobalExpr(name, '_cffi_const_%s' % name, type_op)) - - # ---------- - # enums - - def _generate_cpy_enum_collecttype(self, tp, name): - self._do_collect_type(tp) - - def _generate_cpy_enum_decl(self, tp, name=None): - for enumerator in tp.enumerators: - self._generate_cpy_const(True, enumerator) - - def _enum_ctx(self, tp, cname): - type_index = self._typesdict[tp] - type_op = CffiOp(OP_ENUM, -1) - if self.target_is_python: - tp.check_not_partial() - for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): - self._lsts["global"].append( - GlobalExpr(enumerator, '_cffi_const_%s' % enumerator, type_op, - check_value=enumvalue)) - # - if cname is not None and '$' not in cname and not self.target_is_python: - size = "sizeof(%s)" % cname - signed = "((%s)-1) <= 0" % cname - else: - basetp = tp.build_baseinttype(self.ffi, []) - size = self.ffi.sizeof(basetp) - signed = int(int(self.ffi.cast(basetp, -1)) < 0) - allenums = ",".join(tp.enumerators) - self._lsts["enum"].append( - EnumExpr(tp.name, type_index, size, signed, allenums)) - - def _generate_cpy_enum_ctx(self, tp, name): - self._enum_ctx(tp, tp._get_c_name()) - - # ---------- - # macros: for now only for integers - - def _generate_cpy_macro_collecttype(self, tp, name): - pass - - def _generate_cpy_macro_decl(self, tp, name): - if tp == '...': - check_value = None - else: - check_value = tp # an integer - self._generate_cpy_const(True, name, check_value=check_value) - - def _generate_cpy_macro_ctx(self, tp, name): - if tp == '...': - if self.target_is_python: - raise ffiplatform.VerificationError( - "cannot use the syntax '...' in '#define %s ...' when " - "using the ABI mode" % (name,)) - check_value = None - else: - check_value = tp # an integer - type_op = CffiOp(OP_CONSTANT_INT, -1) - self._lsts["global"].append( - GlobalExpr(name, '_cffi_const_%s' % name, type_op, - check_value=check_value)) - - # ---------- - # global variables - - def _global_type(self, tp, global_name): - if isinstance(tp, model.ArrayType): - actual_length = tp.length - if actual_length == '...': - actual_length = '_cffi_array_len(%s)' % (global_name,) - tp_item = self._global_type(tp.item, '%s[0]' % global_name) - tp = model.ArrayType(tp_item, actual_length) - return tp - - def _generate_cpy_variable_collecttype(self, tp, name): - self._do_collect_type(self._global_type(tp, name)) - - def _generate_cpy_variable_decl(self, tp, name): - prnt = self._prnt - tp = self._global_type(tp, name) - if isinstance(tp, model.ArrayType) and tp.length is None: - tp = tp.item - ampersand = '' - else: - ampersand = '&' - # This code assumes that casts from "tp *" to "void *" is a - # no-op, i.e. a function that returns a "tp *" can be called - # as if it returned a "void *". This should be generally true - # on any modern machine. The only exception to that rule (on - # uncommon architectures, and as far as I can tell) might be - # if 'tp' were a function type, but that is not possible here. - # (If 'tp' is a function _pointer_ type, then casts from "fn_t - # **" to "void *" are again no-ops, as far as I can tell.) - decl = '*_cffi_var_%s(void)' % (name,) - prnt('static ' + tp.get_c_name(decl, quals=self._current_quals)) - prnt('{') - prnt(' return %s(%s);' % (ampersand, name)) - prnt('}') - prnt() - - def _generate_cpy_variable_ctx(self, tp, name): - tp = self._global_type(tp, name) - type_index = self._typesdict[tp] - if self.target_is_python: - op = OP_GLOBAL_VAR - else: - op = OP_GLOBAL_VAR_F - self._lsts["global"].append( - GlobalExpr(name, '_cffi_var_%s' % name, CffiOp(op, type_index))) - - # ---------- - # emitting the opcodes for individual types - - def _emit_bytecode_VoidType(self, tp, index): - self.cffi_types[index] = CffiOp(OP_PRIMITIVE, PRIM_VOID) - - def _emit_bytecode_PrimitiveType(self, tp, index): - prim_index = PRIMITIVE_TO_INDEX[tp.name] - self.cffi_types[index] = CffiOp(OP_PRIMITIVE, prim_index) - - def _emit_bytecode_UnknownIntegerType(self, tp, index): - s = ('_cffi_prim_int(sizeof(%s), (\n' - ' ((%s)-1) << 0 /* check that %s is an integer type */\n' - ' ) <= 0)' % (tp.name, tp.name, tp.name)) - self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s) - - def _emit_bytecode_UnknownFloatType(self, tp, index): - s = ('_cffi_prim_float(sizeof(%s) *\n' - ' (((%s)1) / 2) * 2 /* integer => 0, float => 1 */\n' - ' )' % (tp.name, tp.name)) - self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s) - - def _emit_bytecode_RawFunctionType(self, tp, index): - self.cffi_types[index] = CffiOp(OP_FUNCTION, self._typesdict[tp.result]) - index += 1 - for tp1 in tp.args: - realindex = self._typesdict[tp1] - if index != realindex: - if isinstance(tp1, model.PrimitiveType): - self._emit_bytecode_PrimitiveType(tp1, index) - else: - self.cffi_types[index] = CffiOp(OP_NOOP, realindex) - index += 1 - flags = int(tp.ellipsis) - if tp.abi is not None: - if tp.abi == '__stdcall': - flags |= 2 - else: - raise NotImplementedError("abi=%r" % (tp.abi,)) - self.cffi_types[index] = CffiOp(OP_FUNCTION_END, flags) - - def _emit_bytecode_PointerType(self, tp, index): - self.cffi_types[index] = CffiOp(OP_POINTER, self._typesdict[tp.totype]) - - _emit_bytecode_ConstPointerType = _emit_bytecode_PointerType - _emit_bytecode_NamedPointerType = _emit_bytecode_PointerType - - def _emit_bytecode_FunctionPtrType(self, tp, index): - raw = tp.as_raw_function() - self.cffi_types[index] = CffiOp(OP_POINTER, self._typesdict[raw]) - - def _emit_bytecode_ArrayType(self, tp, index): - item_index = self._typesdict[tp.item] - if tp.length is None: - self.cffi_types[index] = CffiOp(OP_OPEN_ARRAY, item_index) - elif tp.length == '...': - raise ffiplatform.VerificationError( - "type %s badly placed: the '...' array length can only be " - "used on global arrays or on fields of structures" % ( - str(tp).replace('/*...*/', '...'),)) - else: - assert self.cffi_types[index + 1] == 'LEN' - self.cffi_types[index] = CffiOp(OP_ARRAY, item_index) - self.cffi_types[index + 1] = CffiOp(None, str(tp.length)) - - def _emit_bytecode_StructType(self, tp, index): - struct_index = self._struct_unions[tp] - self.cffi_types[index] = CffiOp(OP_STRUCT_UNION, struct_index) - _emit_bytecode_UnionType = _emit_bytecode_StructType - - def _emit_bytecode_EnumType(self, tp, index): - enum_index = self._enums[tp] - self.cffi_types[index] = CffiOp(OP_ENUM, enum_index) - - -if sys.version_info >= (3,): - NativeIO = io.StringIO -else: - class NativeIO(io.BytesIO): - def write(self, s): - if isinstance(s, unicode): - s = s.encode('ascii') - super(NativeIO, self).write(s) - -def _make_c_or_py_source(ffi, module_name, preamble, target_file): - recompiler = Recompiler(ffi, module_name, - target_is_python=(preamble is None)) - recompiler.collect_type_table() - recompiler.collect_step_tables() - f = NativeIO() - recompiler.write_source_to_f(f, preamble) - output = f.getvalue() - try: - with open(target_file, 'r') as f1: - if f1.read(len(output) + 1) != output: - raise IOError - return False # already up-to-date - except IOError: - tmp_file = '%s.~%d' % (target_file, os.getpid()) - with open(tmp_file, 'w') as f1: - f1.write(output) - try: - os.rename(tmp_file, target_file) - except OSError: - os.unlink(target_file) - os.rename(tmp_file, target_file) - return True - -def make_c_source(ffi, module_name, preamble, target_c_file): - assert preamble is not None - return _make_c_or_py_source(ffi, module_name, preamble, target_c_file) - -def make_py_source(ffi, module_name, target_py_file): - return _make_c_or_py_source(ffi, module_name, None, target_py_file) - -def _modname_to_file(outputdir, modname, extension): - parts = modname.split('.') - try: - os.makedirs(os.path.join(outputdir, *parts[:-1])) - except OSError: - pass - parts[-1] += extension - return os.path.join(outputdir, *parts), parts - -def recompile(ffi, module_name, preamble, tmpdir='.', call_c_compiler=True, - c_file=None, source_extension='.c', extradir=None, **kwds): - if not isinstance(module_name, str): - module_name = module_name.encode('ascii') - if ffi._windows_unicode: - ffi._apply_windows_unicode(kwds) - if preamble is not None: - if c_file is None: - c_file, parts = _modname_to_file(tmpdir, module_name, - source_extension) - if extradir: - parts = [extradir] + parts - ext_c_file = os.path.join(*parts) - else: - ext_c_file = c_file - ext = ffiplatform.get_extension(ext_c_file, module_name, **kwds) - updated = make_c_source(ffi, module_name, preamble, c_file) - if call_c_compiler: - cwd = os.getcwd() - try: - os.chdir(tmpdir) - outputfilename = ffiplatform.compile('.', ext) - finally: - os.chdir(cwd) - return outputfilename - else: - return ext, updated - else: - if c_file is None: - c_file, _ = _modname_to_file(tmpdir, module_name, '.py') - updated = make_py_source(ffi, module_name, c_file) - if call_c_compiler: - return c_file - else: - return None, updated - -def _verify(ffi, module_name, preamble, *args, **kwds): - # FOR TESTS ONLY - from testing.udir import udir - import imp - assert module_name not in sys.modules, "module name conflict: %r" % ( - module_name,) - kwds.setdefault('tmpdir', str(udir)) - outputfilename = recompile(ffi, module_name, preamble, *args, **kwds) - module = imp.load_dynamic(module_name, outputfilename) - # - # hack hack hack: copy all *bound methods* from module.ffi back to the - # ffi instance. Then calls like ffi.new() will invoke module.ffi.new(). - for name in dir(module.ffi): - if not name.startswith('_'): - attr = getattr(module.ffi, name) - if attr is not getattr(ffi, name, object()): - setattr(ffi, name, attr) - def typeof_disabled(*args, **kwds): - raise NotImplementedError - ffi._typeof = typeof_disabled - return module.lib diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/setuptools_ext.py b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/setuptools_ext.py deleted file mode 100644 index 9c6436d..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/setuptools_ext.py +++ /dev/null @@ -1,161 +0,0 @@ -import os - -try: - basestring -except NameError: - # Python 3.x - basestring = str - -def error(msg): - from distutils.errors import DistutilsSetupError - raise DistutilsSetupError(msg) - - -def execfile(filename, glob): - # We use execfile() (here rewritten for Python 3) instead of - # __import__() to load the build script. The problem with - # a normal import is that in some packages, the intermediate - # __init__.py files may already try to import the file that - # we are generating. - with open(filename) as f: - src = f.read() - src += '\n' # Python 2.6 compatibility - code = compile(src, filename, 'exec') - exec(code, glob, glob) - - -def add_cffi_module(dist, mod_spec): - from cffi.api import FFI - - if not isinstance(mod_spec, basestring): - error("argument to 'cffi_modules=...' must be a str or a list of str," - " not %r" % (type(mod_spec).__name__,)) - mod_spec = str(mod_spec) - try: - build_file_name, ffi_var_name = mod_spec.split(':') - except ValueError: - error("%r must be of the form 'path/build.py:ffi_variable'" % - (mod_spec,)) - if not os.path.exists(build_file_name): - ext = '' - rewritten = build_file_name.replace('.', '/') + '.py' - if os.path.exists(rewritten): - ext = ' (rewrite cffi_modules to [%r])' % ( - rewritten + ':' + ffi_var_name,) - error("%r does not name an existing file%s" % (build_file_name, ext)) - - mod_vars = {'__name__': '__cffi__', '__file__': build_file_name} - execfile(build_file_name, mod_vars) - - try: - ffi = mod_vars[ffi_var_name] - except KeyError: - error("%r: object %r not found in module" % (mod_spec, - ffi_var_name)) - if not isinstance(ffi, FFI): - ffi = ffi() # maybe it's a function instead of directly an ffi - if not isinstance(ffi, FFI): - error("%r is not an FFI instance (got %r)" % (mod_spec, - type(ffi).__name__)) - if not hasattr(ffi, '_assigned_source'): - error("%r: the set_source() method was not called" % (mod_spec,)) - module_name, source, source_extension, kwds = ffi._assigned_source - if ffi._windows_unicode: - kwds = kwds.copy() - ffi._apply_windows_unicode(kwds) - - if source is None: - _add_py_module(dist, ffi, module_name) - else: - _add_c_module(dist, ffi, module_name, source, source_extension, kwds) - - -def _add_c_module(dist, ffi, module_name, source, source_extension, kwds): - from distutils.core import Extension - from distutils.command.build_ext import build_ext - from distutils.dir_util import mkpath - from distutils import log - from cffi import recompiler - - allsources = ['$PLACEHOLDER'] - allsources.extend(kwds.pop('sources', [])) - ext = Extension(name=module_name, sources=allsources, **kwds) - - def make_mod(tmpdir, pre_run=None): - c_file = os.path.join(tmpdir, module_name + source_extension) - log.info("generating cffi module %r" % c_file) - mkpath(tmpdir) - # a setuptools-only, API-only hook: called with the "ext" and "ffi" - # arguments just before we turn the ffi into C code. To use it, - # subclass the 'distutils.command.build_ext.build_ext' class and - # add a method 'def pre_run(self, ext, ffi)'. - if pre_run is not None: - pre_run(ext, ffi) - updated = recompiler.make_c_source(ffi, module_name, source, c_file) - if not updated: - log.info("already up-to-date") - return c_file - - if dist.ext_modules is None: - dist.ext_modules = [] - dist.ext_modules.append(ext) - - base_class = dist.cmdclass.get('build_ext', build_ext) - class build_ext_make_mod(base_class): - def run(self): - if ext.sources[0] == '$PLACEHOLDER': - pre_run = getattr(self, 'pre_run', None) - ext.sources[0] = make_mod(self.build_temp, pre_run) - base_class.run(self) - dist.cmdclass['build_ext'] = build_ext_make_mod - # NB. multiple runs here will create multiple 'build_ext_make_mod' - # classes. Even in this case the 'build_ext' command should be - # run once; but just in case, the logic above does nothing if - # called again. - - -def _add_py_module(dist, ffi, module_name): - from distutils.dir_util import mkpath - from distutils.command.build_py import build_py - from distutils.command.build_ext import build_ext - from distutils import log - from cffi import recompiler - - def generate_mod(py_file): - log.info("generating cffi module %r" % py_file) - mkpath(os.path.dirname(py_file)) - updated = recompiler.make_py_source(ffi, module_name, py_file) - if not updated: - log.info("already up-to-date") - - base_class = dist.cmdclass.get('build_py', build_py) - class build_py_make_mod(base_class): - def run(self): - base_class.run(self) - module_path = module_name.split('.') - module_path[-1] += '.py' - generate_mod(os.path.join(self.build_lib, *module_path)) - dist.cmdclass['build_py'] = build_py_make_mod - - # the following is only for "build_ext -i" - base_class_2 = dist.cmdclass.get('build_ext', build_ext) - class build_ext_make_mod(base_class_2): - def run(self): - base_class_2.run(self) - if self.inplace: - # from get_ext_fullpath() in distutils/command/build_ext.py - module_path = module_name.split('.') - package = '.'.join(module_path[:-1]) - build_py = self.get_finalized_command('build_py') - package_dir = build_py.get_package_dir(package) - file_name = module_path[-1] + '.py' - generate_mod(os.path.join(package_dir, file_name)) - dist.cmdclass['build_ext'] = build_ext_make_mod - -def cffi_modules(dist, attr, value): - assert attr == 'cffi_modules' - if isinstance(value, basestring): - value = [value] - - for cffi_module in value: - add_cffi_module(dist, cffi_module) diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/vengine_cpy.py b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/vengine_cpy.py deleted file mode 100644 index 9f82988..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/vengine_cpy.py +++ /dev/null @@ -1,1007 +0,0 @@ -import sys, imp -from . import model, ffiplatform - - -class VCPythonEngine(object): - _class_key = 'x' - _gen_python_module = True - - def __init__(self, verifier): - self.verifier = verifier - self.ffi = verifier.ffi - self._struct_pending_verification = {} - self._types_of_builtin_functions = {} - - def patch_extension_kwds(self, kwds): - pass - - def find_module(self, module_name, path, so_suffixes): - try: - f, filename, descr = imp.find_module(module_name, path) - except ImportError: - return None - if f is not None: - f.close() - # Note that after a setuptools installation, there are both .py - # and .so files with the same basename. The code here relies on - # imp.find_module() locating the .so in priority. - if descr[0] not in so_suffixes: - return None - return filename - - def collect_types(self): - self._typesdict = {} - self._generate("collecttype") - - def _prnt(self, what=''): - self._f.write(what + '\n') - - def _gettypenum(self, type): - # a KeyError here is a bug. please report it! :-) - return self._typesdict[type] - - def _do_collect_type(self, tp): - if ((not isinstance(tp, model.PrimitiveType) - or tp.name == 'long double') - and tp not in self._typesdict): - num = len(self._typesdict) - self._typesdict[tp] = num - - def write_source_to_f(self): - self.collect_types() - # - # The new module will have a _cffi_setup() function that receives - # objects from the ffi world, and that calls some setup code in - # the module. This setup code is split in several independent - # functions, e.g. one per constant. The functions are "chained" - # by ending in a tail call to each other. - # - # This is further split in two chained lists, depending on if we - # can do it at import-time or if we must wait for _cffi_setup() to - # provide us with the objects. This is needed because we - # need the values of the enum constants in order to build the - # that we may have to pass to _cffi_setup(). - # - # The following two 'chained_list_constants' items contains - # the head of these two chained lists, as a string that gives the - # call to do, if any. - self._chained_list_constants = ['((void)lib,0)', '((void)lib,0)'] - # - prnt = self._prnt - # first paste some standard set of lines that are mostly '#define' - prnt(cffimod_header) - prnt() - # then paste the C source given by the user, verbatim. - prnt(self.verifier.preamble) - prnt() - # - # call generate_cpy_xxx_decl(), for every xxx found from - # ffi._parser._declarations. This generates all the functions. - self._generate("decl") - # - # implement the function _cffi_setup_custom() as calling the - # head of the chained list. - self._generate_setup_custom() - prnt() - # - # produce the method table, including the entries for the - # generated Python->C function wrappers, which are done - # by generate_cpy_function_method(). - prnt('static PyMethodDef _cffi_methods[] = {') - self._generate("method") - prnt(' {"_cffi_setup", _cffi_setup, METH_VARARGS, NULL},') - prnt(' {NULL, NULL, 0, NULL} /* Sentinel */') - prnt('};') - prnt() - # - # standard init. - modname = self.verifier.get_module_name() - constants = self._chained_list_constants[False] - prnt('#if PY_MAJOR_VERSION >= 3') - prnt() - prnt('static struct PyModuleDef _cffi_module_def = {') - prnt(' PyModuleDef_HEAD_INIT,') - prnt(' "%s",' % modname) - prnt(' NULL,') - prnt(' -1,') - prnt(' _cffi_methods,') - prnt(' NULL, NULL, NULL, NULL') - prnt('};') - prnt() - prnt('PyMODINIT_FUNC') - prnt('PyInit_%s(void)' % modname) - prnt('{') - prnt(' PyObject *lib;') - prnt(' lib = PyModule_Create(&_cffi_module_def);') - prnt(' if (lib == NULL)') - prnt(' return NULL;') - prnt(' if (%s < 0 || _cffi_init() < 0) {' % (constants,)) - prnt(' Py_DECREF(lib);') - prnt(' return NULL;') - prnt(' }') - prnt(' return lib;') - prnt('}') - prnt() - prnt('#else') - prnt() - prnt('PyMODINIT_FUNC') - prnt('init%s(void)' % modname) - prnt('{') - prnt(' PyObject *lib;') - prnt(' lib = Py_InitModule("%s", _cffi_methods);' % modname) - prnt(' if (lib == NULL)') - prnt(' return;') - prnt(' if (%s < 0 || _cffi_init() < 0)' % (constants,)) - prnt(' return;') - prnt(' return;') - prnt('}') - prnt() - prnt('#endif') - - def load_library(self, flags=None): - # XXX review all usages of 'self' here! - # import it as a new extension module - imp.acquire_lock() - try: - if hasattr(sys, "getdlopenflags"): - previous_flags = sys.getdlopenflags() - try: - if hasattr(sys, "setdlopenflags") and flags is not None: - sys.setdlopenflags(flags) - module = imp.load_dynamic(self.verifier.get_module_name(), - self.verifier.modulefilename) - except ImportError as e: - error = "importing %r: %s" % (self.verifier.modulefilename, e) - raise ffiplatform.VerificationError(error) - finally: - if hasattr(sys, "setdlopenflags"): - sys.setdlopenflags(previous_flags) - finally: - imp.release_lock() - # - # call loading_cpy_struct() to get the struct layout inferred by - # the C compiler - self._load(module, 'loading') - # - # the C code will need the objects. Collect them in - # order in a list. - revmapping = dict([(value, key) - for (key, value) in self._typesdict.items()]) - lst = [revmapping[i] for i in range(len(revmapping))] - lst = list(map(self.ffi._get_cached_btype, lst)) - # - # build the FFILibrary class and instance and call _cffi_setup(). - # this will set up some fields like '_cffi_types', and only then - # it will invoke the chained list of functions that will really - # build (notably) the constant objects, as if they are - # pointers, and store them as attributes on the 'library' object. - class FFILibrary(object): - _cffi_python_module = module - _cffi_ffi = self.ffi - _cffi_dir = [] - def __dir__(self): - return FFILibrary._cffi_dir + list(self.__dict__) - library = FFILibrary() - if module._cffi_setup(lst, ffiplatform.VerificationError, library): - import warnings - warnings.warn("reimporting %r might overwrite older definitions" - % (self.verifier.get_module_name())) - # - # finally, call the loaded_cpy_xxx() functions. This will perform - # the final adjustments, like copying the Python->C wrapper - # functions from the module to the 'library' object, and setting - # up the FFILibrary class with properties for the global C variables. - self._load(module, 'loaded', library=library) - module._cffi_original_ffi = self.ffi - module._cffi_types_of_builtin_funcs = self._types_of_builtin_functions - return library - - def _get_declarations(self): - lst = [(key, tp) for (key, (tp, qual)) in - self.ffi._parser._declarations.items()] - lst.sort() - return lst - - def _generate(self, step_name): - for name, tp in self._get_declarations(): - kind, realname = name.split(' ', 1) - try: - method = getattr(self, '_generate_cpy_%s_%s' % (kind, - step_name)) - except AttributeError: - raise ffiplatform.VerificationError( - "not implemented in verify(): %r" % name) - try: - method(tp, realname) - except Exception as e: - model.attach_exception_info(e, name) - raise - - def _load(self, module, step_name, **kwds): - for name, tp in self._get_declarations(): - kind, realname = name.split(' ', 1) - method = getattr(self, '_%s_cpy_%s' % (step_name, kind)) - try: - method(tp, realname, module, **kwds) - except Exception as e: - model.attach_exception_info(e, name) - raise - - def _generate_nothing(self, tp, name): - pass - - def _loaded_noop(self, tp, name, module, **kwds): - pass - - # ---------- - - def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode): - extraarg = '' - if isinstance(tp, model.PrimitiveType): - if tp.is_integer_type() and tp.name != '_Bool': - converter = '_cffi_to_c_int' - extraarg = ', %s' % tp.name - else: - converter = '(%s)_cffi_to_c_%s' % (tp.get_c_name(''), - tp.name.replace(' ', '_')) - errvalue = '-1' - # - elif isinstance(tp, model.PointerType): - self._convert_funcarg_to_c_ptr_or_array(tp, fromvar, - tovar, errcode) - return - # - elif isinstance(tp, (model.StructOrUnion, model.EnumType)): - # a struct (not a struct pointer) as a function argument - self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)' - % (tovar, self._gettypenum(tp), fromvar)) - self._prnt(' %s;' % errcode) - return - # - elif isinstance(tp, model.FunctionPtrType): - converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('') - extraarg = ', _cffi_type(%d)' % self._gettypenum(tp) - errvalue = 'NULL' - # - else: - raise NotImplementedError(tp) - # - self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg)) - self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % ( - tovar, tp.get_c_name(''), errvalue)) - self._prnt(' %s;' % errcode) - - def _extra_local_variables(self, tp, localvars): - if isinstance(tp, model.PointerType): - localvars.add('Py_ssize_t datasize') - - def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): - self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') - self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( - self._gettypenum(tp), fromvar, tovar)) - self._prnt(' if (datasize != 0) {') - self._prnt(' if (datasize < 0)') - self._prnt(' %s;' % errcode) - self._prnt(' %s = alloca((size_t)datasize);' % (tovar,)) - self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,)) - self._prnt(' if (_cffi_convert_array_from_object(' - '(char *)%s, _cffi_type(%d), %s) < 0)' % ( - tovar, self._gettypenum(tp), fromvar)) - self._prnt(' %s;' % errcode) - self._prnt(' }') - - def _convert_expr_from_c(self, tp, var, context): - if isinstance(tp, model.PrimitiveType): - if tp.is_integer_type(): - return '_cffi_from_c_int(%s, %s)' % (var, tp.name) - elif tp.name != 'long double': - return '_cffi_from_c_%s(%s)' % (tp.name.replace(' ', '_'), var) - else: - return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - elif isinstance(tp, (model.PointerType, model.FunctionPtrType)): - return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - elif isinstance(tp, model.ArrayType): - return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( - var, self._gettypenum(model.PointerType(tp.item))) - elif isinstance(tp, model.StructType): - if tp.fldnames is None: - raise TypeError("'%s' is used as %s, but is opaque" % ( - tp._get_c_name(), context)) - return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - elif isinstance(tp, model.EnumType): - return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - else: - raise NotImplementedError(tp) - - # ---------- - # typedefs: generates no code so far - - _generate_cpy_typedef_collecttype = _generate_nothing - _generate_cpy_typedef_decl = _generate_nothing - _generate_cpy_typedef_method = _generate_nothing - _loading_cpy_typedef = _loaded_noop - _loaded_cpy_typedef = _loaded_noop - - # ---------- - # function declarations - - def _generate_cpy_function_collecttype(self, tp, name): - assert isinstance(tp, model.FunctionPtrType) - if tp.ellipsis: - self._do_collect_type(tp) - else: - # don't call _do_collect_type(tp) in this common case, - # otherwise test_autofilled_struct_as_argument fails - for type in tp.args: - self._do_collect_type(type) - self._do_collect_type(tp.result) - - def _generate_cpy_function_decl(self, tp, name): - assert isinstance(tp, model.FunctionPtrType) - if tp.ellipsis: - # cannot support vararg functions better than this: check for its - # exact type (including the fixed arguments), and build it as a - # constant function pointer (no CPython wrapper) - self._generate_cpy_const(False, name, tp) - return - prnt = self._prnt - numargs = len(tp.args) - if numargs == 0: - argname = 'noarg' - elif numargs == 1: - argname = 'arg0' - else: - argname = 'args' - prnt('static PyObject *') - prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname)) - prnt('{') - # - context = 'argument of %s' % name - for i, type in enumerate(tp.args): - prnt(' %s;' % type.get_c_name(' x%d' % i, context)) - # - localvars = set() - for type in tp.args: - self._extra_local_variables(type, localvars) - for decl in localvars: - prnt(' %s;' % (decl,)) - # - if not isinstance(tp.result, model.VoidType): - result_code = 'result = ' - context = 'result of %s' % name - prnt(' %s;' % tp.result.get_c_name(' result', context)) - else: - result_code = '' - # - if len(tp.args) > 1: - rng = range(len(tp.args)) - for i in rng: - prnt(' PyObject *arg%d;' % i) - prnt() - prnt(' if (!PyArg_ParseTuple(args, "%s:%s", %s))' % ( - 'O' * numargs, name, ', '.join(['&arg%d' % i for i in rng]))) - prnt(' return NULL;') - prnt() - # - for i, type in enumerate(tp.args): - self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i, - 'return NULL') - prnt() - # - prnt(' Py_BEGIN_ALLOW_THREADS') - prnt(' _cffi_restore_errno();') - prnt(' { %s%s(%s); }' % ( - result_code, name, - ', '.join(['x%d' % i for i in range(len(tp.args))]))) - prnt(' _cffi_save_errno();') - prnt(' Py_END_ALLOW_THREADS') - prnt() - # - prnt(' (void)self; /* unused */') - if numargs == 0: - prnt(' (void)noarg; /* unused */') - if result_code: - prnt(' return %s;' % - self._convert_expr_from_c(tp.result, 'result', 'result type')) - else: - prnt(' Py_INCREF(Py_None);') - prnt(' return Py_None;') - prnt('}') - prnt() - - def _generate_cpy_function_method(self, tp, name): - if tp.ellipsis: - return - numargs = len(tp.args) - if numargs == 0: - meth = 'METH_NOARGS' - elif numargs == 1: - meth = 'METH_O' - else: - meth = 'METH_VARARGS' - self._prnt(' {"%s", _cffi_f_%s, %s, NULL},' % (name, name, meth)) - - _loading_cpy_function = _loaded_noop - - def _loaded_cpy_function(self, tp, name, module, library): - if tp.ellipsis: - return - func = getattr(module, name) - setattr(library, name, func) - self._types_of_builtin_functions[func] = tp - - # ---------- - # named structs - - _generate_cpy_struct_collecttype = _generate_nothing - def _generate_cpy_struct_decl(self, tp, name): - assert name == tp.name - self._generate_struct_or_union_decl(tp, 'struct', name) - def _generate_cpy_struct_method(self, tp, name): - self._generate_struct_or_union_method(tp, 'struct', name) - def _loading_cpy_struct(self, tp, name, module): - self._loading_struct_or_union(tp, 'struct', name, module) - def _loaded_cpy_struct(self, tp, name, module, **kwds): - self._loaded_struct_or_union(tp) - - _generate_cpy_union_collecttype = _generate_nothing - def _generate_cpy_union_decl(self, tp, name): - assert name == tp.name - self._generate_struct_or_union_decl(tp, 'union', name) - def _generate_cpy_union_method(self, tp, name): - self._generate_struct_or_union_method(tp, 'union', name) - def _loading_cpy_union(self, tp, name, module): - self._loading_struct_or_union(tp, 'union', name, module) - def _loaded_cpy_union(self, tp, name, module, **kwds): - self._loaded_struct_or_union(tp) - - def _generate_struct_or_union_decl(self, tp, prefix, name): - if tp.fldnames is None: - return # nothing to do with opaque structs - checkfuncname = '_cffi_check_%s_%s' % (prefix, name) - layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) - cname = ('%s %s' % (prefix, name)).strip() - # - prnt = self._prnt - prnt('static void %s(%s *p)' % (checkfuncname, cname)) - prnt('{') - prnt(' /* only to generate compile-time warnings or errors */') - prnt(' (void)p;') - for fname, ftype, fbitsize, fqual in tp.enumfields(): - if (isinstance(ftype, model.PrimitiveType) - and ftype.is_integer_type()) or fbitsize >= 0: - # accept all integers, but complain on float or double - prnt(' (void)((p->%s) << 1);' % fname) - else: - # only accept exactly the type declared. - try: - prnt(' { %s = &p->%s; (void)tmp; }' % ( - ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual), - fname)) - except ffiplatform.VerificationError as e: - prnt(' /* %s */' % str(e)) # cannot verify it, ignore - prnt('}') - prnt('static PyObject *') - prnt('%s(PyObject *self, PyObject *noarg)' % (layoutfuncname,)) - prnt('{') - prnt(' struct _cffi_aligncheck { char x; %s y; };' % cname) - prnt(' static Py_ssize_t nums[] = {') - prnt(' sizeof(%s),' % cname) - prnt(' offsetof(struct _cffi_aligncheck, y),') - for fname, ftype, fbitsize, fqual in tp.enumfields(): - if fbitsize >= 0: - continue # xxx ignore fbitsize for now - prnt(' offsetof(%s, %s),' % (cname, fname)) - if isinstance(ftype, model.ArrayType) and ftype.length is None: - prnt(' 0, /* %s */' % ftype._get_c_name()) - else: - prnt(' sizeof(((%s *)0)->%s),' % (cname, fname)) - prnt(' -1') - prnt(' };') - prnt(' (void)self; /* unused */') - prnt(' (void)noarg; /* unused */') - prnt(' return _cffi_get_struct_layout(nums);') - prnt(' /* the next line is not executed, but compiled */') - prnt(' %s(0);' % (checkfuncname,)) - prnt('}') - prnt() - - def _generate_struct_or_union_method(self, tp, prefix, name): - if tp.fldnames is None: - return # nothing to do with opaque structs - layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) - self._prnt(' {"%s", %s, METH_NOARGS, NULL},' % (layoutfuncname, - layoutfuncname)) - - def _loading_struct_or_union(self, tp, prefix, name, module): - if tp.fldnames is None: - return # nothing to do with opaque structs - layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) - # - function = getattr(module, layoutfuncname) - layout = function() - if isinstance(tp, model.StructOrUnion) and tp.partial: - # use the function()'s sizes and offsets to guide the - # layout of the struct - totalsize = layout[0] - totalalignment = layout[1] - fieldofs = layout[2::2] - fieldsize = layout[3::2] - tp.force_flatten() - assert len(fieldofs) == len(fieldsize) == len(tp.fldnames) - tp.fixedlayout = fieldofs, fieldsize, totalsize, totalalignment - else: - cname = ('%s %s' % (prefix, name)).strip() - self._struct_pending_verification[tp] = layout, cname - - def _loaded_struct_or_union(self, tp): - if tp.fldnames is None: - return # nothing to do with opaque structs - self.ffi._get_cached_btype(tp) # force 'fixedlayout' to be considered - - if tp in self._struct_pending_verification: - # check that the layout sizes and offsets match the real ones - def check(realvalue, expectedvalue, msg): - if realvalue != expectedvalue: - raise ffiplatform.VerificationError( - "%s (we have %d, but C compiler says %d)" - % (msg, expectedvalue, realvalue)) - ffi = self.ffi - BStruct = ffi._get_cached_btype(tp) - layout, cname = self._struct_pending_verification.pop(tp) - check(layout[0], ffi.sizeof(BStruct), "wrong total size") - check(layout[1], ffi.alignof(BStruct), "wrong total alignment") - i = 2 - for fname, ftype, fbitsize, fqual in tp.enumfields(): - if fbitsize >= 0: - continue # xxx ignore fbitsize for now - check(layout[i], ffi.offsetof(BStruct, fname), - "wrong offset for field %r" % (fname,)) - if layout[i+1] != 0: - BField = ffi._get_cached_btype(ftype) - check(layout[i+1], ffi.sizeof(BField), - "wrong size for field %r" % (fname,)) - i += 2 - assert i == len(layout) - - # ---------- - # 'anonymous' declarations. These are produced for anonymous structs - # or unions; the 'name' is obtained by a typedef. - - _generate_cpy_anonymous_collecttype = _generate_nothing - - def _generate_cpy_anonymous_decl(self, tp, name): - if isinstance(tp, model.EnumType): - self._generate_cpy_enum_decl(tp, name, '') - else: - self._generate_struct_or_union_decl(tp, '', name) - - def _generate_cpy_anonymous_method(self, tp, name): - if not isinstance(tp, model.EnumType): - self._generate_struct_or_union_method(tp, '', name) - - def _loading_cpy_anonymous(self, tp, name, module): - if isinstance(tp, model.EnumType): - self._loading_cpy_enum(tp, name, module) - else: - self._loading_struct_or_union(tp, '', name, module) - - def _loaded_cpy_anonymous(self, tp, name, module, **kwds): - if isinstance(tp, model.EnumType): - self._loaded_cpy_enum(tp, name, module, **kwds) - else: - self._loaded_struct_or_union(tp) - - # ---------- - # constants, likely declared with '#define' - - def _generate_cpy_const(self, is_int, name, tp=None, category='const', - vartp=None, delayed=True, size_too=False, - check_value=None): - prnt = self._prnt - funcname = '_cffi_%s_%s' % (category, name) - prnt('static int %s(PyObject *lib)' % funcname) - prnt('{') - prnt(' PyObject *o;') - prnt(' int res;') - if not is_int: - prnt(' %s;' % (vartp or tp).get_c_name(' i', name)) - else: - assert category == 'const' - # - if check_value is not None: - self._check_int_constant_value(name, check_value) - # - if not is_int: - if category == 'var': - realexpr = '&' + name - else: - realexpr = name - prnt(' i = (%s);' % (realexpr,)) - prnt(' o = %s;' % (self._convert_expr_from_c(tp, 'i', - 'variable type'),)) - assert delayed - else: - prnt(' o = _cffi_from_c_int_const(%s);' % name) - prnt(' if (o == NULL)') - prnt(' return -1;') - if size_too: - prnt(' {') - prnt(' PyObject *o1 = o;') - prnt(' o = Py_BuildValue("On", o1, (Py_ssize_t)sizeof(%s));' - % (name,)) - prnt(' Py_DECREF(o1);') - prnt(' if (o == NULL)') - prnt(' return -1;') - prnt(' }') - prnt(' res = PyObject_SetAttrString(lib, "%s", o);' % name) - prnt(' Py_DECREF(o);') - prnt(' if (res < 0)') - prnt(' return -1;') - prnt(' return %s;' % self._chained_list_constants[delayed]) - self._chained_list_constants[delayed] = funcname + '(lib)' - prnt('}') - prnt() - - def _generate_cpy_constant_collecttype(self, tp, name): - is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() - if not is_int: - self._do_collect_type(tp) - - def _generate_cpy_constant_decl(self, tp, name): - is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() - self._generate_cpy_const(is_int, name, tp) - - _generate_cpy_constant_method = _generate_nothing - _loading_cpy_constant = _loaded_noop - _loaded_cpy_constant = _loaded_noop - - # ---------- - # enums - - def _check_int_constant_value(self, name, value, err_prefix=''): - prnt = self._prnt - if value <= 0: - prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % ( - name, name, value)) - else: - prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % ( - name, name, value)) - prnt(' char buf[64];') - prnt(' if ((%s) <= 0)' % name) - prnt(' snprintf(buf, 63, "%%ld", (long)(%s));' % name) - prnt(' else') - prnt(' snprintf(buf, 63, "%%lu", (unsigned long)(%s));' % - name) - prnt(' PyErr_Format(_cffi_VerificationError,') - prnt(' "%s%s has the real value %s, not %s",') - prnt(' "%s", "%s", buf, "%d");' % ( - err_prefix, name, value)) - prnt(' return -1;') - prnt(' }') - - def _enum_funcname(self, prefix, name): - # "$enum_$1" => "___D_enum____D_1" - name = name.replace('$', '___D_') - return '_cffi_e_%s_%s' % (prefix, name) - - def _generate_cpy_enum_decl(self, tp, name, prefix='enum'): - if tp.partial: - for enumerator in tp.enumerators: - self._generate_cpy_const(True, enumerator, delayed=False) - return - # - funcname = self._enum_funcname(prefix, name) - prnt = self._prnt - prnt('static int %s(PyObject *lib)' % funcname) - prnt('{') - for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): - self._check_int_constant_value(enumerator, enumvalue, - "enum %s: " % name) - prnt(' return %s;' % self._chained_list_constants[True]) - self._chained_list_constants[True] = funcname + '(lib)' - prnt('}') - prnt() - - _generate_cpy_enum_collecttype = _generate_nothing - _generate_cpy_enum_method = _generate_nothing - - def _loading_cpy_enum(self, tp, name, module): - if tp.partial: - enumvalues = [getattr(module, enumerator) - for enumerator in tp.enumerators] - tp.enumvalues = tuple(enumvalues) - tp.partial_resolved = True - - def _loaded_cpy_enum(self, tp, name, module, library): - for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): - setattr(library, enumerator, enumvalue) - - # ---------- - # macros: for now only for integers - - def _generate_cpy_macro_decl(self, tp, name): - if tp == '...': - check_value = None - else: - check_value = tp # an integer - self._generate_cpy_const(True, name, check_value=check_value) - - _generate_cpy_macro_collecttype = _generate_nothing - _generate_cpy_macro_method = _generate_nothing - _loading_cpy_macro = _loaded_noop - _loaded_cpy_macro = _loaded_noop - - # ---------- - # global variables - - def _generate_cpy_variable_collecttype(self, tp, name): - if isinstance(tp, model.ArrayType): - tp_ptr = model.PointerType(tp.item) - else: - tp_ptr = model.PointerType(tp) - self._do_collect_type(tp_ptr) - - def _generate_cpy_variable_decl(self, tp, name): - if isinstance(tp, model.ArrayType): - tp_ptr = model.PointerType(tp.item) - self._generate_cpy_const(False, name, tp, vartp=tp_ptr, - size_too = (tp.length == '...')) - else: - tp_ptr = model.PointerType(tp) - self._generate_cpy_const(False, name, tp_ptr, category='var') - - _generate_cpy_variable_method = _generate_nothing - _loading_cpy_variable = _loaded_noop - - def _loaded_cpy_variable(self, tp, name, module, library): - value = getattr(library, name) - if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the - # sense that "a=..." is forbidden - if tp.length == '...': - assert isinstance(value, tuple) - (value, size) = value - BItemType = self.ffi._get_cached_btype(tp.item) - length, rest = divmod(size, self.ffi.sizeof(BItemType)) - if rest != 0: - raise ffiplatform.VerificationError( - "bad size: %r does not seem to be an array of %s" % - (name, tp.item)) - tp = tp.resolve_length(length) - # 'value' is a which we have to replace with - # a if the N is actually known - if tp.length is not None: - BArray = self.ffi._get_cached_btype(tp) - value = self.ffi.cast(BArray, value) - setattr(library, name, value) - return - # remove ptr= from the library instance, and replace - # it by a property on the class, which reads/writes into ptr[0]. - ptr = value - delattr(library, name) - def getter(library): - return ptr[0] - def setter(library, value): - ptr[0] = value - setattr(type(library), name, property(getter, setter)) - type(library)._cffi_dir.append(name) - - # ---------- - - def _generate_setup_custom(self): - prnt = self._prnt - prnt('static int _cffi_setup_custom(PyObject *lib)') - prnt('{') - prnt(' return %s;' % self._chained_list_constants[True]) - prnt('}') - -cffimod_header = r''' -#include -#include - -/* this block of #ifs should be kept exactly identical between - c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py */ -#if defined(_MSC_VER) -# include /* for alloca() */ -# if _MSC_VER < 1600 /* MSVC < 2010 */ - typedef __int8 int8_t; - typedef __int16 int16_t; - typedef __int32 int32_t; - typedef __int64 int64_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; - typedef unsigned __int64 uint64_t; - typedef __int8 int_least8_t; - typedef __int16 int_least16_t; - typedef __int32 int_least32_t; - typedef __int64 int_least64_t; - typedef unsigned __int8 uint_least8_t; - typedef unsigned __int16 uint_least16_t; - typedef unsigned __int32 uint_least32_t; - typedef unsigned __int64 uint_least64_t; - typedef __int8 int_fast8_t; - typedef __int16 int_fast16_t; - typedef __int32 int_fast32_t; - typedef __int64 int_fast64_t; - typedef unsigned __int8 uint_fast8_t; - typedef unsigned __int16 uint_fast16_t; - typedef unsigned __int32 uint_fast32_t; - typedef unsigned __int64 uint_fast64_t; - typedef __int64 intmax_t; - typedef unsigned __int64 uintmax_t; -# else -# include -# endif -# if _MSC_VER < 1800 /* MSVC < 2013 */ - typedef unsigned char _Bool; -# endif -#else -# include -# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) -# include -# endif -#endif - -#if PY_MAJOR_VERSION < 3 -# undef PyCapsule_CheckExact -# undef PyCapsule_GetPointer -# define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule)) -# define PyCapsule_GetPointer(capsule, name) \ - (PyCObject_AsVoidPtr(capsule)) -#endif - -#if PY_MAJOR_VERSION >= 3 -# define PyInt_FromLong PyLong_FromLong -#endif - -#define _cffi_from_c_double PyFloat_FromDouble -#define _cffi_from_c_float PyFloat_FromDouble -#define _cffi_from_c_long PyInt_FromLong -#define _cffi_from_c_ulong PyLong_FromUnsignedLong -#define _cffi_from_c_longlong PyLong_FromLongLong -#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong - -#define _cffi_to_c_double PyFloat_AsDouble -#define _cffi_to_c_float PyFloat_AsDouble - -#define _cffi_from_c_int_const(x) \ - (((x) > 0) ? \ - ((unsigned long long)(x) <= (unsigned long long)LONG_MAX) ? \ - PyInt_FromLong((long)(x)) : \ - PyLong_FromUnsignedLongLong((unsigned long long)(x)) : \ - ((long long)(x) >= (long long)LONG_MIN) ? \ - PyInt_FromLong((long)(x)) : \ - PyLong_FromLongLong((long long)(x))) - -#define _cffi_from_c_int(x, type) \ - (((type)-1) > 0 ? /* unsigned */ \ - (sizeof(type) < sizeof(long) ? \ - PyInt_FromLong((long)x) : \ - sizeof(type) == sizeof(long) ? \ - PyLong_FromUnsignedLong((unsigned long)x) : \ - PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ - (sizeof(type) <= sizeof(long) ? \ - PyInt_FromLong((long)x) : \ - PyLong_FromLongLong((long long)x))) - -#define _cffi_to_c_int(o, type) \ - ((type)( \ - sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ - : (type)_cffi_to_c_i8(o)) : \ - sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ - : (type)_cffi_to_c_i16(o)) : \ - sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ - : (type)_cffi_to_c_i32(o)) : \ - sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ - : (type)_cffi_to_c_i64(o)) : \ - (Py_FatalError("unsupported size for type " #type), (type)0))) - -#define _cffi_to_c_i8 \ - ((int(*)(PyObject *))_cffi_exports[1]) -#define _cffi_to_c_u8 \ - ((int(*)(PyObject *))_cffi_exports[2]) -#define _cffi_to_c_i16 \ - ((int(*)(PyObject *))_cffi_exports[3]) -#define _cffi_to_c_u16 \ - ((int(*)(PyObject *))_cffi_exports[4]) -#define _cffi_to_c_i32 \ - ((int(*)(PyObject *))_cffi_exports[5]) -#define _cffi_to_c_u32 \ - ((unsigned int(*)(PyObject *))_cffi_exports[6]) -#define _cffi_to_c_i64 \ - ((long long(*)(PyObject *))_cffi_exports[7]) -#define _cffi_to_c_u64 \ - ((unsigned long long(*)(PyObject *))_cffi_exports[8]) -#define _cffi_to_c_char \ - ((int(*)(PyObject *))_cffi_exports[9]) -#define _cffi_from_c_pointer \ - ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[10]) -#define _cffi_to_c_pointer \ - ((char *(*)(PyObject *, CTypeDescrObject *))_cffi_exports[11]) -#define _cffi_get_struct_layout \ - ((PyObject *(*)(Py_ssize_t[]))_cffi_exports[12]) -#define _cffi_restore_errno \ - ((void(*)(void))_cffi_exports[13]) -#define _cffi_save_errno \ - ((void(*)(void))_cffi_exports[14]) -#define _cffi_from_c_char \ - ((PyObject *(*)(char))_cffi_exports[15]) -#define _cffi_from_c_deref \ - ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[16]) -#define _cffi_to_c \ - ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[17]) -#define _cffi_from_c_struct \ - ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[18]) -#define _cffi_to_c_wchar_t \ - ((wchar_t(*)(PyObject *))_cffi_exports[19]) -#define _cffi_from_c_wchar_t \ - ((PyObject *(*)(wchar_t))_cffi_exports[20]) -#define _cffi_to_c_long_double \ - ((long double(*)(PyObject *))_cffi_exports[21]) -#define _cffi_to_c__Bool \ - ((_Bool(*)(PyObject *))_cffi_exports[22]) -#define _cffi_prepare_pointer_call_argument \ - ((Py_ssize_t(*)(CTypeDescrObject *, PyObject *, char **))_cffi_exports[23]) -#define _cffi_convert_array_from_object \ - ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24]) -#define _CFFI_NUM_EXPORTS 25 - -typedef struct _ctypedescr CTypeDescrObject; - -static void *_cffi_exports[_CFFI_NUM_EXPORTS]; -static PyObject *_cffi_types, *_cffi_VerificationError; - -static int _cffi_setup_custom(PyObject *lib); /* forward */ - -static PyObject *_cffi_setup(PyObject *self, PyObject *args) -{ - PyObject *library; - int was_alive = (_cffi_types != NULL); - (void)self; /* unused */ - if (!PyArg_ParseTuple(args, "OOO", &_cffi_types, &_cffi_VerificationError, - &library)) - return NULL; - Py_INCREF(_cffi_types); - Py_INCREF(_cffi_VerificationError); - if (_cffi_setup_custom(library) < 0) - return NULL; - return PyBool_FromLong(was_alive); -} - -static int _cffi_init(void) -{ - PyObject *module, *c_api_object = NULL; - - module = PyImport_ImportModule("_cffi_backend"); - if (module == NULL) - goto failure; - - c_api_object = PyObject_GetAttrString(module, "_C_API"); - if (c_api_object == NULL) - goto failure; - if (!PyCapsule_CheckExact(c_api_object)) { - PyErr_SetNone(PyExc_ImportError); - goto failure; - } - memcpy(_cffi_exports, PyCapsule_GetPointer(c_api_object, "cffi"), - _CFFI_NUM_EXPORTS * sizeof(void *)); - - Py_DECREF(module); - Py_DECREF(c_api_object); - return 0; - - failure: - Py_XDECREF(module); - Py_XDECREF(c_api_object); - return -1; -} - -#define _cffi_type(num) ((CTypeDescrObject *)PyList_GET_ITEM(_cffi_types, num)) - -/**********/ -''' diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/vengine_gen.py b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/vengine_gen.py deleted file mode 100644 index 9cc3853..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/vengine_gen.py +++ /dev/null @@ -1,668 +0,0 @@ -import sys, os -import types - -from . import model, ffiplatform - - -class VGenericEngine(object): - _class_key = 'g' - _gen_python_module = False - - def __init__(self, verifier): - self.verifier = verifier - self.ffi = verifier.ffi - self.export_symbols = [] - self._struct_pending_verification = {} - - def patch_extension_kwds(self, kwds): - # add 'export_symbols' to the dictionary. Note that we add the - # list before filling it. When we fill it, it will thus also show - # up in kwds['export_symbols']. - kwds.setdefault('export_symbols', self.export_symbols) - - def find_module(self, module_name, path, so_suffixes): - for so_suffix in so_suffixes: - basename = module_name + so_suffix - if path is None: - path = sys.path - for dirname in path: - filename = os.path.join(dirname, basename) - if os.path.isfile(filename): - return filename - - def collect_types(self): - pass # not needed in the generic engine - - def _prnt(self, what=''): - self._f.write(what + '\n') - - def write_source_to_f(self): - prnt = self._prnt - # first paste some standard set of lines that are mostly '#include' - prnt(cffimod_header) - # then paste the C source given by the user, verbatim. - prnt(self.verifier.preamble) - # - # call generate_gen_xxx_decl(), for every xxx found from - # ffi._parser._declarations. This generates all the functions. - self._generate('decl') - # - # on Windows, distutils insists on putting init_cffi_xyz in - # 'export_symbols', so instead of fighting it, just give up and - # give it one - if sys.platform == 'win32': - if sys.version_info >= (3,): - prefix = 'PyInit_' - else: - prefix = 'init' - modname = self.verifier.get_module_name() - prnt("void %s%s(void) { }\n" % (prefix, modname)) - - def load_library(self, flags=0): - # import it with the CFFI backend - backend = self.ffi._backend - # needs to make a path that contains '/', on Posix - filename = os.path.join(os.curdir, self.verifier.modulefilename) - module = backend.load_library(filename, flags) - # - # call loading_gen_struct() to get the struct layout inferred by - # the C compiler - self._load(module, 'loading') - - # build the FFILibrary class and instance, this is a module subclass - # because modules are expected to have usually-constant-attributes and - # in PyPy this means the JIT is able to treat attributes as constant, - # which we want. - class FFILibrary(types.ModuleType): - _cffi_generic_module = module - _cffi_ffi = self.ffi - _cffi_dir = [] - def __dir__(self): - return FFILibrary._cffi_dir - library = FFILibrary("") - # - # finally, call the loaded_gen_xxx() functions. This will set - # up the 'library' object. - self._load(module, 'loaded', library=library) - return library - - def _get_declarations(self): - lst = [(key, tp) for (key, (tp, qual)) in - self.ffi._parser._declarations.items()] - lst.sort() - return lst - - def _generate(self, step_name): - for name, tp in self._get_declarations(): - kind, realname = name.split(' ', 1) - try: - method = getattr(self, '_generate_gen_%s_%s' % (kind, - step_name)) - except AttributeError: - raise ffiplatform.VerificationError( - "not implemented in verify(): %r" % name) - try: - method(tp, realname) - except Exception as e: - model.attach_exception_info(e, name) - raise - - def _load(self, module, step_name, **kwds): - for name, tp in self._get_declarations(): - kind, realname = name.split(' ', 1) - method = getattr(self, '_%s_gen_%s' % (step_name, kind)) - try: - method(tp, realname, module, **kwds) - except Exception as e: - model.attach_exception_info(e, name) - raise - - def _generate_nothing(self, tp, name): - pass - - def _loaded_noop(self, tp, name, module, **kwds): - pass - - # ---------- - # typedefs: generates no code so far - - _generate_gen_typedef_decl = _generate_nothing - _loading_gen_typedef = _loaded_noop - _loaded_gen_typedef = _loaded_noop - - # ---------- - # function declarations - - def _generate_gen_function_decl(self, tp, name): - assert isinstance(tp, model.FunctionPtrType) - if tp.ellipsis: - # cannot support vararg functions better than this: check for its - # exact type (including the fixed arguments), and build it as a - # constant function pointer (no _cffi_f_%s wrapper) - self._generate_gen_const(False, name, tp) - return - prnt = self._prnt - numargs = len(tp.args) - argnames = [] - for i, type in enumerate(tp.args): - indirection = '' - if isinstance(type, model.StructOrUnion): - indirection = '*' - argnames.append('%sx%d' % (indirection, i)) - context = 'argument of %s' % name - arglist = [type.get_c_name(' %s' % arg, context) - for type, arg in zip(tp.args, argnames)] - tpresult = tp.result - if isinstance(tpresult, model.StructOrUnion): - arglist.insert(0, tpresult.get_c_name(' *r', context)) - tpresult = model.void_type - arglist = ', '.join(arglist) or 'void' - wrappername = '_cffi_f_%s' % name - self.export_symbols.append(wrappername) - if tp.abi: - abi = tp.abi + ' ' - else: - abi = '' - funcdecl = ' %s%s(%s)' % (abi, wrappername, arglist) - context = 'result of %s' % name - prnt(tpresult.get_c_name(funcdecl, context)) - prnt('{') - # - if isinstance(tp.result, model.StructOrUnion): - result_code = '*r = ' - elif not isinstance(tp.result, model.VoidType): - result_code = 'return ' - else: - result_code = '' - prnt(' %s%s(%s);' % (result_code, name, ', '.join(argnames))) - prnt('}') - prnt() - - _loading_gen_function = _loaded_noop - - def _loaded_gen_function(self, tp, name, module, library): - assert isinstance(tp, model.FunctionPtrType) - if tp.ellipsis: - newfunction = self._load_constant(False, tp, name, module) - else: - indirections = [] - base_tp = tp - if (any(isinstance(typ, model.StructOrUnion) for typ in tp.args) - or isinstance(tp.result, model.StructOrUnion)): - indirect_args = [] - for i, typ in enumerate(tp.args): - if isinstance(typ, model.StructOrUnion): - typ = model.PointerType(typ) - indirections.append((i, typ)) - indirect_args.append(typ) - indirect_result = tp.result - if isinstance(indirect_result, model.StructOrUnion): - if indirect_result.fldtypes is None: - raise TypeError("'%s' is used as result type, " - "but is opaque" % ( - indirect_result._get_c_name(),)) - indirect_result = model.PointerType(indirect_result) - indirect_args.insert(0, indirect_result) - indirections.insert(0, ("result", indirect_result)) - indirect_result = model.void_type - tp = model.FunctionPtrType(tuple(indirect_args), - indirect_result, tp.ellipsis) - BFunc = self.ffi._get_cached_btype(tp) - wrappername = '_cffi_f_%s' % name - newfunction = module.load_function(BFunc, wrappername) - for i, typ in indirections: - newfunction = self._make_struct_wrapper(newfunction, i, typ, - base_tp) - setattr(library, name, newfunction) - type(library)._cffi_dir.append(name) - - def _make_struct_wrapper(self, oldfunc, i, tp, base_tp): - backend = self.ffi._backend - BType = self.ffi._get_cached_btype(tp) - if i == "result": - ffi = self.ffi - def newfunc(*args): - res = ffi.new(BType) - oldfunc(res, *args) - return res[0] - else: - def newfunc(*args): - args = args[:i] + (backend.newp(BType, args[i]),) + args[i+1:] - return oldfunc(*args) - newfunc._cffi_base_type = base_tp - return newfunc - - # ---------- - # named structs - - def _generate_gen_struct_decl(self, tp, name): - assert name == tp.name - self._generate_struct_or_union_decl(tp, 'struct', name) - - def _loading_gen_struct(self, tp, name, module): - self._loading_struct_or_union(tp, 'struct', name, module) - - def _loaded_gen_struct(self, tp, name, module, **kwds): - self._loaded_struct_or_union(tp) - - def _generate_gen_union_decl(self, tp, name): - assert name == tp.name - self._generate_struct_or_union_decl(tp, 'union', name) - - def _loading_gen_union(self, tp, name, module): - self._loading_struct_or_union(tp, 'union', name, module) - - def _loaded_gen_union(self, tp, name, module, **kwds): - self._loaded_struct_or_union(tp) - - def _generate_struct_or_union_decl(self, tp, prefix, name): - if tp.fldnames is None: - return # nothing to do with opaque structs - checkfuncname = '_cffi_check_%s_%s' % (prefix, name) - layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) - cname = ('%s %s' % (prefix, name)).strip() - # - prnt = self._prnt - prnt('static void %s(%s *p)' % (checkfuncname, cname)) - prnt('{') - prnt(' /* only to generate compile-time warnings or errors */') - prnt(' (void)p;') - for fname, ftype, fbitsize, fqual in tp.enumfields(): - if (isinstance(ftype, model.PrimitiveType) - and ftype.is_integer_type()) or fbitsize >= 0: - # accept all integers, but complain on float or double - prnt(' (void)((p->%s) << 1);' % fname) - else: - # only accept exactly the type declared. - try: - prnt(' { %s = &p->%s; (void)tmp; }' % ( - ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual), - fname)) - except ffiplatform.VerificationError as e: - prnt(' /* %s */' % str(e)) # cannot verify it, ignore - prnt('}') - self.export_symbols.append(layoutfuncname) - prnt('intptr_t %s(intptr_t i)' % (layoutfuncname,)) - prnt('{') - prnt(' struct _cffi_aligncheck { char x; %s y; };' % cname) - prnt(' static intptr_t nums[] = {') - prnt(' sizeof(%s),' % cname) - prnt(' offsetof(struct _cffi_aligncheck, y),') - for fname, ftype, fbitsize, fqual in tp.enumfields(): - if fbitsize >= 0: - continue # xxx ignore fbitsize for now - prnt(' offsetof(%s, %s),' % (cname, fname)) - if isinstance(ftype, model.ArrayType) and ftype.length is None: - prnt(' 0, /* %s */' % ftype._get_c_name()) - else: - prnt(' sizeof(((%s *)0)->%s),' % (cname, fname)) - prnt(' -1') - prnt(' };') - prnt(' return nums[i];') - prnt(' /* the next line is not executed, but compiled */') - prnt(' %s(0);' % (checkfuncname,)) - prnt('}') - prnt() - - def _loading_struct_or_union(self, tp, prefix, name, module): - if tp.fldnames is None: - return # nothing to do with opaque structs - layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) - # - BFunc = self.ffi._typeof_locked("intptr_t(*)(intptr_t)")[0] - function = module.load_function(BFunc, layoutfuncname) - layout = [] - num = 0 - while True: - x = function(num) - if x < 0: break - layout.append(x) - num += 1 - if isinstance(tp, model.StructOrUnion) and tp.partial: - # use the function()'s sizes and offsets to guide the - # layout of the struct - totalsize = layout[0] - totalalignment = layout[1] - fieldofs = layout[2::2] - fieldsize = layout[3::2] - tp.force_flatten() - assert len(fieldofs) == len(fieldsize) == len(tp.fldnames) - tp.fixedlayout = fieldofs, fieldsize, totalsize, totalalignment - else: - cname = ('%s %s' % (prefix, name)).strip() - self._struct_pending_verification[tp] = layout, cname - - def _loaded_struct_or_union(self, tp): - if tp.fldnames is None: - return # nothing to do with opaque structs - self.ffi._get_cached_btype(tp) # force 'fixedlayout' to be considered - - if tp in self._struct_pending_verification: - # check that the layout sizes and offsets match the real ones - def check(realvalue, expectedvalue, msg): - if realvalue != expectedvalue: - raise ffiplatform.VerificationError( - "%s (we have %d, but C compiler says %d)" - % (msg, expectedvalue, realvalue)) - ffi = self.ffi - BStruct = ffi._get_cached_btype(tp) - layout, cname = self._struct_pending_verification.pop(tp) - check(layout[0], ffi.sizeof(BStruct), "wrong total size") - check(layout[1], ffi.alignof(BStruct), "wrong total alignment") - i = 2 - for fname, ftype, fbitsize, fqual in tp.enumfields(): - if fbitsize >= 0: - continue # xxx ignore fbitsize for now - check(layout[i], ffi.offsetof(BStruct, fname), - "wrong offset for field %r" % (fname,)) - if layout[i+1] != 0: - BField = ffi._get_cached_btype(ftype) - check(layout[i+1], ffi.sizeof(BField), - "wrong size for field %r" % (fname,)) - i += 2 - assert i == len(layout) - - # ---------- - # 'anonymous' declarations. These are produced for anonymous structs - # or unions; the 'name' is obtained by a typedef. - - def _generate_gen_anonymous_decl(self, tp, name): - if isinstance(tp, model.EnumType): - self._generate_gen_enum_decl(tp, name, '') - else: - self._generate_struct_or_union_decl(tp, '', name) - - def _loading_gen_anonymous(self, tp, name, module): - if isinstance(tp, model.EnumType): - self._loading_gen_enum(tp, name, module, '') - else: - self._loading_struct_or_union(tp, '', name, module) - - def _loaded_gen_anonymous(self, tp, name, module, **kwds): - if isinstance(tp, model.EnumType): - self._loaded_gen_enum(tp, name, module, **kwds) - else: - self._loaded_struct_or_union(tp) - - # ---------- - # constants, likely declared with '#define' - - def _generate_gen_const(self, is_int, name, tp=None, category='const', - check_value=None): - prnt = self._prnt - funcname = '_cffi_%s_%s' % (category, name) - self.export_symbols.append(funcname) - if check_value is not None: - assert is_int - assert category == 'const' - prnt('int %s(char *out_error)' % funcname) - prnt('{') - self._check_int_constant_value(name, check_value) - prnt(' return 0;') - prnt('}') - elif is_int: - assert category == 'const' - prnt('int %s(long long *out_value)' % funcname) - prnt('{') - prnt(' *out_value = (long long)(%s);' % (name,)) - prnt(' return (%s) <= 0;' % (name,)) - prnt('}') - else: - assert tp is not None - assert check_value is None - if category == 'var': - ampersand = '&' - else: - ampersand = '' - extra = '' - if category == 'const' and isinstance(tp, model.StructOrUnion): - extra = 'const *' - ampersand = '&' - prnt(tp.get_c_name(' %s%s(void)' % (extra, funcname), name)) - prnt('{') - prnt(' return (%s%s);' % (ampersand, name)) - prnt('}') - prnt() - - def _generate_gen_constant_decl(self, tp, name): - is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() - self._generate_gen_const(is_int, name, tp) - - _loading_gen_constant = _loaded_noop - - def _load_constant(self, is_int, tp, name, module, check_value=None): - funcname = '_cffi_const_%s' % name - if check_value is not None: - assert is_int - self._load_known_int_constant(module, funcname) - value = check_value - elif is_int: - BType = self.ffi._typeof_locked("long long*")[0] - BFunc = self.ffi._typeof_locked("int(*)(long long*)")[0] - function = module.load_function(BFunc, funcname) - p = self.ffi.new(BType) - negative = function(p) - value = int(p[0]) - if value < 0 and not negative: - BLongLong = self.ffi._typeof_locked("long long")[0] - value += (1 << (8*self.ffi.sizeof(BLongLong))) - else: - assert check_value is None - fntypeextra = '(*)(void)' - if isinstance(tp, model.StructOrUnion): - fntypeextra = '*' + fntypeextra - BFunc = self.ffi._typeof_locked(tp.get_c_name(fntypeextra, name))[0] - function = module.load_function(BFunc, funcname) - value = function() - if isinstance(tp, model.StructOrUnion): - value = value[0] - return value - - def _loaded_gen_constant(self, tp, name, module, library): - is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() - value = self._load_constant(is_int, tp, name, module) - setattr(library, name, value) - type(library)._cffi_dir.append(name) - - # ---------- - # enums - - def _check_int_constant_value(self, name, value): - prnt = self._prnt - if value <= 0: - prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % ( - name, name, value)) - else: - prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % ( - name, name, value)) - prnt(' char buf[64];') - prnt(' if ((%s) <= 0)' % name) - prnt(' sprintf(buf, "%%ld", (long)(%s));' % name) - prnt(' else') - prnt(' sprintf(buf, "%%lu", (unsigned long)(%s));' % - name) - prnt(' sprintf(out_error, "%s has the real value %s, not %s",') - prnt(' "%s", buf, "%d");' % (name[:100], value)) - prnt(' return -1;') - prnt(' }') - - def _load_known_int_constant(self, module, funcname): - BType = self.ffi._typeof_locked("char[]")[0] - BFunc = self.ffi._typeof_locked("int(*)(char*)")[0] - function = module.load_function(BFunc, funcname) - p = self.ffi.new(BType, 256) - if function(p) < 0: - error = self.ffi.string(p) - if sys.version_info >= (3,): - error = str(error, 'utf-8') - raise ffiplatform.VerificationError(error) - - def _enum_funcname(self, prefix, name): - # "$enum_$1" => "___D_enum____D_1" - name = name.replace('$', '___D_') - return '_cffi_e_%s_%s' % (prefix, name) - - def _generate_gen_enum_decl(self, tp, name, prefix='enum'): - if tp.partial: - for enumerator in tp.enumerators: - self._generate_gen_const(True, enumerator) - return - # - funcname = self._enum_funcname(prefix, name) - self.export_symbols.append(funcname) - prnt = self._prnt - prnt('int %s(char *out_error)' % funcname) - prnt('{') - for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): - self._check_int_constant_value(enumerator, enumvalue) - prnt(' return 0;') - prnt('}') - prnt() - - def _loading_gen_enum(self, tp, name, module, prefix='enum'): - if tp.partial: - enumvalues = [self._load_constant(True, tp, enumerator, module) - for enumerator in tp.enumerators] - tp.enumvalues = tuple(enumvalues) - tp.partial_resolved = True - else: - funcname = self._enum_funcname(prefix, name) - self._load_known_int_constant(module, funcname) - - def _loaded_gen_enum(self, tp, name, module, library): - for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): - setattr(library, enumerator, enumvalue) - type(library)._cffi_dir.append(enumerator) - - # ---------- - # macros: for now only for integers - - def _generate_gen_macro_decl(self, tp, name): - if tp == '...': - check_value = None - else: - check_value = tp # an integer - self._generate_gen_const(True, name, check_value=check_value) - - _loading_gen_macro = _loaded_noop - - def _loaded_gen_macro(self, tp, name, module, library): - if tp == '...': - check_value = None - else: - check_value = tp # an integer - value = self._load_constant(True, tp, name, module, - check_value=check_value) - setattr(library, name, value) - type(library)._cffi_dir.append(name) - - # ---------- - # global variables - - def _generate_gen_variable_decl(self, tp, name): - if isinstance(tp, model.ArrayType): - if tp.length == '...': - prnt = self._prnt - funcname = '_cffi_sizeof_%s' % (name,) - self.export_symbols.append(funcname) - prnt("size_t %s(void)" % funcname) - prnt("{") - prnt(" return sizeof(%s);" % (name,)) - prnt("}") - tp_ptr = model.PointerType(tp.item) - self._generate_gen_const(False, name, tp_ptr) - else: - tp_ptr = model.PointerType(tp) - self._generate_gen_const(False, name, tp_ptr, category='var') - - _loading_gen_variable = _loaded_noop - - def _loaded_gen_variable(self, tp, name, module, library): - if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the - # sense that "a=..." is forbidden - if tp.length == '...': - funcname = '_cffi_sizeof_%s' % (name,) - BFunc = self.ffi._typeof_locked('size_t(*)(void)')[0] - function = module.load_function(BFunc, funcname) - size = function() - BItemType = self.ffi._get_cached_btype(tp.item) - length, rest = divmod(size, self.ffi.sizeof(BItemType)) - if rest != 0: - raise ffiplatform.VerificationError( - "bad size: %r does not seem to be an array of %s" % - (name, tp.item)) - tp = tp.resolve_length(length) - tp_ptr = model.PointerType(tp.item) - value = self._load_constant(False, tp_ptr, name, module) - # 'value' is a which we have to replace with - # a if the N is actually known - if tp.length is not None: - BArray = self.ffi._get_cached_btype(tp) - value = self.ffi.cast(BArray, value) - setattr(library, name, value) - type(library)._cffi_dir.append(name) - return - # remove ptr= from the library instance, and replace - # it by a property on the class, which reads/writes into ptr[0]. - funcname = '_cffi_var_%s' % name - BFunc = self.ffi._typeof_locked(tp.get_c_name('*(*)(void)', name))[0] - function = module.load_function(BFunc, funcname) - ptr = function() - def getter(library): - return ptr[0] - def setter(library, value): - ptr[0] = value - setattr(type(library), name, property(getter, setter)) - type(library)._cffi_dir.append(name) - -cffimod_header = r''' -#include -#include -#include -#include -#include /* XXX for ssize_t on some platforms */ - -/* this block of #ifs should be kept exactly identical between - c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py */ -#if defined(_MSC_VER) -# include /* for alloca() */ -# if _MSC_VER < 1600 /* MSVC < 2010 */ - typedef __int8 int8_t; - typedef __int16 int16_t; - typedef __int32 int32_t; - typedef __int64 int64_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; - typedef unsigned __int64 uint64_t; - typedef __int8 int_least8_t; - typedef __int16 int_least16_t; - typedef __int32 int_least32_t; - typedef __int64 int_least64_t; - typedef unsigned __int8 uint_least8_t; - typedef unsigned __int16 uint_least16_t; - typedef unsigned __int32 uint_least32_t; - typedef unsigned __int64 uint_least64_t; - typedef __int8 int_fast8_t; - typedef __int16 int_fast16_t; - typedef __int32 int_fast32_t; - typedef __int64 int_fast64_t; - typedef unsigned __int8 uint_fast8_t; - typedef unsigned __int16 uint_fast16_t; - typedef unsigned __int32 uint_fast32_t; - typedef unsigned __int64 uint_fast64_t; - typedef __int64 intmax_t; - typedef unsigned __int64 uintmax_t; -# else -# include -# endif -# if _MSC_VER < 1800 /* MSVC < 2013 */ - typedef unsigned char _Bool; -# endif -#else -# include -# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) -# include -# endif -#endif -''' diff --git a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/verifier.py b/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/verifier.py deleted file mode 100644 index 01728ae..0000000 --- a/virtualenv/lib/python3.5/site-packages/cffi-1.3.1-py3.5-macosx-10.6-intel.egg/cffi/verifier.py +++ /dev/null @@ -1,313 +0,0 @@ -import sys, os, binascii, shutil, io -from . import __version_verifier_modules__ -from . import ffiplatform - -if sys.version_info >= (3, 3): - import importlib.machinery - def _extension_suffixes(): - return importlib.machinery.EXTENSION_SUFFIXES[:] -else: - import imp - def _extension_suffixes(): - return [suffix for suffix, _, type in imp.get_suffixes() - if type == imp.C_EXTENSION] - - -if sys.version_info >= (3,): - NativeIO = io.StringIO -else: - class NativeIO(io.BytesIO): - def write(self, s): - if isinstance(s, unicode): - s = s.encode('ascii') - super(NativeIO, self).write(s) - -def _hack_at_distutils(): - # Windows-only workaround for some configurations: see - # https://bugs.python.org/issue23246 (Python 2.7 with - # a specific MS compiler suite download) - if sys.platform == "win32": - try: - import setuptools # for side-effects, patches distutils - except ImportError: - pass - - -class Verifier(object): - - def __init__(self, ffi, preamble, tmpdir=None, modulename=None, - ext_package=None, tag='', force_generic_engine=False, - source_extension='.c', flags=None, relative_to=None, **kwds): - if ffi._parser._uses_new_feature: - raise ffiplatform.VerificationError( - "feature not supported with ffi.verify(), but only " - "with ffi.set_source(): %s" % (ffi._parser._uses_new_feature,)) - self.ffi = ffi - self.preamble = preamble - if not modulename: - flattened_kwds = ffiplatform.flatten(kwds) - vengine_class = _locate_engine_class(ffi, force_generic_engine) - self._vengine = vengine_class(self) - self._vengine.patch_extension_kwds(kwds) - self.flags = flags - self.kwds = self.make_relative_to(kwds, relative_to) - # - if modulename: - if tag: - raise TypeError("can't specify both 'modulename' and 'tag'") - else: - key = '\x00'.join([sys.version[:3], __version_verifier_modules__, - preamble, flattened_kwds] + - ffi._cdefsources) - if sys.version_info >= (3,): - key = key.encode('utf-8') - k1 = hex(binascii.crc32(key[0::2]) & 0xffffffff) - k1 = k1.lstrip('0x').rstrip('L') - k2 = hex(binascii.crc32(key[1::2]) & 0xffffffff) - k2 = k2.lstrip('0').rstrip('L') - modulename = '_cffi_%s_%s%s%s' % (tag, self._vengine._class_key, - k1, k2) - suffix = _get_so_suffixes()[0] - self.tmpdir = tmpdir or _caller_dir_pycache() - self.sourcefilename = os.path.join(self.tmpdir, modulename + source_extension) - self.modulefilename = os.path.join(self.tmpdir, modulename + suffix) - self.ext_package = ext_package - self._has_source = False - self._has_module = False - - def write_source(self, file=None): - """Write the C source code. It is produced in 'self.sourcefilename', - which can be tweaked beforehand.""" - with self.ffi._lock: - if self._has_source and file is None: - raise ffiplatform.VerificationError( - "source code already written") - self._write_source(file) - - def compile_module(self): - """Write the C source code (if not done already) and compile it. - This produces a dynamic link library in 'self.modulefilename'.""" - with self.ffi._lock: - if self._has_module: - raise ffiplatform.VerificationError("module already compiled") - if not self._has_source: - self._write_source() - self._compile_module() - - def load_library(self): - """Get a C module from this Verifier instance. - Returns an instance of a FFILibrary class that behaves like the - objects returned by ffi.dlopen(), but that delegates all - operations to the C module. If necessary, the C code is written - and compiled first. - """ - with self.ffi._lock: - if not self._has_module: - self._locate_module() - if not self._has_module: - if not self._has_source: - self._write_source() - self._compile_module() - return self._load_library() - - def get_module_name(self): - basename = os.path.basename(self.modulefilename) - # kill both the .so extension and the other .'s, as introduced - # by Python 3: 'basename.cpython-33m.so' - basename = basename.split('.', 1)[0] - # and the _d added in Python 2 debug builds --- but try to be - # conservative and not kill a legitimate _d - if basename.endswith('_d') and hasattr(sys, 'gettotalrefcount'): - basename = basename[:-2] - return basename - - def get_extension(self): - _hack_at_distutils() # backward compatibility hack - if not self._has_source: - with self.ffi._lock: - if not self._has_source: - self._write_source() - sourcename = ffiplatform.maybe_relative_path(self.sourcefilename) - modname = self.get_module_name() - return ffiplatform.get_extension(sourcename, modname, **self.kwds) - - def generates_python_module(self): - return self._vengine._gen_python_module - - def make_relative_to(self, kwds, relative_to): - if relative_to and os.path.dirname(relative_to): - dirname = os.path.dirname(relative_to) - kwds = kwds.copy() - for key in ffiplatform.LIST_OF_FILE_NAMES: - if key in kwds: - lst = kwds[key] - if not isinstance(lst, (list, tuple)): - raise TypeError("keyword '%s' should be a list or tuple" - % (key,)) - lst = [os.path.join(dirname, fn) for fn in lst] - kwds[key] = lst - return kwds - - # ---------- - - def _locate_module(self): - if not os.path.isfile(self.modulefilename): - if self.ext_package: - try: - pkg = __import__(self.ext_package, None, None, ['__doc__']) - except ImportError: - return # cannot import the package itself, give up - # (e.g. it might be called differently before installation) - path = pkg.__path__ - else: - path = None - filename = self._vengine.find_module(self.get_module_name(), path, - _get_so_suffixes()) - if filename is None: - return - self.modulefilename = filename - self._vengine.collect_types() - self._has_module = True - - def _write_source_to(self, file): - self._vengine._f = file - try: - self._vengine.write_source_to_f() - finally: - del self._vengine._f - - def _write_source(self, file=None): - if file is not None: - self._write_source_to(file) - else: - # Write our source file to an in memory file. - f = NativeIO() - self._write_source_to(f) - source_data = f.getvalue() - - # Determine if this matches the current file - if os.path.exists(self.sourcefilename): - with open(self.sourcefilename, "r") as fp: - needs_written = not (fp.read() == source_data) - else: - needs_written = True - - # Actually write the file out if it doesn't match - if needs_written: - _ensure_dir(self.sourcefilename) - with open(self.sourcefilename, "w") as fp: - fp.write(source_data) - - # Set this flag - self._has_source = True - - def _compile_module(self): - # compile this C source - tmpdir = os.path.dirname(self.sourcefilename) - outputfilename = ffiplatform.compile(tmpdir, self.get_extension()) - try: - same = ffiplatform.samefile(outputfilename, self.modulefilename) - except OSError: - same = False - if not same: - _ensure_dir(self.modulefilename) - shutil.move(outputfilename, self.modulefilename) - self._has_module = True - - def _load_library(self): - assert self._has_module - if self.flags is not None: - return self._vengine.load_library(self.flags) - else: - return self._vengine.load_library() - -# ____________________________________________________________ - -_FORCE_GENERIC_ENGINE = False # for tests - -def _locate_engine_class(ffi, force_generic_engine): - if _FORCE_GENERIC_ENGINE: - force_generic_engine = True - if not force_generic_engine: - if '__pypy__' in sys.builtin_module_names: - force_generic_engine = True - else: - try: - import _cffi_backend - except ImportError: - _cffi_backend = '?' - if ffi._backend is not _cffi_backend: - force_generic_engine = True - if force_generic_engine: - from . import vengine_gen - return vengine_gen.VGenericEngine - else: - from . import vengine_cpy - return vengine_cpy.VCPythonEngine - -# ____________________________________________________________ - -_TMPDIR = None - -def _caller_dir_pycache(): - if _TMPDIR: - return _TMPDIR - result = os.environ.get('CFFI_TMPDIR') - if result: - return result - filename = sys._getframe(2).f_code.co_filename - return os.path.abspath(os.path.join(os.path.dirname(filename), - '__pycache__')) - -def set_tmpdir(dirname): - """Set the temporary directory to use instead of __pycache__.""" - global _TMPDIR - _TMPDIR = dirname - -def cleanup_tmpdir(tmpdir=None, keep_so=False): - """Clean up the temporary directory by removing all files in it - called `_cffi_*.{c,so}` as well as the `build` subdirectory.""" - tmpdir = tmpdir or _caller_dir_pycache() - try: - filelist = os.listdir(tmpdir) - except OSError: - return - if keep_so: - suffix = '.c' # only remove .c files - else: - suffix = _get_so_suffixes()[0].lower() - for fn in filelist: - if fn.lower().startswith('_cffi_') and ( - fn.lower().endswith(suffix) or fn.lower().endswith('.c')): - try: - os.unlink(os.path.join(tmpdir, fn)) - except OSError: - pass - clean_dir = [os.path.join(tmpdir, 'build')] - for dir in clean_dir: - try: - for fn in os.listdir(dir): - fn = os.path.join(dir, fn) - if os.path.isdir(fn): - clean_dir.append(fn) - else: - os.unlink(fn) - except OSError: - pass - -def _get_so_suffixes(): - suffixes = _extension_suffixes() - if not suffixes: - # bah, no C_EXTENSION available. Occurs on pypy without cpyext - if sys.platform == 'win32': - suffixes = [".pyd"] - else: - suffixes = [".so"] - - return suffixes - -def _ensure_dir(filename): - try: - os.makedirs(os.path.dirname(filename)) - except OSError: - pass diff --git a/virtualenv/lib/python3.5/site-packages/dateutil/__init__.py b/virtualenv/lib/python3.5/site-packages/dateutil/__init__.py deleted file mode 100644 index 743669c..0000000 --- a/virtualenv/lib/python3.5/site-packages/dateutil/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# -*- coding: utf-8 -*- -__version__ = "2.4.2" diff --git a/virtualenv/lib/python3.5/site-packages/dateutil/easter.py b/virtualenv/lib/python3.5/site-packages/dateutil/easter.py deleted file mode 100644 index 8d30c4e..0000000 --- a/virtualenv/lib/python3.5/site-packages/dateutil/easter.py +++ /dev/null @@ -1,89 +0,0 @@ -# -*- coding: utf-8 -*- -""" -This module offers a generic easter computing method for any given year, using -Western, Orthodox or Julian algorithms. -""" - -import datetime - -__all__ = ["easter", "EASTER_JULIAN", "EASTER_ORTHODOX", "EASTER_WESTERN"] - -EASTER_JULIAN = 1 -EASTER_ORTHODOX = 2 -EASTER_WESTERN = 3 - - -def easter(year, method=EASTER_WESTERN): - """ - This method was ported from the work done by GM Arts, - on top of the algorithm by Claus Tondering, which was - based in part on the algorithm of Ouding (1940), as - quoted in "Explanatory Supplement to the Astronomical - Almanac", P. Kenneth Seidelmann, editor. - - This algorithm implements three different easter - calculation methods: - - 1 - Original calculation in Julian calendar, valid in - dates after 326 AD - 2 - Original method, with date converted to Gregorian - calendar, valid in years 1583 to 4099 - 3 - Revised method, in Gregorian calendar, valid in - years 1583 to 4099 as well - - These methods are represented by the constants: - - EASTER_JULIAN = 1 - EASTER_ORTHODOX = 2 - EASTER_WESTERN = 3 - - The default method is method 3. - - More about the algorithm may be found at: - - http://users.chariot.net.au/~gmarts/eastalg.htm - - and - - http://www.tondering.dk/claus/calendar.html - - """ - - if not (1 <= method <= 3): - raise ValueError("invalid method") - - # g - Golden year - 1 - # c - Century - # h - (23 - Epact) mod 30 - # i - Number of days from March 21 to Paschal Full Moon - # j - Weekday for PFM (0=Sunday, etc) - # p - Number of days from March 21 to Sunday on or before PFM - # (-6 to 28 methods 1 & 3, to 56 for method 2) - # e - Extra days to add for method 2 (converting Julian - # date to Gregorian date) - - y = year - g = y % 19 - e = 0 - if method < 3: - # Old method - i = (19*g + 15) % 30 - j = (y + y//4 + i) % 7 - if method == 2: - # Extra dates to convert Julian to Gregorian date - e = 10 - if y > 1600: - e = e + y//100 - 16 - (y//100 - 16)//4 - else: - # New method - c = y//100 - h = (c - c//4 - (8*c + 13)//25 + 19*g + 15) % 30 - i = h - (h//28)*(1 - (h//28)*(29//(h + 1))*((21 - g)//11)) - j = (y + y//4 + i + 2 - c + c//4) % 7 - - # p can be from -6 to 56 corresponding to dates 22 March to 23 May - # (later dates apply to method 2, although 23 May never actually occurs) - p = i - j + e - d = 1 + (p + 27 + (p + 6)//40) % 31 - m = 3 + (p + 26)//30 - return datetime.date(int(y), int(m), int(d)) diff --git a/virtualenv/lib/python3.5/site-packages/dateutil/parser.py b/virtualenv/lib/python3.5/site-packages/dateutil/parser.py deleted file mode 100644 index 8c074b3..0000000 --- a/virtualenv/lib/python3.5/site-packages/dateutil/parser.py +++ /dev/null @@ -1,1205 +0,0 @@ -# -*- coding:iso-8859-1 -*- -""" -This module offers a generic date/time string parser which is able to parse -most known formats to represent a date and/or time. - -Additional resources about date/time string formats can be found below: - -- `A summary of the international standard date and time notation - `_ -- `W3C Date and Time Formats `_ -- `Time Formats (Planetary Rings Node) `_ -- `CPAN ParseDate module - `_ -- `Java SimpleDateFormat Class - `_ -""" -from __future__ import unicode_literals - -import datetime -import string -import time -import collections -from io import StringIO - -from six import text_type, binary_type, integer_types - -from . import relativedelta -from . import tz - -__all__ = ["parse", "parserinfo"] - - -class _timelex(object): - - def __init__(self, instream): - if isinstance(instream, text_type): - instream = StringIO(instream) - - self.instream = instream - self.wordchars = ('abcdfeghijklmnopqrstuvwxyz' - 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_' - 'ßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ' - 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ') - self.numchars = '0123456789' - self.whitespace = ' \t\r\n' - self.charstack = [] - self.tokenstack = [] - self.eof = False - - def get_token(self): - """ - This function breaks the time string into lexical units (tokens), which - can be parsed by the parser. Lexical units are demarcated by changes in - the character set, so any continuous string of letters is considered one - unit, any continuous string of numbers is considered one unit. - - The main complication arises from the fact that dots ('.') can be used - both as separators (e.g. "Sep.20.2009") or decimal points (e.g. - "4:30:21.447"). As such, it is necessary to read the full context of - any dot-separated strings before breaking it into tokens; as such, this - function maintains a "token stack", for when the ambiguous context - demands that multiple tokens be parsed at once. - """ - if self.tokenstack: - return self.tokenstack.pop(0) - - seenletters = False - token = None - state = None - wordchars = self.wordchars - numchars = self.numchars - whitespace = self.whitespace - - while not self.eof: - # We only realize that we've reached the end of a token when we find - # a character that's not part of the current token - since that - # character may be part of the next token, it's stored in the - # charstack. - if self.charstack: - nextchar = self.charstack.pop(0) - else: - nextchar = self.instream.read(1) - while nextchar == '\x00': - nextchar = self.instream.read(1) - - if not nextchar: - self.eof = True - break - elif not state: - # First character of the token - determines if we're starting - # to parse a word, a number or something else. - token = nextchar - if nextchar in wordchars: - state = 'a' - elif nextchar in numchars: - state = '0' - elif nextchar in whitespace: - token = ' ' - break # emit token - else: - break # emit token - elif state == 'a': - # If we've already started reading a word, we keep reading - # letters until we find something that's not part of a word. - seenletters = True - if nextchar in wordchars: - token += nextchar - elif nextchar == '.': - token += nextchar - state = 'a.' - else: - self.charstack.append(nextchar) - break # emit token - elif state == '0': - # If we've already started reading a number, we keep reading - # numbers until we find something that doesn't fit. - if nextchar in numchars: - token += nextchar - elif nextchar == '.': - token += nextchar - state = '0.' - else: - self.charstack.append(nextchar) - break # emit token - elif state == 'a.': - # If we've seen some letters and a dot separator, continue - # parsing, and the tokens will be broken up later. - seenletters = True - if nextchar == '.' or nextchar in wordchars: - token += nextchar - elif nextchar in numchars and token[-1] == '.': - token += nextchar - state = '0.' - else: - self.charstack.append(nextchar) - break # emit token - elif state == '0.': - # If we've seen at least one dot separator, keep going, we'll - # break up the tokens later. - if nextchar == '.' or nextchar in numchars: - token += nextchar - elif nextchar in wordchars and token[-1] == '.': - token += nextchar - state = 'a.' - else: - self.charstack.append(nextchar) - break # emit token - - if (state in ('a.', '0.') and (seenletters or token.count('.') > 1 or - token[-1] == '.')): - l = token.split('.') - token = l[0] - for tok in l[1:]: - self.tokenstack.append('.') - if tok: - self.tokenstack.append(tok) - - return token - - def __iter__(self): - return self - - def __next__(self): - token = self.get_token() - if token is None: - raise StopIteration - - return token - - def next(self): - return self.__next__() # Python 2.x support - - def split(cls, s): - return list(cls(s)) - split = classmethod(split) - - -class _resultbase(object): - - def __init__(self): - for attr in self.__slots__: - setattr(self, attr, None) - - def _repr(self, classname): - l = [] - for attr in self.__slots__: - value = getattr(self, attr) - if value is not None: - l.append("%s=%s" % (attr, repr(value))) - return "%s(%s)" % (classname, ", ".join(l)) - - def __repr__(self): - return self._repr(self.__class__.__name__) - - -class parserinfo(object): - """ - Class which handles what inputs are accepted. Subclass this to customize the - language and acceptable values for each parameter. - - :param dayfirst: - Whether to interpret the first value in an ambiguous 3-integer date - (e.g. 01/05/09) as the day (`True`) or month (`False`). If - `yearfirst` is set to `True`, this distinguishes between YDM and - YMD. Default is `False`. - - :param yearfirst: - Whether to interpret the first value in an ambiguous 3-integer date - (e.g. 01/05/09) as the year. If `True`, the first number is taken to - be the year, otherwise the last number is taken to be the year. - Default is `False`. - """ - - # m from a.m/p.m, t from ISO T separator - JUMP = [" ", ".", ",", ";", "-", "/", "'", - "at", "on", "and", "ad", "m", "t", "of", - "st", "nd", "rd", "th"] - - WEEKDAYS = [("Mon", "Monday"), - ("Tue", "Tuesday"), - ("Wed", "Wednesday"), - ("Thu", "Thursday"), - ("Fri", "Friday"), - ("Sat", "Saturday"), - ("Sun", "Sunday")] - MONTHS = [("Jan", "January"), - ("Feb", "February"), - ("Mar", "March"), - ("Apr", "April"), - ("May", "May"), - ("Jun", "June"), - ("Jul", "July"), - ("Aug", "August"), - ("Sep", "Sept", "September"), - ("Oct", "October"), - ("Nov", "November"), - ("Dec", "December")] - HMS = [("h", "hour", "hours"), - ("m", "minute", "minutes"), - ("s", "second", "seconds")] - AMPM = [("am", "a"), - ("pm", "p")] - UTCZONE = ["UTC", "GMT", "Z"] - PERTAIN = ["of"] - TZOFFSET = {} - - def __init__(self, dayfirst=False, yearfirst=False): - self._jump = self._convert(self.JUMP) - self._weekdays = self._convert(self.WEEKDAYS) - self._months = self._convert(self.MONTHS) - self._hms = self._convert(self.HMS) - self._ampm = self._convert(self.AMPM) - self._utczone = self._convert(self.UTCZONE) - self._pertain = self._convert(self.PERTAIN) - - self.dayfirst = dayfirst - self.yearfirst = yearfirst - - self._year = time.localtime().tm_year - self._century = self._year // 100*100 - - def _convert(self, lst): - dct = {} - for i, v in enumerate(lst): - if isinstance(v, tuple): - for v in v: - dct[v.lower()] = i - else: - dct[v.lower()] = i - return dct - - def jump(self, name): - return name.lower() in self._jump - - def weekday(self, name): - if len(name) >= 3: - try: - return self._weekdays[name.lower()] - except KeyError: - pass - return None - - def month(self, name): - if len(name) >= 3: - try: - return self._months[name.lower()]+1 - except KeyError: - pass - return None - - def hms(self, name): - try: - return self._hms[name.lower()] - except KeyError: - return None - - def ampm(self, name): - try: - return self._ampm[name.lower()] - except KeyError: - return None - - def pertain(self, name): - return name.lower() in self._pertain - - def utczone(self, name): - return name.lower() in self._utczone - - def tzoffset(self, name): - if name in self._utczone: - return 0 - - return self.TZOFFSET.get(name) - - def convertyear(self, year): - if year < 100: - year += self._century - if abs(year-self._year) >= 50: - if year < self._year: - year += 100 - else: - year -= 100 - return year - - def validate(self, res): - # move to info - if res.year is not None: - res.year = self.convertyear(res.year) - - if res.tzoffset == 0 and not res.tzname or res.tzname == 'Z': - res.tzname = "UTC" - res.tzoffset = 0 - elif res.tzoffset != 0 and res.tzname and self.utczone(res.tzname): - res.tzoffset = 0 - return True - - -class parser(object): - - def __init__(self, info=None): - self.info = info or parserinfo() - - def parse(self, timestr, default=None, ignoretz=False, tzinfos=None, - **kwargs): - """ - Parse the date/time string into a datetime object. - - :param timestr: - Any date/time string using the supported formats. - - :param default: - The default datetime object, if this is a datetime object and not - `None`, elements specified in `timestr` replace elements in the - default object. - - :param ignoretz: - Whether or not to ignore the time zone. - - :param tzinfos: - A time zone, to be applied to the date, if `ignoretz` is `True`. - This can be either a subclass of `tzinfo`, a time zone string or an - integer offset. - - :param **kwargs: - Keyword arguments as passed to `_parse()`. - - :return: - Returns a `datetime.datetime` object or, if the `fuzzy_with_tokens` - option is `True`, returns a tuple, the first element being a - `datetime.datetime` object, the second a tuple containing the - fuzzy tokens. - - :raises ValueError: - Raised for invalid or unknown string format, if the provided - `tzinfo` is not in a valid format, or if an invalid date would - be created. - - :raises OverFlowError: - Raised if the parsed date exceeds the largest valid C integer on - your system. - """ - - default_specified = default is not None - - if not default_specified: - default = datetime.datetime.now().replace(hour=0, minute=0, - second=0, microsecond=0) - - if kwargs.get('fuzzy_with_tokens', False): - res, skipped_tokens = self._parse(timestr, **kwargs) - else: - res = self._parse(timestr, **kwargs) - - if res is None: - raise ValueError("Unknown string format") - - repl = {} - for attr in ["year", "month", "day", "hour", - "minute", "second", "microsecond"]: - value = getattr(res, attr) - if value is not None: - repl[attr] = value - - ret = default.replace(**repl) - - if res.weekday is not None and not res.day: - ret = ret+relativedelta.relativedelta(weekday=res.weekday) - - if not ignoretz: - if (isinstance(tzinfos, collections.Callable) or - tzinfos and res.tzname in tzinfos): - - if isinstance(tzinfos, collections.Callable): - tzdata = tzinfos(res.tzname, res.tzoffset) - else: - tzdata = tzinfos.get(res.tzname) - - if isinstance(tzdata, datetime.tzinfo): - tzinfo = tzdata - elif isinstance(tzdata, text_type): - tzinfo = tz.tzstr(tzdata) - elif isinstance(tzdata, integer_types): - tzinfo = tz.tzoffset(res.tzname, tzdata) - else: - raise ValueError("Offset must be tzinfo subclass, " - "tz string, or int offset.") - ret = ret.replace(tzinfo=tzinfo) - elif res.tzname and res.tzname in time.tzname: - ret = ret.replace(tzinfo=tz.tzlocal()) - elif res.tzoffset == 0: - ret = ret.replace(tzinfo=tz.tzutc()) - elif res.tzoffset: - ret = ret.replace(tzinfo=tz.tzoffset(res.tzname, res.tzoffset)) - - if kwargs.get('fuzzy_with_tokens', False): - return ret, skipped_tokens - else: - return ret - - class _result(_resultbase): - __slots__ = ["year", "month", "day", "weekday", - "hour", "minute", "second", "microsecond", - "tzname", "tzoffset", "ampm"] - - def _parse(self, timestr, dayfirst=None, yearfirst=None, fuzzy=False, - fuzzy_with_tokens=False): - """ - Private method which performs the heavy lifting of parsing, called from - `parse()`, which passes on its `kwargs` to this function. - - :param timestr: - The string to parse. - - :param dayfirst: - Whether to interpret the first value in an ambiguous 3-integer date - (e.g. 01/05/09) as the day (`True`) or month (`False`). If - `yearfirst` is set to `True`, this distinguishes between YDM and - YMD. If set to `None`, this value is retrieved from the current - `parserinfo` object (which itself defaults to `False`). - - :param yearfirst: - Whether to interpret the first value in an ambiguous 3-integer date - (e.g. 01/05/09) as the year. If `True`, the first number is taken to - be the year, otherwise the last number is taken to be the year. If - this is set to `None`, the value is retrieved from the current - `parserinfo` object (which itself defaults to `False`). - - :param fuzzy: - Whether to allow fuzzy parsing, allowing for string like "Today is - January 1, 2047 at 8:21:00AM". - - :param fuzzy_with_tokens: - If `True`, `fuzzy` is automatically set to True, and the parser will - return a tuple where the first element is the parsed - `datetime.datetime` datetimestamp and the second element is a tuple - containing the portions of the string which were ignored, e.g. - "Today is January 1, 2047 at 8:21:00AM" should return - `(datetime.datetime(2011, 1, 1, 8, 21), (u'Today is ', u' ', u'at '))` - """ - if fuzzy_with_tokens: - fuzzy = True - - info = self.info - - if dayfirst is None: - dayfirst = info.dayfirst - - if yearfirst is None: - yearfirst = info.yearfirst - - res = self._result() - l = _timelex.split(timestr) # Splits the timestr into tokens - - # keep up with the last token skipped so we can recombine - # consecutively skipped tokens (-2 for when i begins at 0). - last_skipped_token_i = -2 - skipped_tokens = list() - - try: - # year/month/day list - ymd = [] - - # Index of the month string in ymd - mstridx = -1 - - len_l = len(l) - i = 0 - while i < len_l: - - # Check if it's a number - try: - value_repr = l[i] - value = float(value_repr) - except ValueError: - value = None - - if value is not None: - # Token is a number - len_li = len(l[i]) - i += 1 - - if (len(ymd) == 3 and len_li in (2, 4) - and res.hour is None and (i >= len_l or (l[i] != ':' and - info.hms(l[i]) is None))): - # 19990101T23[59] - s = l[i-1] - res.hour = int(s[:2]) - - if len_li == 4: - res.minute = int(s[2:]) - - elif len_li == 6 or (len_li > 6 and l[i-1].find('.') == 6): - # YYMMDD or HHMMSS[.ss] - s = l[i-1] - - if not ymd and l[i-1].find('.') == -1: - ymd.append(info.convertyear(int(s[:2]))) - ymd.append(int(s[2:4])) - ymd.append(int(s[4:])) - else: - # 19990101T235959[.59] - res.hour = int(s[:2]) - res.minute = int(s[2:4]) - res.second, res.microsecond = _parsems(s[4:]) - - elif len_li == 8: - # YYYYMMDD - s = l[i-1] - ymd.append(int(s[:4])) - ymd.append(int(s[4:6])) - ymd.append(int(s[6:])) - - elif len_li in (12, 14): - # YYYYMMDDhhmm[ss] - s = l[i-1] - ymd.append(int(s[:4])) - ymd.append(int(s[4:6])) - ymd.append(int(s[6:8])) - res.hour = int(s[8:10]) - res.minute = int(s[10:12]) - - if len_li == 14: - res.second = int(s[12:]) - - elif ((i < len_l and info.hms(l[i]) is not None) or - (i+1 < len_l and l[i] == ' ' and - info.hms(l[i+1]) is not None)): - - # HH[ ]h or MM[ ]m or SS[.ss][ ]s - if l[i] == ' ': - i += 1 - - idx = info.hms(l[i]) - - while True: - if idx == 0: - res.hour = int(value) - - if value % 1: - res.minute = int(60*(value % 1)) - - elif idx == 1: - res.minute = int(value) - - if value % 1: - res.second = int(60*(value % 1)) - - elif idx == 2: - res.second, res.microsecond = \ - _parsems(value_repr) - - i += 1 - - if i >= len_l or idx == 2: - break - - # 12h00 - try: - value_repr = l[i] - value = float(value_repr) - except ValueError: - break - else: - i += 1 - idx += 1 - - if i < len_l: - newidx = info.hms(l[i]) - - if newidx is not None: - idx = newidx - - elif (i == len_l and l[i-2] == ' ' and - info.hms(l[i-3]) is not None): - # X h MM or X m SS - idx = info.hms(l[i-3]) + 1 - - if idx == 1: - res.minute = int(value) - - if value % 1: - res.second = int(60*(value % 1)) - elif idx == 2: - res.second, res.microsecond = \ - _parsems(value_repr) - i += 1 - - elif i+1 < len_l and l[i] == ':': - # HH:MM[:SS[.ss]] - res.hour = int(value) - i += 1 - value = float(l[i]) - res.minute = int(value) - - if value % 1: - res.second = int(60*(value % 1)) - - i += 1 - - if i < len_l and l[i] == ':': - res.second, res.microsecond = _parsems(l[i+1]) - i += 2 - - elif i < len_l and l[i] in ('-', '/', '.'): - sep = l[i] - ymd.append(int(value)) - i += 1 - - if i < len_l and not info.jump(l[i]): - try: - # 01-01[-01] - ymd.append(int(l[i])) - except ValueError: - # 01-Jan[-01] - value = info.month(l[i]) - - if value is not None: - ymd.append(value) - assert mstridx == -1 - mstridx = len(ymd)-1 - else: - return None - - i += 1 - - if i < len_l and l[i] == sep: - # We have three members - i += 1 - value = info.month(l[i]) - - if value is not None: - ymd.append(value) - mstridx = len(ymd)-1 - assert mstridx == -1 - else: - ymd.append(int(l[i])) - - i += 1 - elif i >= len_l or info.jump(l[i]): - if i+1 < len_l and info.ampm(l[i+1]) is not None: - # 12 am - res.hour = int(value) - - if res.hour < 12 and info.ampm(l[i+1]) == 1: - res.hour += 12 - elif res.hour == 12 and info.ampm(l[i+1]) == 0: - res.hour = 0 - - i += 1 - else: - # Year, month or day - ymd.append(int(value)) - i += 1 - elif info.ampm(l[i]) is not None: - - # 12am - res.hour = int(value) - - if res.hour < 12 and info.ampm(l[i]) == 1: - res.hour += 12 - elif res.hour == 12 and info.ampm(l[i]) == 0: - res.hour = 0 - i += 1 - - elif not fuzzy: - return None - else: - i += 1 - continue - - # Check weekday - value = info.weekday(l[i]) - if value is not None: - res.weekday = value - i += 1 - continue - - # Check month name - value = info.month(l[i]) - if value is not None: - ymd.append(value) - assert mstridx == -1 - mstridx = len(ymd)-1 - - i += 1 - if i < len_l: - if l[i] in ('-', '/'): - # Jan-01[-99] - sep = l[i] - i += 1 - ymd.append(int(l[i])) - i += 1 - - if i < len_l and l[i] == sep: - # Jan-01-99 - i += 1 - ymd.append(int(l[i])) - i += 1 - - elif (i+3 < len_l and l[i] == l[i+2] == ' ' - and info.pertain(l[i+1])): - # Jan of 01 - # In this case, 01 is clearly year - try: - value = int(l[i+3]) - except ValueError: - # Wrong guess - pass - else: - # Convert it here to become unambiguous - ymd.append(info.convertyear(value)) - i += 4 - continue - - # Check am/pm - value = info.ampm(l[i]) - if value is not None: - # For fuzzy parsing, 'a' or 'am' (both valid English words) - # may erroneously trigger the AM/PM flag. Deal with that - # here. - val_is_ampm = True - - # If there's already an AM/PM flag, this one isn't one. - if fuzzy and res.ampm is not None: - val_is_ampm = False - - # If AM/PM is found and hour is not, raise a ValueError - if res.hour is None: - if fuzzy: - val_is_ampm = False - else: - raise ValueError('No hour specified with ' + - 'AM or PM flag.') - elif not 0 <= res.hour <= 12: - # If AM/PM is found, it's a 12 hour clock, so raise - # an error for invalid range - if fuzzy: - val_is_ampm = False - else: - raise ValueError('Invalid hour specified for ' + - '12-hour clock.') - - if val_is_ampm: - if value == 1 and res.hour < 12: - res.hour += 12 - elif value == 0 and res.hour == 12: - res.hour = 0 - - res.ampm = value - - i += 1 - continue - - # Check for a timezone name - if (res.hour is not None and len(l[i]) <= 5 and - res.tzname is None and res.tzoffset is None and - not [x for x in l[i] if x not in - string.ascii_uppercase]): - res.tzname = l[i] - res.tzoffset = info.tzoffset(res.tzname) - i += 1 - - # Check for something like GMT+3, or BRST+3. Notice - # that it doesn't mean "I am 3 hours after GMT", but - # "my time +3 is GMT". If found, we reverse the - # logic so that timezone parsing code will get it - # right. - if i < len_l and l[i] in ('+', '-'): - l[i] = ('+', '-')[l[i] == '+'] - res.tzoffset = None - if info.utczone(res.tzname): - # With something like GMT+3, the timezone - # is *not* GMT. - res.tzname = None - - continue - - # Check for a numbered timezone - if res.hour is not None and l[i] in ('+', '-'): - signal = (-1, 1)[l[i] == '+'] - i += 1 - len_li = len(l[i]) - - if len_li == 4: - # -0300 - res.tzoffset = int(l[i][:2])*3600+int(l[i][2:])*60 - elif i+1 < len_l and l[i+1] == ':': - # -03:00 - res.tzoffset = int(l[i])*3600+int(l[i+2])*60 - i += 2 - elif len_li <= 2: - # -[0]3 - res.tzoffset = int(l[i][:2])*3600 - else: - return None - i += 1 - - res.tzoffset *= signal - - # Look for a timezone name between parenthesis - if (i+3 < len_l and - info.jump(l[i]) and l[i+1] == '(' and l[i+3] == ')' and - 3 <= len(l[i+2]) <= 5 and - not [x for x in l[i+2] - if x not in string.ascii_uppercase]): - # -0300 (BRST) - res.tzname = l[i+2] - i += 4 - continue - - # Check jumps - if not (info.jump(l[i]) or fuzzy): - return None - - if last_skipped_token_i == i - 1: - # recombine the tokens - skipped_tokens[-1] += l[i] - else: - # just append - skipped_tokens.append(l[i]) - last_skipped_token_i = i - i += 1 - - # Process year/month/day - len_ymd = len(ymd) - if len_ymd > 3: - # More than three members!? - return None - elif len_ymd == 1 or (mstridx != -1 and len_ymd == 2): - # One member, or two members with a month string - if mstridx != -1: - res.month = ymd[mstridx] - del ymd[mstridx] - - if len_ymd > 1 or mstridx == -1: - if ymd[0] > 31: - res.year = ymd[0] - else: - res.day = ymd[0] - - elif len_ymd == 2: - # Two members with numbers - if ymd[0] > 31: - # 99-01 - res.year, res.month = ymd - elif ymd[1] > 31: - # 01-99 - res.month, res.year = ymd - elif dayfirst and ymd[1] <= 12: - # 13-01 - res.day, res.month = ymd - else: - # 01-13 - res.month, res.day = ymd - - elif len_ymd == 3: - # Three members - if mstridx == 0: - res.month, res.day, res.year = ymd - elif mstridx == 1: - if ymd[0] > 31 or (yearfirst and ymd[2] <= 31): - # 99-Jan-01 - res.year, res.month, res.day = ymd - else: - # 01-Jan-01 - # Give precendence to day-first, since - # two-digit years is usually hand-written. - res.day, res.month, res.year = ymd - - elif mstridx == 2: - # WTF!? - if ymd[1] > 31: - # 01-99-Jan - res.day, res.year, res.month = ymd - else: - # 99-01-Jan - res.year, res.day, res.month = ymd - - else: - if ymd[0] > 31 or \ - (yearfirst and ymd[1] <= 12 and ymd[2] <= 31): - # 99-01-01 - res.year, res.month, res.day = ymd - elif ymd[0] > 12 or (dayfirst and ymd[1] <= 12): - # 13-01-01 - res.day, res.month, res.year = ymd - else: - # 01-13-01 - res.month, res.day, res.year = ymd - - except (IndexError, ValueError, AssertionError): - return None - - if not info.validate(res): - return None - - if fuzzy_with_tokens: - return res, tuple(skipped_tokens) - else: - return res - -DEFAULTPARSER = parser() - - -def parse(timestr, parserinfo=None, **kwargs): - """ - Parse a string in one of the supported formats, using the `parserinfo` - parameters. - - :param timestr: - A string containing a date/time stamp. - - :param parserinfo: - A :class:`parserinfo` object containing parameters for the parser. - If `None`, the default arguments to the `parserinfo` constructor are - used. - - The `**kwargs` parameter takes the following keyword arguments: - - :param default: - The default datetime object, if this is a datetime object and not - `None`, elements specified in `timestr` replace elements in the - default object. - - :param ignoretz: - Whether or not to ignore the time zone (boolean). - - :param tzinfos: - A time zone, to be applied to the date, if `ignoretz` is `True`. - This can be either a subclass of `tzinfo`, a time zone string or an - integer offset. - - :param dayfirst: - Whether to interpret the first value in an ambiguous 3-integer date - (e.g. 01/05/09) as the day (`True`) or month (`False`). If - `yearfirst` is set to `True`, this distinguishes between YDM and - YMD. If set to `None`, this value is retrieved from the current - :class:`parserinfo` object (which itself defaults to `False`). - - :param yearfirst: - Whether to interpret the first value in an ambiguous 3-integer date - (e.g. 01/05/09) as the year. If `True`, the first number is taken to - be the year, otherwise the last number is taken to be the year. If - this is set to `None`, the value is retrieved from the current - :class:`parserinfo` object (which itself defaults to `False`). - - :param fuzzy: - Whether to allow fuzzy parsing, allowing for string like "Today is - January 1, 2047 at 8:21:00AM". - - :param fuzzy_with_tokens: - If `True`, `fuzzy` is automatically set to True, and the parser will - return a tuple where the first element is the parsed - `datetime.datetime` datetimestamp and the second element is a tuple - containing the portions of the string which were ignored, e.g. - "Today is January 1, 2047 at 8:21:00AM" should return - `(datetime.datetime(2011, 1, 1, 8, 21), (u'Today is ', u' ', u'at '))` - """ - # Python 2.x support: datetimes return their string presentation as - # bytes in 2.x and unicode in 3.x, so it's reasonable to expect that - # the parser will get both kinds. Internally we use unicode only. - if isinstance(timestr, binary_type): - timestr = timestr.decode() - - if parserinfo: - return parser(parserinfo).parse(timestr, **kwargs) - else: - return DEFAULTPARSER.parse(timestr, **kwargs) - - -class _tzparser(object): - - class _result(_resultbase): - - __slots__ = ["stdabbr", "stdoffset", "dstabbr", "dstoffset", - "start", "end"] - - class _attr(_resultbase): - __slots__ = ["month", "week", "weekday", - "yday", "jyday", "day", "time"] - - def __repr__(self): - return self._repr("") - - def __init__(self): - _resultbase.__init__(self) - self.start = self._attr() - self.end = self._attr() - - def parse(self, tzstr): - # Python 2.x compatibility: tzstr should be converted to unicode before - # being passed to _timelex. - if isinstance(tzstr, binary_type): - tzstr = tzstr.decode() - - res = self._result() - l = _timelex.split(tzstr) - try: - - len_l = len(l) - - i = 0 - while i < len_l: - # BRST+3[BRDT[+2]] - j = i - while j < len_l and not [x for x in l[j] - if x in "0123456789:,-+"]: - j += 1 - if j != i: - if not res.stdabbr: - offattr = "stdoffset" - res.stdabbr = "".join(l[i:j]) - else: - offattr = "dstoffset" - res.dstabbr = "".join(l[i:j]) - i = j - if (i < len_l and (l[i] in ('+', '-') or l[i][0] in - "0123456789")): - if l[i] in ('+', '-'): - # Yes, that's right. See the TZ variable - # documentation. - signal = (1, -1)[l[i] == '+'] - i += 1 - else: - signal = -1 - len_li = len(l[i]) - if len_li == 4: - # -0300 - setattr(res, offattr, (int(l[i][:2])*3600 + - int(l[i][2:])*60)*signal) - elif i+1 < len_l and l[i+1] == ':': - # -03:00 - setattr(res, offattr, - (int(l[i])*3600+int(l[i+2])*60)*signal) - i += 2 - elif len_li <= 2: - # -[0]3 - setattr(res, offattr, - int(l[i][:2])*3600*signal) - else: - return None - i += 1 - if res.dstabbr: - break - else: - break - - if i < len_l: - for j in range(i, len_l): - if l[j] == ';': - l[j] = ',' - - assert l[i] == ',' - - i += 1 - - if i >= len_l: - pass - elif (8 <= l.count(',') <= 9 and - not [y for x in l[i:] if x != ',' - for y in x if y not in "0123456789"]): - # GMT0BST,3,0,30,3600,10,0,26,7200[,3600] - for x in (res.start, res.end): - x.month = int(l[i]) - i += 2 - if l[i] == '-': - value = int(l[i+1])*-1 - i += 1 - else: - value = int(l[i]) - i += 2 - if value: - x.week = value - x.weekday = (int(l[i])-1) % 7 - else: - x.day = int(l[i]) - i += 2 - x.time = int(l[i]) - i += 2 - if i < len_l: - if l[i] in ('-', '+'): - signal = (-1, 1)[l[i] == "+"] - i += 1 - else: - signal = 1 - res.dstoffset = (res.stdoffset+int(l[i]))*signal - elif (l.count(',') == 2 and l[i:].count('/') <= 2 and - not [y for x in l[i:] if x not in (',', '/', 'J', 'M', - '.', '-', ':') - for y in x if y not in "0123456789"]): - for x in (res.start, res.end): - if l[i] == 'J': - # non-leap year day (1 based) - i += 1 - x.jyday = int(l[i]) - elif l[i] == 'M': - # month[-.]week[-.]weekday - i += 1 - x.month = int(l[i]) - i += 1 - assert l[i] in ('-', '.') - i += 1 - x.week = int(l[i]) - if x.week == 5: - x.week = -1 - i += 1 - assert l[i] in ('-', '.') - i += 1 - x.weekday = (int(l[i])-1) % 7 - else: - # year day (zero based) - x.yday = int(l[i])+1 - - i += 1 - - if i < len_l and l[i] == '/': - i += 1 - # start time - len_li = len(l[i]) - if len_li == 4: - # -0300 - x.time = (int(l[i][:2])*3600+int(l[i][2:])*60) - elif i+1 < len_l and l[i+1] == ':': - # -03:00 - x.time = int(l[i])*3600+int(l[i+2])*60 - i += 2 - if i+1 < len_l and l[i+1] == ':': - i += 2 - x.time += int(l[i]) - elif len_li <= 2: - # -[0]3 - x.time = (int(l[i][:2])*3600) - else: - return None - i += 1 - - assert i == len_l or l[i] == ',' - - i += 1 - - assert i >= len_l - - except (IndexError, ValueError, AssertionError): - return None - - return res - - -DEFAULTTZPARSER = _tzparser() - - -def _parsetz(tzstr): - return DEFAULTTZPARSER.parse(tzstr) - - -def _parsems(value): - """Parse a I[.F] seconds value into (seconds, microseconds).""" - if "." not in value: - return int(value), 0 - else: - i, f = value.split(".") - return int(i), int(f.ljust(6, "0")[:6]) - - -# vim:ts=4:sw=4:et diff --git a/virtualenv/lib/python3.5/site-packages/dateutil/relativedelta.py b/virtualenv/lib/python3.5/site-packages/dateutil/relativedelta.py deleted file mode 100644 index da05572..0000000 --- a/virtualenv/lib/python3.5/site-packages/dateutil/relativedelta.py +++ /dev/null @@ -1,450 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -import calendar - -from six import integer_types - -__all__ = ["relativedelta", "MO", "TU", "WE", "TH", "FR", "SA", "SU"] - - -class weekday(object): - __slots__ = ["weekday", "n"] - - def __init__(self, weekday, n=None): - self.weekday = weekday - self.n = n - - def __call__(self, n): - if n == self.n: - return self - else: - return self.__class__(self.weekday, n) - - def __eq__(self, other): - try: - if self.weekday != other.weekday or self.n != other.n: - return False - except AttributeError: - return False - return True - - def __repr__(self): - s = ("MO", "TU", "WE", "TH", "FR", "SA", "SU")[self.weekday] - if not self.n: - return s - else: - return "%s(%+d)" % (s, self.n) - -MO, TU, WE, TH, FR, SA, SU = weekdays = tuple([weekday(x) for x in range(7)]) - - -class relativedelta(object): - """ -The relativedelta type is based on the specification of the excellent -work done by M.-A. Lemburg in his -`mx.DateTime `_ extension. -However, notice that this type does *NOT* implement the same algorithm as -his work. Do *NOT* expect it to behave like mx.DateTime's counterpart. - -There are two different ways to build a relativedelta instance. The -first one is passing it two date/datetime classes:: - - relativedelta(datetime1, datetime2) - -The second one is passing it any number of the following keyword arguments:: - - relativedelta(arg1=x,arg2=y,arg3=z...) - - year, month, day, hour, minute, second, microsecond: - Absolute information (argument is singular); adding or subtracting a - relativedelta with absolute information does not perform an aritmetic - operation, but rather REPLACES the corresponding value in the - original datetime with the value(s) in relativedelta. - - years, months, weeks, days, hours, minutes, seconds, microseconds: - Relative information, may be negative (argument is plural); adding - or subtracting a relativedelta with relative information performs - the corresponding aritmetic operation on the original datetime value - with the information in the relativedelta. - - weekday: - One of the weekday instances (MO, TU, etc). These instances may - receive a parameter N, specifying the Nth weekday, which could - be positive or negative (like MO(+1) or MO(-2). Not specifying - it is the same as specifying +1. You can also use an integer, - where 0=MO. - - leapdays: - Will add given days to the date found, if year is a leap - year, and the date found is post 28 of february. - - yearday, nlyearday: - Set the yearday or the non-leap year day (jump leap days). - These are converted to day/month/leapdays information. - -Here is the behavior of operations with relativedelta: - -1. Calculate the absolute year, using the 'year' argument, or the - original datetime year, if the argument is not present. - -2. Add the relative 'years' argument to the absolute year. - -3. Do steps 1 and 2 for month/months. - -4. Calculate the absolute day, using the 'day' argument, or the - original datetime day, if the argument is not present. Then, - subtract from the day until it fits in the year and month - found after their operations. - -5. Add the relative 'days' argument to the absolute day. Notice - that the 'weeks' argument is multiplied by 7 and added to - 'days'. - -6. Do steps 1 and 2 for hour/hours, minute/minutes, second/seconds, - microsecond/microseconds. - -7. If the 'weekday' argument is present, calculate the weekday, - with the given (wday, nth) tuple. wday is the index of the - weekday (0-6, 0=Mon), and nth is the number of weeks to add - forward or backward, depending on its signal. Notice that if - the calculated date is already Monday, for example, using - (0, 1) or (0, -1) won't change the day. - """ - - def __init__(self, dt1=None, dt2=None, - years=0, months=0, days=0, leapdays=0, weeks=0, - hours=0, minutes=0, seconds=0, microseconds=0, - year=None, month=None, day=None, weekday=None, - yearday=None, nlyearday=None, - hour=None, minute=None, second=None, microsecond=None): - if dt1 and dt2: - # datetime is a subclass of date. So both must be date - if not (isinstance(dt1, datetime.date) and - isinstance(dt2, datetime.date)): - raise TypeError("relativedelta only diffs datetime/date") - # We allow two dates, or two datetimes, so we coerce them to be - # of the same type - if (isinstance(dt1, datetime.datetime) != - isinstance(dt2, datetime.datetime)): - if not isinstance(dt1, datetime.datetime): - dt1 = datetime.datetime.fromordinal(dt1.toordinal()) - elif not isinstance(dt2, datetime.datetime): - dt2 = datetime.datetime.fromordinal(dt2.toordinal()) - self.years = 0 - self.months = 0 - self.days = 0 - self.leapdays = 0 - self.hours = 0 - self.minutes = 0 - self.seconds = 0 - self.microseconds = 0 - self.year = None - self.month = None - self.day = None - self.weekday = None - self.hour = None - self.minute = None - self.second = None - self.microsecond = None - self._has_time = 0 - - months = (dt1.year*12+dt1.month)-(dt2.year*12+dt2.month) - self._set_months(months) - dtm = self.__radd__(dt2) - if dt1 < dt2: - while dt1 > dtm: - months += 1 - self._set_months(months) - dtm = self.__radd__(dt2) - else: - while dt1 < dtm: - months -= 1 - self._set_months(months) - dtm = self.__radd__(dt2) - delta = dt1 - dtm - self.seconds = delta.seconds+delta.days*86400 - self.microseconds = delta.microseconds - else: - self.years = years - self.months = months - self.days = days+weeks*7 - self.leapdays = leapdays - self.hours = hours - self.minutes = minutes - self.seconds = seconds - self.microseconds = microseconds - self.year = year - self.month = month - self.day = day - self.hour = hour - self.minute = minute - self.second = second - self.microsecond = microsecond - - if isinstance(weekday, integer_types): - self.weekday = weekdays[weekday] - else: - self.weekday = weekday - - yday = 0 - if nlyearday: - yday = nlyearday - elif yearday: - yday = yearday - if yearday > 59: - self.leapdays = -1 - if yday: - ydayidx = [31, 59, 90, 120, 151, 181, 212, - 243, 273, 304, 334, 366] - for idx, ydays in enumerate(ydayidx): - if yday <= ydays: - self.month = idx+1 - if idx == 0: - self.day = yday - else: - self.day = yday-ydayidx[idx-1] - break - else: - raise ValueError("invalid year day (%d)" % yday) - - self._fix() - - def _fix(self): - if abs(self.microseconds) > 999999: - s = self.microseconds//abs(self.microseconds) - div, mod = divmod(self.microseconds*s, 1000000) - self.microseconds = mod*s - self.seconds += div*s - if abs(self.seconds) > 59: - s = self.seconds//abs(self.seconds) - div, mod = divmod(self.seconds*s, 60) - self.seconds = mod*s - self.minutes += div*s - if abs(self.minutes) > 59: - s = self.minutes//abs(self.minutes) - div, mod = divmod(self.minutes*s, 60) - self.minutes = mod*s - self.hours += div*s - if abs(self.hours) > 23: - s = self.hours//abs(self.hours) - div, mod = divmod(self.hours*s, 24) - self.hours = mod*s - self.days += div*s - if abs(self.months) > 11: - s = self.months//abs(self.months) - div, mod = divmod(self.months*s, 12) - self.months = mod*s - self.years += div*s - if (self.hours or self.minutes or self.seconds or self.microseconds - or self.hour is not None or self.minute is not None or - self.second is not None or self.microsecond is not None): - self._has_time = 1 - else: - self._has_time = 0 - - def _set_months(self, months): - self.months = months - if abs(self.months) > 11: - s = self.months//abs(self.months) - div, mod = divmod(self.months*s, 12) - self.months = mod*s - self.years = div*s - else: - self.years = 0 - - def __add__(self, other): - if isinstance(other, relativedelta): - return relativedelta(years=other.years+self.years, - months=other.months+self.months, - days=other.days+self.days, - hours=other.hours+self.hours, - minutes=other.minutes+self.minutes, - seconds=other.seconds+self.seconds, - microseconds=(other.microseconds + - self.microseconds), - leapdays=other.leapdays or self.leapdays, - year=other.year or self.year, - month=other.month or self.month, - day=other.day or self.day, - weekday=other.weekday or self.weekday, - hour=other.hour or self.hour, - minute=other.minute or self.minute, - second=other.second or self.second, - microsecond=(other.microsecond or - self.microsecond)) - if not isinstance(other, datetime.date): - raise TypeError("unsupported type for add operation") - elif self._has_time and not isinstance(other, datetime.datetime): - other = datetime.datetime.fromordinal(other.toordinal()) - year = (self.year or other.year)+self.years - month = self.month or other.month - if self.months: - assert 1 <= abs(self.months) <= 12 - month += self.months - if month > 12: - year += 1 - month -= 12 - elif month < 1: - year -= 1 - month += 12 - day = min(calendar.monthrange(year, month)[1], - self.day or other.day) - repl = {"year": year, "month": month, "day": day} - for attr in ["hour", "minute", "second", "microsecond"]: - value = getattr(self, attr) - if value is not None: - repl[attr] = value - days = self.days - if self.leapdays and month > 2 and calendar.isleap(year): - days += self.leapdays - ret = (other.replace(**repl) - + datetime.timedelta(days=days, - hours=self.hours, - minutes=self.minutes, - seconds=self.seconds, - microseconds=self.microseconds)) - if self.weekday: - weekday, nth = self.weekday.weekday, self.weekday.n or 1 - jumpdays = (abs(nth)-1)*7 - if nth > 0: - jumpdays += (7-ret.weekday()+weekday) % 7 - else: - jumpdays += (ret.weekday()-weekday) % 7 - jumpdays *= -1 - ret += datetime.timedelta(days=jumpdays) - return ret - - def __radd__(self, other): - return self.__add__(other) - - def __rsub__(self, other): - return self.__neg__().__radd__(other) - - def __sub__(self, other): - if not isinstance(other, relativedelta): - raise TypeError("unsupported type for sub operation") - return relativedelta(years=self.years-other.years, - months=self.months-other.months, - days=self.days-other.days, - hours=self.hours-other.hours, - minutes=self.minutes-other.minutes, - seconds=self.seconds-other.seconds, - microseconds=self.microseconds-other.microseconds, - leapdays=self.leapdays or other.leapdays, - year=self.year or other.year, - month=self.month or other.month, - day=self.day or other.day, - weekday=self.weekday or other.weekday, - hour=self.hour or other.hour, - minute=self.minute or other.minute, - second=self.second or other.second, - microsecond=self.microsecond or other.microsecond) - - def __neg__(self): - return relativedelta(years=-self.years, - months=-self.months, - days=-self.days, - hours=-self.hours, - minutes=-self.minutes, - seconds=-self.seconds, - microseconds=-self.microseconds, - leapdays=self.leapdays, - year=self.year, - month=self.month, - day=self.day, - weekday=self.weekday, - hour=self.hour, - minute=self.minute, - second=self.second, - microsecond=self.microsecond) - - def __bool__(self): - return not (not self.years and - not self.months and - not self.days and - not self.hours and - not self.minutes and - not self.seconds and - not self.microseconds and - not self.leapdays and - self.year is None and - self.month is None and - self.day is None and - self.weekday is None and - self.hour is None and - self.minute is None and - self.second is None and - self.microsecond is None) - # Compatibility with Python 2.x - __nonzero__ = __bool__ - - def __mul__(self, other): - f = float(other) - return relativedelta(years=int(self.years*f), - months=int(self.months*f), - days=int(self.days*f), - hours=int(self.hours*f), - minutes=int(self.minutes*f), - seconds=int(self.seconds*f), - microseconds=int(self.microseconds*f), - leapdays=self.leapdays, - year=self.year, - month=self.month, - day=self.day, - weekday=self.weekday, - hour=self.hour, - minute=self.minute, - second=self.second, - microsecond=self.microsecond) - - __rmul__ = __mul__ - - def __eq__(self, other): - if not isinstance(other, relativedelta): - return False - if self.weekday or other.weekday: - if not self.weekday or not other.weekday: - return False - if self.weekday.weekday != other.weekday.weekday: - return False - n1, n2 = self.weekday.n, other.weekday.n - if n1 != n2 and not ((not n1 or n1 == 1) and (not n2 or n2 == 1)): - return False - return (self.years == other.years and - self.months == other.months and - self.days == other.days and - self.hours == other.hours and - self.minutes == other.minutes and - self.seconds == other.seconds and - self.leapdays == other.leapdays and - self.year == other.year and - self.month == other.month and - self.day == other.day and - self.hour == other.hour and - self.minute == other.minute and - self.second == other.second and - self.microsecond == other.microsecond) - - def __ne__(self, other): - return not self.__eq__(other) - - def __div__(self, other): - return self.__mul__(1/float(other)) - - __truediv__ = __div__ - - def __repr__(self): - l = [] - for attr in ["years", "months", "days", "leapdays", - "hours", "minutes", "seconds", "microseconds"]: - value = getattr(self, attr) - if value: - l.append("%s=%+d" % (attr, value)) - for attr in ["year", "month", "day", "weekday", - "hour", "minute", "second", "microsecond"]: - value = getattr(self, attr) - if value is not None: - l.append("%s=%s" % (attr, repr(value))) - return "%s(%s)" % (self.__class__.__name__, ", ".join(l)) - -# vim:ts=4:sw=4:et diff --git a/virtualenv/lib/python3.5/site-packages/dateutil/rrule.py b/virtualenv/lib/python3.5/site-packages/dateutil/rrule.py deleted file mode 100644 index 141780b..0000000 --- a/virtualenv/lib/python3.5/site-packages/dateutil/rrule.py +++ /dev/null @@ -1,1375 +0,0 @@ -# -*- coding: utf-8 -*- -""" -The rrule module offers a small, complete, and very fast, implementation of -the recurrence rules documented in the -`iCalendar RFC `_, -including support for caching of results. -""" -import itertools -import datetime -import calendar -import sys - -from fractions import gcd - -from six import advance_iterator, integer_types -from six.moves import _thread - -__all__ = ["rrule", "rruleset", "rrulestr", - "YEARLY", "MONTHLY", "WEEKLY", "DAILY", - "HOURLY", "MINUTELY", "SECONDLY", - "MO", "TU", "WE", "TH", "FR", "SA", "SU"] - -# Every mask is 7 days longer to handle cross-year weekly periods. -M366MASK = tuple([1]*31+[2]*29+[3]*31+[4]*30+[5]*31+[6]*30 + - [7]*31+[8]*31+[9]*30+[10]*31+[11]*30+[12]*31+[1]*7) -M365MASK = list(M366MASK) -M29, M30, M31 = list(range(1, 30)), list(range(1, 31)), list(range(1, 32)) -MDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7]) -MDAY365MASK = list(MDAY366MASK) -M29, M30, M31 = list(range(-29, 0)), list(range(-30, 0)), list(range(-31, 0)) -NMDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7]) -NMDAY365MASK = list(NMDAY366MASK) -M366RANGE = (0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366) -M365RANGE = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365) -WDAYMASK = [0, 1, 2, 3, 4, 5, 6]*55 -del M29, M30, M31, M365MASK[59], MDAY365MASK[59], NMDAY365MASK[31] -MDAY365MASK = tuple(MDAY365MASK) -M365MASK = tuple(M365MASK) - -(YEARLY, - MONTHLY, - WEEKLY, - DAILY, - HOURLY, - MINUTELY, - SECONDLY) = list(range(7)) - -# Imported on demand. -easter = None -parser = None - - -class weekday(object): - __slots__ = ["weekday", "n"] - - def __init__(self, weekday, n=None): - if n == 0: - raise ValueError("Can't create weekday with n == 0") - self.weekday = weekday - self.n = n - - def __call__(self, n): - if n == self.n: - return self - else: - return self.__class__(self.weekday, n) - - def __eq__(self, other): - try: - if self.weekday != other.weekday or self.n != other.n: - return False - except AttributeError: - return False - return True - - def __repr__(self): - s = ("MO", "TU", "WE", "TH", "FR", "SA", "SU")[self.weekday] - if not self.n: - return s - else: - return "%s(%+d)" % (s, self.n) - -MO, TU, WE, TH, FR, SA, SU = weekdays = tuple([weekday(x) for x in range(7)]) - - -class rrulebase(object): - def __init__(self, cache=False): - if cache: - self._cache = [] - self._cache_lock = _thread.allocate_lock() - self._cache_gen = self._iter() - self._cache_complete = False - else: - self._cache = None - self._cache_complete = False - self._len = None - - def __iter__(self): - if self._cache_complete: - return iter(self._cache) - elif self._cache is None: - return self._iter() - else: - return self._iter_cached() - - def _iter_cached(self): - i = 0 - gen = self._cache_gen - cache = self._cache - acquire = self._cache_lock.acquire - release = self._cache_lock.release - while gen: - if i == len(cache): - acquire() - if self._cache_complete: - break - try: - for j in range(10): - cache.append(advance_iterator(gen)) - except StopIteration: - self._cache_gen = gen = None - self._cache_complete = True - break - release() - yield cache[i] - i += 1 - while i < self._len: - yield cache[i] - i += 1 - - def __getitem__(self, item): - if self._cache_complete: - return self._cache[item] - elif isinstance(item, slice): - if item.step and item.step < 0: - return list(iter(self))[item] - else: - return list(itertools.islice(self, - item.start or 0, - item.stop or sys.maxsize, - item.step or 1)) - elif item >= 0: - gen = iter(self) - try: - for i in range(item+1): - res = advance_iterator(gen) - except StopIteration: - raise IndexError - return res - else: - return list(iter(self))[item] - - def __contains__(self, item): - if self._cache_complete: - return item in self._cache - else: - for i in self: - if i == item: - return True - elif i > item: - return False - return False - - # __len__() introduces a large performance penality. - def count(self): - """ Returns the number of recurrences in this set. It will have go - trough the whole recurrence, if this hasn't been done before. """ - if self._len is None: - for x in self: - pass - return self._len - - def before(self, dt, inc=False): - """ Returns the last recurrence before the given datetime instance. The - inc keyword defines what happens if dt is an occurrence. With - inc=True, if dt itself is an occurrence, it will be returned. """ - if self._cache_complete: - gen = self._cache - else: - gen = self - last = None - if inc: - for i in gen: - if i > dt: - break - last = i - else: - for i in gen: - if i >= dt: - break - last = i - return last - - def after(self, dt, inc=False): - """ Returns the first recurrence after the given datetime instance. The - inc keyword defines what happens if dt is an occurrence. With - inc=True, if dt itself is an occurrence, it will be returned. """ - if self._cache_complete: - gen = self._cache - else: - gen = self - if inc: - for i in gen: - if i >= dt: - return i - else: - for i in gen: - if i > dt: - return i - return None - - def between(self, after, before, inc=False): - """ Returns all the occurrences of the rrule between after and before. - The inc keyword defines what happens if after and/or before are - themselves occurrences. With inc=True, they will be included in the - list, if they are found in the recurrence set. """ - if self._cache_complete: - gen = self._cache - else: - gen = self - started = False - l = [] - if inc: - for i in gen: - if i > before: - break - elif not started: - if i >= after: - started = True - l.append(i) - else: - l.append(i) - else: - for i in gen: - if i >= before: - break - elif not started: - if i > after: - started = True - l.append(i) - else: - l.append(i) - return l - - -class rrule(rrulebase): - """ - That's the base of the rrule operation. It accepts all the keywords - defined in the RFC as its constructor parameters (except byday, - which was renamed to byweekday) and more. The constructor prototype is:: - - rrule(freq) - - Where freq must be one of YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY, - or SECONDLY. - - Additionally, it supports the following keyword arguments: - - :param cache: - If given, it must be a boolean value specifying to enable or disable - caching of results. If you will use the same rrule instance multiple - times, enabling caching will improve the performance considerably. - :param dtstart: - The recurrence start. Besides being the base for the recurrence, - missing parameters in the final recurrence instances will also be - extracted from this date. If not given, datetime.now() will be used - instead. - :param interval: - The interval between each freq iteration. For example, when using - YEARLY, an interval of 2 means once every two years, but with HOURLY, - it means once every two hours. The default interval is 1. - :param wkst: - The week start day. Must be one of the MO, TU, WE constants, or an - integer, specifying the first day of the week. This will affect - recurrences based on weekly periods. The default week start is got - from calendar.firstweekday(), and may be modified by - calendar.setfirstweekday(). - :param count: - How many occurrences will be generated. - :param until: - If given, this must be a datetime instance, that will specify the - limit of the recurrence. If a recurrence instance happens to be the - same as the datetime instance given in the until keyword, this will - be the last occurrence. - :param bysetpos: - If given, it must be either an integer, or a sequence of integers, - positive or negative. Each given integer will specify an occurrence - number, corresponding to the nth occurrence of the rule inside the - frequency period. For example, a bysetpos of -1 if combined with a - MONTHLY frequency, and a byweekday of (MO, TU, WE, TH, FR), will - result in the last work day of every month. - :param bymonth: - If given, it must be either an integer, or a sequence of integers, - meaning the months to apply the recurrence to. - :param bymonthday: - If given, it must be either an integer, or a sequence of integers, - meaning the month days to apply the recurrence to. - :param byyearday: - If given, it must be either an integer, or a sequence of integers, - meaning the year days to apply the recurrence to. - :param byweekno: - If given, it must be either an integer, or a sequence of integers, - meaning the week numbers to apply the recurrence to. Week numbers - have the meaning described in ISO8601, that is, the first week of - the year is that containing at least four days of the new year. - :param byweekday: - If given, it must be either an integer (0 == MO), a sequence of - integers, one of the weekday constants (MO, TU, etc), or a sequence - of these constants. When given, these variables will define the - weekdays where the recurrence will be applied. It's also possible to - use an argument n for the weekday instances, which will mean the nth - occurrence of this weekday in the period. For example, with MONTHLY, - or with YEARLY and BYMONTH, using FR(+1) in byweekday will specify the - first friday of the month where the recurrence happens. Notice that in - the RFC documentation, this is specified as BYDAY, but was renamed to - avoid the ambiguity of that keyword. - :param byhour: - If given, it must be either an integer, or a sequence of integers, - meaning the hours to apply the recurrence to. - :param byminute: - If given, it must be either an integer, or a sequence of integers, - meaning the minutes to apply the recurrence to. - :param bysecond: - If given, it must be either an integer, or a sequence of integers, - meaning the seconds to apply the recurrence to. - :param byeaster: - If given, it must be either an integer, or a sequence of integers, - positive or negative. Each integer will define an offset from the - Easter Sunday. Passing the offset 0 to byeaster will yield the Easter - Sunday itself. This is an extension to the RFC specification. - """ - def __init__(self, freq, dtstart=None, - interval=1, wkst=None, count=None, until=None, bysetpos=None, - bymonth=None, bymonthday=None, byyearday=None, byeaster=None, - byweekno=None, byweekday=None, - byhour=None, byminute=None, bysecond=None, - cache=False): - super(rrule, self).__init__(cache) - global easter - if not dtstart: - dtstart = datetime.datetime.now().replace(microsecond=0) - elif not isinstance(dtstart, datetime.datetime): - dtstart = datetime.datetime.fromordinal(dtstart.toordinal()) - else: - dtstart = dtstart.replace(microsecond=0) - self._dtstart = dtstart - self._tzinfo = dtstart.tzinfo - self._freq = freq - self._interval = interval - self._count = count - - if until and not isinstance(until, datetime.datetime): - until = datetime.datetime.fromordinal(until.toordinal()) - self._until = until - - if wkst is None: - self._wkst = calendar.firstweekday() - elif isinstance(wkst, integer_types): - self._wkst = wkst - else: - self._wkst = wkst.weekday - - if bysetpos is None: - self._bysetpos = None - elif isinstance(bysetpos, integer_types): - if bysetpos == 0 or not (-366 <= bysetpos <= 366): - raise ValueError("bysetpos must be between 1 and 366, " - "or between -366 and -1") - self._bysetpos = (bysetpos,) - else: - self._bysetpos = tuple(bysetpos) - for pos in self._bysetpos: - if pos == 0 or not (-366 <= pos <= 366): - raise ValueError("bysetpos must be between 1 and 366, " - "or between -366 and -1") - - if (byweekno is None and byyearday is None and bymonthday is None and - byweekday is None and byeaster is None): - if freq == YEARLY: - if bymonth is None: - bymonth = dtstart.month - bymonthday = dtstart.day - elif freq == MONTHLY: - bymonthday = dtstart.day - elif freq == WEEKLY: - byweekday = dtstart.weekday() - - # bymonth - if bymonth is None: - self._bymonth = None - else: - if isinstance(bymonth, integer_types): - bymonth = (bymonth,) - - self._bymonth = tuple(sorted(set(bymonth))) - - # byyearday - if byyearday is None: - self._byyearday = None - else: - if isinstance(byyearday, integer_types): - byyearday = (byyearday,) - - self._byyearday = tuple(sorted(set(byyearday))) - - # byeaster - if byeaster is not None: - if not easter: - from dateutil import easter - if isinstance(byeaster, integer_types): - self._byeaster = (byeaster,) - else: - self._byeaster = tuple(sorted(byeaster)) - else: - self._byeaster = None - - # bymonthay - if bymonthday is None: - self._bymonthday = () - self._bynmonthday = () - else: - if isinstance(bymonthday, integer_types): - bymonthday = (bymonthday,) - - self._bymonthday = tuple(sorted(set([x for x in bymonthday if x > 0]))) - self._bynmonthday = tuple(sorted(set([x for x in bymonthday if x < 0]))) - - # byweekno - if byweekno is None: - self._byweekno = None - else: - if isinstance(byweekno, integer_types): - byweekno = (byweekno,) - - self._byweekno = tuple(sorted(set(byweekno))) - - # byweekday / bynweekday - if byweekday is None: - self._byweekday = None - self._bynweekday = None - else: - # If it's one of the valid non-sequence types, convert to a - # single-element sequence before the iterator that builds the - # byweekday set. - if isinstance(byweekday, integer_types) or hasattr(byweekday, "n"): - byweekday = (byweekday,) - - self._byweekday = set() - self._bynweekday = set() - for wday in byweekday: - if isinstance(wday, integer_types): - self._byweekday.add(wday) - elif not wday.n or freq > MONTHLY: - self._byweekday.add(wday.weekday) - else: - self._bynweekday.add((wday.weekday, wday.n)) - - if not self._byweekday: - self._byweekday = None - elif not self._bynweekday: - self._bynweekday = None - - if self._byweekday is not None: - self._byweekday = tuple(sorted(self._byweekday)) - - if self._bynweekday is not None: - self._bynweekday = tuple(sorted(self._bynweekday)) - - # byhour - if byhour is None: - if freq < HOURLY: - self._byhour = set((dtstart.hour,)) - else: - self._byhour = None - else: - if isinstance(byhour, integer_types): - byhour = (byhour,) - - if freq == HOURLY: - self._byhour = self.__construct_byset(start=dtstart.hour, - byxxx=byhour, - base=24) - else: - self._byhour = set(byhour) - - self._byhour = tuple(sorted(self._byhour)) - - # byminute - if byminute is None: - if freq < MINUTELY: - self._byminute = set((dtstart.minute,)) - else: - self._byminute = None - else: - if isinstance(byminute, integer_types): - byminute = (byminute,) - - if freq == MINUTELY: - self._byminute = self.__construct_byset(start=dtstart.minute, - byxxx=byminute, - base=60) - else: - self._byminute = set(byminute) - - self._byminute = tuple(sorted(self._byminute)) - - # bysecond - if bysecond is None: - if freq < SECONDLY: - self._bysecond = ((dtstart.second,)) - else: - self._bysecond = None - else: - if isinstance(bysecond, integer_types): - bysecond = (bysecond,) - - self._bysecond = set(bysecond) - - if freq == SECONDLY: - self._bysecond = self.__construct_byset(start=dtstart.second, - byxxx=bysecond, - base=60) - else: - self._bysecond = set(bysecond) - - self._bysecond = tuple(sorted(self._bysecond)) - - if self._freq >= HOURLY: - self._timeset = None - else: - self._timeset = [] - for hour in self._byhour: - for minute in self._byminute: - for second in self._bysecond: - self._timeset.append( - datetime.time(hour, minute, second, - tzinfo=self._tzinfo)) - self._timeset.sort() - self._timeset = tuple(self._timeset) - - def _iter(self): - year, month, day, hour, minute, second, weekday, yearday, _ = \ - self._dtstart.timetuple() - - # Some local variables to speed things up a bit - freq = self._freq - interval = self._interval - wkst = self._wkst - until = self._until - bymonth = self._bymonth - byweekno = self._byweekno - byyearday = self._byyearday - byweekday = self._byweekday - byeaster = self._byeaster - bymonthday = self._bymonthday - bynmonthday = self._bynmonthday - bysetpos = self._bysetpos - byhour = self._byhour - byminute = self._byminute - bysecond = self._bysecond - - ii = _iterinfo(self) - ii.rebuild(year, month) - - getdayset = {YEARLY: ii.ydayset, - MONTHLY: ii.mdayset, - WEEKLY: ii.wdayset, - DAILY: ii.ddayset, - HOURLY: ii.ddayset, - MINUTELY: ii.ddayset, - SECONDLY: ii.ddayset}[freq] - - if freq < HOURLY: - timeset = self._timeset - else: - gettimeset = {HOURLY: ii.htimeset, - MINUTELY: ii.mtimeset, - SECONDLY: ii.stimeset}[freq] - if ((freq >= HOURLY and - self._byhour and hour not in self._byhour) or - (freq >= MINUTELY and - self._byminute and minute not in self._byminute) or - (freq >= SECONDLY and - self._bysecond and second not in self._bysecond)): - timeset = () - else: - timeset = gettimeset(hour, minute, second) - - total = 0 - count = self._count - while True: - # Get dayset with the right frequency - dayset, start, end = getdayset(year, month, day) - - # Do the "hard" work ;-) - filtered = False - for i in dayset[start:end]: - if ((bymonth and ii.mmask[i] not in bymonth) or - (byweekno and not ii.wnomask[i]) or - (byweekday and ii.wdaymask[i] not in byweekday) or - (ii.nwdaymask and not ii.nwdaymask[i]) or - (byeaster and not ii.eastermask[i]) or - ((bymonthday or bynmonthday) and - ii.mdaymask[i] not in bymonthday and - ii.nmdaymask[i] not in bynmonthday) or - (byyearday and - ((i < ii.yearlen and i+1 not in byyearday and - -ii.yearlen+i not in byyearday) or - (i >= ii.yearlen and i+1-ii.yearlen not in byyearday and - -ii.nextyearlen+i-ii.yearlen not in byyearday)))): - dayset[i] = None - filtered = True - - # Output results - if bysetpos and timeset: - poslist = [] - for pos in bysetpos: - if pos < 0: - daypos, timepos = divmod(pos, len(timeset)) - else: - daypos, timepos = divmod(pos-1, len(timeset)) - try: - i = [x for x in dayset[start:end] - if x is not None][daypos] - time = timeset[timepos] - except IndexError: - pass - else: - date = datetime.date.fromordinal(ii.yearordinal+i) - res = datetime.datetime.combine(date, time) - if res not in poslist: - poslist.append(res) - poslist.sort() - for res in poslist: - if until and res > until: - self._len = total - return - elif res >= self._dtstart: - total += 1 - yield res - if count: - count -= 1 - if not count: - self._len = total - return - else: - for i in dayset[start:end]: - if i is not None: - date = datetime.date.fromordinal(ii.yearordinal+i) - for time in timeset: - res = datetime.datetime.combine(date, time) - if until and res > until: - self._len = total - return - elif res >= self._dtstart: - total += 1 - yield res - if count: - count -= 1 - if not count: - self._len = total - return - - # Handle frequency and interval - fixday = False - if freq == YEARLY: - year += interval - if year > datetime.MAXYEAR: - self._len = total - return - ii.rebuild(year, month) - elif freq == MONTHLY: - month += interval - if month > 12: - div, mod = divmod(month, 12) - month = mod - year += div - if month == 0: - month = 12 - year -= 1 - if year > datetime.MAXYEAR: - self._len = total - return - ii.rebuild(year, month) - elif freq == WEEKLY: - if wkst > weekday: - day += -(weekday+1+(6-wkst))+self._interval*7 - else: - day += -(weekday-wkst)+self._interval*7 - weekday = wkst - fixday = True - elif freq == DAILY: - day += interval - fixday = True - elif freq == HOURLY: - if filtered: - # Jump to one iteration before next day - hour += ((23-hour)//interval)*interval - - if byhour: - ndays, hour = self.__mod_distance(value=hour, - byxxx=self._byhour, - base=24) - else: - ndays, hour = divmod(hour+interval, 24) - - if ndays: - day += ndays - fixday = True - - timeset = gettimeset(hour, minute, second) - elif freq == MINUTELY: - if filtered: - # Jump to one iteration before next day - minute += ((1439-(hour*60+minute))//interval)*interval - - valid = False - rep_rate = (24*60) - for j in range(rep_rate // gcd(interval, rep_rate)): - if byminute: - nhours, minute = \ - self.__mod_distance(value=minute, - byxxx=self._byminute, - base=60) - else: - nhours, minute = divmod(minute+interval, 60) - - div, hour = divmod(hour+nhours, 24) - if div: - day += div - fixday = True - filtered = False - - if not byhour or hour in byhour: - valid = True - break - - if not valid: - raise ValueError('Invalid combination of interval and ' + - 'byhour resulting in empty rule.') - - timeset = gettimeset(hour, minute, second) - elif freq == SECONDLY: - if filtered: - # Jump to one iteration before next day - second += (((86399-(hour*3600+minute*60+second)) - // interval)*interval) - - rep_rate = (24*3600) - valid = False - for j in range(0, rep_rate // gcd(interval, rep_rate)): - if bysecond: - nminutes, second = \ - self.__mod_distance(value=second, - byxxx=self._bysecond, - base=60) - else: - nminutes, second = divmod(second+interval, 60) - - div, minute = divmod(minute+nminutes, 60) - if div: - hour += div - div, hour = divmod(hour, 24) - if div: - day += div - fixday = True - - if ((not byhour or hour in byhour) and - (not byminute or minute in byminute) and - (not bysecond or second in bysecond)): - valid = True - break - - if not valid: - raise ValueError('Invalid combination of interval, ' + - 'byhour and byminute resulting in empty' + - ' rule.') - - timeset = gettimeset(hour, minute, second) - - if fixday and day > 28: - daysinmonth = calendar.monthrange(year, month)[1] - if day > daysinmonth: - while day > daysinmonth: - day -= daysinmonth - month += 1 - if month == 13: - month = 1 - year += 1 - if year > datetime.MAXYEAR: - self._len = total - return - daysinmonth = calendar.monthrange(year, month)[1] - ii.rebuild(year, month) - - def __construct_byset(self, start, byxxx, base): - """ - If a `BYXXX` sequence is passed to the constructor at the same level as - `FREQ` (e.g. `FREQ=HOURLY,BYHOUR={2,4,7},INTERVAL=3`), there are some - specifications which cannot be reached given some starting conditions. - - This occurs whenever the interval is not coprime with the base of a - given unit and the difference between the starting position and the - ending position is not coprime with the greatest common denominator - between the interval and the base. For example, with a FREQ of hourly - starting at 17:00 and an interval of 4, the only valid values for - BYHOUR would be {21, 1, 5, 9, 13, 17}, because 4 and 24 are not - coprime. - - :param start: - Specifies the starting position. - :param byxxx: - An iterable containing the list of allowed values. - :param base: - The largest allowable value for the specified frequency (e.g. - 24 hours, 60 minutes). - - This does not preserve the type of the iterable, returning a set, since - the values should be unique and the order is irrelevant, this will - speed up later lookups. - - In the event of an empty set, raises a :exception:`ValueError`, as this - results in an empty rrule. - """ - - cset = set() - - # Support a single byxxx value. - if isinstance(byxxx, integer_types): - byxxx = (byxxx, ) - - for num in byxxx: - i_gcd = gcd(self._interval, base) - # Use divmod rather than % because we need to wrap negative nums. - if i_gcd == 1 or divmod(num - start, i_gcd)[1] == 0: - cset.add(num) - - if len(cset) == 0: - raise ValueError("Invalid rrule byxxx generates an empty set.") - - return cset - - def __mod_distance(self, value, byxxx, base): - """ - Calculates the next value in a sequence where the `FREQ` parameter is - specified along with a `BYXXX` parameter at the same "level" - (e.g. `HOURLY` specified with `BYHOUR`). - - :param value: - The old value of the component. - :param byxxx: - The `BYXXX` set, which should have been generated by - `rrule._construct_byset`, or something else which checks that a - valid rule is present. - :param base: - The largest allowable value for the specified frequency (e.g. - 24 hours, 60 minutes). - - If a valid value is not found after `base` iterations (the maximum - number before the sequence would start to repeat), this raises a - :exception:`ValueError`, as no valid values were found. - - This returns a tuple of `divmod(n*interval, base)`, where `n` is the - smallest number of `interval` repetitions until the next specified - value in `byxxx` is found. - """ - accumulator = 0 - for ii in range(1, base + 1): - # Using divmod() over % to account for negative intervals - div, value = divmod(value + self._interval, base) - accumulator += div - if value in byxxx: - return (accumulator, value) - - -class _iterinfo(object): - __slots__ = ["rrule", "lastyear", "lastmonth", - "yearlen", "nextyearlen", "yearordinal", "yearweekday", - "mmask", "mrange", "mdaymask", "nmdaymask", - "wdaymask", "wnomask", "nwdaymask", "eastermask"] - - def __init__(self, rrule): - for attr in self.__slots__: - setattr(self, attr, None) - self.rrule = rrule - - def rebuild(self, year, month): - # Every mask is 7 days longer to handle cross-year weekly periods. - rr = self.rrule - if year != self.lastyear: - self.yearlen = 365+calendar.isleap(year) - self.nextyearlen = 365+calendar.isleap(year+1) - firstyday = datetime.date(year, 1, 1) - self.yearordinal = firstyday.toordinal() - self.yearweekday = firstyday.weekday() - - wday = datetime.date(year, 1, 1).weekday() - if self.yearlen == 365: - self.mmask = M365MASK - self.mdaymask = MDAY365MASK - self.nmdaymask = NMDAY365MASK - self.wdaymask = WDAYMASK[wday:] - self.mrange = M365RANGE - else: - self.mmask = M366MASK - self.mdaymask = MDAY366MASK - self.nmdaymask = NMDAY366MASK - self.wdaymask = WDAYMASK[wday:] - self.mrange = M366RANGE - - if not rr._byweekno: - self.wnomask = None - else: - self.wnomask = [0]*(self.yearlen+7) - # no1wkst = firstwkst = self.wdaymask.index(rr._wkst) - no1wkst = firstwkst = (7-self.yearweekday+rr._wkst) % 7 - if no1wkst >= 4: - no1wkst = 0 - # Number of days in the year, plus the days we got - # from last year. - wyearlen = self.yearlen+(self.yearweekday-rr._wkst) % 7 - else: - # Number of days in the year, minus the days we - # left in last year. - wyearlen = self.yearlen-no1wkst - div, mod = divmod(wyearlen, 7) - numweeks = div+mod//4 - for n in rr._byweekno: - if n < 0: - n += numweeks+1 - if not (0 < n <= numweeks): - continue - if n > 1: - i = no1wkst+(n-1)*7 - if no1wkst != firstwkst: - i -= 7-firstwkst - else: - i = no1wkst - for j in range(7): - self.wnomask[i] = 1 - i += 1 - if self.wdaymask[i] == rr._wkst: - break - if 1 in rr._byweekno: - # Check week number 1 of next year as well - # TODO: Check -numweeks for next year. - i = no1wkst+numweeks*7 - if no1wkst != firstwkst: - i -= 7-firstwkst - if i < self.yearlen: - # If week starts in next year, we - # don't care about it. - for j in range(7): - self.wnomask[i] = 1 - i += 1 - if self.wdaymask[i] == rr._wkst: - break - if no1wkst: - # Check last week number of last year as - # well. If no1wkst is 0, either the year - # started on week start, or week number 1 - # got days from last year, so there are no - # days from last year's last week number in - # this year. - if -1 not in rr._byweekno: - lyearweekday = datetime.date(year-1, 1, 1).weekday() - lno1wkst = (7-lyearweekday+rr._wkst) % 7 - lyearlen = 365+calendar.isleap(year-1) - if lno1wkst >= 4: - lno1wkst = 0 - lnumweeks = 52+(lyearlen + - (lyearweekday-rr._wkst) % 7) % 7//4 - else: - lnumweeks = 52+(self.yearlen-no1wkst) % 7//4 - else: - lnumweeks = -1 - if lnumweeks in rr._byweekno: - for i in range(no1wkst): - self.wnomask[i] = 1 - - if (rr._bynweekday and (month != self.lastmonth or - year != self.lastyear)): - ranges = [] - if rr._freq == YEARLY: - if rr._bymonth: - for month in rr._bymonth: - ranges.append(self.mrange[month-1:month+1]) - else: - ranges = [(0, self.yearlen)] - elif rr._freq == MONTHLY: - ranges = [self.mrange[month-1:month+1]] - if ranges: - # Weekly frequency won't get here, so we may not - # care about cross-year weekly periods. - self.nwdaymask = [0]*self.yearlen - for first, last in ranges: - last -= 1 - for wday, n in rr._bynweekday: - if n < 0: - i = last+(n+1)*7 - i -= (self.wdaymask[i]-wday) % 7 - else: - i = first+(n-1)*7 - i += (7-self.wdaymask[i]+wday) % 7 - if first <= i <= last: - self.nwdaymask[i] = 1 - - if rr._byeaster: - self.eastermask = [0]*(self.yearlen+7) - eyday = easter.easter(year).toordinal()-self.yearordinal - for offset in rr._byeaster: - self.eastermask[eyday+offset] = 1 - - self.lastyear = year - self.lastmonth = month - - def ydayset(self, year, month, day): - return list(range(self.yearlen)), 0, self.yearlen - - def mdayset(self, year, month, day): - dset = [None]*self.yearlen - start, end = self.mrange[month-1:month+1] - for i in range(start, end): - dset[i] = i - return dset, start, end - - def wdayset(self, year, month, day): - # We need to handle cross-year weeks here. - dset = [None]*(self.yearlen+7) - i = datetime.date(year, month, day).toordinal()-self.yearordinal - start = i - for j in range(7): - dset[i] = i - i += 1 - # if (not (0 <= i < self.yearlen) or - # self.wdaymask[i] == self.rrule._wkst): - # This will cross the year boundary, if necessary. - if self.wdaymask[i] == self.rrule._wkst: - break - return dset, start, i - - def ddayset(self, year, month, day): - dset = [None]*self.yearlen - i = datetime.date(year, month, day).toordinal()-self.yearordinal - dset[i] = i - return dset, i, i+1 - - def htimeset(self, hour, minute, second): - tset = [] - rr = self.rrule - for minute in rr._byminute: - for second in rr._bysecond: - tset.append(datetime.time(hour, minute, second, - tzinfo=rr._tzinfo)) - tset.sort() - return tset - - def mtimeset(self, hour, minute, second): - tset = [] - rr = self.rrule - for second in rr._bysecond: - tset.append(datetime.time(hour, minute, second, tzinfo=rr._tzinfo)) - tset.sort() - return tset - - def stimeset(self, hour, minute, second): - return (datetime.time(hour, minute, second, - tzinfo=self.rrule._tzinfo),) - - -class rruleset(rrulebase): - """ The rruleset type allows more complex recurrence setups, mixing - multiple rules, dates, exclusion rules, and exclusion dates. The type - constructor takes the following keyword arguments: - - :param cache: If True, caching of results will be enabled, improving - performance of multiple queries considerably. """ - - class _genitem(object): - def __init__(self, genlist, gen): - try: - self.dt = advance_iterator(gen) - genlist.append(self) - except StopIteration: - pass - self.genlist = genlist - self.gen = gen - - def __next__(self): - try: - self.dt = advance_iterator(self.gen) - except StopIteration: - self.genlist.remove(self) - - next = __next__ - - def __lt__(self, other): - return self.dt < other.dt - - def __gt__(self, other): - return self.dt > other.dt - - def __eq__(self, other): - return self.dt == other.dt - - def __ne__(self, other): - return self.dt != other.dt - - def __init__(self, cache=False): - super(rruleset, self).__init__(cache) - self._rrule = [] - self._rdate = [] - self._exrule = [] - self._exdate = [] - - def rrule(self, rrule): - """ Include the given :py:class:`rrule` instance in the recurrence set - generation. """ - self._rrule.append(rrule) - - def rdate(self, rdate): - """ Include the given :py:class:`datetime` instance in the recurrence - set generation. """ - self._rdate.append(rdate) - - def exrule(self, exrule): - """ Include the given rrule instance in the recurrence set exclusion - list. Dates which are part of the given recurrence rules will not - be generated, even if some inclusive rrule or rdate matches them. - """ - self._exrule.append(exrule) - - def exdate(self, exdate): - """ Include the given datetime instance in the recurrence set - exclusion list. Dates included that way will not be generated, - even if some inclusive rrule or rdate matches them. """ - self._exdate.append(exdate) - - def _iter(self): - rlist = [] - self._rdate.sort() - self._genitem(rlist, iter(self._rdate)) - for gen in [iter(x) for x in self._rrule]: - self._genitem(rlist, gen) - rlist.sort() - exlist = [] - self._exdate.sort() - self._genitem(exlist, iter(self._exdate)) - for gen in [iter(x) for x in self._exrule]: - self._genitem(exlist, gen) - exlist.sort() - lastdt = None - total = 0 - while rlist: - ritem = rlist[0] - if not lastdt or lastdt != ritem.dt: - while exlist and exlist[0] < ritem: - advance_iterator(exlist[0]) - exlist.sort() - if not exlist or ritem != exlist[0]: - total += 1 - yield ritem.dt - lastdt = ritem.dt - advance_iterator(ritem) - rlist.sort() - self._len = total - - -class _rrulestr(object): - - _freq_map = {"YEARLY": YEARLY, - "MONTHLY": MONTHLY, - "WEEKLY": WEEKLY, - "DAILY": DAILY, - "HOURLY": HOURLY, - "MINUTELY": MINUTELY, - "SECONDLY": SECONDLY} - - _weekday_map = {"MO": 0, "TU": 1, "WE": 2, "TH": 3, - "FR": 4, "SA": 5, "SU": 6} - - def _handle_int(self, rrkwargs, name, value, **kwargs): - rrkwargs[name.lower()] = int(value) - - def _handle_int_list(self, rrkwargs, name, value, **kwargs): - rrkwargs[name.lower()] = [int(x) for x in value.split(',')] - - _handle_INTERVAL = _handle_int - _handle_COUNT = _handle_int - _handle_BYSETPOS = _handle_int_list - _handle_BYMONTH = _handle_int_list - _handle_BYMONTHDAY = _handle_int_list - _handle_BYYEARDAY = _handle_int_list - _handle_BYEASTER = _handle_int_list - _handle_BYWEEKNO = _handle_int_list - _handle_BYHOUR = _handle_int_list - _handle_BYMINUTE = _handle_int_list - _handle_BYSECOND = _handle_int_list - - def _handle_FREQ(self, rrkwargs, name, value, **kwargs): - rrkwargs["freq"] = self._freq_map[value] - - def _handle_UNTIL(self, rrkwargs, name, value, **kwargs): - global parser - if not parser: - from dateutil import parser - try: - rrkwargs["until"] = parser.parse(value, - ignoretz=kwargs.get("ignoretz"), - tzinfos=kwargs.get("tzinfos")) - except ValueError: - raise ValueError("invalid until date") - - def _handle_WKST(self, rrkwargs, name, value, **kwargs): - rrkwargs["wkst"] = self._weekday_map[value] - - def _handle_BYWEEKDAY(self, rrkwargs, name, value, **kwarsg): - l = [] - for wday in value.split(','): - for i in range(len(wday)): - if wday[i] not in '+-0123456789': - break - n = wday[:i] or None - w = wday[i:] - if n: - n = int(n) - l.append(weekdays[self._weekday_map[w]](n)) - rrkwargs["byweekday"] = l - - _handle_BYDAY = _handle_BYWEEKDAY - - def _parse_rfc_rrule(self, line, - dtstart=None, - cache=False, - ignoretz=False, - tzinfos=None): - if line.find(':') != -1: - name, value = line.split(':') - if name != "RRULE": - raise ValueError("unknown parameter name") - else: - value = line - rrkwargs = {} - for pair in value.split(';'): - name, value = pair.split('=') - name = name.upper() - value = value.upper() - try: - getattr(self, "_handle_"+name)(rrkwargs, name, value, - ignoretz=ignoretz, - tzinfos=tzinfos) - except AttributeError: - raise ValueError("unknown parameter '%s'" % name) - except (KeyError, ValueError): - raise ValueError("invalid '%s': %s" % (name, value)) - return rrule(dtstart=dtstart, cache=cache, **rrkwargs) - - def _parse_rfc(self, s, - dtstart=None, - cache=False, - unfold=False, - forceset=False, - compatible=False, - ignoretz=False, - tzinfos=None): - global parser - if compatible: - forceset = True - unfold = True - s = s.upper() - if not s.strip(): - raise ValueError("empty string") - if unfold: - lines = s.splitlines() - i = 0 - while i < len(lines): - line = lines[i].rstrip() - if not line: - del lines[i] - elif i > 0 and line[0] == " ": - lines[i-1] += line[1:] - del lines[i] - else: - i += 1 - else: - lines = s.split() - if (not forceset and len(lines) == 1 and (s.find(':') == -1 or - s.startswith('RRULE:'))): - return self._parse_rfc_rrule(lines[0], cache=cache, - dtstart=dtstart, ignoretz=ignoretz, - tzinfos=tzinfos) - else: - rrulevals = [] - rdatevals = [] - exrulevals = [] - exdatevals = [] - for line in lines: - if not line: - continue - if line.find(':') == -1: - name = "RRULE" - value = line - else: - name, value = line.split(':', 1) - parms = name.split(';') - if not parms: - raise ValueError("empty property name") - name = parms[0] - parms = parms[1:] - if name == "RRULE": - for parm in parms: - raise ValueError("unsupported RRULE parm: "+parm) - rrulevals.append(value) - elif name == "RDATE": - for parm in parms: - if parm != "VALUE=DATE-TIME": - raise ValueError("unsupported RDATE parm: "+parm) - rdatevals.append(value) - elif name == "EXRULE": - for parm in parms: - raise ValueError("unsupported EXRULE parm: "+parm) - exrulevals.append(value) - elif name == "EXDATE": - for parm in parms: - if parm != "VALUE=DATE-TIME": - raise ValueError("unsupported RDATE parm: "+parm) - exdatevals.append(value) - elif name == "DTSTART": - for parm in parms: - raise ValueError("unsupported DTSTART parm: "+parm) - if not parser: - from dateutil import parser - dtstart = parser.parse(value, ignoretz=ignoretz, - tzinfos=tzinfos) - else: - raise ValueError("unsupported property: "+name) - if (forceset or len(rrulevals) > 1 or rdatevals - or exrulevals or exdatevals): - if not parser and (rdatevals or exdatevals): - from dateutil import parser - rset = rruleset(cache=cache) - for value in rrulevals: - rset.rrule(self._parse_rfc_rrule(value, dtstart=dtstart, - ignoretz=ignoretz, - tzinfos=tzinfos)) - for value in rdatevals: - for datestr in value.split(','): - rset.rdate(parser.parse(datestr, - ignoretz=ignoretz, - tzinfos=tzinfos)) - for value in exrulevals: - rset.exrule(self._parse_rfc_rrule(value, dtstart=dtstart, - ignoretz=ignoretz, - tzinfos=tzinfos)) - for value in exdatevals: - for datestr in value.split(','): - rset.exdate(parser.parse(datestr, - ignoretz=ignoretz, - tzinfos=tzinfos)) - if compatible and dtstart: - rset.rdate(dtstart) - return rset - else: - return self._parse_rfc_rrule(rrulevals[0], - dtstart=dtstart, - cache=cache, - ignoretz=ignoretz, - tzinfos=tzinfos) - - def __call__(self, s, **kwargs): - return self._parse_rfc(s, **kwargs) - -rrulestr = _rrulestr() - -# vim:ts=4:sw=4:et diff --git a/virtualenv/lib/python3.5/site-packages/dateutil/tz.py b/virtualenv/lib/python3.5/site-packages/dateutil/tz.py deleted file mode 100644 index 31879e8..0000000 --- a/virtualenv/lib/python3.5/site-packages/dateutil/tz.py +++ /dev/null @@ -1,986 +0,0 @@ -# -*- coding: utf-8 -*- -""" -This module offers timezone implementations subclassing the abstract -:py:`datetime.tzinfo` type. There are classes to handle tzfile format files -(usually are in :file:`/etc/localtime`, :file:`/usr/share/zoneinfo`, etc), TZ -environment string (in all known formats), given ranges (with help from -relative deltas), local machine timezone, fixed offset timezone, and UTC -timezone. -""" -import datetime -import struct -import time -import sys -import os - -from six import string_types, PY3 - -try: - from dateutil.tzwin import tzwin, tzwinlocal -except ImportError: - tzwin = tzwinlocal = None - -relativedelta = None -parser = None -rrule = None - -__all__ = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange", - "tzstr", "tzical", "tzwin", "tzwinlocal", "gettz"] - - -def tzname_in_python2(myfunc): - """Change unicode output into bytestrings in Python 2 - - tzname() API changed in Python 3. It used to return bytes, but was changed - to unicode strings - """ - def inner_func(*args, **kwargs): - if PY3: - return myfunc(*args, **kwargs) - else: - return myfunc(*args, **kwargs).encode() - return inner_func - -ZERO = datetime.timedelta(0) -EPOCHORDINAL = datetime.datetime.utcfromtimestamp(0).toordinal() - - -class tzutc(datetime.tzinfo): - - def utcoffset(self, dt): - return ZERO - - def dst(self, dt): - return ZERO - - @tzname_in_python2 - def tzname(self, dt): - return "UTC" - - def __eq__(self, other): - return (isinstance(other, tzutc) or - (isinstance(other, tzoffset) and other._offset == ZERO)) - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - return "%s()" % self.__class__.__name__ - - __reduce__ = object.__reduce__ - - -class tzoffset(datetime.tzinfo): - - def __init__(self, name, offset): - self._name = name - self._offset = datetime.timedelta(seconds=offset) - - def utcoffset(self, dt): - return self._offset - - def dst(self, dt): - return ZERO - - @tzname_in_python2 - def tzname(self, dt): - return self._name - - def __eq__(self, other): - return (isinstance(other, tzoffset) and - self._offset == other._offset) - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - return "%s(%s, %s)" % (self.__class__.__name__, - repr(self._name), - self._offset.days*86400+self._offset.seconds) - - __reduce__ = object.__reduce__ - - -class tzlocal(datetime.tzinfo): - - _std_offset = datetime.timedelta(seconds=-time.timezone) - if time.daylight: - _dst_offset = datetime.timedelta(seconds=-time.altzone) - else: - _dst_offset = _std_offset - - def utcoffset(self, dt): - if self._isdst(dt): - return self._dst_offset - else: - return self._std_offset - - def dst(self, dt): - if self._isdst(dt): - return self._dst_offset-self._std_offset - else: - return ZERO - - @tzname_in_python2 - def tzname(self, dt): - return time.tzname[self._isdst(dt)] - - def _isdst(self, dt): - # We can't use mktime here. It is unstable when deciding if - # the hour near to a change is DST or not. - # - # timestamp = time.mktime((dt.year, dt.month, dt.day, dt.hour, - # dt.minute, dt.second, dt.weekday(), 0, -1)) - # return time.localtime(timestamp).tm_isdst - # - # The code above yields the following result: - # - # >>> import tz, datetime - # >>> t = tz.tzlocal() - # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() - # 'BRDT' - # >>> datetime.datetime(2003,2,16,0,tzinfo=t).tzname() - # 'BRST' - # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() - # 'BRST' - # >>> datetime.datetime(2003,2,15,22,tzinfo=t).tzname() - # 'BRDT' - # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() - # 'BRDT' - # - # Here is a more stable implementation: - # - timestamp = ((dt.toordinal() - EPOCHORDINAL) * 86400 - + dt.hour * 3600 - + dt.minute * 60 - + dt.second) - return time.localtime(timestamp+time.timezone).tm_isdst - - def __eq__(self, other): - if not isinstance(other, tzlocal): - return False - return (self._std_offset == other._std_offset and - self._dst_offset == other._dst_offset) - return True - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - return "%s()" % self.__class__.__name__ - - __reduce__ = object.__reduce__ - - -class _ttinfo(object): - __slots__ = ["offset", "delta", "isdst", "abbr", "isstd", "isgmt"] - - def __init__(self): - for attr in self.__slots__: - setattr(self, attr, None) - - def __repr__(self): - l = [] - for attr in self.__slots__: - value = getattr(self, attr) - if value is not None: - l.append("%s=%s" % (attr, repr(value))) - return "%s(%s)" % (self.__class__.__name__, ", ".join(l)) - - def __eq__(self, other): - if not isinstance(other, _ttinfo): - return False - return (self.offset == other.offset and - self.delta == other.delta and - self.isdst == other.isdst and - self.abbr == other.abbr and - self.isstd == other.isstd and - self.isgmt == other.isgmt) - - def __ne__(self, other): - return not self.__eq__(other) - - def __getstate__(self): - state = {} - for name in self.__slots__: - state[name] = getattr(self, name, None) - return state - - def __setstate__(self, state): - for name in self.__slots__: - if name in state: - setattr(self, name, state[name]) - - -class tzfile(datetime.tzinfo): - - # http://www.twinsun.com/tz/tz-link.htm - # ftp://ftp.iana.org/tz/tz*.tar.gz - - def __init__(self, fileobj, filename=None): - file_opened_here = False - if isinstance(fileobj, string_types): - self._filename = fileobj - fileobj = open(fileobj, 'rb') - file_opened_here = True - elif filename is not None: - self._filename = filename - elif hasattr(fileobj, "name"): - self._filename = fileobj.name - else: - self._filename = repr(fileobj) - - # From tzfile(5): - # - # The time zone information files used by tzset(3) - # begin with the magic characters "TZif" to identify - # them as time zone information files, followed by - # sixteen bytes reserved for future use, followed by - # six four-byte values of type long, written in a - # ``standard'' byte order (the high-order byte - # of the value is written first). - try: - if fileobj.read(4).decode() != "TZif": - raise ValueError("magic not found") - - fileobj.read(16) - - ( - # The number of UTC/local indicators stored in the file. - ttisgmtcnt, - - # The number of standard/wall indicators stored in the file. - ttisstdcnt, - - # The number of leap seconds for which data is - # stored in the file. - leapcnt, - - # The number of "transition times" for which data - # is stored in the file. - timecnt, - - # The number of "local time types" for which data - # is stored in the file (must not be zero). - typecnt, - - # The number of characters of "time zone - # abbreviation strings" stored in the file. - charcnt, - - ) = struct.unpack(">6l", fileobj.read(24)) - - # The above header is followed by tzh_timecnt four-byte - # values of type long, sorted in ascending order. - # These values are written in ``standard'' byte order. - # Each is used as a transition time (as returned by - # time(2)) at which the rules for computing local time - # change. - - if timecnt: - self._trans_list = struct.unpack(">%dl" % timecnt, - fileobj.read(timecnt*4)) - else: - self._trans_list = [] - - # Next come tzh_timecnt one-byte values of type unsigned - # char; each one tells which of the different types of - # ``local time'' types described in the file is associated - # with the same-indexed transition time. These values - # serve as indices into an array of ttinfo structures that - # appears next in the file. - - if timecnt: - self._trans_idx = struct.unpack(">%dB" % timecnt, - fileobj.read(timecnt)) - else: - self._trans_idx = [] - - # Each ttinfo structure is written as a four-byte value - # for tt_gmtoff of type long, in a standard byte - # order, followed by a one-byte value for tt_isdst - # and a one-byte value for tt_abbrind. In each - # structure, tt_gmtoff gives the number of - # seconds to be added to UTC, tt_isdst tells whether - # tm_isdst should be set by localtime(3), and - # tt_abbrind serves as an index into the array of - # time zone abbreviation characters that follow the - # ttinfo structure(s) in the file. - - ttinfo = [] - - for i in range(typecnt): - ttinfo.append(struct.unpack(">lbb", fileobj.read(6))) - - abbr = fileobj.read(charcnt).decode() - - # Then there are tzh_leapcnt pairs of four-byte - # values, written in standard byte order; the - # first value of each pair gives the time (as - # returned by time(2)) at which a leap second - # occurs; the second gives the total number of - # leap seconds to be applied after the given time. - # The pairs of values are sorted in ascending order - # by time. - - # Not used, for now - # if leapcnt: - # leap = struct.unpack(">%dl" % (leapcnt*2), - # fileobj.read(leapcnt*8)) - - # Then there are tzh_ttisstdcnt standard/wall - # indicators, each stored as a one-byte value; - # they tell whether the transition times associated - # with local time types were specified as standard - # time or wall clock time, and are used when - # a time zone file is used in handling POSIX-style - # time zone environment variables. - - if ttisstdcnt: - isstd = struct.unpack(">%db" % ttisstdcnt, - fileobj.read(ttisstdcnt)) - - # Finally, there are tzh_ttisgmtcnt UTC/local - # indicators, each stored as a one-byte value; - # they tell whether the transition times associated - # with local time types were specified as UTC or - # local time, and are used when a time zone file - # is used in handling POSIX-style time zone envi- - # ronment variables. - - if ttisgmtcnt: - isgmt = struct.unpack(">%db" % ttisgmtcnt, - fileobj.read(ttisgmtcnt)) - - # ** Everything has been read ** - finally: - if file_opened_here: - fileobj.close() - - # Build ttinfo list - self._ttinfo_list = [] - for i in range(typecnt): - gmtoff, isdst, abbrind = ttinfo[i] - # Round to full-minutes if that's not the case. Python's - # datetime doesn't accept sub-minute timezones. Check - # http://python.org/sf/1447945 for some information. - gmtoff = (gmtoff+30)//60*60 - tti = _ttinfo() - tti.offset = gmtoff - tti.delta = datetime.timedelta(seconds=gmtoff) - tti.isdst = isdst - tti.abbr = abbr[abbrind:abbr.find('\x00', abbrind)] - tti.isstd = (ttisstdcnt > i and isstd[i] != 0) - tti.isgmt = (ttisgmtcnt > i and isgmt[i] != 0) - self._ttinfo_list.append(tti) - - # Replace ttinfo indexes for ttinfo objects. - trans_idx = [] - for idx in self._trans_idx: - trans_idx.append(self._ttinfo_list[idx]) - self._trans_idx = tuple(trans_idx) - - # Set standard, dst, and before ttinfos. before will be - # used when a given time is before any transitions, - # and will be set to the first non-dst ttinfo, or to - # the first dst, if all of them are dst. - self._ttinfo_std = None - self._ttinfo_dst = None - self._ttinfo_before = None - if self._ttinfo_list: - if not self._trans_list: - self._ttinfo_std = self._ttinfo_first = self._ttinfo_list[0] - else: - for i in range(timecnt-1, -1, -1): - tti = self._trans_idx[i] - if not self._ttinfo_std and not tti.isdst: - self._ttinfo_std = tti - elif not self._ttinfo_dst and tti.isdst: - self._ttinfo_dst = tti - if self._ttinfo_std and self._ttinfo_dst: - break - else: - if self._ttinfo_dst and not self._ttinfo_std: - self._ttinfo_std = self._ttinfo_dst - - for tti in self._ttinfo_list: - if not tti.isdst: - self._ttinfo_before = tti - break - else: - self._ttinfo_before = self._ttinfo_list[0] - - # Now fix transition times to become relative to wall time. - # - # I'm not sure about this. In my tests, the tz source file - # is setup to wall time, and in the binary file isstd and - # isgmt are off, so it should be in wall time. OTOH, it's - # always in gmt time. Let me know if you have comments - # about this. - laststdoffset = 0 - self._trans_list = list(self._trans_list) - for i in range(len(self._trans_list)): - tti = self._trans_idx[i] - if not tti.isdst: - # This is std time. - self._trans_list[i] += tti.offset - laststdoffset = tti.offset - else: - # This is dst time. Convert to std. - self._trans_list[i] += laststdoffset - self._trans_list = tuple(self._trans_list) - - def _find_ttinfo(self, dt, laststd=0): - timestamp = ((dt.toordinal() - EPOCHORDINAL) * 86400 - + dt.hour * 3600 - + dt.minute * 60 - + dt.second) - idx = 0 - for trans in self._trans_list: - if timestamp < trans: - break - idx += 1 - else: - return self._ttinfo_std - if idx == 0: - return self._ttinfo_before - if laststd: - while idx > 0: - tti = self._trans_idx[idx-1] - if not tti.isdst: - return tti - idx -= 1 - else: - return self._ttinfo_std - else: - return self._trans_idx[idx-1] - - def utcoffset(self, dt): - if not self._ttinfo_std: - return ZERO - return self._find_ttinfo(dt).delta - - def dst(self, dt): - if not self._ttinfo_dst: - return ZERO - tti = self._find_ttinfo(dt) - if not tti.isdst: - return ZERO - - # The documentation says that utcoffset()-dst() must - # be constant for every dt. - return tti.delta-self._find_ttinfo(dt, laststd=1).delta - - # An alternative for that would be: - # - # return self._ttinfo_dst.offset-self._ttinfo_std.offset - # - # However, this class stores historical changes in the - # dst offset, so I belive that this wouldn't be the right - # way to implement this. - - @tzname_in_python2 - def tzname(self, dt): - if not self._ttinfo_std: - return None - return self._find_ttinfo(dt).abbr - - def __eq__(self, other): - if not isinstance(other, tzfile): - return False - return (self._trans_list == other._trans_list and - self._trans_idx == other._trans_idx and - self._ttinfo_list == other._ttinfo_list) - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, repr(self._filename)) - - def __reduce__(self): - if not os.path.isfile(self._filename): - raise ValueError("Unpickable %s class" % self.__class__.__name__) - return (self.__class__, (self._filename,)) - - -class tzrange(datetime.tzinfo): - def __init__(self, stdabbr, stdoffset=None, - dstabbr=None, dstoffset=None, - start=None, end=None): - global relativedelta - if not relativedelta: - from dateutil import relativedelta - self._std_abbr = stdabbr - self._dst_abbr = dstabbr - if stdoffset is not None: - self._std_offset = datetime.timedelta(seconds=stdoffset) - else: - self._std_offset = ZERO - if dstoffset is not None: - self._dst_offset = datetime.timedelta(seconds=dstoffset) - elif dstabbr and stdoffset is not None: - self._dst_offset = self._std_offset+datetime.timedelta(hours=+1) - else: - self._dst_offset = ZERO - if dstabbr and start is None: - self._start_delta = relativedelta.relativedelta( - hours=+2, month=4, day=1, weekday=relativedelta.SU(+1)) - else: - self._start_delta = start - if dstabbr and end is None: - self._end_delta = relativedelta.relativedelta( - hours=+1, month=10, day=31, weekday=relativedelta.SU(-1)) - else: - self._end_delta = end - - def utcoffset(self, dt): - if self._isdst(dt): - return self._dst_offset - else: - return self._std_offset - - def dst(self, dt): - if self._isdst(dt): - return self._dst_offset-self._std_offset - else: - return ZERO - - @tzname_in_python2 - def tzname(self, dt): - if self._isdst(dt): - return self._dst_abbr - else: - return self._std_abbr - - def _isdst(self, dt): - if not self._start_delta: - return False - year = datetime.datetime(dt.year, 1, 1) - start = year+self._start_delta - end = year+self._end_delta - dt = dt.replace(tzinfo=None) - if start < end: - return dt >= start and dt < end - else: - return dt >= start or dt < end - - def __eq__(self, other): - if not isinstance(other, tzrange): - return False - return (self._std_abbr == other._std_abbr and - self._dst_abbr == other._dst_abbr and - self._std_offset == other._std_offset and - self._dst_offset == other._dst_offset and - self._start_delta == other._start_delta and - self._end_delta == other._end_delta) - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - return "%s(...)" % self.__class__.__name__ - - __reduce__ = object.__reduce__ - - -class tzstr(tzrange): - - def __init__(self, s): - global parser - if not parser: - from dateutil import parser - self._s = s - - res = parser._parsetz(s) - if res is None: - raise ValueError("unknown string format") - - # Here we break the compatibility with the TZ variable handling. - # GMT-3 actually *means* the timezone -3. - if res.stdabbr in ("GMT", "UTC"): - res.stdoffset *= -1 - - # We must initialize it first, since _delta() needs - # _std_offset and _dst_offset set. Use False in start/end - # to avoid building it two times. - tzrange.__init__(self, res.stdabbr, res.stdoffset, - res.dstabbr, res.dstoffset, - start=False, end=False) - - if not res.dstabbr: - self._start_delta = None - self._end_delta = None - else: - self._start_delta = self._delta(res.start) - if self._start_delta: - self._end_delta = self._delta(res.end, isend=1) - - def _delta(self, x, isend=0): - kwargs = {} - if x.month is not None: - kwargs["month"] = x.month - if x.weekday is not None: - kwargs["weekday"] = relativedelta.weekday(x.weekday, x.week) - if x.week > 0: - kwargs["day"] = 1 - else: - kwargs["day"] = 31 - elif x.day: - kwargs["day"] = x.day - elif x.yday is not None: - kwargs["yearday"] = x.yday - elif x.jyday is not None: - kwargs["nlyearday"] = x.jyday - if not kwargs: - # Default is to start on first sunday of april, and end - # on last sunday of october. - if not isend: - kwargs["month"] = 4 - kwargs["day"] = 1 - kwargs["weekday"] = relativedelta.SU(+1) - else: - kwargs["month"] = 10 - kwargs["day"] = 31 - kwargs["weekday"] = relativedelta.SU(-1) - if x.time is not None: - kwargs["seconds"] = x.time - else: - # Default is 2AM. - kwargs["seconds"] = 7200 - if isend: - # Convert to standard time, to follow the documented way - # of working with the extra hour. See the documentation - # of the tzinfo class. - delta = self._dst_offset-self._std_offset - kwargs["seconds"] -= delta.seconds+delta.days*86400 - return relativedelta.relativedelta(**kwargs) - - def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, repr(self._s)) - - -class _tzicalvtzcomp(object): - def __init__(self, tzoffsetfrom, tzoffsetto, isdst, - tzname=None, rrule=None): - self.tzoffsetfrom = datetime.timedelta(seconds=tzoffsetfrom) - self.tzoffsetto = datetime.timedelta(seconds=tzoffsetto) - self.tzoffsetdiff = self.tzoffsetto-self.tzoffsetfrom - self.isdst = isdst - self.tzname = tzname - self.rrule = rrule - - -class _tzicalvtz(datetime.tzinfo): - def __init__(self, tzid, comps=[]): - self._tzid = tzid - self._comps = comps - self._cachedate = [] - self._cachecomp = [] - - def _find_comp(self, dt): - if len(self._comps) == 1: - return self._comps[0] - dt = dt.replace(tzinfo=None) - try: - return self._cachecomp[self._cachedate.index(dt)] - except ValueError: - pass - lastcomp = None - lastcompdt = None - for comp in self._comps: - if not comp.isdst: - # Handle the extra hour in DST -> STD - compdt = comp.rrule.before(dt-comp.tzoffsetdiff, inc=True) - else: - compdt = comp.rrule.before(dt, inc=True) - if compdt and (not lastcompdt or lastcompdt < compdt): - lastcompdt = compdt - lastcomp = comp - if not lastcomp: - # RFC says nothing about what to do when a given - # time is before the first onset date. We'll look for the - # first standard component, or the first component, if - # none is found. - for comp in self._comps: - if not comp.isdst: - lastcomp = comp - break - else: - lastcomp = comp[0] - self._cachedate.insert(0, dt) - self._cachecomp.insert(0, lastcomp) - if len(self._cachedate) > 10: - self._cachedate.pop() - self._cachecomp.pop() - return lastcomp - - def utcoffset(self, dt): - return self._find_comp(dt).tzoffsetto - - def dst(self, dt): - comp = self._find_comp(dt) - if comp.isdst: - return comp.tzoffsetdiff - else: - return ZERO - - @tzname_in_python2 - def tzname(self, dt): - return self._find_comp(dt).tzname - - def __repr__(self): - return "" % repr(self._tzid) - - __reduce__ = object.__reduce__ - - -class tzical(object): - def __init__(self, fileobj): - global rrule - if not rrule: - from dateutil import rrule - - if isinstance(fileobj, string_types): - self._s = fileobj - # ical should be encoded in UTF-8 with CRLF - fileobj = open(fileobj, 'r') - elif hasattr(fileobj, "name"): - self._s = fileobj.name - else: - self._s = repr(fileobj) - - self._vtz = {} - - self._parse_rfc(fileobj.read()) - - def keys(self): - return list(self._vtz.keys()) - - def get(self, tzid=None): - if tzid is None: - keys = list(self._vtz.keys()) - if len(keys) == 0: - raise ValueError("no timezones defined") - elif len(keys) > 1: - raise ValueError("more than one timezone available") - tzid = keys[0] - return self._vtz.get(tzid) - - def _parse_offset(self, s): - s = s.strip() - if not s: - raise ValueError("empty offset") - if s[0] in ('+', '-'): - signal = (-1, +1)[s[0] == '+'] - s = s[1:] - else: - signal = +1 - if len(s) == 4: - return (int(s[:2])*3600+int(s[2:])*60)*signal - elif len(s) == 6: - return (int(s[:2])*3600+int(s[2:4])*60+int(s[4:]))*signal - else: - raise ValueError("invalid offset: "+s) - - def _parse_rfc(self, s): - lines = s.splitlines() - if not lines: - raise ValueError("empty string") - - # Unfold - i = 0 - while i < len(lines): - line = lines[i].rstrip() - if not line: - del lines[i] - elif i > 0 and line[0] == " ": - lines[i-1] += line[1:] - del lines[i] - else: - i += 1 - - tzid = None - comps = [] - invtz = False - comptype = None - for line in lines: - if not line: - continue - name, value = line.split(':', 1) - parms = name.split(';') - if not parms: - raise ValueError("empty property name") - name = parms[0].upper() - parms = parms[1:] - if invtz: - if name == "BEGIN": - if value in ("STANDARD", "DAYLIGHT"): - # Process component - pass - else: - raise ValueError("unknown component: "+value) - comptype = value - founddtstart = False - tzoffsetfrom = None - tzoffsetto = None - rrulelines = [] - tzname = None - elif name == "END": - if value == "VTIMEZONE": - if comptype: - raise ValueError("component not closed: "+comptype) - if not tzid: - raise ValueError("mandatory TZID not found") - if not comps: - raise ValueError( - "at least one component is needed") - # Process vtimezone - self._vtz[tzid] = _tzicalvtz(tzid, comps) - invtz = False - elif value == comptype: - if not founddtstart: - raise ValueError("mandatory DTSTART not found") - if tzoffsetfrom is None: - raise ValueError( - "mandatory TZOFFSETFROM not found") - if tzoffsetto is None: - raise ValueError( - "mandatory TZOFFSETFROM not found") - # Process component - rr = None - if rrulelines: - rr = rrule.rrulestr("\n".join(rrulelines), - compatible=True, - ignoretz=True, - cache=True) - comp = _tzicalvtzcomp(tzoffsetfrom, tzoffsetto, - (comptype == "DAYLIGHT"), - tzname, rr) - comps.append(comp) - comptype = None - else: - raise ValueError("invalid component end: "+value) - elif comptype: - if name == "DTSTART": - rrulelines.append(line) - founddtstart = True - elif name in ("RRULE", "RDATE", "EXRULE", "EXDATE"): - rrulelines.append(line) - elif name == "TZOFFSETFROM": - if parms: - raise ValueError( - "unsupported %s parm: %s " % (name, parms[0])) - tzoffsetfrom = self._parse_offset(value) - elif name == "TZOFFSETTO": - if parms: - raise ValueError( - "unsupported TZOFFSETTO parm: "+parms[0]) - tzoffsetto = self._parse_offset(value) - elif name == "TZNAME": - if parms: - raise ValueError( - "unsupported TZNAME parm: "+parms[0]) - tzname = value - elif name == "COMMENT": - pass - else: - raise ValueError("unsupported property: "+name) - else: - if name == "TZID": - if parms: - raise ValueError( - "unsupported TZID parm: "+parms[0]) - tzid = value - elif name in ("TZURL", "LAST-MODIFIED", "COMMENT"): - pass - else: - raise ValueError("unsupported property: "+name) - elif name == "BEGIN" and value == "VTIMEZONE": - tzid = None - comps = [] - invtz = True - - def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, repr(self._s)) - -if sys.platform != "win32": - TZFILES = ["/etc/localtime", "localtime"] - TZPATHS = ["/usr/share/zoneinfo", "/usr/lib/zoneinfo", "/etc/zoneinfo"] -else: - TZFILES = [] - TZPATHS = [] - - -def gettz(name=None): - tz = None - if not name: - try: - name = os.environ["TZ"] - except KeyError: - pass - if name is None or name == ":": - for filepath in TZFILES: - if not os.path.isabs(filepath): - filename = filepath - for path in TZPATHS: - filepath = os.path.join(path, filename) - if os.path.isfile(filepath): - break - else: - continue - if os.path.isfile(filepath): - try: - tz = tzfile(filepath) - break - except (IOError, OSError, ValueError): - pass - else: - tz = tzlocal() - else: - if name.startswith(":"): - name = name[:-1] - if os.path.isabs(name): - if os.path.isfile(name): - tz = tzfile(name) - else: - tz = None - else: - for path in TZPATHS: - filepath = os.path.join(path, name) - if not os.path.isfile(filepath): - filepath = filepath.replace(' ', '_') - if not os.path.isfile(filepath): - continue - try: - tz = tzfile(filepath) - break - except (IOError, OSError, ValueError): - pass - else: - tz = None - if tzwin is not None: - try: - tz = tzwin(name) - except WindowsError: - tz = None - if not tz: - from dateutil.zoneinfo import gettz - tz = gettz(name) - if not tz: - for c in name: - # name must have at least one offset to be a tzstr - if c in "0123456789": - try: - tz = tzstr(name) - except ValueError: - pass - break - else: - if name in ("GMT", "UTC"): - tz = tzutc() - elif name in time.tzname: - tz = tzlocal() - return tz - -# vim:ts=4:sw=4:et diff --git a/virtualenv/lib/python3.5/site-packages/dateutil/tzwin.py b/virtualenv/lib/python3.5/site-packages/dateutil/tzwin.py deleted file mode 100644 index e8a82d7..0000000 --- a/virtualenv/lib/python3.5/site-packages/dateutil/tzwin.py +++ /dev/null @@ -1,184 +0,0 @@ -# This code was originally contributed by Jeffrey Harris. -import datetime -import struct - -from six.moves import winreg - -__all__ = ["tzwin", "tzwinlocal"] - -ONEWEEK = datetime.timedelta(7) - -TZKEYNAMENT = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones" -TZKEYNAME9X = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Time Zones" -TZLOCALKEYNAME = r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation" - - -def _settzkeyname(): - handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) - try: - winreg.OpenKey(handle, TZKEYNAMENT).Close() - TZKEYNAME = TZKEYNAMENT - except WindowsError: - TZKEYNAME = TZKEYNAME9X - handle.Close() - return TZKEYNAME - -TZKEYNAME = _settzkeyname() - - -class tzwinbase(datetime.tzinfo): - """tzinfo class based on win32's timezones available in the registry.""" - - def utcoffset(self, dt): - if self._isdst(dt): - return datetime.timedelta(minutes=self._dstoffset) - else: - return datetime.timedelta(minutes=self._stdoffset) - - def dst(self, dt): - if self._isdst(dt): - minutes = self._dstoffset - self._stdoffset - return datetime.timedelta(minutes=minutes) - else: - return datetime.timedelta(0) - - def tzname(self, dt): - if self._isdst(dt): - return self._dstname - else: - return self._stdname - - def list(): - """Return a list of all time zones known to the system.""" - handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) - tzkey = winreg.OpenKey(handle, TZKEYNAME) - result = [winreg.EnumKey(tzkey, i) - for i in range(winreg.QueryInfoKey(tzkey)[0])] - tzkey.Close() - handle.Close() - return result - list = staticmethod(list) - - def display(self): - return self._display - - def _isdst(self, dt): - if not self._dstmonth: - # dstmonth == 0 signals the zone has no daylight saving time - return False - dston = picknthweekday(dt.year, self._dstmonth, self._dstdayofweek, - self._dsthour, self._dstminute, - self._dstweeknumber) - dstoff = picknthweekday(dt.year, self._stdmonth, self._stddayofweek, - self._stdhour, self._stdminute, - self._stdweeknumber) - if dston < dstoff: - return dston <= dt.replace(tzinfo=None) < dstoff - else: - return not dstoff <= dt.replace(tzinfo=None) < dston - - -class tzwin(tzwinbase): - - def __init__(self, name): - self._name = name - - # multiple contexts only possible in 2.7 and 3.1, we still support 2.6 - with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: - with winreg.OpenKey(handle, - "%s\%s" % (TZKEYNAME, name)) as tzkey: - keydict = valuestodict(tzkey) - - self._stdname = keydict["Std"].encode("iso-8859-1") - self._dstname = keydict["Dlt"].encode("iso-8859-1") - - self._display = keydict["Display"] - - # See http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm - tup = struct.unpack("=3l16h", keydict["TZI"]) - self._stdoffset = -tup[0]-tup[1] # Bias + StandardBias * -1 - self._dstoffset = self._stdoffset-tup[2] # + DaylightBias * -1 - - # for the meaning see the win32 TIME_ZONE_INFORMATION structure docs - # http://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx - (self._stdmonth, - self._stddayofweek, # Sunday = 0 - self._stdweeknumber, # Last = 5 - self._stdhour, - self._stdminute) = tup[4:9] - - (self._dstmonth, - self._dstdayofweek, # Sunday = 0 - self._dstweeknumber, # Last = 5 - self._dsthour, - self._dstminute) = tup[12:17] - - def __repr__(self): - return "tzwin(%s)" % repr(self._name) - - def __reduce__(self): - return (self.__class__, (self._name,)) - - -class tzwinlocal(tzwinbase): - - def __init__(self): - - with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: - - with winreg.OpenKey(handle, TZLOCALKEYNAME) as tzlocalkey: - keydict = valuestodict(tzlocalkey) - - self._stdname = keydict["StandardName"].encode("iso-8859-1") - self._dstname = keydict["DaylightName"].encode("iso-8859-1") - - try: - with winreg.OpenKey( - handle, "%s\%s" % (TZKEYNAME, self._stdname)) as tzkey: - _keydict = valuestodict(tzkey) - self._display = _keydict["Display"] - except OSError: - self._display = None - - self._stdoffset = -keydict["Bias"]-keydict["StandardBias"] - self._dstoffset = self._stdoffset-keydict["DaylightBias"] - - # See http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm - tup = struct.unpack("=8h", keydict["StandardStart"]) - - (self._stdmonth, - self._stddayofweek, # Sunday = 0 - self._stdweeknumber, # Last = 5 - self._stdhour, - self._stdminute) = tup[1:6] - - tup = struct.unpack("=8h", keydict["DaylightStart"]) - - (self._dstmonth, - self._dstdayofweek, # Sunday = 0 - self._dstweeknumber, # Last = 5 - self._dsthour, - self._dstminute) = tup[1:6] - - def __reduce__(self): - return (self.__class__, ()) - - -def picknthweekday(year, month, dayofweek, hour, minute, whichweek): - """dayofweek == 0 means Sunday, whichweek 5 means last instance""" - first = datetime.datetime(year, month, 1, hour, minute) - weekdayone = first.replace(day=((dayofweek-first.isoweekday()) % 7+1)) - for n in range(whichweek): - dt = weekdayone+(whichweek-n)*ONEWEEK - if dt.month == month: - return dt - - -def valuestodict(key): - """Convert a registry key's values to a dictionary.""" - dict = {} - size = winreg.QueryInfoKey(key)[1] - for i in range(size): - data = winreg.EnumValue(key, i) - dict[data[0]] = data[1] - return dict diff --git a/virtualenv/lib/python3.5/site-packages/dateutil/zoneinfo/__init__.py b/virtualenv/lib/python3.5/site-packages/dateutil/zoneinfo/__init__.py deleted file mode 100644 index e33384f..0000000 --- a/virtualenv/lib/python3.5/site-packages/dateutil/zoneinfo/__init__.py +++ /dev/null @@ -1,108 +0,0 @@ -# -*- coding: utf-8 -*- -import logging -import os -import warnings -import tempfile -import shutil -from subprocess import check_call -from tarfile import TarFile -from pkgutil import get_data -from io import BytesIO -from contextlib import closing - -from dateutil.tz import tzfile - -__all__ = ["gettz", "rebuild"] - -_ZONEFILENAME = "dateutil-zoneinfo.tar.gz" - -# python2.6 compatability. Note that TarFile.__exit__ != TarFile.close, but -# it's close enough for python2.6 -_tar_open = TarFile.open -if not hasattr(TarFile, '__exit__'): - def _tar_open(*args, **kwargs): - return closing(TarFile.open(*args, **kwargs)) - - -class tzfile(tzfile): - def __reduce__(self): - return (gettz, (self._filename,)) - - -def getzoneinfofile_stream(): - try: - return BytesIO(get_data(__name__, _ZONEFILENAME)) - except IOError as e: # TODO switch to FileNotFoundError? - warnings.warn("I/O error({0}): {1}".format(e.errno, e.strerror)) - return None - - -class ZoneInfoFile(object): - def __init__(self, zonefile_stream=None): - if zonefile_stream is not None: - with _tar_open(fileobj=zonefile_stream, mode='r') as tf: - # dict comprehension does not work on python2.6 - # TODO: get back to the nicer syntax when we ditch python2.6 - # self.zones = {zf.name: tzfile(tf.extractfile(zf), - # filename = zf.name) - # for zf in tf.getmembers() if zf.isfile()} - self.zones = dict((zf.name, tzfile(tf.extractfile(zf), - filename=zf.name)) - for zf in tf.getmembers() if zf.isfile()) - # deal with links: They'll point to their parent object. Less - # waste of memory - # links = {zl.name: self.zones[zl.linkname] - # for zl in tf.getmembers() if zl.islnk() or zl.issym()} - links = dict((zl.name, self.zones[zl.linkname]) - for zl in tf.getmembers() if - zl.islnk() or zl.issym()) - self.zones.update(links) - else: - self.zones = dict() - - -# The current API has gettz as a module function, although in fact it taps into -# a stateful class. So as a workaround for now, without changing the API, we -# will create a new "global" class instance the first time a user requests a -# timezone. Ugly, but adheres to the api. -# -# TODO: deprecate this. -_CLASS_ZONE_INSTANCE = list() - - -def gettz(name): - if len(_CLASS_ZONE_INSTANCE) == 0: - _CLASS_ZONE_INSTANCE.append(ZoneInfoFile(getzoneinfofile_stream())) - return _CLASS_ZONE_INSTANCE[0].zones.get(name) - - -def rebuild(filename, tag=None, format="gz", zonegroups=[]): - """Rebuild the internal timezone info in dateutil/zoneinfo/zoneinfo*tar* - - filename is the timezone tarball from ftp.iana.org/tz. - - """ - tmpdir = tempfile.mkdtemp() - zonedir = os.path.join(tmpdir, "zoneinfo") - moduledir = os.path.dirname(__file__) - try: - with _tar_open(filename) as tf: - for name in zonegroups: - tf.extract(name, tmpdir) - filepaths = [os.path.join(tmpdir, n) for n in zonegroups] - try: - check_call(["zic", "-d", zonedir] + filepaths) - except OSError as e: - if e.errno == 2: - logging.error( - "Could not find zic. Perhaps you need to install " - "libc-bin or some other package that provides it, " - "or it's not in your PATH?") - raise - target = os.path.join(moduledir, _ZONEFILENAME) - with _tar_open(target, "w:%s" % format) as tf: - for entry in os.listdir(zonedir): - entrypath = os.path.join(zonedir, entry) - tf.add(entrypath, entry) - finally: - shutil.rmtree(tmpdir) diff --git a/virtualenv/lib/python3.5/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz b/virtualenv/lib/python3.5/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz deleted file mode 100644 index 657c8ca69c67ddb55f517709efee1ffabc4f8a45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 151011 zcmXV1bzD>L+on4P1|cPlG=emnigZYcbc3{XGY|v>q(fRtO1c~A?(Xhx80@^~`}@3q zZ0EkO`?{_t&UUsv=NWAn4$hl-N)0r?)X3S)#o5w^)6?G0%+k)>p3B+D5#>-17p6XS z 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≻Pm6zbZD~xyCkNlUN8&Jr)b(FHK_zi@* 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 Xo_+E^g`w3I0RP$P?h2j;HQxUL5PhqR diff --git a/virtualenv/lib/python3.5/site-packages/easy-install.pth b/virtualenv/lib/python3.5/site-packages/easy-install.pth deleted file mode 100644 index 2c76916..0000000 --- a/virtualenv/lib/python3.5/site-packages/easy-install.pth +++ /dev/null @@ -1,3 +0,0 @@ -import sys; sys.__plen = len(sys.path) -./cffi-1.3.1-py3.5-macosx-10.6-intel.egg -import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p=getattr(sys,'__egginsert',0); sys.path[p:p]=new; sys.__egginsert = p+len(new) diff --git a/virtualenv/lib/python3.5/site-packages/easy_install.py b/virtualenv/lib/python3.5/site-packages/easy_install.py deleted file mode 100644 index d87e984..0000000 --- a/virtualenv/lib/python3.5/site-packages/easy_install.py +++ /dev/null @@ -1,5 +0,0 @@ -"""Run the EasyInstall command""" - -if __name__ == '__main__': - from setuptools.command.easy_install import main - main() diff --git a/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/DESCRIPTION.rst b/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/DESCRIPTION.rst deleted file mode 100644 index ac1c662..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/DESCRIPTION.rst +++ /dev/null @@ -1,25 +0,0 @@ -pip -=== - -The `PyPA recommended -`_ -tool for installing Python packages. - -* `Installation `_ -* `Documentation `_ -* `Changelog `_ -* `Github Page `_ -* `Issue Tracking `_ -* `User mailing list `_ -* `Dev mailing list `_ -* User IRC: #pypa on Freenode. -* Dev IRC: #pypa-dev on Freenode. - - -.. image:: https://pypip.in/v/pip/badge.png - :target: https://pypi.python.org/pypi/pip - -.. image:: https://secure.travis-ci.org/pypa/pip.png?branch=develop - :target: http://travis-ci.org/pypa/pip - - diff --git a/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/METADATA b/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/METADATA deleted file mode 100644 index 868ced7..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/METADATA +++ /dev/null @@ -1,53 +0,0 @@ -Metadata-Version: 2.0 -Name: pip -Version: 7.1.2 -Summary: The PyPA recommended tool for installing Python packages. -Home-page: https://pip.pypa.io/ -Author: The pip developers -Author-email: python-virtualenv@groups.google.com -License: MIT -Keywords: easy_install distutils setuptools egg virtualenv -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Topic :: Software Development :: Build Tools -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.2 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: Implementation :: PyPy -Provides-Extra: testing -Requires-Dist: pytest; extra == 'testing' -Requires-Dist: virtualenv (>=1.10); extra == 'testing' -Requires-Dist: scripttest (>=1.3); extra == 'testing' -Requires-Dist: mock; extra == 'testing' - -pip -=== - -The `PyPA recommended -`_ -tool for installing Python packages. - -* `Installation `_ -* `Documentation `_ -* `Changelog `_ -* `Github Page `_ -* `Issue Tracking `_ -* `User mailing list `_ -* `Dev mailing list `_ -* User IRC: #pypa on Freenode. -* Dev IRC: #pypa-dev on Freenode. - - -.. image:: https://pypip.in/v/pip/badge.png - :target: https://pypi.python.org/pypi/pip - -.. image:: https://secure.travis-ci.org/pypa/pip.png?branch=develop - :target: http://travis-ci.org/pypa/pip - - diff --git a/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/RECORD b/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/RECORD deleted file mode 100644 index d0b08e9..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/RECORD +++ /dev/null @@ -1,461 +0,0 @@ -pip/__init__.py,sha256=m7PqiHbqrEDh1FABYrQPXy1nGzBgsw1NxFmXff46ERI,10414 -pip/__main__.py,sha256=V6Kh-IEDEFpt1cahRE6MajUF_14qJR_Qsvn4MjWZXzE,584 -pip/basecommand.py,sha256=ogTu4U-jtdAeOjtwaMpAlEdW_EBSUUtLG9WD8DmVatI,10617 -pip/baseparser.py,sha256=Nlc7Un9gat27xtB24SnKL_3pZZOoh62gNNRdS6tDRZY,10465 -pip/cmdoptions.py,sha256=KsnFWOkho2FORJxYw9TDV9Ys1q7BFyuepRJSo07JMM8,14701 -pip/download.py,sha256=N_YJKby1svBZyEHt3d3IYGhQW0oH6V8rGEnQ5rrdqmk,31936 -pip/exceptions.py,sha256=8hfyL6jntWp7aejEkDFMe4idF1IIFYiUHDBuVRRBOv0,1257 -pip/index.py,sha256=f6zG23oVm4c5gCh2xCf1rUzv22kJxWXDfj-Hd8MbhA4,47847 -pip/locations.py,sha256=6PSdEha93gk2WKjGz-AxBdxNncA1DVQL6TLDeJoTUuQ,6644 -pip/pep425tags.py,sha256=jdIwmMwubI6wT5pw7znJPMtdh9WkNUQiORw6nz987XM,4427 -pip/status_codes.py,sha256=F6uDG6Gj7RNKQJUDnd87QKqI16Us-t-B0wPF_4QMpWc,156 -pip/wheel.py,sha256=f49Yp-dJHqSNRfWEmdzXwPcDKsFGoTbzyS9ALFgy6Q4,30186 -pip/_vendor/__init__.py,sha256=FyU1LxurgMgzgJiAvsaflSMMOgldJWKP-Pmh9jfSOJA,2508 -pip/_vendor/ipaddress.py,sha256=1atIh2cVrwtjr9_2rgSwZTQdLRMcdpYqwwZE1wQcQoI,79659 -pip/_vendor/re-vendor.py,sha256=PcdZ40d0ohMsdJmA4t0AeAWbPXi1tFsvAwA5KE5FGeY,773 -pip/_vendor/retrying.py,sha256=k3fflf5_Mm0XcIJYhB7Tj34bqCCPhUDkYbx1NvW2FPE,9972 -pip/_vendor/six.py,sha256=zKxWCKje5Gpr06IIWNgQL8-8GJ9rwAulE0DnWBKzmhE,29664 -pip/_vendor/_markerlib/__init__.py,sha256=2hgtRuYDOrimZF9-ENCkrP8gnJ59HZEtlk-zoTEvn1Y,564 -pip/_vendor/_markerlib/markers.py,sha256=YuFp0-osufFIoqnzG3L0Z2fDCx4Vln3VUDeXJ2DA_1I,3979 -pip/_vendor/cachecontrol/__init__.py,sha256=D6mWmLQUEUGCs0pWDk7GtNmBHr_syFuPfijpWL84gN4,302 -pip/_vendor/cachecontrol/adapter.py,sha256=eizWWJwOnG5TToxL-XiEywPEf2k20--e-5C6u6wAEts,4196 -pip/_vendor/cachecontrol/cache.py,sha256=xtl-V-pr9KSt9VvFDRCB9yrHPEvqvbk-5M1vAInZb5k,790 -pip/_vendor/cachecontrol/compat.py,sha256=kjqVbQGXwDm8xsBFtnLtJ50VQoOAUzgLvv5bjxrzguM,311 -pip/_vendor/cachecontrol/controller.py,sha256=NyC69aG2oMqlex7zH_tihj0rLmWzSngj3vw7GzMs-tU,10124 -pip/_vendor/cachecontrol/filewrapper.py,sha256=jkC0GOorbWIpy9CzP3PwxSHx5J2CXBAxNbGH68HmP1M,2168 -pip/_vendor/cachecontrol/heuristics.py,sha256=2P6eQo5sn4v6Eu3VzF3k8SflNUuaTSiY4q_j2q3jPQc,4053 -pip/_vendor/cachecontrol/serialize.py,sha256=5EBnH_7HrVzBH80yDqcv3s2Y6ccvxasODW2ka3sBq2E,6189 -pip/_vendor/cachecontrol/wrapper.py,sha256=Kqyu_3TW_54XDudha4-HF21vyEOAJ4ZnRXFysTiLmXA,498 -pip/_vendor/cachecontrol/caches/__init__.py,sha256=uWnUtyMvHY_LULaL_4_IR1F_xPgK5zHfJyRnBq4DnPE,369 -pip/_vendor/cachecontrol/caches/file_cache.py,sha256=FsDug3bwUAQ3okjjfGzxlDaBf2fwVSn1iBKMTL6SyGU,3532 -pip/_vendor/cachecontrol/caches/redis_cache.py,sha256=XywqxkS9MkCaflTOY_wjrE02neKdywB9YwlOBbP7Ywc,973 -pip/_vendor/colorama/__init__.py,sha256=MaGNdH3aaGqXbOrn-V50ojZcxPx_Lak3WkD943_gG3o,225 -pip/_vendor/colorama/ansi.py,sha256=QqrSoEXqVOpqsz0ChbSqxQ3pkRNbrmdpuiFRTX7bceY,2304 -pip/_vendor/colorama/ansitowin32.py,sha256=BfJ_7-Ya6odmjvOlpI32KUTY2K2QWIeFmhg5oNymVsM,9262 -pip/_vendor/colorama/initialise.py,sha256=CRwgjKdSGhivhfBITpB9vyQsVgc6TyCGvFqVymqxK90,1597 -pip/_vendor/colorama/win32.py,sha256=pm8dhPtaCDr8W2V7b0bVJUHuz0rVM896z6OfA-iRV24,5121 -pip/_vendor/colorama/winterm.py,sha256=6KM_v7qYo-_GM7ZECbPV8ZY8iLwP-5mFqJHCGGOp11g,5732 -pip/_vendor/distlib/__init__.py,sha256=iQfvezhw6UAHvpHnVjHTpgihkVdORxsaplTI85GdPgQ,581 -pip/_vendor/distlib/compat.py,sha256=cQpdOl3c94jOx7KQXvDzDjdDaqxzs0kdnGYe5lMspAc,40660 -pip/_vendor/distlib/database.py,sha256=ox41J2cwXW2J0bZvgaKf8dhm3DfuiCR4o1icl5qr9c4,49268 -pip/_vendor/distlib/index.py,sha256=qU38JCRI5F_1Z-QmydiocDE58d4KvHzKjS_T0dBsPlg,20976 -pip/_vendor/distlib/locators.py,sha256=J720MSOYW3l35af3f5IpsUYiz1EgmUxTtMZ0y1Bm3Nk,50347 -pip/_vendor/distlib/manifest.py,sha256=JF5EstaCOPnsW2tUdXCdjIFn-Zkf48Dqw0TcxKjuni0,13598 -pip/_vendor/distlib/markers.py,sha256=iRrVWwpyVwjkKJSX8NEQ92_MRMwpROcfNGKCD-Ch1QM,6282 -pip/_vendor/distlib/metadata.py,sha256=HvsxgUBUdrJe3pnRQCyCVtKrX5GIw0vjPEzvnmC5by0,38314 -pip/_vendor/distlib/resources.py,sha256=oQ58hJM6egiGve0P6UzdSTGvV5Bt8raW_Dla2LCrOWs,10615 -pip/_vendor/distlib/scripts.py,sha256=y5v9QEHw_Z1fLU-ETjU9z_-nQZlKBu49r0meUlj1qp4,14183 -pip/_vendor/distlib/t32.exe,sha256=rOJD6eDYk88TJ5lJtyt58El-nYNip4UvnYIDJ2y6QNs,89088 -pip/_vendor/distlib/t64.exe,sha256=qDBQu9uPHCVdBFM6ANg-Xp9nc5Wz_iFnSmsCTvdEQec,97792 -pip/_vendor/distlib/util.py,sha256=1t4_TO0LcXzgWUQHv4OZrRmD2P-JrxX0TutY08L_11w,51518 -pip/_vendor/distlib/version.py,sha256=GeYZxzA0k6zytPBOC5R6RQiUWRoIR2arUrpwUejRUWo,23711 -pip/_vendor/distlib/w32.exe,sha256=LrnXXqK-Yb1tzS0lxymvQPiMlkQZWAB0eHM5jnL0mAk,85504 -pip/_vendor/distlib/w64.exe,sha256=GbKq4oBmzHZXdcpaLupKLenmQD7_DXsYX8PDPWo_U3M,94208 -pip/_vendor/distlib/wheel.py,sha256=xvaNt5tYH1qI--jo7mG7EQgHM8Gb3CxdWD3bpksy0QM,39043 -pip/_vendor/distlib/_backport/__init__.py,sha256=bqS_dTOH6uW9iGgd0uzfpPjo6vZ4xpPZ7kyfZJ2vNaw,274 -pip/_vendor/distlib/_backport/misc.py,sha256=KWecINdbFNOxSOP1fGF680CJnaC6S4fBRgEtaYTw0ig,971 -pip/_vendor/distlib/_backport/shutil.py,sha256=AUi8718iRoJ9K26mRi-rywtt8Gx7ykvrvbUbZszjfYE,25650 -pip/_vendor/distlib/_backport/sysconfig.cfg,sha256=swZKxq9RY5e9r3PXCrlvQPMsvOdiWZBTHLEbqS8LJLU,2617 -pip/_vendor/distlib/_backport/sysconfig.py,sha256=7WdYP0wbw8izH1eAEGNA-HXUyJrhzIAGK_LniUs4UNI,26958 -pip/_vendor/distlib/_backport/tarfile.py,sha256=bjyTNONZb-YEXrHFLExOSuagtSOoPaONP2UUoxwkAqE,92627 -pip/_vendor/html5lib/__init__.py,sha256=s_L7sZU8SZtyY1cYNdHuF0WcA21XDiojviES6MBjLC8,714 -pip/_vendor/html5lib/constants.py,sha256=B5LN2DMP-6lEp9wpON4ecX3Kx01n_cbMjuGd6AteixE,86873 -pip/_vendor/html5lib/html5parser.py,sha256=o9FOrhdLGYOtUhsueAsuXwduydagASvwxJ0lUpGYrYg,117347 -pip/_vendor/html5lib/ihatexml.py,sha256=MT12cVXAKaW-ALUkUeN175HpUP73xK8wAIpPzQ8cgfI,16581 -pip/_vendor/html5lib/inputstream.py,sha256=ss3wjtlObOVoVGWFsBztYdpnUqRaezyJ0sTXfdb4Ly4,31665 -pip/_vendor/html5lib/sanitizer.py,sha256=GR-Qc1OKabhKH7Z220fw2kaevU1jLpzBV3ii3a2M900,17660 -pip/_vendor/html5lib/tokenizer.py,sha256=6Uf8sDUkvNn661bcBSBYUCTfXzSs9EyCTiPcj5PAjYI,76929 -pip/_vendor/html5lib/utils.py,sha256=PSVv1ig9oAZa-DU16DT4cbbggnG7K3qQIkPm6uJKxFg,3267 -pip/_vendor/html5lib/filters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/html5lib/filters/_base.py,sha256=z-IU9ZAYjpsVsqmVt7kuWC63jR11hDMr6CVrvuao8W0,286 -pip/_vendor/html5lib/filters/alphabeticalattributes.py,sha256=fpRLbz6TCe5yXEkGmyMlJ80FekWsTR-sHk3Ano0U9LQ,624 -pip/_vendor/html5lib/filters/inject_meta_charset.py,sha256=xllv1I7unxhcyZTf3LTsv30wh2mAkT7wmTZx7zIhpuY,2746 -pip/_vendor/html5lib/filters/lint.py,sha256=8eJo0SXDcY40OhsNd0Cft36kUXCZ5t-30mNFSUf4LnE,4208 -pip/_vendor/html5lib/filters/optionaltags.py,sha256=4ozLwBgMRaxe7iqxefLQpDhp3irK7YHo9LgSGsvZYMw,10500 -pip/_vendor/html5lib/filters/sanitizer.py,sha256=MvGUs_v2taWPgGhjxswRSUiHfxrqMUhsNPz-eSeUYUQ,352 -pip/_vendor/html5lib/filters/whitespace.py,sha256=LbOUcC0zQ9z703KNZrArOr0kVBO7OMXjKjucDW32LU4,1142 -pip/_vendor/html5lib/serializer/__init__.py,sha256=xFXFP-inaTNlbnau5c5DGrH_O8yPm-C6HWbJxpiSqFE,490 -pip/_vendor/html5lib/serializer/htmlserializer.py,sha256=G-aVHmlR7uMR011jO0ev7sZvkVHpLr3OrLSYMZ7liVs,12855 -pip/_vendor/html5lib/treeadapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/html5lib/treeadapters/sax.py,sha256=3of4vvaUYIAic7pngebwJV24hpOS7Zg9ggJa_WQegy4,1661 -pip/_vendor/html5lib/treebuilders/__init__.py,sha256=Xz4X6B5DA1R-5GyRa44j0sJwfl6dUNyb0NBu9-7sK3U,3405 -pip/_vendor/html5lib/treebuilders/_base.py,sha256=Xf0FZVcVwIQS6tEseJdj5wKbYucbNCnbAsnsG4lONis,13711 -pip/_vendor/html5lib/treebuilders/dom.py,sha256=jvmtvnERtpxXpHvBgiq1FpzAUYAAzoolOTx_DoXwGEI,8469 -pip/_vendor/html5lib/treebuilders/etree.py,sha256=etbO6yQlyV46rWlj9mSyVqQOWrgoHgyJ01Tut4lWZkk,12621 -pip/_vendor/html5lib/treebuilders/etree_lxml.py,sha256=z3Bnfm2MstEEb_lbaAeicl5l-ab6MSQa5Q1ZZreK7Pc,14031 -pip/_vendor/html5lib/treewalkers/__init__.py,sha256=m2-4a5P4dMNlQb26MNIhgj69p6ms1i-JD2HPDr7iTfw,5766 -pip/_vendor/html5lib/treewalkers/_base.py,sha256=9nXtXtgubdWKFlKxhVzWarE0Hiv3T4VC7_Wt9ulVzB0,7014 -pip/_vendor/html5lib/treewalkers/dom.py,sha256=Lb63Nuz8HtgvkuuvSmU5LOyUkEtstH5saPPAg5xN4r8,1421 -pip/_vendor/html5lib/treewalkers/etree.py,sha256=dO_3d81tdFtjTTR4cCBMh5kB_BNNvqdT7GxrCBJ7IFM,4590 -pip/_vendor/html5lib/treewalkers/genshistream.py,sha256=IbBFrlgi-59-K7P1zm0d7ZFIknBN4c5E57PHJDkx39s,2278 -pip/_vendor/html5lib/treewalkers/lxmletree.py,sha256=am6t_JHh_Fpm10CaW-zDaGGsDwTPK3Pas7TRBezFs4w,5992 -pip/_vendor/html5lib/treewalkers/pulldom.py,sha256=9W6i8yWtUzayV6EwX-okVacttHaqpQZwdBCc2S3XeQ4,2302 -pip/_vendor/html5lib/trie/__init__.py,sha256=mec5zyJ5wIKRM8819gIcIsYQwncg91rEmPwGH1dG3Ho,212 -pip/_vendor/html5lib/trie/_base.py,sha256=WGY8SGptFmx4O0aKLJ54zrIQOoyuvhS0ngA36vAcIcc,927 -pip/_vendor/html5lib/trie/datrie.py,sha256=EQpqSfkZRuTbE-DuhW7xMdVDxdZNZ0CfmnYfHA_3zxM,1178 -pip/_vendor/html5lib/trie/py.py,sha256=wXmQLrZRf4MyWNyg0m3h81m9InhLR7GJ002mIIZh-8o,1775 -pip/_vendor/lockfile/__init__.py,sha256=tRsliCGxIGRfQ_OsAEoA70UatRbdIiVh0OZrYL_xIn0,9162 -pip/_vendor/lockfile/linklockfile.py,sha256=pLUQvtn6BLNfzEy5Vd_SH86mx5hO3XpVDu1xAdSeRaw,2649 -pip/_vendor/lockfile/mkdirlockfile.py,sha256=D5msAvl2kXtvGh5dhHf39eah-7KiZRsAPArRfWBAYm8,3098 -pip/_vendor/lockfile/pidlockfile.py,sha256=frwO5ouxdegU7mgFS-lOvUKIbq8STLc41hHWDiG9yAk,6221 -pip/_vendor/lockfile/sqlitelockfile.py,sha256=DXtqjbp4qFzbaAP6r8AqiCH7WBwl3NzfLwM1srC1ObM,5540 -pip/_vendor/lockfile/symlinklockfile.py,sha256=O1l2YuZs1RQuWGHRx4dyQ2Jkb4NSzKAxipS3vN5Chtw,2613 -pip/_vendor/packaging/__about__.py,sha256=YzdrW-1lWmyCBDyrcNkZbJo4tiDWXpoiqPjfyCYMzIE,1073 -pip/_vendor/packaging/__init__.py,sha256=2V8n-eEpSgBuXlV8hlMmhU7ZklpsrrusWMZNp2gC4Hs,906 -pip/_vendor/packaging/_compat.py,sha256=wofog8iYo_zudt_10i6JiXKHDs5GhCuXC09hCuSJiv4,1253 -pip/_vendor/packaging/_structures.py,sha256=93YvgrEE2HgFp8AdXy0pwCRVnZeutRHO_-puJ7T0cPw,1809 -pip/_vendor/packaging/specifiers.py,sha256=UV9T01_kKloA8PSeMI3HTYBSJ_4KLs00yLvrlciZ3yU,28079 -pip/_vendor/packaging/version.py,sha256=dEGrWZJZ6sef1xMxSfDCego2hS3Q86by0hUIFVk-AGc,11949 -pip/_vendor/pkg_resources/__init__.py,sha256=XxyhKV_SdPpFlALmKOe4g4jkrgn6rWx21THQP4-nZQI,106466 -pip/_vendor/progress/__init__.py,sha256=Wn1074LUDZovd4zfoVYojnPBgOc6ctHbQX7rp_p8lRA,3023 -pip/_vendor/progress/bar.py,sha256=bH72DehBggOGvZsv4839W2p-981_AOSC8e7ZihxQ3gU,2707 -pip/_vendor/progress/counter.py,sha256=UZcnk68HkBOCRjz25W8MmHY-ev2BGn-sYWsR-iSfQds,1529 -pip/_vendor/progress/helpers.py,sha256=aPoo84DShYXFe2Aqwm9Wj-gt3Lj9BJY9-bwC4C2c2II,2894 -pip/_vendor/progress/spinner.py,sha256=LRVxxpM1-EZ5JJe-yYriiHWPTYZnaYUxsbxyFWQVOQc,1341 -pip/_vendor/requests/__init__.py,sha256=3TJHLc9RZ_3QCQYiP0r9lshzLMIdLm1gn0wVwNqaZmg,1861 -pip/_vendor/requests/adapters.py,sha256=MEedP-slXqxDnYdi4JxuCE3y2NTizShvL_SfP3ncge4,16810 -pip/_vendor/requests/api.py,sha256=X8Znh82s62_3FBPFkqafNQn7s4L-5q8-GLclLKKHs3I,5415 -pip/_vendor/requests/auth.py,sha256=pD2td_DoHl-YWQQITk5ZPSKjsR5_sBxRkseYMx1n704,6794 -pip/_vendor/requests/cacert.pem,sha256=ak7q_q8ozHdQ9ff27U-E1vCNrLisFRQSMy9zJkdpQlM,308434 -pip/_vendor/requests/certs.py,sha256=RX5H1cSiB52Hbjh_qv3eMW8hqHEF_r4Qiv_4AwfziuU,613 -pip/_vendor/requests/compat.py,sha256=hq7CKHoykNs8yzKPAJiOkHQJPoNp9A89MufTdhlCniY,1469 -pip/_vendor/requests/cookies.py,sha256=Um1lXApUUO0-P6U1TOudXu1cYVXBFN77f16OFxiIAt8,17191 -pip/_vendor/requests/exceptions.py,sha256=zZhHieXgR1teqbvuo_9OrwDMHnrvRtulW97VfzumQv4,2517 -pip/_vendor/requests/hooks.py,sha256=9vNiuiRHRd5Qy6BX_0p1H3NsUzDo1M_HaFR2AFL41Tg,820 -pip/_vendor/requests/models.py,sha256=_vxB3Z3QDkV_HYcZFqFrPq31TmworMeYEM094Q9Vf00,29176 -pip/_vendor/requests/sessions.py,sha256=kWfupbWN_Uhu-FKPEc7y1NyvyQNE5jryuA5Uad2Yy0U,24250 -pip/_vendor/requests/status_codes.py,sha256=DVA33t4UthIiZhP4iYSChbWjuhrJWvVA04qle9nwj2Q,3200 -pip/_vendor/requests/structures.py,sha256=i3yMaaDbl4_gNJKdcK3kDmeSLoo0r59XEIWoc_qtNyo,2977 -pip/_vendor/requests/utils.py,sha256=yh5am9D9nG_oAYyYU2upkXIth2QOi1LJhiHSx5dSVbw,21334 -pip/_vendor/requests/packages/__init__.py,sha256=aXkbNCjM_WhryRBocE4AaA_p7-CTxL5LOutY7XzKm4s,62 -pip/_vendor/requests/packages/chardet/__init__.py,sha256=XuTKCYOR7JwsoHxqZTYH86LVyMDbDI3s1s0W_qoGEBM,1295 -pip/_vendor/requests/packages/chardet/big5freq.py,sha256=D8oTdz-GM7Jg8TsaWJDm65vM_OLHC3xub6qUJ3rOgsQ,82594 -pip/_vendor/requests/packages/chardet/big5prober.py,sha256=XX96C--6WKYW36mL-z7pJSAtc169Z8ZImByCP4pEN9A,1684 -pip/_vendor/requests/packages/chardet/chardetect.py,sha256=f4299UZG6uWd3i3r_N0OdrFj2sA9JFI54PAmDLAFmWA,2504 -pip/_vendor/requests/packages/chardet/chardistribution.py,sha256=cUARQFr1oTLXeJCDQrDRkUP778AvSMzhSCnG8VLCV58,9226 -pip/_vendor/requests/packages/chardet/charsetgroupprober.py,sha256=0lKk7VE516fgMw119tNefFqLOxKfIE9WfdkpIT69OKU,3791 -pip/_vendor/requests/packages/chardet/charsetprober.py,sha256=Z48o2KiOj23FNqYH8FqzhH5m1qdm3rI8DcTm2Yqtklg,1902 -pip/_vendor/requests/packages/chardet/codingstatemachine.py,sha256=E85rYhHVMw9xDEJVgiQhp0OnLGr6i2r8_7QOWMKTH08,2318 -pip/_vendor/requests/packages/chardet/compat.py,sha256=5mm6yrHwef1JEG5OxkPJlSq5lkjLVpEGh3iPgFBkpkM,1157 -pip/_vendor/requests/packages/chardet/constants.py,sha256=-UnY8U7EP7z9fTyd09yq35BEkSFEAUAiv9ohd1DW1s4,1335 -pip/_vendor/requests/packages/chardet/cp949prober.py,sha256=FMvdLyB7fejPXRsTbca7LK1P3RUvvssmjUNyaEfz8zY,1782 -pip/_vendor/requests/packages/chardet/escprober.py,sha256=q5TcQKeVq31WxrW7Sv8yjpZkjEoaHO8S92EJZ9hodys,3187 -pip/_vendor/requests/packages/chardet/escsm.py,sha256=7iljEKN8lXTh8JFXPUSwlibMno6R6ksq4evLxbkzfro,7839 -pip/_vendor/requests/packages/chardet/eucjpprober.py,sha256=5IpfSEjAb7h3hcGMd6dkU80O900C2N6xku28rdYFKuc,3678 -pip/_vendor/requests/packages/chardet/euckrfreq.py,sha256=T5saK5mImySG5ygQPtsp6o2uKulouCwYm2ElOyFkJqU,45978 -pip/_vendor/requests/packages/chardet/euckrprober.py,sha256=Wo7dnZ5Erw_nB4H-m5alMiOxOuJUmGHlwCSaGqExDZA,1675 -pip/_vendor/requests/packages/chardet/euctwfreq.py,sha256=G_I0BW9i1w0ONeeUwIYqV7_U09buIHdqh-wNHVaql7I,34872 -pip/_vendor/requests/packages/chardet/euctwprober.py,sha256=upS2P6GuT5ujOxXYw-RJLcT7A4PTuo27KGUKU4UZpIQ,1676 -pip/_vendor/requests/packages/chardet/gb2312freq.py,sha256=M2gFdo_qQ_BslStEchrPW5CrPEZEacC0uyDLw4ok-kY,36011 -pip/_vendor/requests/packages/chardet/gb2312prober.py,sha256=VWnjoRa83Y6V6oczMaxyUr0uy48iCnC2nzk9zfEIRHc,1681 -pip/_vendor/requests/packages/chardet/hebrewprober.py,sha256=8pdoUfsVXf_L4BnJde_BewS6H2yInV5688eu0nFhLHY,13359 -pip/_vendor/requests/packages/chardet/jisfreq.py,sha256=ZcL4R5ekHHbP2KCYGakVMBsiKqZZZAABzhwi-uRkOps,47315 -pip/_vendor/requests/packages/chardet/jpcntx.py,sha256=yftmp0QaF6RJO5SJs8I7LU5AF4rwP23ebeCQL4BM1OY,19348 -pip/_vendor/requests/packages/chardet/langbulgarianmodel.py,sha256=ZyPsA796MSVhYdfWhMCgKWckupAKAnKqWcE3Cl3ej6o,12784 -pip/_vendor/requests/packages/chardet/langcyrillicmodel.py,sha256=fkcd5OvogUp-GrNDWAZPgkYsSRCD2omotAEvqjlmLKE,17725 -pip/_vendor/requests/packages/chardet/langgreekmodel.py,sha256=QHMy31CH_ot67UCtmurCEKqKx2WwoaKrw2YCYYBK2Lw,12628 -pip/_vendor/requests/packages/chardet/langhebrewmodel.py,sha256=4ASl5vzKJPng4H278VHKtRYC03TpQpenlHTcsmZH1rE,11318 -pip/_vendor/requests/packages/chardet/langhungarianmodel.py,sha256=SXwuUzh49_cBeMXhshRHdrhlkz0T8_pZWV_pdqBKNFk,12536 -pip/_vendor/requests/packages/chardet/langthaimodel.py,sha256=-k7djh3dGKngAGnt3WfuoJN7acDcWcmHAPojhaUd7q4,11275 -pip/_vendor/requests/packages/chardet/latin1prober.py,sha256=238JHOxH8aRudJY2NmeSv5s7i0Qe3GuklIU3HlYybvg,5232 -pip/_vendor/requests/packages/chardet/mbcharsetprober.py,sha256=9rOCjDVsmSMp6e7q2syqak22j7lrbUZhJhMee2gbVL0,3268 -pip/_vendor/requests/packages/chardet/mbcsgroupprober.py,sha256=SHRzNPLpDXfMJLA8phCHVU0WgqbgDCNxDQMolGX_7yk,1967 -pip/_vendor/requests/packages/chardet/mbcssm.py,sha256=IKwJXyxu34n6NojmxVxC60MLFtJKm-hIfxaFEnb3uBA,19590 -pip/_vendor/requests/packages/chardet/sbcharsetprober.py,sha256=Xq0lODqJnDgxglBiQI4BqTFiPbn63-0a5XNA5-hVu7U,4793 -pip/_vendor/requests/packages/chardet/sbcsgroupprober.py,sha256=8hLyH8RAG-aohBo7o_KciWVgRo42ZE_zEtuNG1JMRYI,3291 -pip/_vendor/requests/packages/chardet/sjisprober.py,sha256=UYOmiMDzttYIkSDoOB08UEagivJpUXz4tuWiWzTiOr8,3764 -pip/_vendor/requests/packages/chardet/universaldetector.py,sha256=h-E2x6XSCzlNjycYWG0Fe4Cf1SGdaIzUNu2HCphpMZA,6840 -pip/_vendor/requests/packages/chardet/utf8prober.py,sha256=7tdNZGrJY7jZUBD483GGMkiP0Tx8Fp-cGvWHoAsilHg,2652 -pip/_vendor/requests/packages/urllib3/__init__.py,sha256=WdpCLx5juBoMArBMbVT125BD8SvK-Id9Js57PTnpfSs,2055 -pip/_vendor/requests/packages/urllib3/_collections.py,sha256=tatXHmN5An3gw-alS68qs3yO_vweJ8eFTUmwMXvlKpQ,10454 -pip/_vendor/requests/packages/urllib3/connection.py,sha256=uqwsV351AZqV008fb7OscFbyZt6dRicjQQrUA0K01iw,9011 -pip/_vendor/requests/packages/urllib3/connectionpool.py,sha256=kGlpxwc2lRax0J7f2tFVWjXefCIdIWyLHqHDa6amN7A,30319 -pip/_vendor/requests/packages/urllib3/exceptions.py,sha256=za-cEwBqxBKOqqKTaIVAMdH3j1nDRqi-MtdojdpU4Wc,4374 -pip/_vendor/requests/packages/urllib3/fields.py,sha256=06XgBjTvEyVYUWA-j_6zhnfXMpd-IxZdzT85ppAFfYg,5833 -pip/_vendor/requests/packages/urllib3/filepost.py,sha256=TEpQ_PMO0loPQERLr4E7VcgbMfhNwOCxt8cudhrpkM0,2281 -pip/_vendor/requests/packages/urllib3/poolmanager.py,sha256=Qw1UStRXPh6RH5BOT7x4NY7Gqkho2njYEDiqk9_8728,9406 -pip/_vendor/requests/packages/urllib3/request.py,sha256=NjnLVqcKZVotmPV335m87AqMFBSH0V_ml2tOGxKSKRI,5751 -pip/_vendor/requests/packages/urllib3/response.py,sha256=t4Pl6JVQ9jYXbriu0cQf5dRuRSpxSP9YltgMu35JFPo,16459 -pip/_vendor/requests/packages/urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/requests/packages/urllib3/contrib/ntlmpool.py,sha256=F29BjpIMId2u9Bwmy0bmg8eDYKvQZiXLsZeK2cDNctQ,4507 -pip/_vendor/requests/packages/urllib3/contrib/pyopenssl.py,sha256=ooNMMfp9cEirGyLRcIE-f-qidQPdDp2kBl-K5ALOJyU,9326 -pip/_vendor/requests/packages/urllib3/packages/__init__.py,sha256=EKCTAOjZtPR_HC50e7X8hS5j4bkFkN87XZOT-Wdpfus,74 -pip/_vendor/requests/packages/urllib3/packages/ordered_dict.py,sha256=VQaPONfhVMsb8B63Xg7ZOydJqIE_jzeMhVN3Pec6ogw,8935 -pip/_vendor/requests/packages/urllib3/packages/six.py,sha256=U-rO-WBrFS8PxHeamSl6okKCjqPF18NhiZb0qPZ67XM,11628 -pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py,sha256=cOWMIn1orgJoA35p6pSzO_-Dc6iOX9Dhl6D2sL9b_2o,460 -pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/_implementation.py,sha256=fK28k37hL7-D79v9iM2fHgNK9Q1Pw0M7qVRL4rkfFjQ,3778 -pip/_vendor/requests/packages/urllib3/util/__init__.py,sha256=zrB1BFTNOUWxgEVvZlicK8uEU2AVpT1TFmWo2gQGfDA,486 -pip/_vendor/requests/packages/urllib3/util/connection.py,sha256=PTxckPfstrFVAPAfYn12kaZYEfoQn-CDCo2VrIBPtpo,3293 -pip/_vendor/requests/packages/urllib3/util/request.py,sha256=zY2x5tBXzvgLWgF3XRk_CEk-X8Q8L9bqpESqWn13I_0,2089 -pip/_vendor/requests/packages/urllib3/util/response.py,sha256=QMrOy69WPkoe42EU0Y5jwRNqBf-w1FF8GJWAx1jQDmY,566 -pip/_vendor/requests/packages/urllib3/util/retry.py,sha256=bcRb3QC1LDMHLx8gBDDGFqZ3dKs6bYcpfWZJ3FpOMtE,9924 -pip/_vendor/requests/packages/urllib3/util/ssl_.py,sha256=X4mp-FA-Jact7Z3sEzxenQ69Jnwlz2-G7gjJXL1CMdw,10037 -pip/_vendor/requests/packages/urllib3/util/timeout.py,sha256=2MqJVD_v_0tLxgm2Mr_ePqYmfnB5zjZXphlIexWocKM,9544 -pip/_vendor/requests/packages/urllib3/util/url.py,sha256=uPcy_lCMdmQhdofnemWyjYjHsPJaZ0VisANa2vaCr3g,5836 -pip/commands/__init__.py,sha256=7nn4pesggkyBI_yFJJkNhqRsbhX4hft582u2G7QTOaI,2007 -pip/commands/completion.py,sha256=7JkLif3DF0QGpjMaUjHvF8knJ3IumcED2gWRvMRpFy0,1991 -pip/commands/freeze.py,sha256=_wHnuHYXC4V0zBLD7LfDhgI_bWL6KdcCgzzQ9bXwDkU,2330 -pip/commands/help.py,sha256=84HWkEdnGP_AEBHnn8gJP2Te0XTXRKFoXqXopbOZTNo,982 -pip/commands/install.py,sha256=PIHF8rHRTYFeeSfYeWjKA93ewIo2PQd5eO6-WkHb2gs,14659 -pip/commands/list.py,sha256=ixgoudq7aPf1KVQO2BayACsb-EfF_8BxAnDF83gH_m4,7251 -pip/commands/search.py,sha256=zOrBophzW_s_gHMFAqibWz-jlLu-lPh08NIbR-8fDOU,4604 -pip/commands/show.py,sha256=5B7ky8SBNLy5mFMyXf2ethe6zQQ_Plr2h8GDWNaeEk8,4974 -pip/commands/uninstall.py,sha256=tz8cXz4WdpUdnt3RvpdQwH6_SNMB50egBIZWa1dwfcc,2884 -pip/commands/wheel.py,sha256=WCafM_PGHxi3AQbifEBJ72wVsA32EjLu0_ATPv0iGJs,7442 -pip/compat/__init__.py,sha256=NmhcnJOm7-4SXCJBntzgxQLSi4tep4qP-ltm8AL8jT8,3402 -pip/compat/dictconfig.py,sha256=dRrelPDWrceDSzFT51RTEVY2GuM7UDyc5Igh_tn4Fvk,23096 -pip/models/__init__.py,sha256=0Rs7_RA4DxeOkWT5Cq4CQzDrSEhvYcN3TH2cazr72PE,71 -pip/models/index.py,sha256=pUfbO__v3mD9j-2n_ClwPS8pVyx4l2wIwyvWt8GMCRA,487 -pip/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/operations/freeze.py,sha256=em8Vw1C2hZ9aVfSGyIVEEQp5KKzRByw4twFWvbEN5Es,3984 -pip/req/__init__.py,sha256=vFwZY8_Vc1WU1zFAespg1My_r_AT3n7cN0W9eX0EFqk,276 -pip/req/req_file.py,sha256=UYkZHztKkDjANbjm8G5InoMZgiW_5R3cxPpuieFz5RQ,9670 -pip/req/req_install.py,sha256=L0gocWgopzIJ3qmXaD9_ECP0UQPXDMFKfnFIp1_rkf0,43096 -pip/req/req_set.py,sha256=ZTemgzstHr8wgmh2ZYk-rQnM99vRe0cN1zK-4KdK3Nc,27444 -pip/req/req_uninstall.py,sha256=r6p9H6EIJheSbi9inIV8iCWerwmVFBLpAU4rM30wa84,7135 -pip/utils/__init__.py,sha256=ws5g9s8zaq2GyXhGZqZ43OM9sZdG49q9ZuGbWslxpjY,26814 -pip/utils/appdirs.py,sha256=DsdEjHfkFGNJ7NmDR_SWQ0PzOXZdyqDzHVN673mLq9o,9173 -pip/utils/build.py,sha256=4smLRrfSCmXmjEnVnMFh2tBEpNcSLRe6J0ejZJ-wWJE,1312 -pip/utils/deprecation.py,sha256=PtwQegNjDSmeT_m65pdcvnKEktTpb5AJvey6l3P6mQI,2152 -pip/utils/filesystem.py,sha256=ZEVBuYM3fqr2_lgOESh4Y7fPFszGD474zVm_M3Mb5Tk,899 -pip/utils/logging.py,sha256=b3wtkeCjcA2YOuAVrPYDFhTL77Hb6LeNMCoSD_Ql1fA,3326 -pip/utils/outdated.py,sha256=sXrNapTD6NXdM9J3I11idYyDm7eXzobbGzb_URPrxpY,5555 -pip/utils/ui.py,sha256=gu7HI4bZ0EeloxhA-CL2ngIVXaN7_-T1erwNOR8M-sM,6774 -pip/vcs/__init__.py,sha256=n_2XKQyjdzLyOJt2pWtlsqXTynp2rI48iN4s_cUJMkI,11760 -pip/vcs/bazaar.py,sha256=ecV1QSNSwEeyFx4H_xPBc2NgCGrhUymVoLszaV5rnUo,4427 -pip/vcs/git.py,sha256=ZlgvRMiionvjFMC1tBpNcPTWOtx1ffRI_e_UTTulu7M,7608 -pip/vcs/mercurial.py,sha256=apGLpsxPSzQkxRxcKINy_C0whu09rkyrbMIfpPfenuo,4974 -pip/vcs/subversion.py,sha256=GvWew87FkTjQQZVnqqUURxPpXufJPfZBmLxXmIHq8SI,10468 -pip-7.1.2.dist-info/DESCRIPTION.rst,sha256=j7Go_0V5jh4mpRZT2o6GGv7Y7bg-DTE6z7Eh64RTcpw,829 -pip-7.1.2.dist-info/entry_points.txt,sha256=1-e4WB_Fe8mWHrMi1YQo_s5knbh0lu_uRmd8Wb6MJfY,68 -pip-7.1.2.dist-info/METADATA,sha256=WKp4C4pXRDMfb5mPhvFcz2gxvcs9g4jWeFFVdO9zmi4,1981 -pip-7.1.2.dist-info/metadata.json,sha256=m-R1CYUzmjj2tKdOtkEgCi6A74oiAUasrtVmpc0g89U,1491 -pip-7.1.2.dist-info/pbr.json,sha256=T9ZxpJEDJEZSD8LQIg_YHJkZSDL0mkKU8sE-cBzvkMc,46 -pip-7.1.2.dist-info/RECORD,, -pip-7.1.2.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -pip-7.1.2.dist-info/WHEEL,sha256=AvR0WeTpDaxT645bl5FQxUK6NPsTls2ttpcGJg3j1Xg,110 -/Volumes/Internal10/Development/p4d/virtualenv/bin/pip,sha256=QlPDdBXVOlTdXQr8MwFVStkPmsy37K6SPgJofXotJXg,249 -/Volumes/Internal10/Development/p4d/virtualenv/bin/pip3,sha256=QlPDdBXVOlTdXQr8MwFVStkPmsy37K6SPgJofXotJXg,249 -/Volumes/Internal10/Development/p4d/virtualenv/bin/pip3.5,sha256=QlPDdBXVOlTdXQr8MwFVStkPmsy37K6SPgJofXotJXg,249 -pip/_vendor/html5lib/filters/__pycache__/_base.cpython-35.pyc,, -pip/_vendor/requests/__pycache__/utils.cpython-35.pyc,, -pip/_vendor/lockfile/__pycache__/linklockfile.cpython-35.pyc,, -pip/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/util/__pycache__/ssl_.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/sbcsgroupprober.cpython-35.pyc,, -pip/_vendor/html5lib/serializer/__pycache__/htmlserializer.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/connection.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/langcyrillicmodel.cpython-35.pyc,, -pip/_vendor/requests/__pycache__/certs.cpython-35.pyc,, -pip/_vendor/distlib/__pycache__/index.cpython-35.pyc,, -pip/commands/__pycache__/list.cpython-35.pyc,, -pip/vcs/__pycache__/subversion.cpython-35.pyc,, -pip/commands/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/chardetect.cpython-35.pyc,, -pip/__pycache__/__main__.cpython-35.pyc,, -pip/_vendor/packaging/__pycache__/_structures.cpython-35.pyc,, -pip/_vendor/__pycache__/re-vendor.cpython-35.pyc,, -pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/sjisprober.cpython-35.pyc,, -pip/_vendor/distlib/_backport/__pycache__/shutil.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/langhungarianmodel.cpython-35.pyc,, -pip/_vendor/distlib/_backport/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/html5lib/__pycache__/html5parser.cpython-35.pyc,, -pip/_vendor/packaging/__pycache__/version.cpython-35.pyc,, -pip/_vendor/html5lib/treebuilders/__pycache__/dom.cpython-35.pyc,, -pip/_vendor/packaging/__pycache__/specifiers.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/jisfreq.cpython-35.pyc,, -pip/__pycache__/baseparser.cpython-35.pyc,, -pip/_vendor/html5lib/__pycache__/sanitizer.cpython-35.pyc,, -pip/req/__pycache__/req_uninstall.cpython-35.pyc,, -pip/_vendor/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/util/__pycache__/connection.cpython-35.pyc,, -pip/_vendor/packaging/__pycache__/__init__.cpython-35.pyc,, -pip/compat/__pycache__/__init__.cpython-35.pyc,, -pip/compat/__pycache__/dictconfig.cpython-35.pyc,, -pip/_vendor/html5lib/filters/__pycache__/whitespace.cpython-35.pyc,, -pip/_vendor/html5lib/filters/__pycache__/inject_meta_charset.cpython-35.pyc,, -pip/_vendor/requests/packages/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/distlib/__pycache__/version.cpython-35.pyc,, -pip/_vendor/html5lib/filters/__pycache__/optionaltags.cpython-35.pyc,, -pip/__pycache__/status_codes.cpython-35.pyc,, -pip/_vendor/requests/__pycache__/models.cpython-35.pyc,, -pip/_vendor/requests/__pycache__/adapters.cpython-35.pyc,, -pip/_vendor/html5lib/__pycache__/constants.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/packages/__pycache__/ordered_dict.cpython-35.pyc,, -pip/_vendor/html5lib/trie/__pycache__/_base.cpython-35.pyc,, -pip/_vendor/progress/__pycache__/counter.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/latin1prober.cpython-35.pyc,, -pip/_vendor/distlib/__pycache__/util.cpython-35.pyc,, -pip/_vendor/html5lib/treewalkers/__pycache__/lxmletree.cpython-35.pyc,, -pip/_vendor/lockfile/__pycache__/mkdirlockfile.cpython-35.pyc,, -pip/models/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/progress/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/requests/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/cp949prober.cpython-35.pyc,, -pip/_vendor/html5lib/treewalkers/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/html5lib/serializer/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/big5freq.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/filepost.cpython-35.pyc,, -pip/_vendor/pkg_resources/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/html5lib/treewalkers/__pycache__/etree.cpython-35.pyc,, -pip/utils/__pycache__/filesystem.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/util/__pycache__/retry.cpython-35.pyc,, -pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/contrib/__pycache__/pyopenssl.cpython-35.pyc,, -pip/_vendor/packaging/__pycache__/_compat.cpython-35.pyc,, -pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-35.pyc,, -pip/utils/__pycache__/outdated.cpython-35.pyc,, -pip/utils/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/html5lib/trie/__pycache__/py.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/util/__pycache__/response.cpython-35.pyc,, -pip/__pycache__/wheel.cpython-35.pyc,, -pip/vcs/__pycache__/__init__.cpython-35.pyc,, -pip/utils/__pycache__/logging.cpython-35.pyc,, -pip/req/__pycache__/req_install.cpython-35.pyc,, -pip/models/__pycache__/index.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/response.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/langthaimodel.cpython-35.pyc,, -pip/_vendor/colorama/__pycache__/ansitowin32.cpython-35.pyc,, -pip/utils/__pycache__/build.cpython-35.pyc,, -pip/operations/__pycache__/freeze.cpython-35.pyc,, -pip/__pycache__/exceptions.cpython-35.pyc,, -pip/_vendor/requests/__pycache__/status_codes.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/langhebrewmodel.cpython-35.pyc,, -pip/_vendor/html5lib/treewalkers/__pycache__/pulldom.cpython-35.pyc,, -pip/_vendor/requests/__pycache__/cookies.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/connectionpool.cpython-35.pyc,, -pip/__pycache__/index.cpython-35.pyc,, -pip/_vendor/distlib/__pycache__/scripts.cpython-35.pyc,, -pip/_vendor/distlib/_backport/__pycache__/tarfile.cpython-35.pyc,, -pip/_vendor/__pycache__/six.cpython-35.pyc,, -pip/_vendor/distlib/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/_markerlib/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/distlib/__pycache__/wheel.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/hebrewprober.cpython-35.pyc,, -pip/_vendor/html5lib/__pycache__/utils.cpython-35.pyc,, -pip/vcs/__pycache__/git.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/escprober.cpython-35.pyc,, -pip/_vendor/lockfile/__pycache__/symlinklockfile.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/compat.cpython-35.pyc,, -pip/commands/__pycache__/install.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/euckrprober.cpython-35.pyc,, -pip/_vendor/__pycache__/retrying.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/__pycache__/_implementation.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/constants.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/poolmanager.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/__pycache__/__init__.cpython-35.pyc,, -pip/utils/__pycache__/appdirs.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/packages/__pycache__/six.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/euctwprober.cpython-35.pyc,, -pip/_vendor/distlib/__pycache__/markers.cpython-35.pyc,, -pip/commands/__pycache__/search.cpython-35.pyc,, -pip/_vendor/html5lib/__pycache__/ihatexml.cpython-35.pyc,, -pip/vcs/__pycache__/mercurial.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/charsetprober.cpython-35.pyc,, -pip/_vendor/distlib/__pycache__/resources.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/util/__pycache__/request.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/mbcsgroupprober.cpython-35.pyc,, -pip/__pycache__/basecommand.cpython-35.pyc,, -pip/req/__pycache__/req_set.cpython-35.pyc,, -pip/commands/__pycache__/freeze.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/packages/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/util/__pycache__/timeout.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/sbcharsetprober.cpython-35.pyc,, -pip/_vendor/lockfile/__pycache__/pidlockfile.cpython-35.pyc,, -pip/_vendor/html5lib/treewalkers/__pycache__/dom.cpython-35.pyc,, -pip/_vendor/html5lib/filters/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/cachecontrol/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/_markerlib/__pycache__/markers.cpython-35.pyc,, -pip/_vendor/html5lib/treewalkers/__pycache__/genshistream.cpython-35.pyc,, -pip/_vendor/html5lib/filters/__pycache__/lint.cpython-35.pyc,, -pip/req/__pycache__/req_file.cpython-35.pyc,, -pip/_vendor/distlib/__pycache__/database.cpython-35.pyc,, -pip/_vendor/colorama/__pycache__/ansi.cpython-35.pyc,, -pip/_vendor/colorama/__pycache__/initialise.cpython-35.pyc,, -pip/_vendor/lockfile/__pycache__/sqlitelockfile.cpython-35.pyc,, -pip/operations/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/lockfile/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/html5lib/__pycache__/tokenizer.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/codingstatemachine.cpython-35.pyc,, -pip/__pycache__/cmdoptions.cpython-35.pyc,, -pip/_vendor/distlib/__pycache__/metadata.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/universaldetector.cpython-35.pyc,, -pip/_vendor/cachecontrol/__pycache__/cache.cpython-35.pyc,, -pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-35.pyc,, -pip/_vendor/html5lib/treeadapters/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/html5lib/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/cachecontrol/__pycache__/controller.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/_collections.cpython-35.pyc,, -pip/_vendor/requests/__pycache__/sessions.cpython-35.pyc,, -pip/_vendor/distlib/__pycache__/compat.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/langgreekmodel.cpython-35.pyc,, -pip/commands/__pycache__/help.cpython-35.pyc,, -pip/_vendor/html5lib/treebuilders/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/requests/__pycache__/hooks.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/euckrfreq.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/eucjpprober.cpython-35.pyc,, -pip/__pycache__/download.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/request.cpython-35.pyc,, -pip/_vendor/requests/__pycache__/api.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/gb2312freq.cpython-35.pyc,, -pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-35.pyc,, -pip/_vendor/distlib/__pycache__/locators.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/chardistribution.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/contrib/__pycache__/ntlmpool.cpython-35.pyc,, -pip/_vendor/html5lib/__pycache__/inputstream.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/gb2312prober.cpython-35.pyc,, -pip/_vendor/colorama/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/exceptions.cpython-35.pyc,, -pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-35.pyc,, -pip/commands/__pycache__/show.cpython-35.pyc,, -pip/commands/__pycache__/wheel.cpython-35.pyc,, -pip/_vendor/colorama/__pycache__/winterm.cpython-35.pyc,, -pip/commands/__pycache__/completion.cpython-35.pyc,, -pip/_vendor/cachecontrol/__pycache__/adapter.cpython-35.pyc,, -pip/_vendor/html5lib/filters/__pycache__/sanitizer.cpython-35.pyc,, -pip/__pycache__/pep425tags.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/big5prober.cpython-35.pyc,, -pip/_vendor/requests/__pycache__/exceptions.cpython-35.pyc,, -pip/_vendor/cachecontrol/__pycache__/serialize.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/util/__pycache__/url.cpython-35.pyc,, -pip/_vendor/progress/__pycache__/spinner.cpython-35.pyc,, -pip/_vendor/cachecontrol/__pycache__/compat.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/utf8prober.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/util/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/distlib/_backport/__pycache__/misc.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/euctwfreq.cpython-35.pyc,, -pip/utils/__pycache__/deprecation.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/mbcssm.cpython-35.pyc,, -pip/_vendor/html5lib/filters/__pycache__/alphabeticalattributes.cpython-35.pyc,, -pip/_vendor/html5lib/trie/__pycache__/__init__.cpython-35.pyc,, -pip/__pycache__/locations.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/mbcharsetprober.cpython-35.pyc,, -pip/_vendor/html5lib/treebuilders/__pycache__/_base.cpython-35.pyc,, -pip/_vendor/requests/__pycache__/structures.cpython-35.pyc,, -pip/_vendor/__pycache__/ipaddress.cpython-35.pyc,, -pip/_vendor/packaging/__pycache__/__about__.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/charsetgroupprober.cpython-35.pyc,, -pip/utils/__pycache__/ui.cpython-35.pyc,, -pip/commands/__pycache__/uninstall.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/langbulgarianmodel.cpython-35.pyc,, -pip/req/__pycache__/__init__.cpython-35.pyc,, -pip/_vendor/html5lib/treewalkers/__pycache__/_base.cpython-35.pyc,, -pip/_vendor/html5lib/trie/__pycache__/datrie.cpython-35.pyc,, -pip/_vendor/requests/__pycache__/compat.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/jpcntx.cpython-35.pyc,, -pip/vcs/__pycache__/bazaar.cpython-35.pyc,, -pip/_vendor/progress/__pycache__/helpers.cpython-35.pyc,, -pip/_vendor/progress/__pycache__/bar.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/__pycache__/fields.cpython-35.pyc,, -pip/_vendor/requests/packages/chardet/__pycache__/escsm.cpython-35.pyc,, -pip/_vendor/html5lib/treeadapters/__pycache__/sax.cpython-35.pyc,, -pip/_vendor/distlib/__pycache__/manifest.cpython-35.pyc,, -pip/_vendor/html5lib/treebuilders/__pycache__/etree.cpython-35.pyc,, -pip/_vendor/html5lib/treebuilders/__pycache__/etree_lxml.cpython-35.pyc,, -pip/_vendor/requests/__pycache__/auth.cpython-35.pyc,, -pip/_vendor/colorama/__pycache__/win32.cpython-35.pyc,, -pip/_vendor/requests/packages/urllib3/contrib/__pycache__/__init__.cpython-35.pyc,, diff --git a/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/WHEEL b/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/WHEEL deleted file mode 100644 index 9dff69d..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.24.0) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/entry_points.txt b/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/entry_points.txt deleted file mode 100644 index a237b5e..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/entry_points.txt +++ /dev/null @@ -1,5 +0,0 @@ -[console_scripts] -pip = pip:main -pip3 = pip:main -pip3.4 = pip:main - diff --git a/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/metadata.json b/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/metadata.json deleted file mode 100644 index 0fb0c09..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/metadata.json +++ /dev/null @@ -1 +0,0 @@ -{"extensions": {"python.details": {"project_urls": {"Home": "https://pip.pypa.io/"}, "contacts": [{"name": "The pip developers", "email": "python-virtualenv@groups.google.com", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}}, "python.commands": {"wrap_console": {"pip3": "pip:main", "pip3.4": "pip:main", "pip": "pip:main"}}, "python.exports": {"console_scripts": {"pip3": "pip:main", "pip3.4": "pip:main", "pip": "pip:main"}}}, "version": "7.1.2", "name": "pip", "license": "MIT", "classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Topic :: Software Development :: Build Tools", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: Implementation :: PyPy"], "extras": ["testing"], "summary": "The PyPA recommended tool for installing Python packages.", "generator": "bdist_wheel (0.24.0)", "keywords": ["easy_install", "distutils", "setuptools", "egg", "virtualenv"], "metadata_version": "2.0", "run_requires": [{"extra": "testing", "requires": ["pytest", "virtualenv (>=1.10)", "scripttest (>=1.3)", "mock"]}], "test_requires": [{"requires": ["pytest", "virtualenv (>=1.10)", "scripttest (>=1.3)", "mock"]}]} \ No newline at end of file diff --git a/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/pbr.json b/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/pbr.json deleted file mode 100644 index 3856fa5..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/pbr.json +++ /dev/null @@ -1 +0,0 @@ -{"is_release": true, "git_version": "78daccc"} \ No newline at end of file diff --git a/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/top_level.txt b/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/top_level.txt deleted file mode 100644 index a1b589e..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip-7.1.2.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/virtualenv/lib/python3.5/site-packages/pip/__init__.py b/virtualenv/lib/python3.5/site-packages/pip/__init__.py deleted file mode 100644 index 114bd59..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/__init__.py +++ /dev/null @@ -1,315 +0,0 @@ -#!/usr/bin/env python -from __future__ import absolute_import - -import logging -import os -import optparse -import warnings - -import sys -import re - -from pip.exceptions import InstallationError, CommandError, PipError -from pip.utils import get_installed_distributions, get_prog -from pip.utils import deprecation -from pip.vcs import git, mercurial, subversion, bazaar # noqa -from pip.baseparser import ConfigOptionParser, UpdatingDefaultsHelpFormatter -from pip.commands import get_summaries, get_similar_commands -from pip.commands import commands_dict -from pip._vendor.requests.packages.urllib3.exceptions import ( - InsecureRequestWarning, -) - - -# assignment for flake8 to be happy - -# This fixes a peculiarity when importing via __import__ - as we are -# initialising the pip module, "from pip import cmdoptions" is recursive -# and appears not to work properly in that situation. -import pip.cmdoptions -cmdoptions = pip.cmdoptions - -# The version as used in the setup.py and the docs conf.py -__version__ = "7.1.2" - - -logger = logging.getLogger(__name__) - -# Hide the InsecureRequestWArning from urllib3 -warnings.filterwarnings("ignore", category=InsecureRequestWarning) - - -def autocomplete(): - """Command and option completion for the main option parser (and options) - and its subcommands (and options). - - Enable by sourcing one of the completion shell scripts (bash or zsh). - """ - # Don't complete if user hasn't sourced bash_completion file. - if 'PIP_AUTO_COMPLETE' not in os.environ: - return - cwords = os.environ['COMP_WORDS'].split()[1:] - cword = int(os.environ['COMP_CWORD']) - try: - current = cwords[cword - 1] - except IndexError: - current = '' - - subcommands = [cmd for cmd, summary in get_summaries()] - options = [] - # subcommand - try: - subcommand_name = [w for w in cwords if w in subcommands][0] - except IndexError: - subcommand_name = None - - parser = create_main_parser() - # subcommand options - if subcommand_name: - # special case: 'help' subcommand has no options - if subcommand_name == 'help': - sys.exit(1) - # special case: list locally installed dists for uninstall command - if subcommand_name == 'uninstall' and not current.startswith('-'): - installed = [] - lc = current.lower() - for dist in get_installed_distributions(local_only=True): - if dist.key.startswith(lc) and dist.key not in cwords[1:]: - installed.append(dist.key) - # if there are no dists installed, fall back to option completion - if installed: - for dist in installed: - print(dist) - sys.exit(1) - - subcommand = commands_dict[subcommand_name]() - options += [(opt.get_opt_string(), opt.nargs) - for opt in subcommand.parser.option_list_all - if opt.help != optparse.SUPPRESS_HELP] - - # filter out previously specified options from available options - prev_opts = [x.split('=')[0] for x in cwords[1:cword - 1]] - options = [(x, v) for (x, v) in options if x not in prev_opts] - # filter options by current input - options = [(k, v) for k, v in options if k.startswith(current)] - for option in options: - opt_label = option[0] - # append '=' to options which require args - if option[1]: - opt_label += '=' - print(opt_label) - else: - # show main parser options only when necessary - if current.startswith('-') or current.startswith('--'): - opts = [i.option_list for i in parser.option_groups] - opts.append(parser.option_list) - opts = (o for it in opts for o in it) - - subcommands += [i.get_opt_string() for i in opts - if i.help != optparse.SUPPRESS_HELP] - - print(' '.join([x for x in subcommands if x.startswith(current)])) - sys.exit(1) - - -def create_main_parser(): - parser_kw = { - 'usage': '\n%prog [options]', - 'add_help_option': False, - 'formatter': UpdatingDefaultsHelpFormatter(), - 'name': 'global', - 'prog': get_prog(), - } - - parser = ConfigOptionParser(**parser_kw) - parser.disable_interspersed_args() - - pip_pkg_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - parser.version = 'pip %s from %s (python %s)' % ( - __version__, pip_pkg_dir, sys.version[:3]) - - # add the general options - gen_opts = cmdoptions.make_option_group(cmdoptions.general_group, parser) - parser.add_option_group(gen_opts) - - parser.main = True # so the help formatter knows - - # create command listing for description - command_summaries = get_summaries() - description = [''] + ['%-27s %s' % (i, j) for i, j in command_summaries] - parser.description = '\n'.join(description) - - return parser - - -def parseopts(args): - parser = create_main_parser() - - # Note: parser calls disable_interspersed_args(), so the result of this - # call is to split the initial args into the general options before the - # subcommand and everything else. - # For example: - # args: ['--timeout=5', 'install', '--user', 'INITools'] - # general_options: ['--timeout==5'] - # args_else: ['install', '--user', 'INITools'] - general_options, args_else = parser.parse_args(args) - - # --version - if general_options.version: - sys.stdout.write(parser.version) - sys.stdout.write(os.linesep) - sys.exit() - - # pip || pip help -> print_help() - if not args_else or (args_else[0] == 'help' and len(args_else) == 1): - parser.print_help() - sys.exit() - - # the subcommand name - cmd_name = args_else[0] - - if cmd_name not in commands_dict: - guess = get_similar_commands(cmd_name) - - msg = ['unknown command "%s"' % cmd_name] - if guess: - msg.append('maybe you meant "%s"' % guess) - - raise CommandError(' - '.join(msg)) - - # all the args without the subcommand - cmd_args = args[:] - cmd_args.remove(cmd_name) - - return cmd_name, cmd_args - - -def check_isolated(args): - isolated = False - - if "--isolated" in args: - isolated = True - - return isolated - - -def main(args=None): - if args is None: - args = sys.argv[1:] - - # Enable our Deprecation Warnings - for deprecation_warning in deprecation.DEPRECATIONS: - warnings.simplefilter("default", deprecation_warning) - - # Configure our deprecation warnings to be sent through loggers - deprecation.install_warning_logger() - - autocomplete() - - try: - cmd_name, cmd_args = parseopts(args) - except PipError as exc: - sys.stderr.write("ERROR: %s" % exc) - sys.stderr.write(os.linesep) - sys.exit(1) - - command = commands_dict[cmd_name](isolated=check_isolated(cmd_args)) - return command.main(cmd_args) - - -# ########################################################### -# # Writing freeze files - -class FrozenRequirement(object): - - def __init__(self, name, req, editable, comments=()): - self.name = name - self.req = req - self.editable = editable - self.comments = comments - - _rev_re = re.compile(r'-r(\d+)$') - _date_re = re.compile(r'-(20\d\d\d\d\d\d)$') - - @classmethod - def from_dist(cls, dist, dependency_links, find_tags=False): - location = os.path.normcase(os.path.abspath(dist.location)) - comments = [] - from pip.vcs import vcs, get_src_requirement - if vcs.get_backend_name(location): - editable = True - try: - req = get_src_requirement(dist, location, find_tags) - except InstallationError as exc: - logger.warning( - "Error when trying to get requirement for VCS system %s, " - "falling back to uneditable format", exc - ) - req = None - if req is None: - logger.warning( - 'Could not determine repository location of %s', location - ) - comments.append( - '## !! Could not determine repository location' - ) - req = dist.as_requirement() - editable = False - else: - editable = False - req = dist.as_requirement() - specs = req.specs - assert len(specs) == 1 and specs[0][0] in ["==", "==="], \ - 'Expected 1 spec with == or ===; specs = %r; dist = %r' % \ - (specs, dist) - version = specs[0][1] - ver_match = cls._rev_re.search(version) - date_match = cls._date_re.search(version) - if ver_match or date_match: - svn_backend = vcs.get_backend('svn') - if svn_backend: - svn_location = svn_backend().get_location( - dist, - dependency_links, - ) - if not svn_location: - logger.warning( - 'Warning: cannot find svn location for %s', req) - comments.append( - '## FIXME: could not find svn URL in dependency_links ' - 'for this package:' - ) - else: - comments.append( - '# Installing as editable to satisfy requirement %s:' % - req - ) - if ver_match: - rev = ver_match.group(1) - else: - rev = '{%s}' % date_match.group(1) - editable = True - req = '%s@%s#egg=%s' % ( - svn_location, - rev, - cls.egg_name(dist) - ) - return cls(dist.project_name, req, editable, comments) - - @staticmethod - def egg_name(dist): - name = dist.egg_name() - match = re.search(r'-py\d\.\d$', name) - if match: - name = name[:match.start()] - return name - - def __str__(self): - req = self.req - if self.editable: - req = '-e %s' % req - return '\n'.join(list(self.comments) + [str(req)]) + '\n' - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/virtualenv/lib/python3.5/site-packages/pip/__main__.py b/virtualenv/lib/python3.5/site-packages/pip/__main__.py deleted file mode 100644 index 5556539..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/__main__.py +++ /dev/null @@ -1,19 +0,0 @@ -from __future__ import absolute_import - -import os -import sys - -# If we are running from a wheel, add the wheel to sys.path -# This allows the usage python pip-*.whl/pip install pip-*.whl -if __package__ == '': - # __file__ is pip-*.whl/pip/__main__.py - # first dirname call strips of '/__main__.py', second strips off '/pip' - # Resulting path is the name of the wheel itself - # Add that to sys.path so we can import pip - path = os.path.dirname(os.path.dirname(__file__)) - sys.path.insert(0, path) - -import pip # noqa - -if __name__ == '__main__': - sys.exit(pip.main()) diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/__init__.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/__init__.py deleted file mode 100644 index ef8851d..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/__init__.py +++ /dev/null @@ -1,66 +0,0 @@ -""" -pip._vendor is for vendoring dependencies of pip to prevent needing pip to -depend on something external. - -Files inside of pip._vendor should be considered immutable and should only be -updated to versions from upstream. -""" -from __future__ import absolute_import - -import glob -import os.path -import sys - -# Downstream redistributors which have debundled our dependencies should also -# patch this value to be true. This will trigger the additional patching -# to cause things like "six" to be available as pip. -DEBUNDLED = False - -# By default, look in this directory for a bunch of .whl files which we will -# add to the beginning of sys.path before attempting to import anything. This -# is done to support downstream re-distributors like Debian and Fedora who -# wish to create their own Wheels for our dependencies to aid in debundling. -WHEEL_DIR = os.path.abspath(os.path.dirname(__file__)) - - -# Define a small helper function to alias our vendored modules to the real ones -# if the vendored ones do not exist. This idea of this was taken from -# https://github.com/kennethreitz/requests/pull/2567. -def vendored(modulename): - vendored_name = "{0}.{1}".format(__name__, modulename) - - try: - __import__(vendored_name, globals(), locals(), level=0) - except ImportError: - __import__(modulename, globals(), locals(), level=0) - sys.modules[vendored_name] = sys.modules[modulename] - base, head = vendored_name.rsplit(".", 1) - setattr(sys.modules[base], head, sys.modules[modulename]) - - -# If we're operating in a debundled setup, then we want to go ahead and trigger -# the aliasing of our vendored libraries as well as looking for wheels to add -# to our sys.path. This will cause all of this code to be a no-op typically -# however downstream redistributors can enable it in a consistent way across -# all platforms. -if DEBUNDLED: - # Actually look inside of WHEEL_DIR to find .whl files and add them to the - # front of our sys.path. - sys.path[:] = glob.glob(os.path.join(WHEEL_DIR, "*.whl")) + sys.path - - # Actually alias all of our vendored dependencies. - vendored("cachecontrol") - vendored("colorama") - vendored("distlib") - vendored("html5lib") - vendored("lockfile") - vendored("six") - vendored("six.moves") - vendored("six.moves.urllib") - vendored("packaging") - vendored("packaging.version") - vendored("packaging.specifiers") - vendored("pkg_resources") - vendored("progress") - vendored("retrying") - vendored("requests") diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/_markerlib/__init__.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/_markerlib/__init__.py deleted file mode 100644 index 197781a..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/_markerlib/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -try: - import ast - from pip._vendor._markerlib.markers import default_environment, compile, interpret -except ImportError: - if 'ast' in globals(): - raise - def default_environment(): - return {} - def compile(marker): - def marker_fn(environment=None, override=None): - # 'empty markers are True' heuristic won't install extra deps. - return not marker.strip() - marker_fn.__doc__ = marker - return marker_fn - def interpret(marker, environment=None, override=None): - return compile(marker)() diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/_markerlib/markers.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/_markerlib/markers.py deleted file mode 100644 index fa83706..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/_markerlib/markers.py +++ /dev/null @@ -1,119 +0,0 @@ -# -*- coding: utf-8 -*- -"""Interpret PEP 345 environment markers. - -EXPR [in|==|!=|not in] EXPR [or|and] ... - -where EXPR belongs to any of those: - - python_version = '%s.%s' % (sys.version_info[0], sys.version_info[1]) - python_full_version = sys.version.split()[0] - os.name = os.name - sys.platform = sys.platform - platform.version = platform.version() - platform.machine = platform.machine() - platform.python_implementation = platform.python_implementation() - a free string, like '2.6', or 'win32' -""" - -__all__ = ['default_environment', 'compile', 'interpret'] - -import ast -import os -import platform -import sys -import weakref - -_builtin_compile = compile - -try: - from platform import python_implementation -except ImportError: - if os.name == "java": - # Jython 2.5 has ast module, but not platform.python_implementation() function. - def python_implementation(): - return "Jython" - else: - raise - - -# restricted set of variables -_VARS = {'sys.platform': sys.platform, - 'python_version': '%s.%s' % sys.version_info[:2], - # FIXME parsing sys.platform is not reliable, but there is no other - # way to get e.g. 2.7.2+, and the PEP is defined with sys.version - 'python_full_version': sys.version.split(' ', 1)[0], - 'os.name': os.name, - 'platform.version': platform.version(), - 'platform.machine': platform.machine(), - 'platform.python_implementation': python_implementation(), - 'extra': None # wheel extension - } - -for var in list(_VARS.keys()): - if '.' in var: - _VARS[var.replace('.', '_')] = _VARS[var] - -def default_environment(): - """Return copy of default PEP 385 globals dictionary.""" - return dict(_VARS) - -class ASTWhitelist(ast.NodeTransformer): - def __init__(self, statement): - self.statement = statement # for error messages - - ALLOWED = (ast.Compare, ast.BoolOp, ast.Attribute, ast.Name, ast.Load, ast.Str) - # Bool operations - ALLOWED += (ast.And, ast.Or) - # Comparison operations - ALLOWED += (ast.Eq, ast.Gt, ast.GtE, ast.In, ast.Is, ast.IsNot, ast.Lt, ast.LtE, ast.NotEq, ast.NotIn) - - def visit(self, node): - """Ensure statement only contains allowed nodes.""" - if not isinstance(node, self.ALLOWED): - raise SyntaxError('Not allowed in environment markers.\n%s\n%s' % - (self.statement, - (' ' * node.col_offset) + '^')) - return ast.NodeTransformer.visit(self, node) - - def visit_Attribute(self, node): - """Flatten one level of attribute access.""" - new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx) - return ast.copy_location(new_node, node) - -def parse_marker(marker): - tree = ast.parse(marker, mode='eval') - new_tree = ASTWhitelist(marker).generic_visit(tree) - return new_tree - -def compile_marker(parsed_marker): - return _builtin_compile(parsed_marker, '', '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/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/__init__.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/__init__.py deleted file mode 100644 index d6af9b9..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -"""CacheControl import Interface. - -Make it easy to import from cachecontrol without long namespaces. -""" -__author__ = 'Eric Larson' -__email__ = 'eric@ionrock.org' -__version__ = '0.11.5' - -from .wrapper import CacheControl -from .adapter import CacheControlAdapter -from .controller import CacheController diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/adapter.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/adapter.py deleted file mode 100644 index 74589e0..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/adapter.py +++ /dev/null @@ -1,117 +0,0 @@ -import functools - -from pip._vendor.requests.adapters import HTTPAdapter - -from .controller import CacheController -from .cache import DictCache -from .filewrapper import CallbackFileWrapper - - -class CacheControlAdapter(HTTPAdapter): - invalidating_methods = set(['PUT', 'DELETE']) - - def __init__(self, cache=None, - cache_etags=True, - controller_class=None, - serializer=None, - heuristic=None, - *args, **kw): - super(CacheControlAdapter, self).__init__(*args, **kw) - self.cache = cache or DictCache() - self.heuristic = heuristic - - controller_factory = controller_class or CacheController - self.controller = controller_factory( - self.cache, - cache_etags=cache_etags, - serializer=serializer, - ) - - def send(self, request, **kw): - """ - Send a request. Use the request information to see if it - exists in the cache and cache the response if we need to and can. - """ - if request.method == 'GET': - cached_response = self.controller.cached_request(request) - if cached_response: - return self.build_response(request, cached_response, - from_cache=True) - - # check for etags and add headers if appropriate - request.headers.update( - self.controller.conditional_headers(request) - ) - - resp = super(CacheControlAdapter, self).send(request, **kw) - - return resp - - def build_response(self, request, response, from_cache=False): - """ - Build a response by making a request or using the cache. - - This will end up calling send and returning a potentially - cached response - """ - if not from_cache and request.method == 'GET': - - # apply any expiration heuristics - if response.status == 304: - # We must have sent an ETag request. This could mean - # that we've been expired already or that we simply - # have an etag. In either case, we want to try and - # update the cache if that is the case. - cached_response = self.controller.update_cached_response( - request, response - ) - - if cached_response is not response: - from_cache = True - - # We are done with the server response, read a - # possible response body (compliant servers will - # not return one, but we cannot be 100% sure) and - # release the connection back to the pool. - response.read(decode_content=False) - response.release_conn() - - response = cached_response - - # We always cache the 301 responses - elif response.status == 301: - self.controller.cache_response(request, response) - else: - # Check for any heuristics that might update headers - # before trying to cache. - if self.heuristic: - response = self.heuristic.apply(response) - - # Wrap the response file with a wrapper that will cache the - # response when the stream has been consumed. - response._fp = CallbackFileWrapper( - response._fp, - functools.partial( - self.controller.cache_response, - request, - response, - ) - ) - - resp = super(CacheControlAdapter, self).build_response( - request, response - ) - - # See if we should invalidate the cache. - if request.method in self.invalidating_methods and resp.ok: - cache_url = self.controller.cache_url(request.url) - self.cache.delete(cache_url) - - # Give the request a from_cache attr to let people use it - resp.from_cache = from_cache - - return resp - - def close(self): - self.cache.close() - super(CacheControlAdapter, self).close() diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/cache.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/cache.py deleted file mode 100644 index 7389a73..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/cache.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -The cache object API for implementing caches. The default is a thread -safe in-memory dictionary. -""" -from threading import Lock - - -class BaseCache(object): - - def get(self, key): - raise NotImplemented() - - def set(self, key, value): - raise NotImplemented() - - def delete(self, key): - raise NotImplemented() - - def close(self): - pass - - -class DictCache(BaseCache): - - def __init__(self, init_dict=None): - self.lock = Lock() - self.data = init_dict or {} - - def get(self, key): - return self.data.get(key, None) - - def set(self, key, value): - with self.lock: - self.data.update({key: value}) - - def delete(self, key): - with self.lock: - if key in self.data: - self.data.pop(key) diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/caches/__init__.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/caches/__init__.py deleted file mode 100644 index f9e66a1..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/caches/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -from textwrap import dedent - -try: - from .file_cache import FileCache -except ImportError: - notice = dedent(''' - NOTE: In order to use the FileCache you must have - lockfile installed. You can install it via pip: - pip install lockfile - ''') - print(notice) - - -try: - import redis - from .redis_cache import RedisCache -except ImportError: - pass diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py deleted file mode 100644 index b77728f..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py +++ /dev/null @@ -1,116 +0,0 @@ -import hashlib -import os - -from pip._vendor.lockfile import LockFile -from pip._vendor.lockfile.mkdirlockfile import MkdirLockFile - -from ..cache import BaseCache -from ..controller import CacheController - - -def _secure_open_write(filename, fmode): - # We only want to write to this file, so open it in write only mode - flags = os.O_WRONLY - - # os.O_CREAT | os.O_EXCL will fail if the file already exists, so we only - # will open *new* files. - # We specify this because we want to ensure that the mode we pass is the - # mode of the file. - flags |= os.O_CREAT | os.O_EXCL - - # Do not follow symlinks to prevent someone from making a symlink that - # we follow and insecurely open a cache file. - if hasattr(os, "O_NOFOLLOW"): - flags |= os.O_NOFOLLOW - - # On Windows we'll mark this file as binary - if hasattr(os, "O_BINARY"): - flags |= os.O_BINARY - - # Before we open our file, we want to delete any existing file that is - # there - try: - os.remove(filename) - except (IOError, OSError): - # The file must not exist already, so we can just skip ahead to opening - pass - - # Open our file, the use of os.O_CREAT | os.O_EXCL will ensure that if a - # race condition happens between the os.remove and this line, that an - # error will be raised. Because we utilize a lockfile this should only - # happen if someone is attempting to attack us. - fd = os.open(filename, flags, fmode) - try: - return os.fdopen(fd, "wb") - except: - # An error occurred wrapping our FD in a file object - os.close(fd) - raise - - -class FileCache(BaseCache): - def __init__(self, directory, forever=False, filemode=0o0600, - dirmode=0o0700, use_dir_lock=None, lock_class=None): - - if use_dir_lock is not None and lock_class is not None: - raise ValueError("Cannot use use_dir_lock and lock_class together") - - if use_dir_lock: - lock_class = MkdirLockFile - - if lock_class is None: - lock_class = LockFile - - self.directory = directory - self.forever = forever - self.filemode = filemode - self.dirmode = dirmode - self.lock_class = lock_class - - - @staticmethod - def encode(x): - return hashlib.sha224(x.encode()).hexdigest() - - def _fn(self, name): - # NOTE: This method should not change as some may depend on it. - # See: https://github.com/ionrock/cachecontrol/issues/63 - hashed = self.encode(name) - parts = list(hashed[:5]) + [hashed] - return os.path.join(self.directory, *parts) - - def get(self, key): - name = self._fn(key) - if not os.path.exists(name): - return None - - with open(name, 'rb') as fh: - return fh.read() - - def set(self, key, value): - name = self._fn(key) - - # Make sure the directory exists - try: - os.makedirs(os.path.dirname(name), self.dirmode) - except (IOError, OSError): - pass - - with self.lock_class(name) as lock: - # Write our actual file - with _secure_open_write(lock.path, self.filemode) as fh: - fh.write(value) - - def delete(self, key): - name = self._fn(key) - if not self.forever: - os.remove(name) - - -def url_to_file_path(url, filecache): - """Return the file cache path based on the URL. - - This does not ensure the file exists! - """ - key = CacheController.cache_url(url) - return filecache._fn(key) diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py deleted file mode 100644 index 9f5d55f..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py +++ /dev/null @@ -1,41 +0,0 @@ -from __future__ import division - -from datetime import datetime - - -def total_seconds(td): - """Python 2.6 compatability""" - if hasattr(td, 'total_seconds'): - return td.total_seconds() - - ms = td.microseconds - secs = (td.seconds + td.days * 24 * 3600) - return (ms + secs * 10**6) / 10**6 - - -class RedisCache(object): - - def __init__(self, conn): - self.conn = conn - - def get(self, key): - return self.conn.get(key) - - def set(self, key, value, expires=None): - if not expires: - self.conn.set(key, value) - else: - expires = expires - datetime.now() - self.conn.setex(key, total_seconds(expires), value) - - def delete(self, key): - self.conn.delete(key) - - def clear(self): - """Helper for clearing all the keys in a database. Use with - caution!""" - for key in self.conn.keys(): - self.conn.delete(key) - - def close(self): - self.conn.disconnect() diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/compat.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/compat.py deleted file mode 100644 index 9878bec..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/compat.py +++ /dev/null @@ -1,14 +0,0 @@ -try: - from urllib.parse import urljoin -except ImportError: - from urlparse import urljoin - - -try: - import cPickle as pickle -except ImportError: - import pickle - - -from pip._vendor.requests.packages.urllib3.response import HTTPResponse -from pip._vendor.requests.packages.urllib3.util import is_fp_closed diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/controller.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/controller.py deleted file mode 100644 index f489b98..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/controller.py +++ /dev/null @@ -1,299 +0,0 @@ -""" -The httplib2 algorithms ported for use with requests. -""" -import re -import calendar -import time -from email.utils import parsedate_tz - -from pip._vendor.requests.structures import CaseInsensitiveDict - -from .cache import DictCache -from .serialize import Serializer - - -URI = re.compile(r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?") - - -def parse_uri(uri): - """Parses a URI using the regex given in Appendix B of RFC 3986. - - (scheme, authority, path, query, fragment) = parse_uri(uri) - """ - groups = URI.match(uri).groups() - return (groups[1], groups[3], groups[4], groups[6], groups[8]) - - -class CacheController(object): - """An interface to see if request should cached or not. - """ - def __init__(self, cache=None, cache_etags=True, serializer=None): - self.cache = cache or DictCache() - self.cache_etags = cache_etags - self.serializer = serializer or Serializer() - - @classmethod - def _urlnorm(cls, uri): - """Normalize the URL to create a safe key for the cache""" - (scheme, authority, path, query, fragment) = parse_uri(uri) - if not scheme or not authority: - raise Exception("Only absolute URIs are allowed. uri = %s" % uri) - - scheme = scheme.lower() - authority = authority.lower() - - if not path: - path = "/" - - # Could do syntax based normalization of the URI before - # computing the digest. See Section 6.2.2 of Std 66. - request_uri = query and "?".join([path, query]) or path - defrag_uri = scheme + "://" + authority + request_uri - - return defrag_uri - - @classmethod - def cache_url(cls, uri): - return cls._urlnorm(uri) - - def parse_cache_control(self, headers): - """ - Parse the cache control headers returning a dictionary with values - for the different directives. - """ - retval = {} - - cc_header = 'cache-control' - if 'Cache-Control' in headers: - cc_header = 'Cache-Control' - - if cc_header in headers: - parts = headers[cc_header].split(',') - parts_with_args = [ - tuple([x.strip().lower() for x in part.split("=", 1)]) - for part in parts if -1 != part.find("=") - ] - parts_wo_args = [ - (name.strip().lower(), 1) - for name in parts if -1 == name.find("=") - ] - retval = dict(parts_with_args + parts_wo_args) - return retval - - def cached_request(self, request): - """ - Return a cached response if it exists in the cache, otherwise - return False. - """ - cache_url = self.cache_url(request.url) - cc = self.parse_cache_control(request.headers) - - # non-caching states - no_cache = True if 'no-cache' in cc else False - if 'max-age' in cc and cc['max-age'] == 0: - no_cache = True - - # Bail out if no-cache was set - if no_cache: - return False - - # It is in the cache, so lets see if it is going to be - # fresh enough - resp = self.serializer.loads(request, self.cache.get(cache_url)) - - # Check to see if we have a cached object - if not resp: - return False - - # If we have a cached 301, return it immediately. We don't - # need to test our response for other headers b/c it is - # intrinsically "cacheable" as it is Permanent. - # See: - # https://tools.ietf.org/html/rfc7231#section-6.4.2 - # - # Client can try to refresh the value by repeating the request - # with cache busting headers as usual (ie no-cache). - if resp.status == 301: - return resp - - headers = CaseInsensitiveDict(resp.headers) - if not headers or 'date' not in headers: - # With date or etag, the cached response can never be used - # and should be deleted. - if 'etag' not in headers: - self.cache.delete(cache_url) - return False - - now = time.time() - date = calendar.timegm( - parsedate_tz(headers['date']) - ) - current_age = max(0, now - date) - - # TODO: There is an assumption that the result will be a - # urllib3 response object. This may not be best since we - # could probably avoid instantiating or constructing the - # response until we know we need it. - resp_cc = self.parse_cache_control(headers) - - # determine freshness - freshness_lifetime = 0 - - # Check the max-age pragma in the cache control header - if 'max-age' in resp_cc and resp_cc['max-age'].isdigit(): - freshness_lifetime = int(resp_cc['max-age']) - - # If there isn't a max-age, check for an expires header - elif 'expires' in headers: - expires = parsedate_tz(headers['expires']) - if expires is not None: - expire_time = calendar.timegm(expires) - date - freshness_lifetime = max(0, expire_time) - - # determine if we are setting freshness limit in the req - if 'max-age' in cc: - try: - freshness_lifetime = int(cc['max-age']) - except ValueError: - freshness_lifetime = 0 - - if 'min-fresh' in cc: - try: - min_fresh = int(cc['min-fresh']) - except ValueError: - min_fresh = 0 - # adjust our current age by our min fresh - current_age += min_fresh - - # see how fresh we actually are - fresh = (freshness_lifetime > current_age) - - if fresh: - return resp - - # we're not fresh. If we don't have an Etag, clear it out - if 'etag' not in headers: - self.cache.delete(cache_url) - - # return the original handler - return False - - def conditional_headers(self, request): - cache_url = self.cache_url(request.url) - resp = self.serializer.loads(request, self.cache.get(cache_url)) - new_headers = {} - - if resp: - headers = CaseInsensitiveDict(resp.headers) - - if 'etag' in headers: - new_headers['If-None-Match'] = headers['ETag'] - - if 'last-modified' in headers: - new_headers['If-Modified-Since'] = headers['Last-Modified'] - - return new_headers - - def cache_response(self, request, response, body=None): - """ - Algorithm for caching requests. - - This assumes a requests Response object. - """ - # From httplib2: Don't cache 206's since we aren't going to - # handle byte range requests - if response.status not in [200, 203, 300, 301]: - return - - response_headers = CaseInsensitiveDict(response.headers) - - cc_req = self.parse_cache_control(request.headers) - cc = self.parse_cache_control(response_headers) - - cache_url = self.cache_url(request.url) - - # Delete it from the cache if we happen to have it stored there - no_store = cc.get('no-store') or cc_req.get('no-store') - if no_store and self.cache.get(cache_url): - self.cache.delete(cache_url) - - # If we've been given an etag, then keep the response - if self.cache_etags and 'etag' in response_headers: - self.cache.set( - cache_url, - self.serializer.dumps(request, response, body=body), - ) - - # Add to the cache any 301s. We do this before looking that - # the Date headers. - elif response.status == 301: - self.cache.set( - cache_url, - self.serializer.dumps(request, response) - ) - - # Add to the cache if the response headers demand it. If there - # is no date header then we can't do anything about expiring - # the cache. - elif 'date' in response_headers: - # cache when there is a max-age > 0 - if cc and cc.get('max-age'): - if int(cc['max-age']) > 0: - self.cache.set( - cache_url, - self.serializer.dumps(request, response, body=body), - ) - - # If the request can expire, it means we should cache it - # in the meantime. - elif 'expires' in response_headers: - if response_headers['expires']: - self.cache.set( - cache_url, - self.serializer.dumps(request, response, body=body), - ) - - def update_cached_response(self, request, response): - """On a 304 we will get a new set of headers that we want to - update our cached value with, assuming we have one. - - This should only ever be called when we've sent an ETag and - gotten a 304 as the response. - """ - cache_url = self.cache_url(request.url) - - cached_response = self.serializer.loads( - request, - self.cache.get(cache_url) - ) - - if not cached_response: - # we didn't have a cached response - return response - - # Lets update our headers with the headers from the new request: - # http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-4.1 - # - # The server isn't supposed to send headers that would make - # the cached body invalid. But... just in case, we'll be sure - # to strip out ones we know that might be problmatic due to - # typical assumptions. - excluded_headers = [ - "content-length", - ] - - cached_response.headers.update( - dict((k, v) for k, v in response.headers.items() - if k.lower() not in excluded_headers) - ) - - # we want a 200 b/c we have content via the cache - cached_response.status = 200 - - # update our cache - self.cache.set( - cache_url, - self.serializer.dumps(request, cached_response), - ) - - return cached_response diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/filewrapper.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/filewrapper.py deleted file mode 100644 index 4b91bce..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/filewrapper.py +++ /dev/null @@ -1,63 +0,0 @@ -from io import BytesIO - - -class CallbackFileWrapper(object): - """ - Small wrapper around a fp object which will tee everything read into a - buffer, and when that file is closed it will execute a callback with the - contents of that buffer. - - All attributes are proxied to the underlying file object. - - This class uses members with a double underscore (__) leading prefix so as - not to accidentally shadow an attribute. - """ - - def __init__(self, fp, callback): - self.__buf = BytesIO() - self.__fp = fp - self.__callback = callback - - def __getattr__(self, name): - # The vaguaries of garbage collection means that self.__fp is - # not always set. By using __getattribute__ and the private - # name[0] allows looking up the attribute value and raising an - # AttributeError when it doesn't exist. This stop thigns from - # infinitely recursing calls to getattr in the case where - # self.__fp hasn't been set. - # - # [0] https://docs.python.org/2/reference/expressions.html#atom-identifiers - fp = self.__getattribute__('_CallbackFileWrapper__fp') - return getattr(fp, name) - - def __is_fp_closed(self): - try: - return self.__fp.fp is None - except AttributeError: - pass - - try: - return self.__fp.closed - except AttributeError: - pass - - # We just don't cache it then. - # TODO: Add some logging here... - return False - - def read(self, amt=None): - data = self.__fp.read(amt) - self.__buf.write(data) - - if self.__is_fp_closed(): - if self.__callback: - self.__callback(self.__buf.getvalue()) - - # We assign this to None here, because otherwise we can get into - # really tricky problems where the CPython interpreter dead locks - # because the callback is holding a reference to something which - # has a __del__ method. Setting this to None breaks the cycle - # and allows the garbage collector to do it's thing normally. - self.__callback = None - - return data diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/heuristics.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/heuristics.py deleted file mode 100644 index 01b6314..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/heuristics.py +++ /dev/null @@ -1,134 +0,0 @@ -import calendar -import time - -from email.utils import formatdate, parsedate, parsedate_tz - -from datetime import datetime, timedelta - -TIME_FMT = "%a, %d %b %Y %H:%M:%S GMT" - - -def expire_after(delta, date=None): - date = date or datetime.now() - return date + delta - - -def datetime_to_header(dt): - return formatdate(calendar.timegm(dt.timetuple())) - - -class BaseHeuristic(object): - - def warning(self, response): - """ - Return a valid 1xx warning header value describing the cache - adjustments. - - The response is provided too allow warnings like 113 - http://tools.ietf.org/html/rfc7234#section-5.5.4 where we need - to explicitly say response is over 24 hours old. - """ - return '110 - "Response is Stale"' - - def update_headers(self, response): - """Update the response headers with any new headers. - - NOTE: This SHOULD always include some Warning header to - signify that the response was cached by the client, not - by way of the provided headers. - """ - return {} - - def apply(self, response): - warning_header_value = self.warning(response) - response.headers.update(self.update_headers(response)) - if warning_header_value is not None: - response.headers.update({'Warning': warning_header_value}) - return response - - -class OneDayCache(BaseHeuristic): - """ - Cache the response by providing an expires 1 day in the - future. - """ - def update_headers(self, response): - headers = {} - - if 'expires' not in response.headers: - date = parsedate(response.headers['date']) - expires = expire_after(timedelta(days=1), - date=datetime(*date[:6])) - headers['expires'] = datetime_to_header(expires) - headers['cache-control'] = 'public' - return headers - - -class ExpiresAfter(BaseHeuristic): - """ - Cache **all** requests for a defined time period. - """ - - def __init__(self, **kw): - self.delta = timedelta(**kw) - - def update_headers(self, response): - expires = expire_after(self.delta) - return { - 'expires': datetime_to_header(expires), - 'cache-control': 'public', - } - - def warning(self, response): - tmpl = '110 - Automatically cached for %s. Response might be stale' - return tmpl % self.delta - - -class LastModified(BaseHeuristic): - """ - If there is no Expires header already, fall back on Last-Modified - using the heuristic from - http://tools.ietf.org/html/rfc7234#section-4.2.2 - to calculate a reasonable value. - - Firefox also does something like this per - https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching_FAQ - http://lxr.mozilla.org/mozilla-release/source/netwerk/protocol/http/nsHttpResponseHead.cpp#397 - Unlike mozilla we limit this to 24-hr. - """ - cacheable_by_default_statuses = set([ - 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501 - ]) - - def update_headers(self, resp): - headers = resp.headers - - if 'expires' in headers: - return {} - - if 'cache-control' in headers and headers['cache-control'] != 'public': - return {} - - if resp.status not in self.cacheable_by_default_statuses: - return {} - - if 'date' not in headers or 'last-modified' not in headers: - return {} - - date = calendar.timegm(parsedate_tz(headers['date'])) - last_modified = parsedate(headers['last-modified']) - if date is None or last_modified is None: - return {} - - now = time.time() - current_age = max(0, now - date) - delta = date - calendar.timegm(last_modified) - freshness_lifetime = max(0, min(delta / 10, 24 * 3600)) - if freshness_lifetime <= current_age: - return {} - - expires = date + freshness_lifetime - return {'expires': time.strftime(TIME_FMT, time.gmtime(expires))} - - def warning(self, resp): - return None diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/serialize.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/serialize.py deleted file mode 100644 index e803a88..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/serialize.py +++ /dev/null @@ -1,184 +0,0 @@ -import base64 -import io -import json -import zlib - -from pip._vendor.requests.structures import CaseInsensitiveDict - -from .compat import HTTPResponse, pickle - - -def _b64_encode_bytes(b): - return base64.b64encode(b).decode("ascii") - - -def _b64_encode_str(s): - return _b64_encode_bytes(s.encode("utf8")) - - -def _b64_decode_bytes(b): - return base64.b64decode(b.encode("ascii")) - - -def _b64_decode_str(s): - return _b64_decode_bytes(s).decode("utf8") - - -class Serializer(object): - - def dumps(self, request, response, body=None): - response_headers = CaseInsensitiveDict(response.headers) - - if body is None: - body = response.read(decode_content=False) - - # NOTE: 99% sure this is dead code. I'm only leaving it - # here b/c I don't have a test yet to prove - # it. Basically, before using - # `cachecontrol.filewrapper.CallbackFileWrapper`, - # this made an effort to reset the file handle. The - # `CallbackFileWrapper` short circuits this code by - # setting the body as the content is consumed, the - # result being a `body` argument is *always* passed - # into cache_response, and in turn, - # `Serializer.dump`. - response._fp = io.BytesIO(body) - - data = { - "response": { - "body": _b64_encode_bytes(body), - "headers": dict( - (_b64_encode_str(k), _b64_encode_str(v)) - for k, v in response.headers.items() - ), - "status": response.status, - "version": response.version, - "reason": _b64_encode_str(response.reason), - "strict": response.strict, - "decode_content": response.decode_content, - }, - } - - # Construct our vary headers - data["vary"] = {} - if "vary" in response_headers: - varied_headers = response_headers['vary'].split(',') - for header in varied_headers: - header = header.strip() - data["vary"][header] = request.headers.get(header, None) - - # Encode our Vary headers to ensure they can be serialized as JSON - data["vary"] = dict( - (_b64_encode_str(k), _b64_encode_str(v) if v is not None else v) - for k, v in data["vary"].items() - ) - - return b",".join([ - b"cc=2", - zlib.compress( - json.dumps( - data, separators=(",", ":"), sort_keys=True, - ).encode("utf8"), - ), - ]) - - def loads(self, request, data): - # Short circuit if we've been given an empty set of data - if not data: - return - - # Determine what version of the serializer the data was serialized - # with - try: - ver, data = data.split(b",", 1) - except ValueError: - ver = b"cc=0" - - # Make sure that our "ver" is actually a version and isn't a false - # positive from a , being in the data stream. - if ver[:3] != b"cc=": - data = ver + data - ver = b"cc=0" - - # Get the version number out of the cc=N - ver = ver.split(b"=", 1)[-1].decode("ascii") - - # Dispatch to the actual load method for the given version - try: - return getattr(self, "_loads_v{0}".format(ver))(request, data) - except AttributeError: - # This is a version we don't have a loads function for, so we'll - # just treat it as a miss and return None - return - - def prepare_response(self, request, cached): - """Verify our vary headers match and construct a real urllib3 - HTTPResponse object. - """ - # Special case the '*' Vary value as it means we cannot actually - # determine if the cached response is suitable for this request. - if "*" in cached.get("vary", {}): - return - - # Ensure that the Vary headers for the cached response match our - # request - for header, value in cached.get("vary", {}).items(): - if request.headers.get(header, None) != value: - return - - body_raw = cached["response"].pop("body") - - try: - body = io.BytesIO(body_raw) - except TypeError: - # This can happen if cachecontrol serialized to v1 format (pickle) - # using Python 2. A Python 2 str(byte string) will be unpickled as - # a Python 3 str (unicode string), which will cause the above to - # fail with: - # - # TypeError: 'str' does not support the buffer interface - body = io.BytesIO(body_raw.encode('utf8')) - - return HTTPResponse( - body=body, - preload_content=False, - **cached["response"] - ) - - def _loads_v0(self, request, data): - # The original legacy cache data. This doesn't contain enough - # information to construct everything we need, so we'll treat this as - # a miss. - return - - def _loads_v1(self, request, data): - try: - cached = pickle.loads(data) - except ValueError: - return - - return self.prepare_response(request, cached) - - def _loads_v2(self, request, data): - try: - cached = json.loads(zlib.decompress(data).decode("utf8")) - except ValueError: - return - - # We need to decode the items that we've base64 encoded - cached["response"]["body"] = _b64_decode_bytes( - cached["response"]["body"] - ) - cached["response"]["headers"] = dict( - (_b64_decode_str(k), _b64_decode_str(v)) - for k, v in cached["response"]["headers"].items() - ) - cached["response"]["reason"] = _b64_decode_str( - cached["response"]["reason"], - ) - cached["vary"] = dict( - (_b64_decode_str(k), _b64_decode_str(v) if v is not None else v) - for k, v in cached["vary"].items() - ) - - return self.prepare_response(request, cached) diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/wrapper.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/wrapper.py deleted file mode 100644 index ea421aa..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/cachecontrol/wrapper.py +++ /dev/null @@ -1,21 +0,0 @@ -from .adapter import CacheControlAdapter -from .cache import DictCache - - -def CacheControl(sess, - cache=None, - cache_etags=True, - serializer=None, - heuristic=None): - - cache = cache or DictCache() - adapter = CacheControlAdapter( - cache, - cache_etags=cache_etags, - serializer=serializer, - heuristic=heuristic, - ) - sess.mount('http://', adapter) - sess.mount('https://', adapter) - - return sess diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/__init__.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/__init__.py deleted file mode 100644 index 4af0c1e..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -from .initialise import init, deinit, reinit -from .ansi import Fore, Back, Style, Cursor -from .ansitowin32 import AnsiToWin32 - -__version__ = '0.3.3' - diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/ansi.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/ansi.py deleted file mode 100644 index 1cc7225..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/ansi.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -''' -This module generates ANSI character codes to printing colors to terminals. -See: http://en.wikipedia.org/wiki/ANSI_escape_code -''' - -CSI = '\033[' -OSC = '\033]' -BEL = '\007' - - -def code_to_chars(code): - return CSI + str(code) + 'm' - - -class AnsiCodes(object): - def __init__(self, codes): - for name in dir(codes): - if not name.startswith('_'): - value = getattr(codes, name) - setattr(self, name, code_to_chars(value)) - - -class AnsiCursor(object): - def UP(self, n=1): - return CSI + str(n) + "A" - def DOWN(self, n=1): - return CSI + str(n) + "B" - def FORWARD(self, n=1): - return CSI + str(n) + "C" - def BACK(self, n=1): - return CSI + str(n) + "D" - def POS(self, x=1, y=1): - return CSI + str(y) + ";" + str(x) + "H" - -def set_title(title): - return OSC + "2;" + title + BEL - -def clear_screen(mode=2): - return CSI + str(mode) + "J" - -def clear_line(mode=2): - return CSI + str(mode) + "K" - - -class AnsiFore: - BLACK = 30 - RED = 31 - GREEN = 32 - YELLOW = 33 - BLUE = 34 - MAGENTA = 35 - CYAN = 36 - WHITE = 37 - RESET = 39 - - # These are fairly well supported, but not part of the standard. - LIGHTBLACK_EX = 90 - LIGHTRED_EX = 91 - LIGHTGREEN_EX = 92 - LIGHTYELLOW_EX = 93 - LIGHTBLUE_EX = 94 - LIGHTMAGENTA_EX = 95 - LIGHTCYAN_EX = 96 - LIGHTWHITE_EX = 97 - - -class AnsiBack: - BLACK = 40 - RED = 41 - GREEN = 42 - YELLOW = 43 - BLUE = 44 - MAGENTA = 45 - CYAN = 46 - WHITE = 47 - RESET = 49 - - # These are fairly well supported, but not part of the standard. - LIGHTBLACK_EX = 100 - LIGHTRED_EX = 101 - LIGHTGREEN_EX = 102 - LIGHTYELLOW_EX = 103 - LIGHTBLUE_EX = 104 - LIGHTMAGENTA_EX = 105 - LIGHTCYAN_EX = 106 - LIGHTWHITE_EX = 107 - - -class AnsiStyle: - BRIGHT = 1 - DIM = 2 - NORMAL = 22 - RESET_ALL = 0 - -Fore = AnsiCodes( AnsiFore ) -Back = AnsiCodes( AnsiBack ) -Style = AnsiCodes( AnsiStyle ) -Cursor = AnsiCursor() diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/ansitowin32.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/ansitowin32.py deleted file mode 100644 index 62e770c..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/ansitowin32.py +++ /dev/null @@ -1,228 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -import re -import sys -import os - -from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style -from .winterm import WinTerm, WinColor, WinStyle -from .win32 import windll - - -winterm = None -if windll is not None: - winterm = WinTerm() - - -def is_a_tty(stream): - return hasattr(stream, 'isatty') and stream.isatty() - - -class StreamWrapper(object): - ''' - Wraps a stream (such as stdout), acting as a transparent proxy for all - attribute access apart from method 'write()', which is delegated to our - Converter instance. - ''' - def __init__(self, wrapped, converter): - # double-underscore everything to prevent clashes with names of - # attributes on the wrapped stream object. - self.__wrapped = wrapped - self.__convertor = converter - - def __getattr__(self, name): - return getattr(self.__wrapped, name) - - def write(self, text): - self.__convertor.write(text) - - -class AnsiToWin32(object): - ''' - Implements a 'write()' method which, on Windows, will strip ANSI character - sequences from the text, and if outputting to a tty, will convert them into - win32 function calls. - ''' - ANSI_CSI_RE = re.compile('\033\[((?:\d|;)*)([a-zA-Z])') # Control Sequence Introducer - ANSI_OSC_RE = re.compile('\033\]((?:.|;)*?)(\x07)') # Operating System Command - - def __init__(self, wrapped, convert=None, strip=None, autoreset=False): - # The wrapped stream (normally sys.stdout or sys.stderr) - self.wrapped = wrapped - - # should we reset colors to defaults after every .write() - self.autoreset = autoreset - - # create the proxy wrapping our output stream - self.stream = StreamWrapper(wrapped, self) - - on_windows = os.name == 'nt' - on_emulated_windows = on_windows and 'TERM' in os.environ - - # should we strip ANSI sequences from our output? - if strip is None: - strip = on_windows and not on_emulated_windows - self.strip = strip - - # should we should convert ANSI sequences into win32 calls? - if convert is None: - convert = on_windows and not wrapped.closed and not on_emulated_windows and is_a_tty(wrapped) - self.convert = convert - - # dict of ansi codes to win32 functions and parameters - self.win32_calls = self.get_win32_calls() - - # are we wrapping stderr? - self.on_stderr = self.wrapped is sys.stderr - - def should_wrap(self): - ''' - True if this class is actually needed. If false, then the output - stream will not be affected, nor will win32 calls be issued, so - wrapping stdout is not actually required. This will generally be - False on non-Windows platforms, unless optional functionality like - autoreset has been requested using kwargs to init() - ''' - return self.convert or self.strip or self.autoreset - - def get_win32_calls(self): - if self.convert and winterm: - return { - AnsiStyle.RESET_ALL: (winterm.reset_all, ), - AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), - AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), - AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), - AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), - AnsiFore.RED: (winterm.fore, WinColor.RED), - AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), - AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), - AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), - AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), - AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), - AnsiFore.WHITE: (winterm.fore, WinColor.GREY), - AnsiFore.RESET: (winterm.fore, ), - AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True), - AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True), - AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True), - AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True), - AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True), - AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True), - AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True), - AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True), - AnsiBack.BLACK: (winterm.back, WinColor.BLACK), - AnsiBack.RED: (winterm.back, WinColor.RED), - AnsiBack.GREEN: (winterm.back, WinColor.GREEN), - AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), - AnsiBack.BLUE: (winterm.back, WinColor.BLUE), - AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), - AnsiBack.CYAN: (winterm.back, WinColor.CYAN), - AnsiBack.WHITE: (winterm.back, WinColor.GREY), - AnsiBack.RESET: (winterm.back, ), - AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True), - AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True), - AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True), - AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True), - AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True), - AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True), - AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True), - AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True), - } - return dict() - - def write(self, text): - if self.strip or self.convert: - self.write_and_convert(text) - else: - self.wrapped.write(text) - self.wrapped.flush() - if self.autoreset: - self.reset_all() - - - def reset_all(self): - if self.convert: - self.call_win32('m', (0,)) - elif not self.wrapped.closed and is_a_tty(self.wrapped): - self.wrapped.write(Style.RESET_ALL) - - - def write_and_convert(self, text): - ''' - Write the given text to our wrapped stream, stripping any ANSI - sequences from the text, and optionally converting them into win32 - calls. - ''' - cursor = 0 - text = self.convert_osc(text) - for match in self.ANSI_CSI_RE.finditer(text): - start, end = match.span() - self.write_plain_text(text, cursor, start) - self.convert_ansi(*match.groups()) - cursor = end - self.write_plain_text(text, cursor, len(text)) - - - def write_plain_text(self, text, start, end): - if start < end: - self.wrapped.write(text[start:end]) - self.wrapped.flush() - - - def convert_ansi(self, paramstring, command): - if self.convert: - params = self.extract_params(command, paramstring) - self.call_win32(command, params) - - - def extract_params(self, command, paramstring): - if command in 'Hf': - params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';')) - while len(params) < 2: - # defaults: - params = params + (1,) - else: - params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0) - if len(params) == 0: - # defaults: - if command in 'JKm': - params = (0,) - elif command in 'ABCD': - params = (1,) - - return params - - - def call_win32(self, command, params): - if command == 'm': - for param in params: - if param in self.win32_calls: - func_args = self.win32_calls[param] - func = func_args[0] - args = func_args[1:] - kwargs = dict(on_stderr=self.on_stderr) - func(*args, **kwargs) - elif command in 'J': - winterm.erase_screen(params[0], on_stderr=self.on_stderr) - elif command in 'K': - winterm.erase_line(params[0], on_stderr=self.on_stderr) - elif command in 'Hf': # cursor position - absolute - winterm.set_cursor_position(params, on_stderr=self.on_stderr) - elif command in 'ABCD': # cursor position - relative - n = params[0] - # A - up, B - down, C - forward, D - back - x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command] - winterm.cursor_adjust(x, y, on_stderr=self.on_stderr) - - - def convert_osc(self, text): - for match in self.ANSI_OSC_RE.finditer(text): - start, end = match.span() - text = text[:start] + text[end:] - paramstring, command = match.groups() - if command in '\x07': # \x07 = BEL - params = paramstring.split(";") - # 0 - change title and icon (we will only change title) - # 1 - change icon (we don't support this) - # 2 - change title - if params[0] in '02': - winterm.set_title(params[1]) - return text diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/initialise.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/initialise.py deleted file mode 100644 index 7e27f84..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/initialise.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -import atexit -import sys - -from .ansitowin32 import AnsiToWin32 - - -orig_stdout = sys.stdout -orig_stderr = sys.stderr - -wrapped_stdout = sys.stdout -wrapped_stderr = sys.stderr - -atexit_done = False - - -def reset_all(): - AnsiToWin32(orig_stdout).reset_all() - - -def init(autoreset=False, convert=None, strip=None, wrap=True): - - if not wrap and any([autoreset, convert, strip]): - raise ValueError('wrap=False conflicts with any other arg=True') - - global wrapped_stdout, wrapped_stderr - if sys.stdout is None: - wrapped_stdout = None - else: - sys.stdout = wrapped_stdout = \ - wrap_stream(orig_stdout, convert, strip, autoreset, wrap) - if sys.stderr is None: - wrapped_stderr = None - else: - sys.stderr = wrapped_stderr = \ - wrap_stream(orig_stderr, convert, strip, autoreset, wrap) - - global atexit_done - if not atexit_done: - atexit.register(reset_all) - atexit_done = True - - -def deinit(): - if orig_stdout is not None: - sys.stdout = orig_stdout - if orig_stderr is not None: - sys.stderr = orig_stderr - - -def reinit(): - if wrapped_stdout is not None: - sys.stdout = wrapped_stdout - if wrapped_stderr is not None: - sys.stderr = wrapped_stderr - - -def wrap_stream(stream, convert, strip, autoreset, wrap): - if wrap: - wrapper = AnsiToWin32(stream, - convert=convert, strip=strip, autoreset=autoreset) - if wrapper.should_wrap(): - stream = wrapper.stream - return stream - - diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/win32.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/win32.py deleted file mode 100644 index c604f37..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/win32.py +++ /dev/null @@ -1,146 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. - -# from winbase.h -STDOUT = -11 -STDERR = -12 - -try: - import ctypes - from ctypes import LibraryLoader - windll = LibraryLoader(ctypes.WinDLL) - from ctypes import wintypes -except (AttributeError, ImportError): - windll = None - SetConsoleTextAttribute = lambda *_: None -else: - from ctypes import byref, Structure, c_char, POINTER - - COORD = wintypes._COORD - - class CONSOLE_SCREEN_BUFFER_INFO(Structure): - """struct in wincon.h.""" - _fields_ = [ - ("dwSize", COORD), - ("dwCursorPosition", COORD), - ("wAttributes", wintypes.WORD), - ("srWindow", wintypes.SMALL_RECT), - ("dwMaximumWindowSize", COORD), - ] - def __str__(self): - return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( - self.dwSize.Y, self.dwSize.X - , self.dwCursorPosition.Y, self.dwCursorPosition.X - , self.wAttributes - , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right - , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X - ) - - _GetStdHandle = windll.kernel32.GetStdHandle - _GetStdHandle.argtypes = [ - wintypes.DWORD, - ] - _GetStdHandle.restype = wintypes.HANDLE - - _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo - _GetConsoleScreenBufferInfo.argtypes = [ - wintypes.HANDLE, - POINTER(CONSOLE_SCREEN_BUFFER_INFO), - ] - _GetConsoleScreenBufferInfo.restype = wintypes.BOOL - - _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute - _SetConsoleTextAttribute.argtypes = [ - wintypes.HANDLE, - wintypes.WORD, - ] - _SetConsoleTextAttribute.restype = wintypes.BOOL - - _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition - _SetConsoleCursorPosition.argtypes = [ - wintypes.HANDLE, - COORD, - ] - _SetConsoleCursorPosition.restype = wintypes.BOOL - - _FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA - _FillConsoleOutputCharacterA.argtypes = [ - wintypes.HANDLE, - c_char, - wintypes.DWORD, - COORD, - POINTER(wintypes.DWORD), - ] - _FillConsoleOutputCharacterA.restype = wintypes.BOOL - - _FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute - _FillConsoleOutputAttribute.argtypes = [ - wintypes.HANDLE, - wintypes.WORD, - wintypes.DWORD, - COORD, - POINTER(wintypes.DWORD), - ] - _FillConsoleOutputAttribute.restype = wintypes.BOOL - - _SetConsoleTitleW = windll.kernel32.SetConsoleTitleA - _SetConsoleTitleW.argtypes = [ - wintypes.LPCSTR - ] - _SetConsoleTitleW.restype = wintypes.BOOL - - handles = { - STDOUT: _GetStdHandle(STDOUT), - STDERR: _GetStdHandle(STDERR), - } - - def GetConsoleScreenBufferInfo(stream_id=STDOUT): - handle = handles[stream_id] - csbi = CONSOLE_SCREEN_BUFFER_INFO() - success = _GetConsoleScreenBufferInfo( - handle, byref(csbi)) - return csbi - - def SetConsoleTextAttribute(stream_id, attrs): - handle = handles[stream_id] - return _SetConsoleTextAttribute(handle, attrs) - - def SetConsoleCursorPosition(stream_id, position, adjust=True): - position = COORD(*position) - # If the position is out of range, do nothing. - if position.Y <= 0 or position.X <= 0: - return - # Adjust for Windows' SetConsoleCursorPosition: - # 1. being 0-based, while ANSI is 1-based. - # 2. expecting (x,y), while ANSI uses (y,x). - adjusted_position = COORD(position.Y - 1, position.X - 1) - if adjust: - # Adjust for viewport's scroll position - sr = GetConsoleScreenBufferInfo(STDOUT).srWindow - adjusted_position.Y += sr.Top - adjusted_position.X += sr.Left - # Resume normal processing - handle = handles[stream_id] - return _SetConsoleCursorPosition(handle, adjusted_position) - - def FillConsoleOutputCharacter(stream_id, char, length, start): - handle = handles[stream_id] - char = c_char(char.encode()) - length = wintypes.DWORD(length) - num_written = wintypes.DWORD(0) - # Note that this is hard-coded for ANSI (vs wide) bytes. - success = _FillConsoleOutputCharacterA( - handle, char, length, start, byref(num_written)) - return num_written.value - - def FillConsoleOutputAttribute(stream_id, attr, length, start): - ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' - handle = handles[stream_id] - attribute = wintypes.WORD(attr) - length = wintypes.DWORD(length) - num_written = wintypes.DWORD(0) - # Note that this is hard-coded for ANSI (vs wide) bytes. - return _FillConsoleOutputAttribute( - handle, attribute, length, start, byref(num_written)) - - def SetConsoleTitle(title): - return _SetConsoleTitleW(title) diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/winterm.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/winterm.py deleted file mode 100644 index fcc774f..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/colorama/winterm.py +++ /dev/null @@ -1,151 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -from . import win32 - - -# from wincon.h -class WinColor(object): - BLACK = 0 - BLUE = 1 - GREEN = 2 - CYAN = 3 - RED = 4 - MAGENTA = 5 - YELLOW = 6 - GREY = 7 - -# from wincon.h -class WinStyle(object): - NORMAL = 0x00 # dim text, dim background - BRIGHT = 0x08 # bright text, dim background - BRIGHT_BACKGROUND = 0x80 # dim text, bright background - -class WinTerm(object): - - def __init__(self): - self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes - self.set_attrs(self._default) - self._default_fore = self._fore - self._default_back = self._back - self._default_style = self._style - - def get_attrs(self): - return self._fore + self._back * 16 + self._style - - def set_attrs(self, value): - self._fore = value & 7 - self._back = (value >> 4) & 7 - self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND) - - def reset_all(self, on_stderr=None): - self.set_attrs(self._default) - self.set_console(attrs=self._default) - - def fore(self, fore=None, light=False, on_stderr=False): - if fore is None: - fore = self._default_fore - self._fore = fore - if light: - self._style |= WinStyle.BRIGHT - self.set_console(on_stderr=on_stderr) - - def back(self, back=None, light=False, on_stderr=False): - if back is None: - back = self._default_back - self._back = back - if light: - self._style |= WinStyle.BRIGHT_BACKGROUND - self.set_console(on_stderr=on_stderr) - - def style(self, style=None, on_stderr=False): - if style is None: - style = self._default_style - self._style = style - self.set_console(on_stderr=on_stderr) - - def set_console(self, attrs=None, on_stderr=False): - if attrs is None: - attrs = self.get_attrs() - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - win32.SetConsoleTextAttribute(handle, attrs) - - def get_position(self, handle): - position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition - # Because Windows coordinates are 0-based, - # and win32.SetConsoleCursorPosition expects 1-based. - position.X += 1 - position.Y += 1 - return position - - def set_cursor_position(self, position=None, on_stderr=False): - if position is None: - #I'm not currently tracking the position, so there is no default. - #position = self.get_position() - return - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - win32.SetConsoleCursorPosition(handle, position) - - def cursor_adjust(self, x, y, on_stderr=False): - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - position = self.get_position(handle) - adjusted_position = (position.Y + y, position.X + x) - win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False) - - def erase_screen(self, mode=0, on_stderr=False): - # 0 should clear from the cursor to the end of the screen. - # 1 should clear from the cursor to the beginning of the screen. - # 2 should clear the entire screen, and move cursor to (1,1) - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - csbi = win32.GetConsoleScreenBufferInfo(handle) - # get the number of character cells in the current buffer - cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y - # get number of character cells before current cursor position - cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X - if mode == 0: - from_coord = csbi.dwCursorPosition - cells_to_erase = cells_in_screen - cells_before_cursor - if mode == 1: - from_coord = win32.COORD(0, 0) - cells_to_erase = cells_before_cursor - elif mode == 2: - from_coord = win32.COORD(0, 0) - cells_to_erase = cells_in_screen - # fill the entire screen with blanks - win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) - # now set the buffer's attributes accordingly - win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) - if mode == 2: - # put the cursor where needed - win32.SetConsoleCursorPosition(handle, (1, 1)) - - def erase_line(self, mode=0, on_stderr=False): - # 0 should clear from the cursor to the end of the line. - # 1 should clear from the cursor to the beginning of the line. - # 2 should clear the entire line. - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - csbi = win32.GetConsoleScreenBufferInfo(handle) - if mode == 0: - from_coord = csbi.dwCursorPosition - cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X - if mode == 1: - from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) - cells_to_erase = csbi.dwCursorPosition.X - elif mode == 2: - from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) - cells_to_erase = csbi.dwSize.X - # fill the entire screen with blanks - win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) - # now set the buffer's attributes accordingly - win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) - - def set_title(self, title): - win32.SetConsoleTitle(title) diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/__init__.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/__init__.py deleted file mode 100644 index 20a4e0c..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012-2014 Vinay Sajip. -# Licensed to the Python Software Foundation under a contributor agreement. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -import logging - -__version__ = '0.2.1' - -class DistlibException(Exception): - pass - -try: - from logging import NullHandler -except ImportError: # pragma: no cover - class NullHandler(logging.Handler): - def handle(self, record): pass - def emit(self, record): pass - def createLock(self): self.lock = None - -logger = logging.getLogger(__name__) -logger.addHandler(NullHandler()) diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/__init__.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/__init__.py deleted file mode 100644 index f7dbf4c..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -"""Modules copied from Python 3 standard libraries, for internal use only. - -Individual classes and functions are found in d2._backport.misc. Intended -usage is to always import things missing from 3.1 from that module: the -built-in/stdlib objects will be used if found. -""" diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/misc.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/misc.py deleted file mode 100644 index cfb318d..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/misc.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012 The Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -"""Backports for individual classes and functions.""" - -import os -import sys - -__all__ = ['cache_from_source', 'callable', 'fsencode'] - - -try: - from imp import cache_from_source -except ImportError: - def cache_from_source(py_file, debug=__debug__): - ext = debug and 'c' or 'o' - return py_file + ext - - -try: - callable = callable -except NameError: - from collections import Callable - - def callable(obj): - return isinstance(obj, Callable) - - -try: - fsencode = os.fsencode -except AttributeError: - def fsencode(filename): - if isinstance(filename, bytes): - return filename - elif isinstance(filename, str): - return filename.encode(sys.getfilesystemencoding()) - else: - raise TypeError("expect bytes or str, not %s" % - type(filename).__name__) diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/shutil.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/shutil.py deleted file mode 100644 index 9e2e234..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/shutil.py +++ /dev/null @@ -1,761 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012 The Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -"""Utility functions for copying and archiving files and directory trees. - -XXX The functions here don't copy the resource fork or other metadata on Mac. - -""" - -import os -import sys -import stat -from os.path import abspath -import fnmatch -import collections -import errno -from . import tarfile - -try: - import bz2 - _BZ2_SUPPORTED = True -except ImportError: - _BZ2_SUPPORTED = False - -try: - from pwd import getpwnam -except ImportError: - getpwnam = None - -try: - from grp import getgrnam -except ImportError: - getgrnam = None - -__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2", - "copytree", "move", "rmtree", "Error", "SpecialFileError", - "ExecError", "make_archive", "get_archive_formats", - "register_archive_format", "unregister_archive_format", - "get_unpack_formats", "register_unpack_format", - "unregister_unpack_format", "unpack_archive", "ignore_patterns"] - -class Error(EnvironmentError): - pass - -class SpecialFileError(EnvironmentError): - """Raised when trying to do a kind of operation (e.g. copying) which is - not supported on a special file (e.g. a named pipe)""" - -class ExecError(EnvironmentError): - """Raised when a command could not be executed""" - -class ReadError(EnvironmentError): - """Raised when an archive cannot be read""" - -class RegistryError(Exception): - """Raised when a registery operation with the archiving - and unpacking registeries fails""" - - -try: - WindowsError -except NameError: - WindowsError = None - -def copyfileobj(fsrc, fdst, length=16*1024): - """copy data from file-like object fsrc to file-like object fdst""" - while 1: - buf = fsrc.read(length) - if not buf: - break - fdst.write(buf) - -def _samefile(src, dst): - # Macintosh, Unix. - if hasattr(os.path, 'samefile'): - try: - return os.path.samefile(src, dst) - except OSError: - return False - - # All other platforms: check for same pathname. - return (os.path.normcase(os.path.abspath(src)) == - os.path.normcase(os.path.abspath(dst))) - -def copyfile(src, dst): - """Copy data from src to dst""" - if _samefile(src, dst): - raise Error("`%s` and `%s` are the same file" % (src, dst)) - - for fn in [src, dst]: - try: - st = os.stat(fn) - except OSError: - # File most likely does not exist - pass - else: - # XXX What about other special files? (sockets, devices...) - if stat.S_ISFIFO(st.st_mode): - raise SpecialFileError("`%s` is a named pipe" % fn) - - with open(src, 'rb') as fsrc: - with open(dst, 'wb') as fdst: - copyfileobj(fsrc, fdst) - -def copymode(src, dst): - """Copy mode bits from src to dst""" - if hasattr(os, 'chmod'): - st = os.stat(src) - mode = stat.S_IMODE(st.st_mode) - os.chmod(dst, mode) - -def copystat(src, dst): - """Copy all stat info (mode bits, atime, mtime, flags) from src to dst""" - st = os.stat(src) - mode = stat.S_IMODE(st.st_mode) - if hasattr(os, 'utime'): - os.utime(dst, (st.st_atime, st.st_mtime)) - if hasattr(os, 'chmod'): - os.chmod(dst, mode) - if hasattr(os, 'chflags') and hasattr(st, 'st_flags'): - try: - os.chflags(dst, st.st_flags) - except OSError as why: - if (not hasattr(errno, 'EOPNOTSUPP') or - why.errno != errno.EOPNOTSUPP): - raise - -def copy(src, dst): - """Copy data and mode bits ("cp src dst"). - - The destination may be a directory. - - """ - if os.path.isdir(dst): - dst = os.path.join(dst, os.path.basename(src)) - copyfile(src, dst) - copymode(src, dst) - -def copy2(src, dst): - """Copy data and all stat info ("cp -p src dst"). - - The destination may be a directory. - - """ - if os.path.isdir(dst): - dst = os.path.join(dst, os.path.basename(src)) - copyfile(src, dst) - copystat(src, dst) - -def ignore_patterns(*patterns): - """Function that can be used as copytree() ignore parameter. - - Patterns is a sequence of glob-style patterns - that are used to exclude files""" - def _ignore_patterns(path, names): - ignored_names = [] - for pattern in patterns: - ignored_names.extend(fnmatch.filter(names, pattern)) - return set(ignored_names) - return _ignore_patterns - -def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, - ignore_dangling_symlinks=False): - """Recursively copy a directory tree. - - The destination directory must not already exist. - If exception(s) occur, an Error is raised with a list of reasons. - - If the optional symlinks flag is true, symbolic links in the - source tree result in symbolic links in the destination tree; if - it is false, the contents of the files pointed to by symbolic - links are copied. If the file pointed by the symlink doesn't - exist, an exception will be added in the list of errors raised in - an Error exception at the end of the copy process. - - You can set the optional ignore_dangling_symlinks flag to true if you - want to silence this exception. Notice that this has no effect on - platforms that don't support os.symlink. - - The optional ignore argument is a callable. If given, it - is called with the `src` parameter, which is the directory - being visited by copytree(), and `names` which is the list of - `src` contents, as returned by os.listdir(): - - callable(src, names) -> ignored_names - - Since copytree() is called recursively, the callable will be - called once for each directory that is copied. It returns a - list of names relative to the `src` directory that should - not be copied. - - The optional copy_function argument is a callable that will be used - to copy each file. It will be called with the source path and the - destination path as arguments. By default, copy2() is used, but any - function that supports the same signature (like copy()) can be used. - - """ - names = os.listdir(src) - if ignore is not None: - ignored_names = ignore(src, names) - else: - ignored_names = set() - - os.makedirs(dst) - errors = [] - for name in names: - if name in ignored_names: - continue - srcname = os.path.join(src, name) - dstname = os.path.join(dst, name) - try: - if os.path.islink(srcname): - linkto = os.readlink(srcname) - if symlinks: - os.symlink(linkto, dstname) - else: - # ignore dangling symlink if the flag is on - if not os.path.exists(linkto) and ignore_dangling_symlinks: - continue - # otherwise let the copy occurs. copy2 will raise an error - copy_function(srcname, dstname) - elif os.path.isdir(srcname): - copytree(srcname, dstname, symlinks, ignore, copy_function) - else: - # Will raise a SpecialFileError for unsupported file types - copy_function(srcname, dstname) - # catch the Error from the recursive copytree so that we can - # continue with other files - except Error as err: - errors.extend(err.args[0]) - except EnvironmentError as why: - errors.append((srcname, dstname, str(why))) - try: - copystat(src, dst) - except OSError as why: - if WindowsError is not None and isinstance(why, WindowsError): - # Copying file access times may fail on Windows - pass - else: - errors.extend((src, dst, str(why))) - if errors: - raise Error(errors) - -def rmtree(path, ignore_errors=False, onerror=None): - """Recursively delete a directory tree. - - If ignore_errors is set, errors are ignored; otherwise, if onerror - is set, it is called to handle the error with arguments (func, - path, exc_info) where func is os.listdir, os.remove, or os.rmdir; - path is the argument to that function that caused it to fail; and - exc_info is a tuple returned by sys.exc_info(). If ignore_errors - is false and onerror is None, an exception is raised. - - """ - if ignore_errors: - def onerror(*args): - pass - elif onerror is None: - def onerror(*args): - raise - try: - if os.path.islink(path): - # symlinks to directories are forbidden, see bug #1669 - raise OSError("Cannot call rmtree on a symbolic link") - except OSError: - onerror(os.path.islink, path, sys.exc_info()) - # can't continue even if onerror hook returns - return - names = [] - try: - names = os.listdir(path) - except os.error: - onerror(os.listdir, path, sys.exc_info()) - for name in names: - fullname = os.path.join(path, name) - try: - mode = os.lstat(fullname).st_mode - except os.error: - mode = 0 - if stat.S_ISDIR(mode): - rmtree(fullname, ignore_errors, onerror) - else: - try: - os.remove(fullname) - except os.error: - onerror(os.remove, fullname, sys.exc_info()) - try: - os.rmdir(path) - except os.error: - onerror(os.rmdir, path, sys.exc_info()) - - -def _basename(path): - # A basename() variant which first strips the trailing slash, if present. - # Thus we always get the last component of the path, even for directories. - return os.path.basename(path.rstrip(os.path.sep)) - -def move(src, dst): - """Recursively move a file or directory to another location. This is - similar to the Unix "mv" command. - - If the destination is a directory or a symlink to a directory, the source - is moved inside the directory. The destination path must not already - exist. - - If the destination already exists but is not a directory, it may be - overwritten depending on os.rename() semantics. - - If the destination is on our current filesystem, then rename() is used. - Otherwise, src is copied to the destination and then removed. - A lot more could be done here... A look at a mv.c shows a lot of - the issues this implementation glosses over. - - """ - real_dst = dst - if os.path.isdir(dst): - if _samefile(src, dst): - # We might be on a case insensitive filesystem, - # perform the rename anyway. - os.rename(src, dst) - return - - real_dst = os.path.join(dst, _basename(src)) - if os.path.exists(real_dst): - raise Error("Destination path '%s' already exists" % real_dst) - try: - os.rename(src, real_dst) - except OSError: - if os.path.isdir(src): - if _destinsrc(src, dst): - raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst)) - copytree(src, real_dst, symlinks=True) - rmtree(src) - else: - copy2(src, real_dst) - os.unlink(src) - -def _destinsrc(src, dst): - src = abspath(src) - dst = abspath(dst) - if not src.endswith(os.path.sep): - src += os.path.sep - if not dst.endswith(os.path.sep): - dst += os.path.sep - return dst.startswith(src) - -def _get_gid(name): - """Returns a gid, given a group name.""" - if getgrnam is None or name is None: - return None - try: - result = getgrnam(name) - except KeyError: - result = None - if result is not None: - return result[2] - return None - -def _get_uid(name): - """Returns an uid, given a user name.""" - if getpwnam is None or name is None: - return None - try: - result = getpwnam(name) - except KeyError: - result = None - if result is not None: - return result[2] - return None - -def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0, - owner=None, group=None, logger=None): - """Create a (possibly compressed) tar file from all the files under - 'base_dir'. - - 'compress' must be "gzip" (the default), "bzip2", or None. - - 'owner' and 'group' can be used to define an owner and a group for the - archive that is being built. If not provided, the current owner and group - will be used. - - The output tar file will be named 'base_name' + ".tar", possibly plus - the appropriate compression extension (".gz", or ".bz2"). - - Returns the output filename. - """ - tar_compression = {'gzip': 'gz', None: ''} - compress_ext = {'gzip': '.gz'} - - if _BZ2_SUPPORTED: - tar_compression['bzip2'] = 'bz2' - compress_ext['bzip2'] = '.bz2' - - # flags for compression program, each element of list will be an argument - if compress is not None and compress not in compress_ext: - raise ValueError("bad value for 'compress', or compression format not " - "supported : {0}".format(compress)) - - archive_name = base_name + '.tar' + compress_ext.get(compress, '') - archive_dir = os.path.dirname(archive_name) - - if not os.path.exists(archive_dir): - if logger is not None: - logger.info("creating %s", archive_dir) - if not dry_run: - os.makedirs(archive_dir) - - # creating the tarball - if logger is not None: - logger.info('Creating tar archive') - - uid = _get_uid(owner) - gid = _get_gid(group) - - def _set_uid_gid(tarinfo): - if gid is not None: - tarinfo.gid = gid - tarinfo.gname = group - if uid is not None: - tarinfo.uid = uid - tarinfo.uname = owner - return tarinfo - - if not dry_run: - tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress]) - try: - tar.add(base_dir, filter=_set_uid_gid) - finally: - tar.close() - - return archive_name - -def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False): - # XXX see if we want to keep an external call here - if verbose: - zipoptions = "-r" - else: - zipoptions = "-rq" - from distutils.errors import DistutilsExecError - from distutils.spawn import spawn - try: - spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run) - except DistutilsExecError: - # XXX really should distinguish between "couldn't find - # external 'zip' command" and "zip failed". - raise ExecError("unable to create zip file '%s': " - "could neither import the 'zipfile' module nor " - "find a standalone zip utility") % zip_filename - -def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None): - """Create a zip file from all the files under 'base_dir'. - - The output zip file will be named 'base_name' + ".zip". Uses either the - "zipfile" Python module (if available) or the InfoZIP "zip" utility - (if installed and found on the default search path). If neither tool is - available, raises ExecError. Returns the name of the output zip - file. - """ - zip_filename = base_name + ".zip" - archive_dir = os.path.dirname(base_name) - - if not os.path.exists(archive_dir): - if logger is not None: - logger.info("creating %s", archive_dir) - if not dry_run: - os.makedirs(archive_dir) - - # If zipfile module is not available, try spawning an external 'zip' - # command. - try: - import zipfile - except ImportError: - zipfile = None - - if zipfile is None: - _call_external_zip(base_dir, zip_filename, verbose, dry_run) - else: - if logger is not None: - logger.info("creating '%s' and adding '%s' to it", - zip_filename, base_dir) - - if not dry_run: - zip = zipfile.ZipFile(zip_filename, "w", - compression=zipfile.ZIP_DEFLATED) - - for dirpath, dirnames, filenames in os.walk(base_dir): - for name in filenames: - path = os.path.normpath(os.path.join(dirpath, name)) - if os.path.isfile(path): - zip.write(path, path) - if logger is not None: - logger.info("adding '%s'", path) - zip.close() - - return zip_filename - -_ARCHIVE_FORMATS = { - 'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"), - 'bztar': (_make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"), - 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"), - 'zip': (_make_zipfile, [], "ZIP file"), - } - -if _BZ2_SUPPORTED: - _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')], - "bzip2'ed tar-file") - -def get_archive_formats(): - """Returns a list of supported formats for archiving and unarchiving. - - Each element of the returned sequence is a tuple (name, description) - """ - formats = [(name, registry[2]) for name, registry in - _ARCHIVE_FORMATS.items()] - formats.sort() - return formats - -def register_archive_format(name, function, extra_args=None, description=''): - """Registers an archive format. - - name is the name of the format. function is the callable that will be - used to create archives. If provided, extra_args is a sequence of - (name, value) tuples that will be passed as arguments to the callable. - description can be provided to describe the format, and will be returned - by the get_archive_formats() function. - """ - if extra_args is None: - extra_args = [] - if not isinstance(function, collections.Callable): - raise TypeError('The %s object is not callable' % function) - if not isinstance(extra_args, (tuple, list)): - raise TypeError('extra_args needs to be a sequence') - for element in extra_args: - if not isinstance(element, (tuple, list)) or len(element) !=2: - raise TypeError('extra_args elements are : (arg_name, value)') - - _ARCHIVE_FORMATS[name] = (function, extra_args, description) - -def unregister_archive_format(name): - del _ARCHIVE_FORMATS[name] - -def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, - dry_run=0, owner=None, group=None, logger=None): - """Create an archive file (eg. zip or tar). - - 'base_name' is the name of the file to create, minus any format-specific - extension; 'format' is the archive format: one of "zip", "tar", "bztar" - or "gztar". - - 'root_dir' is a directory that will be the root directory of the - archive; ie. we typically chdir into 'root_dir' before creating the - archive. 'base_dir' is the directory where we start archiving from; - ie. 'base_dir' will be the common prefix of all files and - directories in the archive. 'root_dir' and 'base_dir' both default - to the current directory. Returns the name of the archive file. - - 'owner' and 'group' are used when creating a tar archive. By default, - uses the current owner and group. - """ - save_cwd = os.getcwd() - if root_dir is not None: - if logger is not None: - logger.debug("changing into '%s'", root_dir) - base_name = os.path.abspath(base_name) - if not dry_run: - os.chdir(root_dir) - - if base_dir is None: - base_dir = os.curdir - - kwargs = {'dry_run': dry_run, 'logger': logger} - - try: - format_info = _ARCHIVE_FORMATS[format] - except KeyError: - raise ValueError("unknown archive format '%s'" % format) - - func = format_info[0] - for arg, val in format_info[1]: - kwargs[arg] = val - - if format != 'zip': - kwargs['owner'] = owner - kwargs['group'] = group - - try: - filename = func(base_name, base_dir, **kwargs) - finally: - if root_dir is not None: - if logger is not None: - logger.debug("changing back to '%s'", save_cwd) - os.chdir(save_cwd) - - return filename - - -def get_unpack_formats(): - """Returns a list of supported formats for unpacking. - - Each element of the returned sequence is a tuple - (name, extensions, description) - """ - formats = [(name, info[0], info[3]) for name, info in - _UNPACK_FORMATS.items()] - formats.sort() - return formats - -def _check_unpack_options(extensions, function, extra_args): - """Checks what gets registered as an unpacker.""" - # first make sure no other unpacker is registered for this extension - existing_extensions = {} - for name, info in _UNPACK_FORMATS.items(): - for ext in info[0]: - existing_extensions[ext] = name - - for extension in extensions: - if extension in existing_extensions: - msg = '%s is already registered for "%s"' - raise RegistryError(msg % (extension, - existing_extensions[extension])) - - if not isinstance(function, collections.Callable): - raise TypeError('The registered function must be a callable') - - -def register_unpack_format(name, extensions, function, extra_args=None, - description=''): - """Registers an unpack format. - - `name` is the name of the format. `extensions` is a list of extensions - corresponding to the format. - - `function` is the callable that will be - used to unpack archives. The callable will receive archives to unpack. - If it's unable to handle an archive, it needs to raise a ReadError - exception. - - If provided, `extra_args` is a sequence of - (name, value) tuples that will be passed as arguments to the callable. - description can be provided to describe the format, and will be returned - by the get_unpack_formats() function. - """ - if extra_args is None: - extra_args = [] - _check_unpack_options(extensions, function, extra_args) - _UNPACK_FORMATS[name] = extensions, function, extra_args, description - -def unregister_unpack_format(name): - """Removes the pack format from the registery.""" - del _UNPACK_FORMATS[name] - -def _ensure_directory(path): - """Ensure that the parent directory of `path` exists""" - dirname = os.path.dirname(path) - if not os.path.isdir(dirname): - os.makedirs(dirname) - -def _unpack_zipfile(filename, extract_dir): - """Unpack zip `filename` to `extract_dir` - """ - try: - import zipfile - except ImportError: - raise ReadError('zlib not supported, cannot unpack this archive.') - - if not zipfile.is_zipfile(filename): - raise ReadError("%s is not a zip file" % filename) - - zip = zipfile.ZipFile(filename) - try: - for info in zip.infolist(): - name = info.filename - - # don't extract absolute paths or ones with .. in them - if name.startswith('/') or '..' in name: - continue - - target = os.path.join(extract_dir, *name.split('/')) - if not target: - continue - - _ensure_directory(target) - if not name.endswith('/'): - # file - data = zip.read(info.filename) - f = open(target, 'wb') - try: - f.write(data) - finally: - f.close() - del data - finally: - zip.close() - -def _unpack_tarfile(filename, extract_dir): - """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir` - """ - try: - tarobj = tarfile.open(filename) - except tarfile.TarError: - raise ReadError( - "%s is not a compressed or uncompressed tar file" % filename) - try: - tarobj.extractall(extract_dir) - finally: - tarobj.close() - -_UNPACK_FORMATS = { - 'gztar': (['.tar.gz', '.tgz'], _unpack_tarfile, [], "gzip'ed tar-file"), - 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"), - 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file") - } - -if _BZ2_SUPPORTED: - _UNPACK_FORMATS['bztar'] = (['.bz2'], _unpack_tarfile, [], - "bzip2'ed tar-file") - -def _find_unpack_format(filename): - for name, info in _UNPACK_FORMATS.items(): - for extension in info[0]: - if filename.endswith(extension): - return name - return None - -def unpack_archive(filename, extract_dir=None, format=None): - """Unpack an archive. - - `filename` is the name of the archive. - - `extract_dir` is the name of the target directory, where the archive - is unpacked. If not provided, the current working directory is used. - - `format` is the archive format: one of "zip", "tar", or "gztar". Or any - other registered format. If not provided, unpack_archive will use the - filename extension and see if an unpacker was registered for that - extension. - - In case none is found, a ValueError is raised. - """ - if extract_dir is None: - extract_dir = os.getcwd() - - if format is not None: - try: - format_info = _UNPACK_FORMATS[format] - except KeyError: - raise ValueError("Unknown unpack format '{0}'".format(format)) - - func = format_info[1] - func(filename, extract_dir, **dict(format_info[2])) - else: - # we need to look at the registered unpackers supported extensions - format = _find_unpack_format(filename) - if format is None: - raise ReadError("Unknown archive format '{0}'".format(filename)) - - func = _UNPACK_FORMATS[format][1] - kwargs = dict(_UNPACK_FORMATS[format][2]) - func(filename, extract_dir, **kwargs) diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg deleted file mode 100644 index 1746bd0..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg +++ /dev/null @@ -1,84 +0,0 @@ -[posix_prefix] -# Configuration directories. Some of these come straight out of the -# configure script. They are for implementing the other variables, not to -# be used directly in [resource_locations]. -confdir = /etc -datadir = /usr/share -libdir = /usr/lib -statedir = /var -# User resource directory -local = ~/.local/{distribution.name} - -stdlib = {base}/lib/python{py_version_short} -platstdlib = {platbase}/lib/python{py_version_short} -purelib = {base}/lib/python{py_version_short}/site-packages -platlib = {platbase}/lib/python{py_version_short}/site-packages -include = {base}/include/python{py_version_short}{abiflags} -platinclude = {platbase}/include/python{py_version_short}{abiflags} -data = {base} - -[posix_home] -stdlib = {base}/lib/python -platstdlib = {base}/lib/python -purelib = {base}/lib/python -platlib = {base}/lib/python -include = {base}/include/python -platinclude = {base}/include/python -scripts = {base}/bin -data = {base} - -[nt] -stdlib = {base}/Lib -platstdlib = {base}/Lib -purelib = {base}/Lib/site-packages -platlib = {base}/Lib/site-packages -include = {base}/Include -platinclude = {base}/Include -scripts = {base}/Scripts -data = {base} - -[os2] -stdlib = {base}/Lib -platstdlib = {base}/Lib -purelib = {base}/Lib/site-packages -platlib = {base}/Lib/site-packages -include = {base}/Include -platinclude = {base}/Include -scripts = {base}/Scripts -data = {base} - -[os2_home] -stdlib = {userbase}/lib/python{py_version_short} -platstdlib = {userbase}/lib/python{py_version_short} -purelib = {userbase}/lib/python{py_version_short}/site-packages -platlib = {userbase}/lib/python{py_version_short}/site-packages -include = {userbase}/include/python{py_version_short} -scripts = {userbase}/bin -data = {userbase} - -[nt_user] -stdlib = {userbase}/Python{py_version_nodot} -platstdlib = {userbase}/Python{py_version_nodot} -purelib = {userbase}/Python{py_version_nodot}/site-packages -platlib = {userbase}/Python{py_version_nodot}/site-packages -include = {userbase}/Python{py_version_nodot}/Include -scripts = {userbase}/Scripts -data = {userbase} - -[posix_user] -stdlib = {userbase}/lib/python{py_version_short} -platstdlib = {userbase}/lib/python{py_version_short} -purelib = {userbase}/lib/python{py_version_short}/site-packages -platlib = {userbase}/lib/python{py_version_short}/site-packages -include = {userbase}/include/python{py_version_short} -scripts = {userbase}/bin -data = {userbase} - -[osx_framework_user] -stdlib = {userbase}/lib/python -platstdlib = {userbase}/lib/python -purelib = {userbase}/lib/python/site-packages -platlib = {userbase}/lib/python/site-packages -include = {userbase}/include -scripts = {userbase}/bin -data = {userbase} diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/sysconfig.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/sysconfig.py deleted file mode 100644 index 1d31326..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/sysconfig.py +++ /dev/null @@ -1,788 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012 The Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -"""Access to Python's configuration information.""" - -import codecs -import os -import re -import sys -from os.path import pardir, realpath -try: - import configparser -except ImportError: - import ConfigParser as configparser - - -__all__ = [ - 'get_config_h_filename', - 'get_config_var', - 'get_config_vars', - 'get_makefile_filename', - 'get_path', - 'get_path_names', - 'get_paths', - 'get_platform', - 'get_python_version', - 'get_scheme_names', - 'parse_config_h', -] - - -def _safe_realpath(path): - try: - return realpath(path) - except OSError: - return path - - -if sys.executable: - _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable)) -else: - # sys.executable can be empty if argv[0] has been changed and Python is - # unable to retrieve the real program name - _PROJECT_BASE = _safe_realpath(os.getcwd()) - -if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower(): - _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir)) -# PC/VS7.1 -if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower(): - _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir)) -# PC/AMD64 -if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower(): - _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir)) - - -def is_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 = is_python_build() - -_cfg_read = False - -def _ensure_cfg_read(): - global _cfg_read - if not _cfg_read: - from ..resources import finder - backport_package = __name__.rsplit('.', 1)[0] - _finder = finder(backport_package) - _cfgfile = _finder.find('sysconfig.cfg') - assert _cfgfile, 'sysconfig.cfg exists' - with _cfgfile.as_stream() as s: - _SCHEMES.readfp(s) - if _PYTHON_BUILD: - for scheme in ('posix_prefix', 'posix_home'): - _SCHEMES.set(scheme, 'include', '{srcdir}/Include') - _SCHEMES.set(scheme, 'platinclude', '{projectbase}/.') - - _cfg_read = True - - -_SCHEMES = configparser.RawConfigParser() -_VAR_REPL = re.compile(r'\{([^{]*?)\}') - -def _expand_globals(config): - _ensure_cfg_read() - if config.has_section('globals'): - globals = config.items('globals') - else: - globals = tuple() - - sections = config.sections() - for section in sections: - if section == 'globals': - continue - for option, value in globals: - if config.has_option(section, option): - continue - config.set(section, option, value) - config.remove_section('globals') - - # now expanding local variables defined in the cfg file - # - for section in config.sections(): - variables = dict(config.items(section)) - - def _replacer(matchobj): - name = matchobj.group(1) - if name in variables: - return variables[name] - return matchobj.group(0) - - for option, value in config.items(section): - config.set(section, option, _VAR_REPL.sub(_replacer, value)) - -#_expand_globals(_SCHEMES) - - # FIXME don't rely on sys.version here, its format is an implementation detail - # of CPython, use sys.version_info or sys.hexversion -_PY_VERSION = sys.version.split()[0] -_PY_VERSION_SHORT = sys.version[:3] -_PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2] -_PREFIX = os.path.normpath(sys.prefix) -_EXEC_PREFIX = os.path.normpath(sys.exec_prefix) -_CONFIG_VARS = None -_USER_BASE = None - - -def _subst_vars(path, local_vars): - """In the string `path`, replace tokens like {some.thing} with the - corresponding value from the map `local_vars`. - - If there is no corresponding value, leave the token unchanged. - """ - def _replacer(matchobj): - name = matchobj.group(1) - if name in local_vars: - return local_vars[name] - elif name in os.environ: - return os.environ[name] - return matchobj.group(0) - return _VAR_REPL.sub(_replacer, path) - - -def _extend_dict(target_dict, other_dict): - target_keys = target_dict.keys() - for key, value in other_dict.items(): - if key in target_keys: - continue - target_dict[key] = value - - -def _expand_vars(scheme, vars): - res = {} - if vars is None: - vars = {} - _extend_dict(vars, get_config_vars()) - - for key, value in _SCHEMES.items(scheme): - if os.name in ('posix', 'nt'): - value = os.path.expanduser(value) - res[key] = os.path.normpath(_subst_vars(value, vars)) - return res - - -def format_value(value, vars): - def _replacer(matchobj): - name = matchobj.group(1) - if name in vars: - return vars[name] - return matchobj.group(0) - return _VAR_REPL.sub(_replacer, value) - - -def _get_default_scheme(): - if os.name == 'posix': - # the default scheme for posix is posix_prefix - return 'posix_prefix' - return os.name - - -def _getuserbase(): - env_base = os.environ.get("PYTHONUSERBASE", None) - - def joinuser(*args): - return os.path.expanduser(os.path.join(*args)) - - # what about 'os2emx', 'riscos' ? - if os.name == "nt": - base = os.environ.get("APPDATA") or "~" - if env_base: - return env_base - else: - return joinuser(base, "Python") - - if sys.platform == "darwin": - framework = get_config_var("PYTHONFRAMEWORK") - if framework: - if env_base: - return env_base - else: - return joinuser("~", "Library", framework, "%d.%d" % - sys.version_info[:2]) - - if env_base: - return env_base - else: - return joinuser("~", ".local") - - -def _parse_makefile(filename, vars=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. - """ - # 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_]*)}") - - if vars is None: - vars = {} - done = {} - notdone = {} - - with codecs.open(filename, encoding='utf-8', errors="surrogateescape") as f: - lines = f.readlines() - - for line in lines: - if line.startswith('#') or line.strip() == '': - continue - 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 - variables = list(notdone.keys()) - - # Variables with a 'PY_' prefix in the makefile. These need to - # be made available without that prefix through sysconfig. - # Special care is needed to ensure that variable expansion works, even - # if the expansion uses the name without a prefix. - renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS') - - while len(variables) > 0: - for name in tuple(variables): - value = notdone[name] - m = _findvar1_rx.search(value) or _findvar2_rx.search(value) - if m is not None: - 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] - - elif n in renamed_variables: - if (name.startswith('PY_') and - name[3:] in renamed_variables): - item = "" - - elif 'PY_' + n in notdone: - found = False - - else: - item = str(done['PY_' + 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 - variables.remove(name) - - if (name.startswith('PY_') and - name[3:] in renamed_variables): - - name = name[3:] - if name not in done: - done[name] = value - - else: - # bogus variable reference (e.g. "prefix=$/opt/python"); - # just drop it since we can't deal - done[name] = value - variables.remove(name) - - # strip spurious spaces - for k, v in done.items(): - if isinstance(v, str): - done[k] = v.strip() - - # save the results in the global dictionary - vars.update(done) - return vars - - -def get_makefile_filename(): - """Return the path of the Makefile.""" - if _PYTHON_BUILD: - return os.path.join(_PROJECT_BASE, "Makefile") - if hasattr(sys, 'abiflags'): - config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags) - else: - config_dir_name = 'config' - return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile') - - -def _init_posix(vars): - """Initialize the module as appropriate for POSIX systems.""" - # load the installed Makefile: - makefile = get_makefile_filename() - try: - _parse_makefile(makefile, vars) - except IOError as e: - msg = "invalid Python installation: unable to open %s" % makefile - if hasattr(e, "strerror"): - msg = msg + " (%s)" % e.strerror - raise IOError(msg) - # load the installed pyconfig.h: - config_h = get_config_h_filename() - try: - with open(config_h) as f: - parse_config_h(f, vars) - except IOError as e: - msg = "invalid Python installation: unable to open %s" % config_h - if hasattr(e, "strerror"): - msg = msg + " (%s)" % e.strerror - raise IOError(msg) - # On AIX, there are wrong paths to the linker scripts in the Makefile - # -- these paths are relative to the Python source, but when installed - # the scripts are in another directory. - if _PYTHON_BUILD: - vars['LDSHARED'] = vars['BLDSHARED'] - - -def _init_non_posix(vars): - """Initialize the module as appropriate for NT""" - # set basic install directories - vars['LIBDEST'] = get_path('stdlib') - vars['BINLIBDEST'] = get_path('platstdlib') - vars['INCLUDEPY'] = get_path('include') - vars['SO'] = '.pyd' - vars['EXE'] = '.exe' - vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT - vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable)) - -# -# public APIs -# - - -def parse_config_h(fp, vars=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 vars is None: - vars = {} - 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 True: - 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 - vars[n] = v - else: - m = undef_rx.match(line) - if m: - vars[m.group(1)] = 0 - return vars - - -def get_config_h_filename(): - """Return the path of pyconfig.h.""" - if _PYTHON_BUILD: - if os.name == "nt": - inc_dir = os.path.join(_PROJECT_BASE, "PC") - else: - inc_dir = _PROJECT_BASE - else: - inc_dir = get_path('platinclude') - return os.path.join(inc_dir, 'pyconfig.h') - - -def get_scheme_names(): - """Return a tuple containing the schemes names.""" - return tuple(sorted(_SCHEMES.sections())) - - -def get_path_names(): - """Return a tuple containing the paths names.""" - # xxx see if we want a static list - return _SCHEMES.options('posix_prefix') - - -def get_paths(scheme=_get_default_scheme(), vars=None, expand=True): - """Return a mapping containing an install scheme. - - ``scheme`` is the install scheme name. If not provided, it will - return the default scheme for the current platform. - """ - _ensure_cfg_read() - if expand: - return _expand_vars(scheme, vars) - else: - return dict(_SCHEMES.items(scheme)) - - -def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True): - """Return a path corresponding to the scheme. - - ``scheme`` is the install scheme name. - """ - return get_paths(scheme, vars, expand)[name] - - -def get_config_vars(*args): - """With no arguments, return a dictionary of all configuration - variables relevant for the current platform. - - 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: - _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 - # distutils2 module. - _CONFIG_VARS['prefix'] = _PREFIX - _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX - _CONFIG_VARS['py_version'] = _PY_VERSION - _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT - _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2] - _CONFIG_VARS['base'] = _PREFIX - _CONFIG_VARS['platbase'] = _EXEC_PREFIX - _CONFIG_VARS['projectbase'] = _PROJECT_BASE - try: - _CONFIG_VARS['abiflags'] = sys.abiflags - except AttributeError: - # sys.abiflags may not be defined on all platforms. - _CONFIG_VARS['abiflags'] = '' - - if os.name in ('nt', 'os2'): - _init_non_posix(_CONFIG_VARS) - if os.name == 'posix': - _init_posix(_CONFIG_VARS) - # Setting 'userbase' is done below the call to the - # init function to enable using 'get_config_var' in - # the init-function. - if sys.version >= '2.6': - _CONFIG_VARS['userbase'] = _getuserbase() - - if 'srcdir' not in _CONFIG_VARS: - _CONFIG_VARS['srcdir'] = _PROJECT_BASE - else: - _CONFIG_VARS['srcdir'] = _safe_realpath(_CONFIG_VARS['srcdir']) - - # Convert srcdir into an absolute path if it appears necessary. - # Normally it is relative to the build directory. However, during - # testing, for example, we might be running a non-installed python - # from a different directory. - if _PYTHON_BUILD and os.name == "posix": - base = _PROJECT_BASE - try: - cwd = os.getcwd() - except OSError: - cwd = None - if (not os.path.isabs(_CONFIG_VARS['srcdir']) and - base != cwd): - # srcdir is relative and we are not in the same directory - # as the executable. Assume executable is in the build - # directory and make srcdir absolute. - srcdir = os.path.join(base, _CONFIG_VARS['srcdir']) - _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir) - - if sys.platform == 'darwin': - kernel_version = os.uname()[2] # Kernel version (8.4.3) - major_version = int(kernel_version.split('.')[0]) - - if major_version < 8: - # 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. - for key in ('LDFLAGS', 'BASECFLAGS', - # a number of derived variables. These need to be - # patched up as well. - 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): - flags = _CONFIG_VARS[key] - flags = re.sub('-arch\s+\w+\s', ' ', flags) - flags = re.sub('-isysroot [^ \t]*', ' ', flags) - _CONFIG_VARS[key] = flags - else: - # Allow the user to override the architecture flags using - # an environment variable. - # 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 key in ('LDFLAGS', 'BASECFLAGS', - # a number of derived variables. These need to be - # patched up as well. - 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): - - flags = _CONFIG_VARS[key] - flags = re.sub('-arch\s+\w+\s', ' ', flags) - flags = flags + ' ' + arch - _CONFIG_VARS[key] = flags - - # If we're on OSX 10.5 or later and the user tries to - # compiles an extension using an SDK that is not present - # on the current machine it is better to not use an SDK - # than to fail. - # - # The major usecase for this is users using a Python.org - # binary installer on OSX 10.6: that installer uses - # the 10.4u SDK, but that SDK is not installed by default - # when you install Xcode. - # - CFLAGS = _CONFIG_VARS.get('CFLAGS', '') - m = re.search('-isysroot\s+(\S+)', CFLAGS) - if m is not None: - sdk = m.group(1) - if not os.path.exists(sdk): - for key in ('LDFLAGS', 'BASECFLAGS', - # a number of derived variables. These need to be - # patched up as well. - 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): - - flags = _CONFIG_VARS[key] - flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags) - _CONFIG_VARS[key] = flags - - 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) - - -def get_platform(): - """Return a string that identifies the current platform. - - This is used mainly to distinguish platform-specific build directories and - platform-specific built distributions. Typically includes the OS name - and version and the architecture (as supplied by 'os.uname()'), - although the exact information included depends on the OS; eg. for IRIX - the architecture isn't particularly important (IRIX only runs on SGI - hardware), but for Linux the kernel version isn't particularly - important. - - Examples of returned values: - linux-i586 - linux-alpha (?) - solaris-2.6-sun4u - irix-5.3 - irix64-6.2 - - Windows will return one of: - win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) - win-ia64 (64bit Windows on Itanium) - win32 (all others - specifically, sys.platform is returned) - - For other non-POSIX platforms, currently just returns 'sys.platform'. - """ - if os.name == 'nt': - # sniff sys.version for architecture. - prefix = " bit (" - i = sys.version.find(prefix) - if i == -1: - return sys.platform - j = sys.version.find(")", i) - look = sys.version[i+len(prefix):j].lower() - if look == 'amd64': - return 'win-amd64' - if look == 'itanium': - return 'win-ia64' - return sys.platform - - if os.name != "posix" or not hasattr(os, 'uname'): - # XXX what about the architecture? NT is Intel or Alpha, - # Mac OS is M68k or PPC, etc. - return sys.platform - - # Try to distinguish various flavours of Unix - osname, host, release, version, machine = os.uname() - - # Convert the OS name to lowercase, remove '/' characters - # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh") - osname = osname.lower().replace('/', '') - machine = machine.replace(' ', '_') - machine = machine.replace('/', '-') - - if osname[:5] == "linux": - # At least on Linux/Intel, 'machine' is the processor -- - # i386, etc. - # XXX what about Alpha, SPARC, etc? - return "%s-%s" % (osname, machine) - elif osname[:5] == "sunos": - if release[0] >= "5": # SunOS 5 == Solaris 2 - osname = "solaris" - release = "%d.%s" % (int(release[0]) - 3, release[2:]) - # 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": - # - # 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. - cfgvars = get_config_vars() - macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET') - - if True: - # Always calculate the release of the running machine, - # needed to determine if we can build fat binaries or not. - - macrelease = macver - # Get the system version. Reading this plist is a documented - # way to get the system version (see the documentation for - # the Gestalt Manager) - try: - f = open('/System/Library/CoreServices/SystemVersion.plist') - except IOError: - # We're on a plain darwin box, fall back to the default - # behaviour. - pass - else: - try: - m = re.search(r'ProductUserVisibleVersion\s*' - r'(.*?)', f.read()) - finally: - f.close() - if m is not None: - macrelease = '.'.join(m.group(1).split('.')[:2]) - # else: fall back to the default behaviour - - if not macver: - macver = macrelease - - if macver: - release = macver - osname = "macosx" - - if ((macrelease + '.') >= '10.4.' and - '-arch' in get_config_vars().get('CFLAGS', '').strip()): - # The universal build will build fat binaries, but not on - # systems before 10.4 - # - # Try to detect 4-way universal builds, those have machine-type - # 'universal' instead of 'fat'. - - machine = 'fat' - cflags = get_config_vars().get('CFLAGS') - - 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.maxsize >= 2**32: - machine = 'x86_64' - - elif machine in ('PowerPC', 'Power_Macintosh'): - # Pick a sane name for the PPC architecture. - # See 'i386' case - if sys.maxsize >= 2**32: - machine = 'ppc64' - else: - machine = 'ppc' - - return "%s-%s-%s" % (osname, release, machine) - - -def get_python_version(): - return _PY_VERSION_SHORT - - -def _print_dict(title, data): - for index, (key, value) in enumerate(sorted(data.items())): - if index == 0: - print('%s: ' % (title)) - print('\t%s = "%s"' % (key, value)) - - -def _main(): - """Display all information sysconfig detains.""" - print('Platform: "%s"' % get_platform()) - print('Python version: "%s"' % get_python_version()) - print('Current installation scheme: "%s"' % _get_default_scheme()) - print() - _print_dict('Paths', get_paths()) - print() - _print_dict('Variables', get_config_vars()) - - -if __name__ == '__main__': - _main() diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/tarfile.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/tarfile.py deleted file mode 100644 index 0580fb7..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/_backport/tarfile.py +++ /dev/null @@ -1,2607 +0,0 @@ -#------------------------------------------------------------------- -# tarfile.py -#------------------------------------------------------------------- -# Copyright (C) 2002 Lars Gustaebel -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation -# files (the "Software"), to deal in the Software without -# restriction, including without limitation the rights to use, -# copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following -# conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. -# -from __future__ import print_function - -"""Read from and write to tar format archives. -""" - -__version__ = "$Revision$" - -version = "0.9.0" -__author__ = "Lars Gust\u00e4bel (lars@gustaebel.de)" -__date__ = "$Date: 2011-02-25 17:42:01 +0200 (Fri, 25 Feb 2011) $" -__cvsid__ = "$Id: tarfile.py 88586 2011-02-25 15:42:01Z marc-andre.lemburg $" -__credits__ = "Gustavo Niemeyer, Niels Gust\u00e4bel, Richard Townsend." - -#--------- -# Imports -#--------- -import sys -import os -import stat -import errno -import time -import struct -import copy -import re - -try: - import grp, pwd -except ImportError: - grp = pwd = None - -# os.symlink on Windows prior to 6.0 raises NotImplementedError -symlink_exception = (AttributeError, NotImplementedError) -try: - # WindowsError (1314) will be raised if the caller does not hold the - # SeCreateSymbolicLinkPrivilege privilege - symlink_exception += (WindowsError,) -except NameError: - pass - -# from tarfile import * -__all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError"] - -if sys.version_info[0] < 3: - import __builtin__ as builtins -else: - import builtins - -_open = builtins.open # Since 'open' is TarFile.open - -#--------------------------------------------------------- -# tar constants -#--------------------------------------------------------- -NUL = b"\0" # the null character -BLOCKSIZE = 512 # length of processing blocks -RECORDSIZE = BLOCKSIZE * 20 # length of records -GNU_MAGIC = b"ustar \0" # magic gnu tar string -POSIX_MAGIC = b"ustar\x0000" # magic posix tar string - -LENGTH_NAME = 100 # maximum length of a filename -LENGTH_LINK = 100 # maximum length of a linkname -LENGTH_PREFIX = 155 # maximum length of the prefix field - -REGTYPE = b"0" # regular file -AREGTYPE = b"\0" # regular file -LNKTYPE = b"1" # link (inside tarfile) -SYMTYPE = b"2" # symbolic link -CHRTYPE = b"3" # character special device -BLKTYPE = b"4" # block special device -DIRTYPE = b"5" # directory -FIFOTYPE = b"6" # fifo special device -CONTTYPE = b"7" # contiguous file - -GNUTYPE_LONGNAME = b"L" # GNU tar longname -GNUTYPE_LONGLINK = b"K" # GNU tar longlink -GNUTYPE_SPARSE = b"S" # GNU tar sparse file - -XHDTYPE = b"x" # POSIX.1-2001 extended header -XGLTYPE = b"g" # POSIX.1-2001 global header -SOLARIS_XHDTYPE = b"X" # Solaris extended header - -USTAR_FORMAT = 0 # POSIX.1-1988 (ustar) format -GNU_FORMAT = 1 # GNU tar format -PAX_FORMAT = 2 # POSIX.1-2001 (pax) format -DEFAULT_FORMAT = GNU_FORMAT - -#--------------------------------------------------------- -# tarfile constants -#--------------------------------------------------------- -# File types that tarfile supports: -SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE, - SYMTYPE, DIRTYPE, FIFOTYPE, - CONTTYPE, CHRTYPE, BLKTYPE, - GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, - GNUTYPE_SPARSE) - -# File types that will be treated as a regular file. -REGULAR_TYPES = (REGTYPE, AREGTYPE, - CONTTYPE, GNUTYPE_SPARSE) - -# File types that are part of the GNU tar format. -GNU_TYPES = (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, - GNUTYPE_SPARSE) - -# Fields from a pax header that override a TarInfo attribute. -PAX_FIELDS = ("path", "linkpath", "size", "mtime", - "uid", "gid", "uname", "gname") - -# Fields from a pax header that are affected by hdrcharset. -PAX_NAME_FIELDS = set(("path", "linkpath", "uname", "gname")) - -# Fields in a pax header that are numbers, all other fields -# are treated as strings. -PAX_NUMBER_FIELDS = { - "atime": float, - "ctime": float, - "mtime": float, - "uid": int, - "gid": int, - "size": int -} - -#--------------------------------------------------------- -# Bits used in the mode field, values in octal. -#--------------------------------------------------------- -S_IFLNK = 0o120000 # symbolic link -S_IFREG = 0o100000 # regular file -S_IFBLK = 0o060000 # block device -S_IFDIR = 0o040000 # directory -S_IFCHR = 0o020000 # character device -S_IFIFO = 0o010000 # fifo - -TSUID = 0o4000 # set UID on execution -TSGID = 0o2000 # set GID on execution -TSVTX = 0o1000 # reserved - -TUREAD = 0o400 # read by owner -TUWRITE = 0o200 # write by owner -TUEXEC = 0o100 # execute/search by owner -TGREAD = 0o040 # read by group -TGWRITE = 0o020 # write by group -TGEXEC = 0o010 # execute/search by group -TOREAD = 0o004 # read by other -TOWRITE = 0o002 # write by other -TOEXEC = 0o001 # execute/search by other - -#--------------------------------------------------------- -# initialization -#--------------------------------------------------------- -if os.name in ("nt", "ce"): - ENCODING = "utf-8" -else: - ENCODING = sys.getfilesystemencoding() - -#--------------------------------------------------------- -# Some useful functions -#--------------------------------------------------------- - -def stn(s, length, encoding, errors): - """Convert a string to a null-terminated bytes object. - """ - s = s.encode(encoding, errors) - return s[:length] + (length - len(s)) * NUL - -def nts(s, encoding, errors): - """Convert a null-terminated bytes object to a string. - """ - p = s.find(b"\0") - if p != -1: - s = s[:p] - return s.decode(encoding, errors) - -def nti(s): - """Convert a number field to a python number. - """ - # There are two possible encodings for a number field, see - # itn() below. - if s[0] != chr(0o200): - try: - n = int(nts(s, "ascii", "strict") or "0", 8) - except ValueError: - raise InvalidHeaderError("invalid header") - else: - n = 0 - for i in range(len(s) - 1): - n <<= 8 - n += ord(s[i + 1]) - return n - -def itn(n, digits=8, format=DEFAULT_FORMAT): - """Convert a python number to a number field. - """ - # POSIX 1003.1-1988 requires numbers to be encoded as a string of - # octal digits followed by a null-byte, this allows values up to - # (8**(digits-1))-1. GNU tar allows storing numbers greater than - # that if necessary. A leading 0o200 byte indicates this particular - # encoding, the following digits-1 bytes are a big-endian - # representation. This allows values up to (256**(digits-1))-1. - if 0 <= n < 8 ** (digits - 1): - s = ("%0*o" % (digits - 1, n)).encode("ascii") + NUL - else: - if format != GNU_FORMAT or n >= 256 ** (digits - 1): - raise ValueError("overflow in number field") - - if n < 0: - # XXX We mimic GNU tar's behaviour with negative numbers, - # this could raise OverflowError. - n = struct.unpack("L", struct.pack("l", n))[0] - - s = bytearray() - for i in range(digits - 1): - s.insert(0, n & 0o377) - n >>= 8 - s.insert(0, 0o200) - return s - -def calc_chksums(buf): - """Calculate the checksum for a member's header by summing up all - characters except for the chksum field which is treated as if - it was filled with spaces. According to the GNU tar sources, - some tars (Sun and NeXT) calculate chksum with signed char, - which will be different if there are chars in the buffer with - the high bit set. So we calculate two checksums, unsigned and - signed. - """ - unsigned_chksum = 256 + sum(struct.unpack("148B", buf[:148]) + struct.unpack("356B", buf[156:512])) - signed_chksum = 256 + sum(struct.unpack("148b", buf[:148]) + struct.unpack("356b", buf[156:512])) - return unsigned_chksum, signed_chksum - -def copyfileobj(src, dst, length=None): - """Copy length bytes from fileobj src to fileobj dst. - If length is None, copy the entire content. - """ - if length == 0: - return - if length is None: - while True: - buf = src.read(16*1024) - if not buf: - break - dst.write(buf) - return - - BUFSIZE = 16 * 1024 - blocks, remainder = divmod(length, BUFSIZE) - for b in range(blocks): - buf = src.read(BUFSIZE) - if len(buf) < BUFSIZE: - raise IOError("end of file reached") - dst.write(buf) - - if remainder != 0: - buf = src.read(remainder) - if len(buf) < remainder: - raise IOError("end of file reached") - dst.write(buf) - return - -filemode_table = ( - ((S_IFLNK, "l"), - (S_IFREG, "-"), - (S_IFBLK, "b"), - (S_IFDIR, "d"), - (S_IFCHR, "c"), - (S_IFIFO, "p")), - - ((TUREAD, "r"),), - ((TUWRITE, "w"),), - ((TUEXEC|TSUID, "s"), - (TSUID, "S"), - (TUEXEC, "x")), - - ((TGREAD, "r"),), - ((TGWRITE, "w"),), - ((TGEXEC|TSGID, "s"), - (TSGID, "S"), - (TGEXEC, "x")), - - ((TOREAD, "r"),), - ((TOWRITE, "w"),), - ((TOEXEC|TSVTX, "t"), - (TSVTX, "T"), - (TOEXEC, "x")) -) - -def filemode(mode): - """Convert a file's mode to a string of the form - -rwxrwxrwx. - Used by TarFile.list() - """ - perm = [] - for table in filemode_table: - for bit, char in table: - if mode & bit == bit: - perm.append(char) - break - else: - perm.append("-") - return "".join(perm) - -class TarError(Exception): - """Base exception.""" - pass -class ExtractError(TarError): - """General exception for extract errors.""" - pass -class ReadError(TarError): - """Exception for unreadble tar archives.""" - pass -class CompressionError(TarError): - """Exception for unavailable compression methods.""" - pass -class StreamError(TarError): - """Exception for unsupported operations on stream-like TarFiles.""" - pass -class HeaderError(TarError): - """Base exception for header errors.""" - pass -class EmptyHeaderError(HeaderError): - """Exception for empty headers.""" - pass -class TruncatedHeaderError(HeaderError): - """Exception for truncated headers.""" - pass -class EOFHeaderError(HeaderError): - """Exception for end of file headers.""" - pass -class InvalidHeaderError(HeaderError): - """Exception for invalid headers.""" - pass -class SubsequentHeaderError(HeaderError): - """Exception for missing and invalid extended headers.""" - pass - -#--------------------------- -# internal stream interface -#--------------------------- -class _LowLevelFile(object): - """Low-level file object. Supports reading and writing. - It is used instead of a regular file object for streaming - access. - """ - - def __init__(self, name, mode): - mode = { - "r": os.O_RDONLY, - "w": os.O_WRONLY | os.O_CREAT | os.O_TRUNC, - }[mode] - if hasattr(os, "O_BINARY"): - mode |= os.O_BINARY - self.fd = os.open(name, mode, 0o666) - - def close(self): - os.close(self.fd) - - def read(self, size): - return os.read(self.fd, size) - - def write(self, s): - os.write(self.fd, s) - -class _Stream(object): - """Class that serves as an adapter between TarFile and - a stream-like object. The stream-like object only - needs to have a read() or write() method and is accessed - blockwise. Use of gzip or bzip2 compression is possible. - A stream-like object could be for example: sys.stdin, - sys.stdout, a socket, a tape device etc. - - _Stream is intended to be used only internally. - """ - - def __init__(self, name, mode, comptype, fileobj, bufsize): - """Construct a _Stream object. - """ - self._extfileobj = True - if fileobj is None: - fileobj = _LowLevelFile(name, mode) - self._extfileobj = False - - if comptype == '*': - # Enable transparent compression detection for the - # stream interface - fileobj = _StreamProxy(fileobj) - comptype = fileobj.getcomptype() - - self.name = name or "" - self.mode = mode - self.comptype = comptype - self.fileobj = fileobj - self.bufsize = bufsize - self.buf = b"" - self.pos = 0 - self.closed = False - - try: - if comptype == "gz": - try: - import zlib - except ImportError: - raise CompressionError("zlib module is not available") - self.zlib = zlib - self.crc = zlib.crc32(b"") - if mode == "r": - self._init_read_gz() - else: - self._init_write_gz() - - if comptype == "bz2": - try: - import bz2 - except ImportError: - raise CompressionError("bz2 module is not available") - if mode == "r": - self.dbuf = b"" - self.cmp = bz2.BZ2Decompressor() - else: - self.cmp = bz2.BZ2Compressor() - except: - if not self._extfileobj: - self.fileobj.close() - self.closed = True - raise - - def __del__(self): - if hasattr(self, "closed") and not self.closed: - self.close() - - def _init_write_gz(self): - """Initialize for writing with gzip compression. - """ - self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED, - -self.zlib.MAX_WBITS, - self.zlib.DEF_MEM_LEVEL, - 0) - timestamp = struct.pack(" self.bufsize: - self.fileobj.write(self.buf[:self.bufsize]) - self.buf = self.buf[self.bufsize:] - - def close(self): - """Close the _Stream object. No operation should be - done on it afterwards. - """ - if self.closed: - return - - if self.mode == "w" and self.comptype != "tar": - self.buf += self.cmp.flush() - - if self.mode == "w" and self.buf: - self.fileobj.write(self.buf) - self.buf = b"" - if self.comptype == "gz": - # The native zlib crc is an unsigned 32-bit integer, but - # the Python wrapper implicitly casts that to a signed C - # long. So, on a 32-bit box self.crc may "look negative", - # while the same crc on a 64-bit box may "look positive". - # To avoid irksome warnings from the `struct` module, force - # it to look positive on all boxes. - self.fileobj.write(struct.pack("= 0: - blocks, remainder = divmod(pos - self.pos, self.bufsize) - for i in range(blocks): - self.read(self.bufsize) - self.read(remainder) - else: - raise StreamError("seeking backwards is not allowed") - return self.pos - - def read(self, size=None): - """Return the next size number of bytes from the stream. - If size is not defined, return all bytes of the stream - up to EOF. - """ - if size is None: - t = [] - while True: - buf = self._read(self.bufsize) - if not buf: - break - t.append(buf) - buf = "".join(t) - else: - buf = self._read(size) - self.pos += len(buf) - return buf - - def _read(self, size): - """Return size bytes from the stream. - """ - if self.comptype == "tar": - return self.__read(size) - - c = len(self.dbuf) - while c < size: - buf = self.__read(self.bufsize) - if not buf: - break - try: - buf = self.cmp.decompress(buf) - except IOError: - raise ReadError("invalid compressed data") - self.dbuf += buf - c += len(buf) - buf = self.dbuf[:size] - self.dbuf = self.dbuf[size:] - return buf - - def __read(self, size): - """Return size bytes from stream. If internal buffer is empty, - read another block from the stream. - """ - c = len(self.buf) - while c < size: - buf = self.fileobj.read(self.bufsize) - if not buf: - break - self.buf += buf - c += len(buf) - buf = self.buf[:size] - self.buf = self.buf[size:] - return buf -# class _Stream - -class _StreamProxy(object): - """Small proxy class that enables transparent compression - detection for the Stream interface (mode 'r|*'). - """ - - def __init__(self, fileobj): - self.fileobj = fileobj - self.buf = self.fileobj.read(BLOCKSIZE) - - def read(self, size): - self.read = self.fileobj.read - return self.buf - - def getcomptype(self): - if self.buf.startswith(b"\037\213\010"): - return "gz" - if self.buf.startswith(b"BZh91"): - return "bz2" - return "tar" - - def close(self): - self.fileobj.close() -# class StreamProxy - -class _BZ2Proxy(object): - """Small proxy class that enables external file object - support for "r:bz2" and "w:bz2" modes. This is actually - a workaround for a limitation in bz2 module's BZ2File - class which (unlike gzip.GzipFile) has no support for - a file object argument. - """ - - blocksize = 16 * 1024 - - def __init__(self, fileobj, mode): - self.fileobj = fileobj - self.mode = mode - self.name = getattr(self.fileobj, "name", None) - self.init() - - def init(self): - import bz2 - self.pos = 0 - if self.mode == "r": - self.bz2obj = bz2.BZ2Decompressor() - self.fileobj.seek(0) - self.buf = b"" - else: - self.bz2obj = bz2.BZ2Compressor() - - def read(self, size): - x = len(self.buf) - while x < size: - raw = self.fileobj.read(self.blocksize) - if not raw: - break - data = self.bz2obj.decompress(raw) - self.buf += data - x += len(data) - - buf = self.buf[:size] - self.buf = self.buf[size:] - self.pos += len(buf) - return buf - - def seek(self, pos): - if pos < self.pos: - self.init() - self.read(pos - self.pos) - - def tell(self): - return self.pos - - def write(self, data): - self.pos += len(data) - raw = self.bz2obj.compress(data) - self.fileobj.write(raw) - - def close(self): - if self.mode == "w": - raw = self.bz2obj.flush() - self.fileobj.write(raw) -# class _BZ2Proxy - -#------------------------ -# Extraction file object -#------------------------ -class _FileInFile(object): - """A thin wrapper around an existing file object that - provides a part of its data as an individual file - object. - """ - - def __init__(self, fileobj, offset, size, blockinfo=None): - self.fileobj = fileobj - self.offset = offset - self.size = size - self.position = 0 - - if blockinfo is None: - blockinfo = [(0, size)] - - # Construct a map with data and zero blocks. - self.map_index = 0 - self.map = [] - lastpos = 0 - realpos = self.offset - for offset, size in blockinfo: - if offset > lastpos: - self.map.append((False, lastpos, offset, None)) - self.map.append((True, offset, offset + size, realpos)) - realpos += size - lastpos = offset + size - if lastpos < self.size: - self.map.append((False, lastpos, self.size, None)) - - def seekable(self): - if not hasattr(self.fileobj, "seekable"): - # XXX gzip.GzipFile and bz2.BZ2File - return True - return self.fileobj.seekable() - - def tell(self): - """Return the current file position. - """ - return self.position - - def seek(self, position): - """Seek to a position in the file. - """ - self.position = position - - def read(self, size=None): - """Read data from the file. - """ - if size is None: - size = self.size - self.position - else: - size = min(size, self.size - self.position) - - buf = b"" - while size > 0: - while True: - data, start, stop, offset = self.map[self.map_index] - if start <= self.position < stop: - break - else: - self.map_index += 1 - if self.map_index == len(self.map): - self.map_index = 0 - length = min(size, stop - self.position) - if data: - self.fileobj.seek(offset + (self.position - start)) - buf += self.fileobj.read(length) - else: - buf += NUL * length - size -= length - self.position += length - return buf -#class _FileInFile - - -class ExFileObject(object): - """File-like object for reading an archive member. - Is returned by TarFile.extractfile(). - """ - blocksize = 1024 - - def __init__(self, tarfile, tarinfo): - self.fileobj = _FileInFile(tarfile.fileobj, - tarinfo.offset_data, - tarinfo.size, - tarinfo.sparse) - self.name = tarinfo.name - self.mode = "r" - self.closed = False - self.size = tarinfo.size - - self.position = 0 - self.buffer = b"" - - def readable(self): - return True - - def writable(self): - return False - - def seekable(self): - return self.fileobj.seekable() - - def read(self, size=None): - """Read at most size bytes from the file. If size is not - present or None, read all data until EOF is reached. - """ - if self.closed: - raise ValueError("I/O operation on closed file") - - buf = b"" - if self.buffer: - if size is None: - buf = self.buffer - self.buffer = b"" - else: - buf = self.buffer[:size] - self.buffer = self.buffer[size:] - - if size is None: - buf += self.fileobj.read() - else: - buf += self.fileobj.read(size - len(buf)) - - self.position += len(buf) - return buf - - # XXX TextIOWrapper uses the read1() method. - read1 = read - - def readline(self, size=-1): - """Read one entire line from the file. If size is present - and non-negative, return a string with at most that - size, which may be an incomplete line. - """ - if self.closed: - raise ValueError("I/O operation on closed file") - - pos = self.buffer.find(b"\n") + 1 - if pos == 0: - # no newline found. - while True: - buf = self.fileobj.read(self.blocksize) - self.buffer += buf - if not buf or b"\n" in buf: - pos = self.buffer.find(b"\n") + 1 - if pos == 0: - # no newline found. - pos = len(self.buffer) - break - - if size != -1: - pos = min(size, pos) - - buf = self.buffer[:pos] - self.buffer = self.buffer[pos:] - self.position += len(buf) - return buf - - def readlines(self): - """Return a list with all remaining lines. - """ - result = [] - while True: - line = self.readline() - if not line: break - result.append(line) - return result - - def tell(self): - """Return the current file position. - """ - if self.closed: - raise ValueError("I/O operation on closed file") - - return self.position - - def seek(self, pos, whence=os.SEEK_SET): - """Seek to a position in the file. - """ - if self.closed: - raise ValueError("I/O operation on closed file") - - if whence == os.SEEK_SET: - self.position = min(max(pos, 0), self.size) - elif whence == os.SEEK_CUR: - if pos < 0: - self.position = max(self.position + pos, 0) - else: - self.position = min(self.position + pos, self.size) - elif whence == os.SEEK_END: - self.position = max(min(self.size + pos, self.size), 0) - else: - raise ValueError("Invalid argument") - - self.buffer = b"" - self.fileobj.seek(self.position) - - def close(self): - """Close the file object. - """ - self.closed = True - - def __iter__(self): - """Get an iterator over the file's lines. - """ - while True: - line = self.readline() - if not line: - break - yield line -#class ExFileObject - -#------------------ -# Exported Classes -#------------------ -class TarInfo(object): - """Informational class which holds the details about an - archive member given by a tar header block. - TarInfo objects are returned by TarFile.getmember(), - TarFile.getmembers() and TarFile.gettarinfo() and are - usually created internally. - """ - - __slots__ = ("name", "mode", "uid", "gid", "size", "mtime", - "chksum", "type", "linkname", "uname", "gname", - "devmajor", "devminor", - "offset", "offset_data", "pax_headers", "sparse", - "tarfile", "_sparse_structs", "_link_target") - - def __init__(self, name=""): - """Construct a TarInfo object. name is the optional name - of the member. - """ - self.name = name # member name - self.mode = 0o644 # file permissions - self.uid = 0 # user id - self.gid = 0 # group id - self.size = 0 # file size - self.mtime = 0 # modification time - self.chksum = 0 # header checksum - self.type = REGTYPE # member type - self.linkname = "" # link name - self.uname = "" # user name - self.gname = "" # group name - self.devmajor = 0 # device major number - self.devminor = 0 # device minor number - - self.offset = 0 # the tar header starts here - self.offset_data = 0 # the file's data starts here - - self.sparse = None # sparse member information - self.pax_headers = {} # pax header information - - # In pax headers the "name" and "linkname" field are called - # "path" and "linkpath". - def _getpath(self): - return self.name - def _setpath(self, name): - self.name = name - path = property(_getpath, _setpath) - - def _getlinkpath(self): - return self.linkname - def _setlinkpath(self, linkname): - self.linkname = linkname - linkpath = property(_getlinkpath, _setlinkpath) - - def __repr__(self): - return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self)) - - def get_info(self): - """Return the TarInfo's attributes as a dictionary. - """ - info = { - "name": self.name, - "mode": self.mode & 0o7777, - "uid": self.uid, - "gid": self.gid, - "size": self.size, - "mtime": self.mtime, - "chksum": self.chksum, - "type": self.type, - "linkname": self.linkname, - "uname": self.uname, - "gname": self.gname, - "devmajor": self.devmajor, - "devminor": self.devminor - } - - if info["type"] == DIRTYPE and not info["name"].endswith("/"): - info["name"] += "/" - - return info - - def tobuf(self, format=DEFAULT_FORMAT, encoding=ENCODING, errors="surrogateescape"): - """Return a tar header as a string of 512 byte blocks. - """ - info = self.get_info() - - if format == USTAR_FORMAT: - return self.create_ustar_header(info, encoding, errors) - elif format == GNU_FORMAT: - return self.create_gnu_header(info, encoding, errors) - elif format == PAX_FORMAT: - return self.create_pax_header(info, encoding) - else: - raise ValueError("invalid format") - - def create_ustar_header(self, info, encoding, errors): - """Return the object as a ustar header block. - """ - info["magic"] = POSIX_MAGIC - - if len(info["linkname"]) > LENGTH_LINK: - raise ValueError("linkname is too long") - - if len(info["name"]) > LENGTH_NAME: - info["prefix"], info["name"] = self._posix_split_name(info["name"]) - - return self._create_header(info, USTAR_FORMAT, encoding, errors) - - def create_gnu_header(self, info, encoding, errors): - """Return the object as a GNU header block sequence. - """ - info["magic"] = GNU_MAGIC - - buf = b"" - if len(info["linkname"]) > LENGTH_LINK: - buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK, encoding, errors) - - if len(info["name"]) > LENGTH_NAME: - buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME, encoding, errors) - - return buf + self._create_header(info, GNU_FORMAT, encoding, errors) - - def create_pax_header(self, info, encoding): - """Return the object as a ustar header block. If it cannot be - represented this way, prepend a pax extended header sequence - with supplement information. - """ - info["magic"] = POSIX_MAGIC - pax_headers = self.pax_headers.copy() - - # Test string fields for values that exceed the field length or cannot - # be represented in ASCII encoding. - for name, hname, length in ( - ("name", "path", LENGTH_NAME), ("linkname", "linkpath", LENGTH_LINK), - ("uname", "uname", 32), ("gname", "gname", 32)): - - if hname in pax_headers: - # The pax header has priority. - continue - - # Try to encode the string as ASCII. - try: - info[name].encode("ascii", "strict") - except UnicodeEncodeError: - pax_headers[hname] = info[name] - continue - - if len(info[name]) > length: - pax_headers[hname] = info[name] - - # Test number fields for values that exceed the field limit or values - # that like to be stored as float. - for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)): - if name in pax_headers: - # The pax header has priority. Avoid overflow. - info[name] = 0 - continue - - val = info[name] - if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float): - pax_headers[name] = str(val) - info[name] = 0 - - # Create a pax extended header if necessary. - if pax_headers: - buf = self._create_pax_generic_header(pax_headers, XHDTYPE, encoding) - else: - buf = b"" - - return buf + self._create_header(info, USTAR_FORMAT, "ascii", "replace") - - @classmethod - def create_pax_global_header(cls, pax_headers): - """Return the object as a pax global header block sequence. - """ - return cls._create_pax_generic_header(pax_headers, XGLTYPE, "utf8") - - def _posix_split_name(self, name): - """Split a name longer than 100 chars into a prefix - and a name part. - """ - prefix = name[:LENGTH_PREFIX + 1] - while prefix and prefix[-1] != "/": - prefix = prefix[:-1] - - name = name[len(prefix):] - prefix = prefix[:-1] - - if not prefix or len(name) > LENGTH_NAME: - raise ValueError("name is too long") - return prefix, name - - @staticmethod - def _create_header(info, format, encoding, errors): - """Return a header block. info is a dictionary with file - information, format must be one of the *_FORMAT constants. - """ - parts = [ - stn(info.get("name", ""), 100, encoding, errors), - itn(info.get("mode", 0) & 0o7777, 8, format), - itn(info.get("uid", 0), 8, format), - itn(info.get("gid", 0), 8, format), - itn(info.get("size", 0), 12, format), - itn(info.get("mtime", 0), 12, format), - b" ", # checksum field - info.get("type", REGTYPE), - stn(info.get("linkname", ""), 100, encoding, errors), - info.get("magic", POSIX_MAGIC), - stn(info.get("uname", ""), 32, encoding, errors), - stn(info.get("gname", ""), 32, encoding, errors), - itn(info.get("devmajor", 0), 8, format), - itn(info.get("devminor", 0), 8, format), - stn(info.get("prefix", ""), 155, encoding, errors) - ] - - buf = struct.pack("%ds" % BLOCKSIZE, b"".join(parts)) - chksum = calc_chksums(buf[-BLOCKSIZE:])[0] - buf = buf[:-364] + ("%06o\0" % chksum).encode("ascii") + buf[-357:] - return buf - - @staticmethod - def _create_payload(payload): - """Return the string payload filled with zero bytes - up to the next 512 byte border. - """ - blocks, remainder = divmod(len(payload), BLOCKSIZE) - if remainder > 0: - payload += (BLOCKSIZE - remainder) * NUL - return payload - - @classmethod - def _create_gnu_long_header(cls, name, type, encoding, errors): - """Return a GNUTYPE_LONGNAME or GNUTYPE_LONGLINK sequence - for name. - """ - name = name.encode(encoding, errors) + NUL - - info = {} - info["name"] = "././@LongLink" - info["type"] = type - info["size"] = len(name) - info["magic"] = GNU_MAGIC - - # create extended header + name blocks. - return cls._create_header(info, USTAR_FORMAT, encoding, errors) + \ - cls._create_payload(name) - - @classmethod - def _create_pax_generic_header(cls, pax_headers, type, encoding): - """Return a POSIX.1-2008 extended or global header sequence - that contains a list of keyword, value pairs. The values - must be strings. - """ - # Check if one of the fields contains surrogate characters and thereby - # forces hdrcharset=BINARY, see _proc_pax() for more information. - binary = False - for keyword, value in pax_headers.items(): - try: - value.encode("utf8", "strict") - except UnicodeEncodeError: - binary = True - break - - records = b"" - if binary: - # Put the hdrcharset field at the beginning of the header. - records += b"21 hdrcharset=BINARY\n" - - for keyword, value in pax_headers.items(): - keyword = keyword.encode("utf8") - if binary: - # Try to restore the original byte representation of `value'. - # Needless to say, that the encoding must match the string. - value = value.encode(encoding, "surrogateescape") - else: - value = value.encode("utf8") - - l = len(keyword) + len(value) + 3 # ' ' + '=' + '\n' - n = p = 0 - while True: - n = l + len(str(p)) - if n == p: - break - p = n - records += bytes(str(p), "ascii") + b" " + keyword + b"=" + value + b"\n" - - # We use a hardcoded "././@PaxHeader" name like star does - # instead of the one that POSIX recommends. - info = {} - info["name"] = "././@PaxHeader" - info["type"] = type - info["size"] = len(records) - info["magic"] = POSIX_MAGIC - - # Create pax header + record blocks. - return cls._create_header(info, USTAR_FORMAT, "ascii", "replace") + \ - cls._create_payload(records) - - @classmethod - def frombuf(cls, buf, encoding, errors): - """Construct a TarInfo object from a 512 byte bytes object. - """ - if len(buf) == 0: - raise EmptyHeaderError("empty header") - if len(buf) != BLOCKSIZE: - raise TruncatedHeaderError("truncated header") - if buf.count(NUL) == BLOCKSIZE: - raise EOFHeaderError("end of file header") - - chksum = nti(buf[148:156]) - if chksum not in calc_chksums(buf): - raise InvalidHeaderError("bad checksum") - - obj = cls() - obj.name = nts(buf[0:100], encoding, errors) - obj.mode = nti(buf[100:108]) - obj.uid = nti(buf[108:116]) - obj.gid = nti(buf[116:124]) - obj.size = nti(buf[124:136]) - obj.mtime = nti(buf[136:148]) - obj.chksum = chksum - obj.type = buf[156:157] - obj.linkname = nts(buf[157:257], encoding, errors) - obj.uname = nts(buf[265:297], encoding, errors) - obj.gname = nts(buf[297:329], encoding, errors) - obj.devmajor = nti(buf[329:337]) - obj.devminor = nti(buf[337:345]) - prefix = nts(buf[345:500], encoding, errors) - - # Old V7 tar format represents a directory as a regular - # file with a trailing slash. - if obj.type == AREGTYPE and obj.name.endswith("/"): - obj.type = DIRTYPE - - # The old GNU sparse format occupies some of the unused - # space in the buffer for up to 4 sparse structures. - # Save the them for later processing in _proc_sparse(). - if obj.type == GNUTYPE_SPARSE: - pos = 386 - structs = [] - for i in range(4): - try: - offset = nti(buf[pos:pos + 12]) - numbytes = nti(buf[pos + 12:pos + 24]) - except ValueError: - break - structs.append((offset, numbytes)) - pos += 24 - isextended = bool(buf[482]) - origsize = nti(buf[483:495]) - obj._sparse_structs = (structs, isextended, origsize) - - # Remove redundant slashes from directories. - if obj.isdir(): - obj.name = obj.name.rstrip("/") - - # Reconstruct a ustar longname. - if prefix and obj.type not in GNU_TYPES: - obj.name = prefix + "/" + obj.name - return obj - - @classmethod - def fromtarfile(cls, tarfile): - """Return the next TarInfo object from TarFile object - tarfile. - """ - buf = tarfile.fileobj.read(BLOCKSIZE) - obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors) - obj.offset = tarfile.fileobj.tell() - BLOCKSIZE - return obj._proc_member(tarfile) - - #-------------------------------------------------------------------------- - # The following are methods that are called depending on the type of a - # member. The entry point is _proc_member() which can be overridden in a - # subclass to add custom _proc_*() methods. A _proc_*() method MUST - # implement the following - # operations: - # 1. Set self.offset_data to the position where the data blocks begin, - # if there is data that follows. - # 2. Set tarfile.offset to the position where the next member's header will - # begin. - # 3. Return self or another valid TarInfo object. - def _proc_member(self, tarfile): - """Choose the right processing method depending on - the type and call it. - """ - if self.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK): - return self._proc_gnulong(tarfile) - elif self.type == GNUTYPE_SPARSE: - return self._proc_sparse(tarfile) - elif self.type in (XHDTYPE, XGLTYPE, SOLARIS_XHDTYPE): - return self._proc_pax(tarfile) - else: - return self._proc_builtin(tarfile) - - def _proc_builtin(self, tarfile): - """Process a builtin type or an unknown type which - will be treated as a regular file. - """ - self.offset_data = tarfile.fileobj.tell() - offset = self.offset_data - if self.isreg() or self.type not in SUPPORTED_TYPES: - # Skip the following data blocks. - offset += self._block(self.size) - tarfile.offset = offset - - # Patch the TarInfo object with saved global - # header information. - self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors) - - return self - - def _proc_gnulong(self, tarfile): - """Process the blocks that hold a GNU longname - or longlink member. - """ - buf = tarfile.fileobj.read(self._block(self.size)) - - # Fetch the next header and process it. - try: - next = self.fromtarfile(tarfile) - except HeaderError: - raise SubsequentHeaderError("missing or bad subsequent header") - - # Patch the TarInfo object from the next header with - # the longname information. - next.offset = self.offset - if self.type == GNUTYPE_LONGNAME: - next.name = nts(buf, tarfile.encoding, tarfile.errors) - elif self.type == GNUTYPE_LONGLINK: - next.linkname = nts(buf, tarfile.encoding, tarfile.errors) - - return next - - def _proc_sparse(self, tarfile): - """Process a GNU sparse header plus extra headers. - """ - # We already collected some sparse structures in frombuf(). - structs, isextended, origsize = self._sparse_structs - del self._sparse_structs - - # Collect sparse structures from extended header blocks. - while isextended: - buf = tarfile.fileobj.read(BLOCKSIZE) - pos = 0 - for i in range(21): - try: - offset = nti(buf[pos:pos + 12]) - numbytes = nti(buf[pos + 12:pos + 24]) - except ValueError: - break - if offset and numbytes: - structs.append((offset, numbytes)) - pos += 24 - isextended = bool(buf[504]) - self.sparse = structs - - self.offset_data = tarfile.fileobj.tell() - tarfile.offset = self.offset_data + self._block(self.size) - self.size = origsize - return self - - def _proc_pax(self, tarfile): - """Process an extended or global header as described in - POSIX.1-2008. - """ - # Read the header information. - buf = tarfile.fileobj.read(self._block(self.size)) - - # A pax header stores supplemental information for either - # the following file (extended) or all following files - # (global). - if self.type == XGLTYPE: - pax_headers = tarfile.pax_headers - else: - pax_headers = tarfile.pax_headers.copy() - - # Check if the pax header contains a hdrcharset field. This tells us - # the encoding of the path, linkpath, uname and gname fields. Normally, - # these fields are UTF-8 encoded but since POSIX.1-2008 tar - # implementations are allowed to store them as raw binary strings if - # the translation to UTF-8 fails. - match = re.search(br"\d+ hdrcharset=([^\n]+)\n", buf) - if match is not None: - pax_headers["hdrcharset"] = match.group(1).decode("utf8") - - # For the time being, we don't care about anything other than "BINARY". - # The only other value that is currently allowed by the standard is - # "ISO-IR 10646 2000 UTF-8" in other words UTF-8. - hdrcharset = pax_headers.get("hdrcharset") - if hdrcharset == "BINARY": - encoding = tarfile.encoding - else: - encoding = "utf8" - - # Parse pax header information. A record looks like that: - # "%d %s=%s\n" % (length, keyword, value). length is the size - # of the complete record including the length field itself and - # the newline. keyword and value are both UTF-8 encoded strings. - regex = re.compile(br"(\d+) ([^=]+)=") - pos = 0 - while True: - match = regex.match(buf, pos) - if not match: - break - - length, keyword = match.groups() - length = int(length) - value = buf[match.end(2) + 1:match.start(1) + length - 1] - - # Normally, we could just use "utf8" as the encoding and "strict" - # as the error handler, but we better not take the risk. For - # example, GNU tar <= 1.23 is known to store filenames it cannot - # translate to UTF-8 as raw strings (unfortunately without a - # hdrcharset=BINARY header). - # We first try the strict standard encoding, and if that fails we - # fall back on the user's encoding and error handler. - keyword = self._decode_pax_field(keyword, "utf8", "utf8", - tarfile.errors) - if keyword in PAX_NAME_FIELDS: - value = self._decode_pax_field(value, encoding, tarfile.encoding, - tarfile.errors) - else: - value = self._decode_pax_field(value, "utf8", "utf8", - tarfile.errors) - - pax_headers[keyword] = value - pos += length - - # Fetch the next header. - try: - next = self.fromtarfile(tarfile) - except HeaderError: - raise SubsequentHeaderError("missing or bad subsequent header") - - # Process GNU sparse information. - if "GNU.sparse.map" in pax_headers: - # GNU extended sparse format version 0.1. - self._proc_gnusparse_01(next, pax_headers) - - elif "GNU.sparse.size" in pax_headers: - # GNU extended sparse format version 0.0. - self._proc_gnusparse_00(next, pax_headers, buf) - - elif pax_headers.get("GNU.sparse.major") == "1" and pax_headers.get("GNU.sparse.minor") == "0": - # GNU extended sparse format version 1.0. - self._proc_gnusparse_10(next, pax_headers, tarfile) - - if self.type in (XHDTYPE, SOLARIS_XHDTYPE): - # Patch the TarInfo object with the extended header info. - next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors) - next.offset = self.offset - - if "size" in pax_headers: - # If the extended header replaces the size field, - # we need to recalculate the offset where the next - # header starts. - offset = next.offset_data - if next.isreg() or next.type not in SUPPORTED_TYPES: - offset += next._block(next.size) - tarfile.offset = offset - - return next - - def _proc_gnusparse_00(self, next, pax_headers, buf): - """Process a GNU tar extended sparse header, version 0.0. - """ - offsets = [] - for match in re.finditer(br"\d+ GNU.sparse.offset=(\d+)\n", buf): - offsets.append(int(match.group(1))) - numbytes = [] - for match in re.finditer(br"\d+ GNU.sparse.numbytes=(\d+)\n", buf): - numbytes.append(int(match.group(1))) - next.sparse = list(zip(offsets, numbytes)) - - def _proc_gnusparse_01(self, next, pax_headers): - """Process a GNU tar extended sparse header, version 0.1. - """ - sparse = [int(x) for x in pax_headers["GNU.sparse.map"].split(",")] - next.sparse = list(zip(sparse[::2], sparse[1::2])) - - def _proc_gnusparse_10(self, next, pax_headers, tarfile): - """Process a GNU tar extended sparse header, version 1.0. - """ - fields = None - sparse = [] - buf = tarfile.fileobj.read(BLOCKSIZE) - fields, buf = buf.split(b"\n", 1) - fields = int(fields) - while len(sparse) < fields * 2: - if b"\n" not in buf: - buf += tarfile.fileobj.read(BLOCKSIZE) - number, buf = buf.split(b"\n", 1) - sparse.append(int(number)) - next.offset_data = tarfile.fileobj.tell() - next.sparse = list(zip(sparse[::2], sparse[1::2])) - - def _apply_pax_info(self, pax_headers, encoding, errors): - """Replace fields with supplemental information from a previous - pax extended or global header. - """ - for keyword, value in pax_headers.items(): - if keyword == "GNU.sparse.name": - setattr(self, "path", value) - elif keyword == "GNU.sparse.size": - setattr(self, "size", int(value)) - elif keyword == "GNU.sparse.realsize": - setattr(self, "size", int(value)) - elif keyword in PAX_FIELDS: - if keyword in PAX_NUMBER_FIELDS: - try: - value = PAX_NUMBER_FIELDS[keyword](value) - except ValueError: - value = 0 - if keyword == "path": - value = value.rstrip("/") - setattr(self, keyword, value) - - self.pax_headers = pax_headers.copy() - - def _decode_pax_field(self, value, encoding, fallback_encoding, fallback_errors): - """Decode a single field from a pax record. - """ - try: - return value.decode(encoding, "strict") - except UnicodeDecodeError: - return value.decode(fallback_encoding, fallback_errors) - - def _block(self, count): - """Round up a byte count by BLOCKSIZE and return it, - e.g. _block(834) => 1024. - """ - blocks, remainder = divmod(count, BLOCKSIZE) - if remainder: - blocks += 1 - return blocks * BLOCKSIZE - - def isreg(self): - return self.type in REGULAR_TYPES - def isfile(self): - return self.isreg() - def isdir(self): - return self.type == DIRTYPE - def issym(self): - return self.type == SYMTYPE - def islnk(self): - return self.type == LNKTYPE - def ischr(self): - return self.type == CHRTYPE - def isblk(self): - return self.type == BLKTYPE - def isfifo(self): - return self.type == FIFOTYPE - def issparse(self): - return self.sparse is not None - def isdev(self): - return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE) -# class TarInfo - -class TarFile(object): - """The TarFile Class provides an interface to tar archives. - """ - - debug = 0 # May be set from 0 (no msgs) to 3 (all msgs) - - dereference = False # If true, add content of linked file to the - # tar file, else the link. - - ignore_zeros = False # If true, skips empty or invalid blocks and - # continues processing. - - errorlevel = 1 # If 0, fatal errors only appear in debug - # messages (if debug >= 0). If > 0, errors - # are passed to the caller as exceptions. - - format = DEFAULT_FORMAT # The format to use when creating an archive. - - encoding = ENCODING # Encoding for 8-bit character strings. - - errors = None # Error handler for unicode conversion. - - tarinfo = TarInfo # The default TarInfo class to use. - - fileobject = ExFileObject # The default ExFileObject class to use. - - def __init__(self, name=None, mode="r", fileobj=None, format=None, - tarinfo=None, dereference=None, ignore_zeros=None, encoding=None, - errors="surrogateescape", pax_headers=None, debug=None, errorlevel=None): - """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to - read from an existing archive, 'a' to append data to an existing - file or 'w' to create a new file overwriting an existing one. `mode' - defaults to 'r'. - If `fileobj' is given, it is used for reading or writing data. If it - can be determined, `mode' is overridden by `fileobj's mode. - `fileobj' is not closed, when TarFile is closed. - """ - if len(mode) > 1 or mode not in "raw": - raise ValueError("mode must be 'r', 'a' or 'w'") - self.mode = mode - self._mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode] - - if not fileobj: - if self.mode == "a" and not os.path.exists(name): - # Create nonexistent files in append mode. - self.mode = "w" - self._mode = "wb" - fileobj = bltn_open(name, self._mode) - self._extfileobj = False - else: - if name is None and hasattr(fileobj, "name"): - name = fileobj.name - if hasattr(fileobj, "mode"): - self._mode = fileobj.mode - self._extfileobj = True - self.name = os.path.abspath(name) if name else None - self.fileobj = fileobj - - # Init attributes. - if format is not None: - self.format = format - if tarinfo is not None: - self.tarinfo = tarinfo - if dereference is not None: - self.dereference = dereference - if ignore_zeros is not None: - self.ignore_zeros = ignore_zeros - if encoding is not None: - self.encoding = encoding - self.errors = errors - - if pax_headers is not None and self.format == PAX_FORMAT: - self.pax_headers = pax_headers - else: - self.pax_headers = {} - - if debug is not None: - self.debug = debug - if errorlevel is not None: - self.errorlevel = errorlevel - - # Init datastructures. - self.closed = False - self.members = [] # list of members as TarInfo objects - self._loaded = False # flag if all members have been read - self.offset = self.fileobj.tell() - # current position in the archive file - self.inodes = {} # dictionary caching the inodes of - # archive members already added - - try: - if self.mode == "r": - self.firstmember = None - self.firstmember = self.next() - - if self.mode == "a": - # Move to the end of the archive, - # before the first empty block. - while True: - self.fileobj.seek(self.offset) - try: - tarinfo = self.tarinfo.fromtarfile(self) - self.members.append(tarinfo) - except EOFHeaderError: - self.fileobj.seek(self.offset) - break - except HeaderError as e: - raise ReadError(str(e)) - - if self.mode in "aw": - self._loaded = True - - if self.pax_headers: - buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy()) - self.fileobj.write(buf) - self.offset += len(buf) - except: - if not self._extfileobj: - self.fileobj.close() - self.closed = True - raise - - #-------------------------------------------------------------------------- - # Below are the classmethods which act as alternate constructors to the - # TarFile class. The open() method is the only one that is needed for - # public use; it is the "super"-constructor and is able to select an - # adequate "sub"-constructor for a particular compression using the mapping - # from OPEN_METH. - # - # This concept allows one to subclass TarFile without losing the comfort of - # the super-constructor. A sub-constructor is registered and made available - # by adding it to the mapping in OPEN_METH. - - @classmethod - def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs): - """Open a tar archive for reading, writing or appending. Return - an appropriate TarFile class. - - mode: - 'r' or 'r:*' open for reading with transparent compression - 'r:' open for reading exclusively uncompressed - 'r:gz' open for reading with gzip compression - 'r:bz2' open for reading with bzip2 compression - 'a' or 'a:' open for appending, creating the file if necessary - 'w' or 'w:' open for writing without compression - 'w:gz' open for writing with gzip compression - 'w:bz2' open for writing with bzip2 compression - - 'r|*' open a stream of tar blocks with transparent compression - 'r|' open an uncompressed stream of tar blocks for reading - 'r|gz' open a gzip compressed stream of tar blocks - 'r|bz2' open a bzip2 compressed stream of tar blocks - 'w|' open an uncompressed stream for writing - 'w|gz' open a gzip compressed stream for writing - 'w|bz2' open a bzip2 compressed stream for writing - """ - - if not name and not fileobj: - raise ValueError("nothing to open") - - if mode in ("r", "r:*"): - # Find out which *open() is appropriate for opening the file. - for comptype in cls.OPEN_METH: - func = getattr(cls, cls.OPEN_METH[comptype]) - if fileobj is not None: - saved_pos = fileobj.tell() - try: - return func(name, "r", fileobj, **kwargs) - except (ReadError, CompressionError) as e: - if fileobj is not None: - fileobj.seek(saved_pos) - continue - raise ReadError("file could not be opened successfully") - - elif ":" in mode: - filemode, comptype = mode.split(":", 1) - filemode = filemode or "r" - comptype = comptype or "tar" - - # Select the *open() function according to - # given compression. - if comptype in cls.OPEN_METH: - func = getattr(cls, cls.OPEN_METH[comptype]) - else: - raise CompressionError("unknown compression type %r" % comptype) - return func(name, filemode, fileobj, **kwargs) - - elif "|" in mode: - filemode, comptype = mode.split("|", 1) - filemode = filemode or "r" - comptype = comptype or "tar" - - if filemode not in "rw": - raise ValueError("mode must be 'r' or 'w'") - - stream = _Stream(name, filemode, comptype, fileobj, bufsize) - try: - t = cls(name, filemode, stream, **kwargs) - except: - stream.close() - raise - t._extfileobj = False - return t - - elif mode in "aw": - return cls.taropen(name, mode, fileobj, **kwargs) - - raise ValueError("undiscernible mode") - - @classmethod - def taropen(cls, name, mode="r", fileobj=None, **kwargs): - """Open uncompressed tar archive name for reading or writing. - """ - if len(mode) > 1 or mode not in "raw": - raise ValueError("mode must be 'r', 'a' or 'w'") - return cls(name, mode, fileobj, **kwargs) - - @classmethod - def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): - """Open gzip compressed tar archive name for reading or writing. - Appending is not allowed. - """ - if len(mode) > 1 or mode not in "rw": - raise ValueError("mode must be 'r' or 'w'") - - try: - import gzip - gzip.GzipFile - except (ImportError, AttributeError): - raise CompressionError("gzip module is not available") - - extfileobj = fileobj is not None - try: - fileobj = gzip.GzipFile(name, mode + "b", compresslevel, fileobj) - t = cls.taropen(name, mode, fileobj, **kwargs) - except IOError: - if not extfileobj and fileobj is not None: - fileobj.close() - if fileobj is None: - raise - raise ReadError("not a gzip file") - except: - if not extfileobj and fileobj is not None: - fileobj.close() - raise - t._extfileobj = extfileobj - return t - - @classmethod - def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): - """Open bzip2 compressed tar archive name for reading or writing. - Appending is not allowed. - """ - if len(mode) > 1 or mode not in "rw": - raise ValueError("mode must be 'r' or 'w'.") - - try: - import bz2 - except ImportError: - raise CompressionError("bz2 module is not available") - - if fileobj is not None: - fileobj = _BZ2Proxy(fileobj, mode) - else: - fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel) - - try: - t = cls.taropen(name, mode, fileobj, **kwargs) - except (IOError, EOFError): - fileobj.close() - raise ReadError("not a bzip2 file") - t._extfileobj = False - return t - - # All *open() methods are registered here. - OPEN_METH = { - "tar": "taropen", # uncompressed tar - "gz": "gzopen", # gzip compressed tar - "bz2": "bz2open" # bzip2 compressed tar - } - - #-------------------------------------------------------------------------- - # The public methods which TarFile provides: - - def close(self): - """Close the TarFile. In write-mode, two finishing zero blocks are - appended to the archive. - """ - if self.closed: - return - - if self.mode in "aw": - self.fileobj.write(NUL * (BLOCKSIZE * 2)) - self.offset += (BLOCKSIZE * 2) - # fill up the end with zero-blocks - # (like option -b20 for tar does) - blocks, remainder = divmod(self.offset, RECORDSIZE) - if remainder > 0: - self.fileobj.write(NUL * (RECORDSIZE - remainder)) - - if not self._extfileobj: - self.fileobj.close() - self.closed = True - - def getmember(self, name): - """Return a TarInfo object for member `name'. If `name' can not be - found in the archive, KeyError is raised. If a member occurs more - than once in the archive, its last occurrence is assumed to be the - most up-to-date version. - """ - tarinfo = self._getmember(name) - if tarinfo is None: - raise KeyError("filename %r not found" % name) - return tarinfo - - def getmembers(self): - """Return the members of the archive as a list of TarInfo objects. The - list has the same order as the members in the archive. - """ - self._check() - if not self._loaded: # if we want to obtain a list of - self._load() # all members, we first have to - # scan the whole archive. - return self.members - - def getnames(self): - """Return the members of the archive as a list of their names. It has - the same order as the list returned by getmembers(). - """ - return [tarinfo.name for tarinfo in self.getmembers()] - - def gettarinfo(self, name=None, arcname=None, fileobj=None): - """Create a TarInfo object for either the file `name' or the file - object `fileobj' (using os.fstat on its file descriptor). You can - modify some of the TarInfo's attributes before you add it using - addfile(). If given, `arcname' specifies an alternative name for the - file in the archive. - """ - self._check("aw") - - # When fileobj is given, replace name by - # fileobj's real name. - if fileobj is not None: - name = fileobj.name - - # Building the name of the member in the archive. - # Backward slashes are converted to forward slashes, - # Absolute paths are turned to relative paths. - if arcname is None: - arcname = name - drv, arcname = os.path.splitdrive(arcname) - arcname = arcname.replace(os.sep, "/") - arcname = arcname.lstrip("/") - - # Now, fill the TarInfo object with - # information specific for the file. - tarinfo = self.tarinfo() - tarinfo.tarfile = self - - # Use os.stat or os.lstat, depending on platform - # and if symlinks shall be resolved. - if fileobj is None: - if hasattr(os, "lstat") and not self.dereference: - statres = os.lstat(name) - else: - statres = os.stat(name) - else: - statres = os.fstat(fileobj.fileno()) - linkname = "" - - stmd = statres.st_mode - if stat.S_ISREG(stmd): - inode = (statres.st_ino, statres.st_dev) - if not self.dereference and statres.st_nlink > 1 and \ - inode in self.inodes and arcname != self.inodes[inode]: - # Is it a hardlink to an already - # archived file? - type = LNKTYPE - linkname = self.inodes[inode] - else: - # The inode is added only if its valid. - # For win32 it is always 0. - type = REGTYPE - if inode[0]: - self.inodes[inode] = arcname - elif stat.S_ISDIR(stmd): - type = DIRTYPE - elif stat.S_ISFIFO(stmd): - type = FIFOTYPE - elif stat.S_ISLNK(stmd): - type = SYMTYPE - linkname = os.readlink(name) - elif stat.S_ISCHR(stmd): - type = CHRTYPE - elif stat.S_ISBLK(stmd): - type = BLKTYPE - else: - return None - - # Fill the TarInfo object with all - # information we can get. - tarinfo.name = arcname - tarinfo.mode = stmd - tarinfo.uid = statres.st_uid - tarinfo.gid = statres.st_gid - if type == REGTYPE: - tarinfo.size = statres.st_size - else: - tarinfo.size = 0 - tarinfo.mtime = statres.st_mtime - tarinfo.type = type - tarinfo.linkname = linkname - if pwd: - try: - tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0] - except KeyError: - pass - if grp: - try: - tarinfo.gname = grp.getgrgid(tarinfo.gid)[0] - except KeyError: - pass - - if type in (CHRTYPE, BLKTYPE): - if hasattr(os, "major") and hasattr(os, "minor"): - tarinfo.devmajor = os.major(statres.st_rdev) - tarinfo.devminor = os.minor(statres.st_rdev) - return tarinfo - - def list(self, verbose=True): - """Print a table of contents to sys.stdout. If `verbose' is False, only - the names of the members are printed. If it is True, an `ls -l'-like - output is produced. - """ - self._check() - - for tarinfo in self: - if verbose: - print(filemode(tarinfo.mode), end=' ') - print("%s/%s" % (tarinfo.uname or tarinfo.uid, - tarinfo.gname or tarinfo.gid), end=' ') - if tarinfo.ischr() or tarinfo.isblk(): - print("%10s" % ("%d,%d" \ - % (tarinfo.devmajor, tarinfo.devminor)), end=' ') - else: - print("%10d" % tarinfo.size, end=' ') - print("%d-%02d-%02d %02d:%02d:%02d" \ - % time.localtime(tarinfo.mtime)[:6], end=' ') - - print(tarinfo.name + ("/" if tarinfo.isdir() else ""), end=' ') - - if verbose: - if tarinfo.issym(): - print("->", tarinfo.linkname, end=' ') - if tarinfo.islnk(): - print("link to", tarinfo.linkname, end=' ') - print() - - def add(self, name, arcname=None, recursive=True, exclude=None, filter=None): - """Add the file `name' to the archive. `name' may be any type of file - (directory, fifo, symbolic link, etc.). If given, `arcname' - specifies an alternative name for the file in the archive. - Directories are added recursively by default. This can be avoided by - setting `recursive' to False. `exclude' is a function that should - return True for each filename to be excluded. `filter' is a function - that expects a TarInfo object argument and returns the changed - TarInfo object, if it returns None the TarInfo object will be - excluded from the archive. - """ - self._check("aw") - - if arcname is None: - arcname = name - - # Exclude pathnames. - if exclude is not None: - import warnings - warnings.warn("use the filter argument instead", - DeprecationWarning, 2) - if exclude(name): - self._dbg(2, "tarfile: Excluded %r" % name) - return - - # Skip if somebody tries to archive the archive... - if self.name is not None and os.path.abspath(name) == self.name: - self._dbg(2, "tarfile: Skipped %r" % name) - return - - self._dbg(1, name) - - # Create a TarInfo object from the file. - tarinfo = self.gettarinfo(name, arcname) - - if tarinfo is None: - self._dbg(1, "tarfile: Unsupported type %r" % name) - return - - # Change or exclude the TarInfo object. - if filter is not None: - tarinfo = filter(tarinfo) - if tarinfo is None: - self._dbg(2, "tarfile: Excluded %r" % name) - return - - # Append the tar header and data to the archive. - if tarinfo.isreg(): - f = bltn_open(name, "rb") - self.addfile(tarinfo, f) - f.close() - - elif tarinfo.isdir(): - self.addfile(tarinfo) - if recursive: - for f in os.listdir(name): - self.add(os.path.join(name, f), os.path.join(arcname, f), - recursive, exclude, filter=filter) - - else: - self.addfile(tarinfo) - - def addfile(self, tarinfo, fileobj=None): - """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is - given, tarinfo.size bytes are read from it and added to the archive. - You can create TarInfo objects using gettarinfo(). - On Windows platforms, `fileobj' should always be opened with mode - 'rb' to avoid irritation about the file size. - """ - self._check("aw") - - tarinfo = copy.copy(tarinfo) - - buf = tarinfo.tobuf(self.format, self.encoding, self.errors) - self.fileobj.write(buf) - self.offset += len(buf) - - # If there's data to follow, append it. - if fileobj is not None: - copyfileobj(fileobj, self.fileobj, tarinfo.size) - blocks, remainder = divmod(tarinfo.size, BLOCKSIZE) - if remainder > 0: - self.fileobj.write(NUL * (BLOCKSIZE - remainder)) - blocks += 1 - self.offset += blocks * BLOCKSIZE - - self.members.append(tarinfo) - - def extractall(self, path=".", members=None): - """Extract all members from the archive to the current working - directory and set owner, modification time and permissions on - directories afterwards. `path' specifies a different directory - to extract to. `members' is optional and must be a subset of the - list returned by getmembers(). - """ - directories = [] - - if members is None: - members = self - - for tarinfo in members: - if tarinfo.isdir(): - # Extract directories with a safe mode. - directories.append(tarinfo) - tarinfo = copy.copy(tarinfo) - tarinfo.mode = 0o700 - # Do not set_attrs directories, as we will do that further down - self.extract(tarinfo, path, set_attrs=not tarinfo.isdir()) - - # Reverse sort directories. - directories.sort(key=lambda a: a.name) - directories.reverse() - - # Set correct owner, mtime and filemode on directories. - for tarinfo in directories: - dirpath = os.path.join(path, tarinfo.name) - try: - self.chown(tarinfo, dirpath) - self.utime(tarinfo, dirpath) - self.chmod(tarinfo, dirpath) - except ExtractError as e: - if self.errorlevel > 1: - raise - else: - self._dbg(1, "tarfile: %s" % e) - - def extract(self, member, path="", set_attrs=True): - """Extract a member from the archive to the current working directory, - using its full name. Its file information is extracted as accurately - as possible. `member' may be a filename or a TarInfo object. You can - specify a different directory using `path'. File attributes (owner, - mtime, mode) are set unless `set_attrs' is False. - """ - self._check("r") - - if isinstance(member, str): - tarinfo = self.getmember(member) - else: - tarinfo = member - - # Prepare the link target for makelink(). - if tarinfo.islnk(): - tarinfo._link_target = os.path.join(path, tarinfo.linkname) - - try: - self._extract_member(tarinfo, os.path.join(path, tarinfo.name), - set_attrs=set_attrs) - except EnvironmentError as e: - if self.errorlevel > 0: - raise - else: - if e.filename is None: - self._dbg(1, "tarfile: %s" % e.strerror) - else: - self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename)) - except ExtractError as e: - if self.errorlevel > 1: - raise - else: - self._dbg(1, "tarfile: %s" % e) - - def extractfile(self, member): - """Extract a member from the archive as a file object. `member' may be - a filename or a TarInfo object. If `member' is a regular file, a - file-like object is returned. If `member' is a link, a file-like - object is constructed from the link's target. If `member' is none of - the above, None is returned. - The file-like object is read-only and provides the following - methods: read(), readline(), readlines(), seek() and tell() - """ - self._check("r") - - if isinstance(member, str): - tarinfo = self.getmember(member) - else: - tarinfo = member - - if tarinfo.isreg(): - return self.fileobject(self, tarinfo) - - elif tarinfo.type not in SUPPORTED_TYPES: - # If a member's type is unknown, it is treated as a - # regular file. - return self.fileobject(self, tarinfo) - - elif tarinfo.islnk() or tarinfo.issym(): - if isinstance(self.fileobj, _Stream): - # A small but ugly workaround for the case that someone tries - # to extract a (sym)link as a file-object from a non-seekable - # stream of tar blocks. - raise StreamError("cannot extract (sym)link as file object") - else: - # A (sym)link's file object is its target's file object. - return self.extractfile(self._find_link_target(tarinfo)) - else: - # If there's no data associated with the member (directory, chrdev, - # blkdev, etc.), return None instead of a file object. - return None - - def _extract_member(self, tarinfo, targetpath, set_attrs=True): - """Extract the TarInfo object tarinfo to a physical - file called targetpath. - """ - # Fetch the TarInfo object for the given name - # and build the destination pathname, replacing - # forward slashes to platform specific separators. - targetpath = targetpath.rstrip("/") - targetpath = targetpath.replace("/", os.sep) - - # Create all upper directories. - upperdirs = os.path.dirname(targetpath) - if upperdirs and not os.path.exists(upperdirs): - # Create directories that are not part of the archive with - # default permissions. - os.makedirs(upperdirs) - - if tarinfo.islnk() or tarinfo.issym(): - self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname)) - else: - self._dbg(1, tarinfo.name) - - if tarinfo.isreg(): - self.makefile(tarinfo, targetpath) - elif tarinfo.isdir(): - self.makedir(tarinfo, targetpath) - elif tarinfo.isfifo(): - self.makefifo(tarinfo, targetpath) - elif tarinfo.ischr() or tarinfo.isblk(): - self.makedev(tarinfo, targetpath) - elif tarinfo.islnk() or tarinfo.issym(): - self.makelink(tarinfo, targetpath) - elif tarinfo.type not in SUPPORTED_TYPES: - self.makeunknown(tarinfo, targetpath) - else: - self.makefile(tarinfo, targetpath) - - if set_attrs: - self.chown(tarinfo, targetpath) - if not tarinfo.issym(): - self.chmod(tarinfo, targetpath) - self.utime(tarinfo, targetpath) - - #-------------------------------------------------------------------------- - # Below are the different file methods. They are called via - # _extract_member() when extract() is called. They can be replaced in a - # subclass to implement other functionality. - - def makedir(self, tarinfo, targetpath): - """Make a directory called targetpath. - """ - try: - # Use a safe mode for the directory, the real mode is set - # later in _extract_member(). - os.mkdir(targetpath, 0o700) - except EnvironmentError as e: - if e.errno != errno.EEXIST: - raise - - def makefile(self, tarinfo, targetpath): - """Make a file called targetpath. - """ - source = self.fileobj - source.seek(tarinfo.offset_data) - target = bltn_open(targetpath, "wb") - if tarinfo.sparse is not None: - for offset, size in tarinfo.sparse: - target.seek(offset) - copyfileobj(source, target, size) - else: - copyfileobj(source, target, tarinfo.size) - target.seek(tarinfo.size) - target.truncate() - target.close() - - def makeunknown(self, tarinfo, targetpath): - """Make a file from a TarInfo object with an unknown type - at targetpath. - """ - self.makefile(tarinfo, targetpath) - self._dbg(1, "tarfile: Unknown file type %r, " \ - "extracted as regular file." % tarinfo.type) - - def makefifo(self, tarinfo, targetpath): - """Make a fifo called targetpath. - """ - if hasattr(os, "mkfifo"): - os.mkfifo(targetpath) - else: - raise ExtractError("fifo not supported by system") - - def makedev(self, tarinfo, targetpath): - """Make a character or block device called targetpath. - """ - if not hasattr(os, "mknod") or not hasattr(os, "makedev"): - raise ExtractError("special devices not supported by system") - - mode = tarinfo.mode - if tarinfo.isblk(): - mode |= stat.S_IFBLK - else: - mode |= stat.S_IFCHR - - os.mknod(targetpath, mode, - os.makedev(tarinfo.devmajor, tarinfo.devminor)) - - def makelink(self, tarinfo, targetpath): - """Make a (symbolic) link called targetpath. If it cannot be created - (platform limitation), we try to make a copy of the referenced file - instead of a link. - """ - try: - # For systems that support symbolic and hard links. - if tarinfo.issym(): - os.symlink(tarinfo.linkname, targetpath) - else: - # See extract(). - if os.path.exists(tarinfo._link_target): - os.link(tarinfo._link_target, targetpath) - else: - self._extract_member(self._find_link_target(tarinfo), - targetpath) - except symlink_exception: - if tarinfo.issym(): - linkpath = os.path.join(os.path.dirname(tarinfo.name), - tarinfo.linkname) - else: - linkpath = tarinfo.linkname - else: - try: - self._extract_member(self._find_link_target(tarinfo), - targetpath) - except KeyError: - raise ExtractError("unable to resolve link inside archive") - - def chown(self, tarinfo, targetpath): - """Set owner of targetpath according to tarinfo. - """ - if pwd and hasattr(os, "geteuid") and os.geteuid() == 0: - # We have to be root to do so. - try: - g = grp.getgrnam(tarinfo.gname)[2] - except KeyError: - g = tarinfo.gid - try: - u = pwd.getpwnam(tarinfo.uname)[2] - except KeyError: - u = tarinfo.uid - try: - if tarinfo.issym() and hasattr(os, "lchown"): - os.lchown(targetpath, u, g) - else: - if sys.platform != "os2emx": - os.chown(targetpath, u, g) - except EnvironmentError as e: - raise ExtractError("could not change owner") - - def chmod(self, tarinfo, targetpath): - """Set file permissions of targetpath according to tarinfo. - """ - if hasattr(os, 'chmod'): - try: - os.chmod(targetpath, tarinfo.mode) - except EnvironmentError as e: - raise ExtractError("could not change mode") - - def utime(self, tarinfo, targetpath): - """Set modification time of targetpath according to tarinfo. - """ - if not hasattr(os, 'utime'): - return - try: - os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime)) - except EnvironmentError as e: - raise ExtractError("could not change modification time") - - #-------------------------------------------------------------------------- - def next(self): - """Return the next member of the archive as a TarInfo object, when - TarFile is opened for reading. Return None if there is no more - available. - """ - self._check("ra") - if self.firstmember is not None: - m = self.firstmember - self.firstmember = None - return m - - # Read the next block. - self.fileobj.seek(self.offset) - tarinfo = None - while True: - try: - tarinfo = self.tarinfo.fromtarfile(self) - except EOFHeaderError as e: - if self.ignore_zeros: - self._dbg(2, "0x%X: %s" % (self.offset, e)) - self.offset += BLOCKSIZE - continue - except InvalidHeaderError as e: - if self.ignore_zeros: - self._dbg(2, "0x%X: %s" % (self.offset, e)) - self.offset += BLOCKSIZE - continue - elif self.offset == 0: - raise ReadError(str(e)) - except EmptyHeaderError: - if self.offset == 0: - raise ReadError("empty file") - except TruncatedHeaderError as e: - if self.offset == 0: - raise ReadError(str(e)) - except SubsequentHeaderError as e: - raise ReadError(str(e)) - break - - if tarinfo is not None: - self.members.append(tarinfo) - else: - self._loaded = True - - return tarinfo - - #-------------------------------------------------------------------------- - # Little helper methods: - - def _getmember(self, name, tarinfo=None, normalize=False): - """Find an archive member by name from bottom to top. - If tarinfo is given, it is used as the starting point. - """ - # Ensure that all members have been loaded. - members = self.getmembers() - - # Limit the member search list up to tarinfo. - if tarinfo is not None: - members = members[:members.index(tarinfo)] - - if normalize: - name = os.path.normpath(name) - - for member in reversed(members): - if normalize: - member_name = os.path.normpath(member.name) - else: - member_name = member.name - - if name == member_name: - return member - - def _load(self): - """Read through the entire archive file and look for readable - members. - """ - while True: - tarinfo = self.next() - if tarinfo is None: - break - self._loaded = True - - def _check(self, mode=None): - """Check if TarFile is still open, and if the operation's mode - corresponds to TarFile's mode. - """ - if self.closed: - raise IOError("%s is closed" % self.__class__.__name__) - if mode is not None and self.mode not in mode: - raise IOError("bad operation for mode %r" % self.mode) - - def _find_link_target(self, tarinfo): - """Find the target member of a symlink or hardlink member in the - archive. - """ - if tarinfo.issym(): - # Always search the entire archive. - linkname = os.path.dirname(tarinfo.name) + "/" + tarinfo.linkname - limit = None - else: - # Search the archive before the link, because a hard link is - # just a reference to an already archived file. - linkname = tarinfo.linkname - limit = tarinfo - - member = self._getmember(linkname, tarinfo=limit, normalize=True) - if member is None: - raise KeyError("linkname %r not found" % linkname) - return member - - def __iter__(self): - """Provide an iterator object. - """ - if self._loaded: - return iter(self.members) - else: - return TarIter(self) - - def _dbg(self, level, msg): - """Write debugging output to sys.stderr. - """ - if level <= self.debug: - print(msg, file=sys.stderr) - - def __enter__(self): - self._check() - return self - - def __exit__(self, type, value, traceback): - if type is None: - self.close() - else: - # An exception occurred. We must not call close() because - # it would try to write end-of-archive blocks and padding. - if not self._extfileobj: - self.fileobj.close() - self.closed = True -# class TarFile - -class TarIter(object): - """Iterator Class. - - for tarinfo in TarFile(...): - suite... - """ - - def __init__(self, tarfile): - """Construct a TarIter object. - """ - self.tarfile = tarfile - self.index = 0 - def __iter__(self): - """Return iterator object. - """ - return self - - def __next__(self): - """Return the next item using TarFile's next() method. - When all members have been read, set TarFile as _loaded. - """ - # Fix for SF #1100429: Under rare circumstances it can - # happen that getmembers() is called during iteration, - # which will cause TarIter to stop prematurely. - if not self.tarfile._loaded: - tarinfo = self.tarfile.next() - if not tarinfo: - self.tarfile._loaded = True - raise StopIteration - else: - try: - tarinfo = self.tarfile.members[self.index] - except IndexError: - raise StopIteration - self.index += 1 - return tarinfo - - next = __next__ # for Python 2.x - -#-------------------- -# exported functions -#-------------------- -def is_tarfile(name): - """Return True if name points to a tar archive that we - are able to handle, else return False. - """ - try: - t = open(name) - t.close() - return True - except TarError: - return False - -bltn_open = open -open = TarFile.open diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/compat.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/compat.py deleted file mode 100644 index 5ed8643..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/compat.py +++ /dev/null @@ -1,1102 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2013-2014 Vinay Sajip. -# Licensed to the Python Software Foundation under a contributor agreement. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -from __future__ import absolute_import - -import os -import re -import sys - -if sys.version_info[0] < 3: # pragma: no cover - from StringIO import StringIO - string_types = basestring, - text_type = unicode - from types import FileType as file_type - import __builtin__ as builtins - import ConfigParser as configparser - from ._backport import shutil - from urlparse import urlparse, urlunparse, urljoin, urlsplit, urlunsplit - from urllib import (urlretrieve, quote as _quote, unquote, url2pathname, - pathname2url, ContentTooShortError, splittype) - - def quote(s): - if isinstance(s, unicode): - s = s.encode('utf-8') - return _quote(s) - - import urllib2 - from urllib2 import (Request, urlopen, URLError, HTTPError, - HTTPBasicAuthHandler, HTTPPasswordMgr, - HTTPSHandler, HTTPHandler, HTTPRedirectHandler, - build_opener) - import httplib - import xmlrpclib - import Queue as queue - from HTMLParser import HTMLParser - import htmlentitydefs - raw_input = raw_input - from itertools import ifilter as filter - from itertools import ifilterfalse as filterfalse - - _userprog = None - def splituser(host): - """splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'.""" - global _userprog - if _userprog is None: - import re - _userprog = re.compile('^(.*)@(.*)$') - - match = _userprog.match(host) - if match: return match.group(1, 2) - return None, host - -else: # pragma: no cover - from io import StringIO - string_types = str, - text_type = str - from io import TextIOWrapper as file_type - import builtins - import configparser - import shutil - from urllib.parse import (urlparse, urlunparse, urljoin, splituser, quote, - unquote, urlsplit, urlunsplit, splittype) - from urllib.request import (urlopen, urlretrieve, Request, url2pathname, - pathname2url, - HTTPBasicAuthHandler, HTTPPasswordMgr, - HTTPSHandler, HTTPHandler, HTTPRedirectHandler, - build_opener) - from urllib.error import HTTPError, URLError, ContentTooShortError - import http.client as httplib - import urllib.request as urllib2 - import xmlrpc.client as xmlrpclib - import queue - from html.parser import HTMLParser - import html.entities as htmlentitydefs - raw_input = input - from itertools import filterfalse - filter = filter - -try: - from ssl import match_hostname, CertificateError -except ImportError: # pragma: no cover - class CertificateError(ValueError): - pass - - - def _dnsname_match(dn, hostname, max_wildcards=1): - """Matching according to RFC 6125, section 6.4.3 - - http://tools.ietf.org/html/rfc6125#section-6.4.3 - """ - pats = [] - if not dn: - return False - - parts = dn.split('.') - leftmost, remainder = parts[0], parts[1:] - - wildcards = leftmost.count('*') - if wildcards > max_wildcards: - # Issue #17980: avoid denials of service by refusing more - # than one wildcard per fragment. A survery of established - # policy among SSL implementations showed it to be a - # reasonable choice. - raise CertificateError( - "too many wildcards in certificate DNS name: " + repr(dn)) - - # speed up common case w/o wildcards - if not wildcards: - return dn.lower() == hostname.lower() - - # RFC 6125, section 6.4.3, subitem 1. - # The client SHOULD NOT attempt to match a presented identifier in which - # the wildcard character comprises a label other than the left-most label. - if leftmost == '*': - # When '*' is a fragment by itself, it matches a non-empty dotless - # fragment. - pats.append('[^.]+') - elif leftmost.startswith('xn--') or hostname.startswith('xn--'): - # RFC 6125, section 6.4.3, subitem 3. - # The client SHOULD NOT attempt to match a presented identifier - # where the wildcard character is embedded within an A-label or - # U-label of an internationalized domain name. - pats.append(re.escape(leftmost)) - else: - # Otherwise, '*' matches any dotless string, e.g. www* - pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) - - # add the remaining fragments, ignore any wildcards - for frag in remainder: - pats.append(re.escape(frag)) - - pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) - return pat.match(hostname) - - - def match_hostname(cert, hostname): - """Verify that *cert* (in decoded format as returned by - SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 - rules are followed, but IP addresses are not accepted for *hostname*. - - CertificateError is raised on failure. On success, the function - returns nothing. - """ - if not cert: - raise ValueError("empty or no certificate, match_hostname needs a " - "SSL socket or SSL context with either " - "CERT_OPTIONAL or CERT_REQUIRED") - dnsnames = [] - san = cert.get('subjectAltName', ()) - for key, value in san: - if key == 'DNS': - if _dnsname_match(value, hostname): - return - dnsnames.append(value) - if not dnsnames: - # The subject is only checked when there is no dNSName entry - # in subjectAltName - for sub in cert.get('subject', ()): - for key, value in sub: - # XXX according to RFC 2818, the most specific Common Name - # must be used. - if key == 'commonName': - if _dnsname_match(value, hostname): - return - dnsnames.append(value) - if len(dnsnames) > 1: - raise CertificateError("hostname %r " - "doesn't match either of %s" - % (hostname, ', '.join(map(repr, dnsnames)))) - elif len(dnsnames) == 1: - raise CertificateError("hostname %r " - "doesn't match %r" - % (hostname, dnsnames[0])) - else: - raise CertificateError("no appropriate commonName or " - "subjectAltName fields were found") - - -try: - from types import SimpleNamespace as Container -except ImportError: # pragma: no cover - class Container(object): - """ - A generic container for when multiple values need to be returned - """ - def __init__(self, **kwargs): - self.__dict__.update(kwargs) - - -try: - from shutil import which -except ImportError: # pragma: no cover - # Implementation from Python 3.3 - def which(cmd, mode=os.F_OK | os.X_OK, path=None): - """Given a command, mode, and a PATH string, return the path which - conforms to the given mode on the PATH, or None if there is no such - file. - - `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result - of os.environ.get("PATH"), or can be overridden with a custom search - path. - - """ - # Check that a given file can be accessed with the correct mode. - # Additionally check that `file` is not a directory, as on Windows - # directories pass the os.access check. - def _access_check(fn, mode): - return (os.path.exists(fn) and os.access(fn, mode) - and not os.path.isdir(fn)) - - # If we're given a path with a directory part, look it up directly rather - # than referring to PATH directories. This includes checking relative to the - # current directory, e.g. ./script - if os.path.dirname(cmd): - if _access_check(cmd, mode): - return cmd - return None - - if path is None: - path = os.environ.get("PATH", os.defpath) - if not path: - return None - path = path.split(os.pathsep) - - if sys.platform == "win32": - # The current directory takes precedence on Windows. - if not os.curdir in path: - path.insert(0, os.curdir) - - # PATHEXT is necessary to check on Windows. - pathext = os.environ.get("PATHEXT", "").split(os.pathsep) - # See if the given file matches any of the expected path extensions. - # This will allow us to short circuit when given "python.exe". - # If it does match, only test that one, otherwise we have to try - # others. - if any(cmd.lower().endswith(ext.lower()) for ext in pathext): - files = [cmd] - else: - files = [cmd + ext for ext in pathext] - else: - # On other platforms you don't have things like PATHEXT to tell you - # what file suffixes are executable, so just pass on cmd as-is. - files = [cmd] - - seen = set() - for dir in path: - normdir = os.path.normcase(dir) - if not normdir in seen: - seen.add(normdir) - for thefile in files: - name = os.path.join(dir, thefile) - if _access_check(name, mode): - return name - return None - - -# ZipFile is a context manager in 2.7, but not in 2.6 - -from zipfile import ZipFile as BaseZipFile - -if hasattr(BaseZipFile, '__enter__'): # pragma: no cover - ZipFile = BaseZipFile -else: - from zipfile import ZipExtFile as BaseZipExtFile - - class ZipExtFile(BaseZipExtFile): - def __init__(self, base): - self.__dict__.update(base.__dict__) - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.close() - # return None, so if an exception occurred, it will propagate - - class ZipFile(BaseZipFile): - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.close() - # return None, so if an exception occurred, it will propagate - - def open(self, *args, **kwargs): - base = BaseZipFile.open(self, *args, **kwargs) - return ZipExtFile(base) - -try: - from platform import python_implementation -except ImportError: # pragma: no cover - def python_implementation(): - """Return a string identifying the Python implementation.""" - if 'PyPy' in sys.version: - return 'PyPy' - if os.name == 'java': - return 'Jython' - if sys.version.startswith('IronPython'): - return 'IronPython' - return 'CPython' - -try: - import sysconfig -except ImportError: # pragma: no cover - from ._backport import sysconfig - -try: - callable = callable -except NameError: # pragma: no cover - from collections import Callable - - def callable(obj): - return isinstance(obj, Callable) - - -try: - fsencode = os.fsencode - fsdecode = os.fsdecode -except AttributeError: # pragma: no cover - _fsencoding = sys.getfilesystemencoding() - if _fsencoding == 'mbcs': - _fserrors = 'strict' - else: - _fserrors = 'surrogateescape' - - def fsencode(filename): - if isinstance(filename, bytes): - return filename - elif isinstance(filename, text_type): - return filename.encode(_fsencoding, _fserrors) - else: - raise TypeError("expect bytes or str, not %s" % - type(filename).__name__) - - def fsdecode(filename): - if isinstance(filename, text_type): - return filename - elif isinstance(filename, bytes): - return filename.decode(_fsencoding, _fserrors) - else: - raise TypeError("expect bytes or str, not %s" % - type(filename).__name__) - -try: - from tokenize import detect_encoding -except ImportError: # pragma: no cover - from codecs import BOM_UTF8, lookup - import re - - cookie_re = re.compile("coding[:=]\s*([-\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 argment, 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. - """ - try: - filename = readline.__self__.name - except AttributeError: - filename = None - bom_found = False - encoding = None - default = 'utf-8' - def read_or_stop(): - try: - return readline() - except StopIteration: - return b'' - - def find_cookie(line): - try: - # Decode as UTF-8. Either the line is an encoding declaration, - # in which case it should be pure ASCII, or it must be UTF-8 - # per default encoding. - line_string = line.decode('utf-8') - except UnicodeDecodeError: - msg = "invalid or missing encoding declaration" - if filename is not None: - msg = '{} for {!r}'.format(msg, filename) - raise SyntaxError(msg) - - matches = cookie_re.findall(line_string) - if not matches: - return None - encoding = _get_normal_name(matches[0]) - try: - codec = lookup(encoding) - except LookupError: - # This behaviour mimics the Python interpreter - if filename is None: - msg = "unknown encoding: " + encoding - else: - msg = "unknown encoding for {!r}: {}".format(filename, - encoding) - raise SyntaxError(msg) - - if bom_found: - if codec.name != 'utf-8': - # This behaviour mimics the Python interpreter - if filename is None: - msg = 'encoding problem: utf-8' - else: - msg = 'encoding problem for {!r}: utf-8'.format(filename) - raise SyntaxError(msg) - 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] - -# For converting & <-> & etc. -try: - from html import escape -except ImportError: - from cgi import escape -if sys.version_info[:2] < (3, 4): - unescape = HTMLParser().unescape -else: - from html import unescape - -try: - from collections import ChainMap -except ImportError: # pragma: no cover - from collections import MutableMapping - - try: - from reprlib import recursive_repr as _recursive_repr - except ImportError: - def _recursive_repr(fillvalue='...'): - ''' - Decorator to make a repr function return fillvalue for a recursive - call - ''' - - def decorating_function(user_function): - repr_running = set() - - def wrapper(self): - key = id(self), get_ident() - if key in repr_running: - return fillvalue - repr_running.add(key) - try: - result = user_function(self) - finally: - repr_running.discard(key) - return result - - # Can't use functools.wraps() here because of bootstrap issues - wrapper.__module__ = getattr(user_function, '__module__') - wrapper.__doc__ = getattr(user_function, '__doc__') - wrapper.__name__ = getattr(user_function, '__name__') - wrapper.__annotations__ = getattr(user_function, '__annotations__', {}) - return wrapper - - return decorating_function - - class ChainMap(MutableMapping): - ''' A ChainMap groups multiple dicts (or other mappings) together - to create a single, updateable view. - - The underlying mappings are stored in a list. That list is public and can - accessed or updated using the *maps* attribute. There is no other state. - - Lookups search the underlying mappings successively until a key is found. - In contrast, writes, updates, and deletions only operate on the first - mapping. - - ''' - - def __init__(self, *maps): - '''Initialize a ChainMap by setting *maps* to the given mappings. - If no mappings are provided, a single empty dictionary is used. - - ''' - self.maps = list(maps) or [{}] # always at least one map - - def __missing__(self, key): - raise KeyError(key) - - def __getitem__(self, key): - for mapping in self.maps: - try: - return mapping[key] # can't use 'key in mapping' with defaultdict - except KeyError: - pass - return self.__missing__(key) # support subclasses that define __missing__ - - def get(self, key, default=None): - return self[key] if key in self else default - - def __len__(self): - return len(set().union(*self.maps)) # reuses stored hash values if possible - - def __iter__(self): - return iter(set().union(*self.maps)) - - def __contains__(self, key): - return any(key in m for m in self.maps) - - def __bool__(self): - return any(self.maps) - - @_recursive_repr() - def __repr__(self): - return '{0.__class__.__name__}({1})'.format( - self, ', '.join(map(repr, self.maps))) - - @classmethod - def fromkeys(cls, iterable, *args): - 'Create a ChainMap with a single dict created from the iterable.' - return cls(dict.fromkeys(iterable, *args)) - - def copy(self): - 'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]' - return self.__class__(self.maps[0].copy(), *self.maps[1:]) - - __copy__ = copy - - def new_child(self): # like Django's Context.push() - 'New ChainMap with a new dict followed by all previous maps.' - return self.__class__({}, *self.maps) - - @property - def parents(self): # like Django's Context.pop() - 'New ChainMap from maps[1:].' - return self.__class__(*self.maps[1:]) - - def __setitem__(self, key, value): - self.maps[0][key] = value - - def __delitem__(self, key): - try: - del self.maps[0][key] - except KeyError: - raise KeyError('Key not found in the first mapping: {!r}'.format(key)) - - def popitem(self): - 'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.' - try: - return self.maps[0].popitem() - except KeyError: - raise KeyError('No keys found in the first mapping.') - - def pop(self, key, *args): - 'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].' - try: - return self.maps[0].pop(key, *args) - except KeyError: - raise KeyError('Key not found in the first mapping: {!r}'.format(key)) - - def clear(self): - 'Clear maps[0], leaving maps[1:] intact.' - self.maps[0].clear() - -try: - from imp import cache_from_source -except ImportError: # pragma: no cover - def cache_from_source(path, debug_override=None): - assert path.endswith('.py') - if debug_override is None: - debug_override = __debug__ - if debug_override: - suffix = 'c' - else: - suffix = 'o' - return path + suffix - -try: - from collections import OrderedDict -except ImportError: # pragma: no cover -## {{{ http://code.activestate.com/recipes/576693/ (r9) -# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. -# Passes Python2.7's test suite and incorporates all the latest updates. - try: - from thread import get_ident as _get_ident - except ImportError: - from dummy_thread import get_ident as _get_ident - - try: - from _abcoll import KeysView, ValuesView, ItemsView - except ImportError: - pass - - - class OrderedDict(dict): - 'Dictionary that remembers insertion order' - # An inherited dict maps keys to values. - # The inherited dict provides __getitem__, __len__, __contains__, and get. - # The remaining methods are order-aware. - # Big-O running times for all methods are the same as for regular dictionaries. - - # The internal self.__map dictionary maps keys to links in a doubly linked list. - # The circular doubly linked list starts and ends with a sentinel element. - # The sentinel element never gets deleted (this simplifies the algorithm). - # Each link is stored as a list of length three: [PREV, NEXT, KEY]. - - def __init__(self, *args, **kwds): - '''Initialize an ordered dictionary. Signature is the same as for - regular dictionaries, but keyword arguments are not recommended - because their insertion order is arbitrary. - - ''' - if len(args) > 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 which goes 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] - 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 is - # then removed by updating the links in the predecessor and successor nodes. - dict_delitem(self, key) - link_prev, link_next, key = self.__map.pop(key) - link_prev[1] = link_next - link_next[0] = link_prev - - def __iter__(self): - 'od.__iter__() <==> iter(od)' - root = self.__root - curr = root[1] - while curr is not root: - yield curr[2] - curr = curr[1] - - def __reversed__(self): - 'od.__reversed__() <==> reversed(od)' - root = self.__root - curr = root[0] - while curr is not root: - yield curr[2] - curr = curr[0] - - def clear(self): - 'od.clear() -> None. Remove all items from od.' - try: - for node in self.__map.itervalues(): - del node[:] - root = self.__root - root[:] = [root, root, None] - self.__map.clear() - except AttributeError: - pass - dict.clear(self) - - 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') - root = self.__root - if last: - link = root[0] - link_prev = link[0] - link_prev[1] = root - root[0] = link_prev - else: - link = root[1] - link_next = link[1] - root[1] = link_next - link_next[0] = root - key = link[2] - del self.__map[key] - value = dict.pop(self, key) - return key, value - - # -- 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) items in od' - for k in self: - yield (k, self[k]) - - def update(*args, **kwds): - '''od.update(E, **F) -> None. Update od from dict/iterable E and F. - - If E is a dict instance, does: for k in E: od[k] = E[k] - If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] - Or if E is an iterable of items, does: for k, v in E: od[k] = v - In either case, this is followed by: for k, v in F.items(): od[k] = v - - ''' - if len(args) > 2: - raise TypeError('update() takes at most 2 positional ' - 'arguments (%d given)' % (len(args),)) - elif not args: - raise TypeError('update() takes at least 1 argument (0 given)') - self = args[0] - # Make progressively weaker assumptions about "other" - other = () - if len(args) == 2: - other = args[1] - if isinstance(other, dict): - 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 - - __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 __repr__(self, _repr_running=None): - 'od.__repr__() <==> repr(od)' - if not _repr_running: _repr_running = {} - 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 - and values equal to v (which defaults to None). - - ''' - d = cls() - for key in iterable: - d[key] = value - return d - - 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 len(self)==len(other) and self.items() == other.items() - return dict.__eq__(self, other) - - def __ne__(self, other): - return not self == other - - # -- the following methods are only used in Python 2.7 -- - - 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) - -try: - from logging.config import BaseConfigurator, valid_ident -except ImportError: # pragma: no cover - 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 - - - # 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): - """A converting dictionary wrapper.""" - - def __getitem__(self, key): - value = dict.__getitem__(self, key) - result = self.configurator.convert(value) - #If the converted value is different, save for next time - if value is not result: - self[key] = result - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - result.key = key - return result - - def get(self, key, default=None): - value = dict.get(self, key, default) - result = self.configurator.convert(value) - #If the converted value is different, save for next time - if value is not result: - self[key] = result - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - result.key = key - return result - - def pop(self, key, default=None): - value = dict.pop(self, key, default) - result = self.configurator.convert(value) - if value is not result: - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - result.key = key - return result - - class ConvertingList(list): - """A converting list wrapper.""" - def __getitem__(self, key): - value = list.__getitem__(self, key) - result = self.configurator.convert(value) - #If the converted value is different, save for next time - if value is not result: - self[key] = result - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - result.key = key - return result - - def pop(self, idx=-1): - value = list.pop(self, idx) - result = self.configurator.convert(value) - if value is not result: - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - return result - - class ConvertingTuple(tuple): - """A converting tuple wrapper.""" - def __getitem__(self, key): - value = tuple.__getitem__(self, key) - result = self.configurator.convert(value) - if value is not result: - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - result.key = key - return result - - 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 = staticmethod(__import__) - - def __init__(self, config): - self.config = ConvertingDict(config) - self.config.configurator = self - - 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, string_types): - 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 callable(c): - 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 diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/database.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/database.py deleted file mode 100644 index 29c62fb..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/database.py +++ /dev/null @@ -1,1305 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012-2014 The Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -"""PEP 376 implementation.""" - -from __future__ import unicode_literals - -import base64 -import codecs -import contextlib -import hashlib -import logging -import os -import posixpath -import sys -import zipimport - -from . import DistlibException, resources -from .compat import StringIO -from .version import get_scheme, UnsupportedVersionError -from .metadata import Metadata, METADATA_FILENAME -from .util import (parse_requirement, cached_property, parse_name_and_version, - read_exports, write_exports, CSVReader, CSVWriter) - - -__all__ = ['Distribution', 'BaseInstalledDistribution', - 'InstalledDistribution', 'EggInfoDistribution', - 'DistributionPath'] - - -logger = logging.getLogger(__name__) - -EXPORTS_FILENAME = 'pydist-exports.json' -COMMANDS_FILENAME = 'pydist-commands.json' - -DIST_FILES = ('INSTALLER', METADATA_FILENAME, 'RECORD', 'REQUESTED', - 'RESOURCES', EXPORTS_FILENAME, 'SHARED') - -DISTINFO_EXT = '.dist-info' - - -class _Cache(object): - """ - A simple cache mapping names and .dist-info paths to distributions - """ - def __init__(self): - """ - Initialise an instance. There is normally one for each DistributionPath. - """ - self.name = {} - self.path = {} - self.generated = False - - def clear(self): - """ - Clear the cache, setting it to its initial state. - """ - self.name.clear() - self.path.clear() - self.generated = False - - def add(self, dist): - """ - Add a distribution to the cache. - :param dist: The distribution to add. - """ - if dist.path not in self.path: - self.path[dist.path] = dist - self.name.setdefault(dist.key, []).append(dist) - - -class DistributionPath(object): - """ - Represents a set of distributions installed on a path (typically sys.path). - """ - def __init__(self, path=None, include_egg=False): - """ - Create an instance from a path, optionally including legacy (distutils/ - setuptools/distribute) distributions. - :param path: The path to use, as a list of directories. If not specified, - sys.path is used. - :param include_egg: If True, this instance will look for and return legacy - distributions as well as those based on PEP 376. - """ - if path is None: - path = sys.path - self.path = path - self._include_dist = True - self._include_egg = include_egg - - self._cache = _Cache() - self._cache_egg = _Cache() - self._cache_enabled = True - self._scheme = get_scheme('default') - - def _get_cache_enabled(self): - return self._cache_enabled - - def _set_cache_enabled(self, value): - self._cache_enabled = value - - cache_enabled = property(_get_cache_enabled, _set_cache_enabled) - - def clear_cache(self): - """ - Clears the internal cache. - """ - self._cache.clear() - self._cache_egg.clear() - - - def _yield_distributions(self): - """ - Yield .dist-info and/or .egg(-info) distributions. - """ - # We need to check if we've seen some resources already, because on - # some Linux systems (e.g. some Debian/Ubuntu variants) there are - # symlinks which alias other files in the environment. - seen = set() - for path in self.path: - finder = resources.finder_for_path(path) - if finder is None: - continue - r = finder.find('') - if not r or not r.is_container: - continue - rset = sorted(r.resources) - for entry in rset: - r = finder.find(entry) - if not r or r.path in seen: - continue - if self._include_dist and entry.endswith(DISTINFO_EXT): - metadata_path = posixpath.join(entry, METADATA_FILENAME) - pydist = finder.find(metadata_path) - if not pydist: - continue - - metadata = Metadata(fileobj=pydist.as_stream(), - scheme='legacy') - logger.debug('Found %s', r.path) - seen.add(r.path) - yield new_dist_class(r.path, metadata=metadata, - env=self) - elif self._include_egg and entry.endswith(('.egg-info', - '.egg')): - logger.debug('Found %s', r.path) - seen.add(r.path) - yield old_dist_class(r.path, self) - - def _generate_cache(self): - """ - Scan the path for distributions and populate the cache with - those that are found. - """ - gen_dist = not self._cache.generated - gen_egg = self._include_egg and not self._cache_egg.generated - if gen_dist or gen_egg: - for dist in self._yield_distributions(): - if isinstance(dist, InstalledDistribution): - self._cache.add(dist) - else: - self._cache_egg.add(dist) - - if gen_dist: - self._cache.generated = True - if gen_egg: - self._cache_egg.generated = True - - @classmethod - def distinfo_dirname(cls, name, version): - """ - The *name* and *version* parameters are converted into their - filename-escaped form, i.e. any ``'-'`` characters are replaced - with ``'_'`` other than the one in ``'dist-info'`` and the one - separating the name from the version number. - - :parameter name: is converted to a standard distribution name by replacing - any runs of non- alphanumeric characters with a single - ``'-'``. - :type name: string - :parameter version: is converted to a standard version string. Spaces - become dots, and all other non-alphanumeric characters - (except dots) become dashes, with runs of multiple - dashes condensed to a single dash. - :type version: string - :returns: directory name - :rtype: string""" - name = name.replace('-', '_') - return '-'.join([name, version]) + DISTINFO_EXT - - def get_distributions(self): - """ - Provides an iterator that looks for distributions and returns - :class:`InstalledDistribution` or - :class:`EggInfoDistribution` instances for each one of them. - - :rtype: iterator of :class:`InstalledDistribution` and - :class:`EggInfoDistribution` instances - """ - if not self._cache_enabled: - for dist in self._yield_distributions(): - yield dist - else: - self._generate_cache() - - for dist in self._cache.path.values(): - yield dist - - if self._include_egg: - for dist in self._cache_egg.path.values(): - yield dist - - def get_distribution(self, name): - """ - Looks for a named distribution on the path. - - This function only returns the first result found, as no more than one - value is expected. If nothing is found, ``None`` is returned. - - :rtype: :class:`InstalledDistribution`, :class:`EggInfoDistribution` - or ``None`` - """ - result = None - name = name.lower() - if not self._cache_enabled: - for dist in self._yield_distributions(): - if dist.key == name: - result = dist - break - else: - self._generate_cache() - - if name in self._cache.name: - result = self._cache.name[name][0] - elif self._include_egg and name in self._cache_egg.name: - result = self._cache_egg.name[name][0] - return result - - def provides_distribution(self, name, version=None): - """ - Iterates over all distributions to find which distributions provide *name*. - If a *version* is provided, it will be used to filter the results. - - This function only returns the first result found, since no more than - one values are expected. If the directory is not found, returns ``None``. - - :parameter version: a version specifier that indicates the version - required, conforming to the format in ``PEP-345`` - - :type name: string - :type version: string - """ - matcher = None - if not version is None: - try: - matcher = self._scheme.matcher('%s (%s)' % (name, version)) - except ValueError: - raise DistlibException('invalid name or version: %r, %r' % - (name, version)) - - for dist in self.get_distributions(): - provided = dist.provides - - for p in provided: - p_name, p_ver = parse_name_and_version(p) - if matcher is None: - if p_name == name: - yield dist - break - else: - if p_name == name and matcher.match(p_ver): - yield dist - break - - def get_file_path(self, name, relative_path): - """ - Return the path to a resource file. - """ - dist = self.get_distribution(name) - if dist is None: - raise LookupError('no distribution named %r found' % name) - return dist.get_resource_path(relative_path) - - def get_exported_entries(self, category, name=None): - """ - Return all of the exported entries in a particular category. - - :param category: The category to search for entries. - :param name: If specified, only entries with that name are returned. - """ - for dist in self.get_distributions(): - r = dist.exports - if category in r: - d = r[category] - if name is not None: - if name in d: - yield d[name] - else: - for v in d.values(): - yield v - - -class Distribution(object): - """ - A base class for distributions, whether installed or from indexes. - Either way, it must have some metadata, so that's all that's needed - for construction. - """ - - build_time_dependency = False - """ - Set to True if it's known to be only a build-time dependency (i.e. - not needed after installation). - """ - - requested = False - """A boolean that indicates whether the ``REQUESTED`` metadata file is - present (in other words, whether the package was installed by user - request or it was installed as a dependency).""" - - def __init__(self, metadata): - """ - Initialise an instance. - :param metadata: The instance of :class:`Metadata` describing this - distribution. - """ - self.metadata = metadata - self.name = metadata.name - self.key = self.name.lower() # for case-insensitive comparisons - self.version = metadata.version - self.locator = None - self.digest = None - self.extras = None # additional features requested - self.context = None # environment marker overrides - self.download_urls = set() - self.digests = {} - - @property - def source_url(self): - """ - The source archive download URL for this distribution. - """ - return self.metadata.source_url - - download_url = source_url # Backward compatibility - - @property - def name_and_version(self): - """ - A utility property which displays the name and version in parentheses. - """ - return '%s (%s)' % (self.name, self.version) - - @property - def provides(self): - """ - A set of distribution names and versions provided by this distribution. - :return: A set of "name (version)" strings. - """ - plist = self.metadata.provides - s = '%s (%s)' % (self.name, self.version) - if s not in plist: - plist.append(s) - return plist - - def _get_requirements(self, req_attr): - md = self.metadata - logger.debug('Getting requirements from metadata %r', md.todict()) - reqts = getattr(md, req_attr) - return set(md.get_requirements(reqts, extras=self.extras, - env=self.context)) - - @property - def run_requires(self): - return self._get_requirements('run_requires') - - @property - def meta_requires(self): - return self._get_requirements('meta_requires') - - @property - def build_requires(self): - return self._get_requirements('build_requires') - - @property - def test_requires(self): - return self._get_requirements('test_requires') - - @property - def dev_requires(self): - return self._get_requirements('dev_requires') - - def matches_requirement(self, req): - """ - Say if this instance matches (fulfills) a requirement. - :param req: The requirement to match. - :rtype req: str - :return: True if it matches, else False. - """ - # Requirement may contain extras - parse to lose those - # from what's passed to the matcher - r = parse_requirement(req) - scheme = get_scheme(self.metadata.scheme) - try: - matcher = scheme.matcher(r.requirement) - except UnsupportedVersionError: - # XXX compat-mode if cannot read the version - logger.warning('could not read version %r - using name only', - req) - name = req.split()[0] - matcher = scheme.matcher(name) - - name = matcher.key # case-insensitive - - result = False - for p in self.provides: - p_name, p_ver = parse_name_and_version(p) - if p_name != name: - continue - try: - result = matcher.match(p_ver) - break - except UnsupportedVersionError: - pass - return result - - def __repr__(self): - """ - Return a textual representation of this instance, - """ - if self.source_url: - suffix = ' [%s]' % self.source_url - else: - suffix = '' - return '' % (self.name, self.version, suffix) - - def __eq__(self, other): - """ - See if this distribution is the same as another. - :param other: The distribution to compare with. To be equal to one - another. distributions must have the same type, name, - version and source_url. - :return: True if it is the same, else False. - """ - if type(other) is not type(self): - result = False - else: - result = (self.name == other.name and - self.version == other.version and - self.source_url == other.source_url) - return result - - def __hash__(self): - """ - Compute hash in a way which matches the equality test. - """ - return hash(self.name) + hash(self.version) + hash(self.source_url) - - -class BaseInstalledDistribution(Distribution): - """ - This is the base class for installed distributions (whether PEP 376 or - legacy). - """ - - hasher = None - - def __init__(self, metadata, path, env=None): - """ - Initialise an instance. - :param metadata: An instance of :class:`Metadata` which describes the - distribution. This will normally have been initialised - from a metadata file in the ``path``. - :param path: The path of the ``.dist-info`` or ``.egg-info`` - directory for the distribution. - :param env: This is normally the :class:`DistributionPath` - instance where this distribution was found. - """ - super(BaseInstalledDistribution, self).__init__(metadata) - self.path = path - self.dist_path = env - - def get_hash(self, data, hasher=None): - """ - Get the hash of some data, using a particular hash algorithm, if - specified. - - :param data: The data to be hashed. - :type data: bytes - :param hasher: The name of a hash implementation, supported by hashlib, - or ``None``. Examples of valid values are ``'sha1'``, - ``'sha224'``, ``'sha384'``, '``sha256'``, ``'md5'`` and - ``'sha512'``. If no hasher is specified, the ``hasher`` - attribute of the :class:`InstalledDistribution` instance - is used. If the hasher is determined to be ``None``, MD5 - is used as the hashing algorithm. - :returns: The hash of the data. If a hasher was explicitly specified, - the returned hash will be prefixed with the specified hasher - followed by '='. - :rtype: str - """ - if hasher is None: - hasher = self.hasher - if hasher is None: - hasher = hashlib.md5 - prefix = '' - else: - hasher = getattr(hashlib, hasher) - prefix = '%s=' % self.hasher - digest = hasher(data).digest() - digest = base64.urlsafe_b64encode(digest).rstrip(b'=').decode('ascii') - return '%s%s' % (prefix, digest) - - -class InstalledDistribution(BaseInstalledDistribution): - """ - Created with the *path* of the ``.dist-info`` directory provided to the - constructor. It reads the metadata contained in ``pydist.json`` when it is - instantiated., or uses a passed in Metadata instance (useful for when - dry-run mode is being used). - """ - - hasher = 'sha256' - - def __init__(self, path, metadata=None, env=None): - self.finder = finder = resources.finder_for_path(path) - if finder is None: - import pdb; pdb.set_trace () - if env and env._cache_enabled and path in env._cache.path: - metadata = env._cache.path[path].metadata - elif metadata is None: - r = finder.find(METADATA_FILENAME) - # Temporary - for legacy support - if r is None: - r = finder.find('METADATA') - if r is None: - raise ValueError('no %s found in %s' % (METADATA_FILENAME, - path)) - with contextlib.closing(r.as_stream()) as stream: - metadata = Metadata(fileobj=stream, scheme='legacy') - - super(InstalledDistribution, self).__init__(metadata, path, env) - - if env and env._cache_enabled: - env._cache.add(self) - - try: - r = finder.find('REQUESTED') - except AttributeError: - import pdb; pdb.set_trace () - self.requested = r is not None - - def __repr__(self): - return '' % ( - self.name, self.version, self.path) - - def __str__(self): - return "%s %s" % (self.name, self.version) - - def _get_records(self): - """ - Get the list of installed files for the distribution - :return: A list of tuples of path, hash and size. Note that hash and - size might be ``None`` for some entries. The path is exactly - as stored in the file (which is as in PEP 376). - """ - results = [] - r = self.get_distinfo_resource('RECORD') - with contextlib.closing(r.as_stream()) as stream: - with CSVReader(stream=stream) as record_reader: - # Base location is parent dir of .dist-info dir - #base_location = os.path.dirname(self.path) - #base_location = os.path.abspath(base_location) - for row in record_reader: - missing = [None for i in range(len(row), 3)] - path, checksum, size = row + missing - #if not os.path.isabs(path): - # path = path.replace('/', os.sep) - # path = os.path.join(base_location, path) - results.append((path, checksum, size)) - return results - - @cached_property - def exports(self): - """ - Return the information exported by this distribution. - :return: A dictionary of exports, mapping an export category to a dict - of :class:`ExportEntry` instances describing the individual - export entries, and keyed by name. - """ - result = {} - r = self.get_distinfo_resource(EXPORTS_FILENAME) - if r: - result = self.read_exports() - return result - - def read_exports(self): - """ - Read exports data from a file in .ini format. - - :return: A dictionary of exports, mapping an export category to a list - of :class:`ExportEntry` instances describing the individual - export entries. - """ - result = {} - r = self.get_distinfo_resource(EXPORTS_FILENAME) - if r: - with contextlib.closing(r.as_stream()) as stream: - result = read_exports(stream) - return result - - def write_exports(self, exports): - """ - Write a dictionary of exports to a file in .ini format. - :param exports: A dictionary of exports, mapping an export category to - a list of :class:`ExportEntry` instances describing the - individual export entries. - """ - rf = self.get_distinfo_file(EXPORTS_FILENAME) - with open(rf, 'w') as f: - write_exports(exports, f) - - def get_resource_path(self, relative_path): - """ - NOTE: This API may change in the future. - - Return the absolute path to a resource file with the given relative - path. - - :param relative_path: The path, relative to .dist-info, of the resource - of interest. - :return: The absolute path where the resource is to be found. - """ - r = self.get_distinfo_resource('RESOURCES') - with contextlib.closing(r.as_stream()) as stream: - with CSVReader(stream=stream) as resources_reader: - for relative, destination in resources_reader: - if relative == relative_path: - return destination - raise KeyError('no resource file with relative path %r ' - 'is installed' % relative_path) - - def list_installed_files(self): - """ - Iterates over the ``RECORD`` entries and returns a tuple - ``(path, hash, size)`` for each line. - - :returns: iterator of (path, hash, size) - """ - for result in self._get_records(): - yield result - - def write_installed_files(self, paths, prefix, dry_run=False): - """ - Writes the ``RECORD`` file, using the ``paths`` iterable passed in. Any - existing ``RECORD`` file is silently overwritten. - - prefix is used to determine when to write absolute paths. - """ - prefix = os.path.join(prefix, '') - base = os.path.dirname(self.path) - base_under_prefix = base.startswith(prefix) - base = os.path.join(base, '') - record_path = self.get_distinfo_file('RECORD') - logger.info('creating %s', record_path) - if dry_run: - return None - with CSVWriter(record_path) as writer: - for path in paths: - if os.path.isdir(path) or path.endswith(('.pyc', '.pyo')): - # do not put size and hash, as in PEP-376 - hash_value = size = '' - else: - size = '%d' % os.path.getsize(path) - with open(path, 'rb') as fp: - hash_value = self.get_hash(fp.read()) - if path.startswith(base) or (base_under_prefix and - path.startswith(prefix)): - path = os.path.relpath(path, base) - writer.writerow((path, hash_value, size)) - - # add the RECORD file itself - if record_path.startswith(base): - record_path = os.path.relpath(record_path, base) - writer.writerow((record_path, '', '')) - return record_path - - def check_installed_files(self): - """ - Checks that the hashes and sizes of the files in ``RECORD`` are - matched by the files themselves. Returns a (possibly empty) list of - mismatches. Each entry in the mismatch list will be a tuple consisting - of the path, 'exists', 'size' or 'hash' according to what didn't match - (existence is checked first, then size, then hash), the expected - value and the actual value. - """ - mismatches = [] - base = os.path.dirname(self.path) - record_path = self.get_distinfo_file('RECORD') - for path, hash_value, size in self.list_installed_files(): - if not os.path.isabs(path): - path = os.path.join(base, path) - if path == record_path: - continue - if not os.path.exists(path): - mismatches.append((path, 'exists', True, False)) - elif os.path.isfile(path): - actual_size = str(os.path.getsize(path)) - if size and actual_size != size: - mismatches.append((path, 'size', size, actual_size)) - elif hash_value: - if '=' in hash_value: - hasher = hash_value.split('=', 1)[0] - else: - hasher = None - - with open(path, 'rb') as f: - actual_hash = self.get_hash(f.read(), hasher) - if actual_hash != hash_value: - mismatches.append((path, 'hash', hash_value, actual_hash)) - return mismatches - - @cached_property - def shared_locations(self): - """ - A dictionary of shared locations whose keys are in the set 'prefix', - 'purelib', 'platlib', 'scripts', 'headers', 'data' and 'namespace'. - The corresponding value is the absolute path of that category for - this distribution, and takes into account any paths selected by the - user at installation time (e.g. via command-line arguments). In the - case of the 'namespace' key, this would be a list of absolute paths - for the roots of namespace packages in this distribution. - - The first time this property is accessed, the relevant information is - read from the SHARED file in the .dist-info directory. - """ - result = {} - shared_path = os.path.join(self.path, 'SHARED') - if os.path.isfile(shared_path): - with codecs.open(shared_path, 'r', encoding='utf-8') as f: - lines = f.read().splitlines() - for line in lines: - key, value = line.split('=', 1) - if key == 'namespace': - result.setdefault(key, []).append(value) - else: - result[key] = value - return result - - def write_shared_locations(self, paths, dry_run=False): - """ - Write shared location information to the SHARED file in .dist-info. - :param paths: A dictionary as described in the documentation for - :meth:`shared_locations`. - :param dry_run: If True, the action is logged but no file is actually - written. - :return: The path of the file written to. - """ - shared_path = os.path.join(self.path, 'SHARED') - logger.info('creating %s', shared_path) - if dry_run: - return None - lines = [] - for key in ('prefix', 'lib', 'headers', 'scripts', 'data'): - path = paths[key] - if os.path.isdir(paths[key]): - lines.append('%s=%s' % (key, path)) - for ns in paths.get('namespace', ()): - lines.append('namespace=%s' % ns) - - with codecs.open(shared_path, 'w', encoding='utf-8') as f: - f.write('\n'.join(lines)) - return shared_path - - def get_distinfo_resource(self, path): - if path not in DIST_FILES: - raise DistlibException('invalid path for a dist-info file: ' - '%r at %r' % (path, self.path)) - finder = resources.finder_for_path(self.path) - if finder is None: - raise DistlibException('Unable to get a finder for %s' % self.path) - return finder.find(path) - - def get_distinfo_file(self, path): - """ - Returns a path located under the ``.dist-info`` directory. Returns a - string representing the path. - - :parameter path: a ``'/'``-separated path relative to the - ``.dist-info`` directory or an absolute path; - If *path* is an absolute path and doesn't start - with the ``.dist-info`` directory path, - a :class:`DistlibException` is raised - :type path: str - :rtype: str - """ - # Check if it is an absolute path # XXX use relpath, add tests - if path.find(os.sep) >= 0: - # it's an absolute path? - distinfo_dirname, path = path.split(os.sep)[-2:] - if distinfo_dirname != self.path.split(os.sep)[-1]: - raise DistlibException( - 'dist-info file %r does not belong to the %r %s ' - 'distribution' % (path, self.name, self.version)) - - # The file must be relative - if path not in DIST_FILES: - raise DistlibException('invalid path for a dist-info file: ' - '%r at %r' % (path, self.path)) - - return os.path.join(self.path, path) - - def list_distinfo_files(self): - """ - Iterates over the ``RECORD`` entries and returns paths for each line if - the path is pointing to a file located in the ``.dist-info`` directory - or one of its subdirectories. - - :returns: iterator of paths - """ - base = os.path.dirname(self.path) - for path, checksum, size in self._get_records(): - # XXX add separator or use real relpath algo - if not os.path.isabs(path): - path = os.path.join(base, path) - if path.startswith(self.path): - yield path - - def __eq__(self, other): - return (isinstance(other, InstalledDistribution) and - self.path == other.path) - - # See http://docs.python.org/reference/datamodel#object.__hash__ - __hash__ = object.__hash__ - - -class EggInfoDistribution(BaseInstalledDistribution): - """Created with the *path* of the ``.egg-info`` directory or file provided - to the constructor. It reads the metadata contained in the file itself, or - if the given path happens to be a directory, the metadata is read from the - file ``PKG-INFO`` under that directory.""" - - requested = True # as we have no way of knowing, assume it was - shared_locations = {} - - def __init__(self, path, env=None): - def set_name_and_version(s, n, v): - s.name = n - s.key = n.lower() # for case-insensitive comparisons - s.version = v - - self.path = path - self.dist_path = env - if env and env._cache_enabled and path in env._cache_egg.path: - metadata = env._cache_egg.path[path].metadata - set_name_and_version(self, metadata.name, metadata.version) - else: - metadata = self._get_metadata(path) - - # Need to be set before caching - set_name_and_version(self, metadata.name, metadata.version) - - if env and env._cache_enabled: - env._cache_egg.add(self) - super(EggInfoDistribution, self).__init__(metadata, path, env) - - def _get_metadata(self, path): - requires = None - - def parse_requires_data(data): - """Create a list of dependencies from a requires.txt file. - - *data*: the contents of a setuptools-produced requires.txt file. - """ - reqs = [] - lines = data.splitlines() - for line in lines: - line = line.strip() - if line.startswith('['): - logger.warning('Unexpected line: quitting requirement scan: %r', - line) - break - r = parse_requirement(line) - if not r: - logger.warning('Not recognised as a requirement: %r', line) - continue - if r.extras: - logger.warning('extra requirements in requires.txt are ' - 'not supported') - if not r.constraints: - reqs.append(r.name) - else: - cons = ', '.join('%s%s' % c for c in r.constraints) - reqs.append('%s (%s)' % (r.name, cons)) - return reqs - - def parse_requires_path(req_path): - """Create a list of dependencies from a requires.txt file. - - *req_path*: the path to a setuptools-produced requires.txt file. - """ - - reqs = [] - try: - with codecs.open(req_path, 'r', 'utf-8') as fp: - reqs = parse_requires_data(fp.read()) - except IOError: - pass - return reqs - - if path.endswith('.egg'): - if os.path.isdir(path): - meta_path = os.path.join(path, 'EGG-INFO', 'PKG-INFO') - metadata = Metadata(path=meta_path, scheme='legacy') - req_path = os.path.join(path, 'EGG-INFO', 'requires.txt') - requires = parse_requires_path(req_path) - else: - # FIXME handle the case where zipfile is not available - zipf = zipimport.zipimporter(path) - fileobj = StringIO( - zipf.get_data('EGG-INFO/PKG-INFO').decode('utf8')) - metadata = Metadata(fileobj=fileobj, scheme='legacy') - try: - data = zipf.get_data('EGG-INFO/requires.txt') - requires = parse_requires_data(data.decode('utf-8')) - except IOError: - requires = None - elif path.endswith('.egg-info'): - if os.path.isdir(path): - req_path = os.path.join(path, 'requires.txt') - requires = parse_requires_path(req_path) - path = os.path.join(path, 'PKG-INFO') - metadata = Metadata(path=path, scheme='legacy') - else: - raise DistlibException('path must end with .egg-info or .egg, ' - 'got %r' % path) - - if requires: - metadata.add_requirements(requires) - return metadata - - def __repr__(self): - return '' % ( - self.name, self.version, self.path) - - def __str__(self): - return "%s %s" % (self.name, self.version) - - def check_installed_files(self): - """ - Checks that the hashes and sizes of the files in ``RECORD`` are - matched by the files themselves. Returns a (possibly empty) list of - mismatches. Each entry in the mismatch list will be a tuple consisting - of the path, 'exists', 'size' or 'hash' according to what didn't match - (existence is checked first, then size, then hash), the expected - value and the actual value. - """ - mismatches = [] - record_path = os.path.join(self.path, 'installed-files.txt') - if os.path.exists(record_path): - for path, _, _ in self.list_installed_files(): - if path == record_path: - continue - if not os.path.exists(path): - mismatches.append((path, 'exists', True, False)) - return mismatches - - def list_installed_files(self): - """ - Iterates over the ``installed-files.txt`` entries and returns a tuple - ``(path, hash, size)`` for each line. - - :returns: a list of (path, hash, size) - """ - - def _md5(path): - f = open(path, 'rb') - try: - content = f.read() - finally: - f.close() - return hashlib.md5(content).hexdigest() - - def _size(path): - return os.stat(path).st_size - - record_path = os.path.join(self.path, 'installed-files.txt') - result = [] - if os.path.exists(record_path): - with codecs.open(record_path, 'r', encoding='utf-8') as f: - for line in f: - line = line.strip() - p = os.path.normpath(os.path.join(self.path, line)) - # "./" is present as a marker between installed files - # and installation metadata files - if not os.path.exists(p): - logger.warning('Non-existent file: %s', p) - if p.endswith(('.pyc', '.pyo')): - continue - #otherwise fall through and fail - if not os.path.isdir(p): - result.append((p, _md5(p), _size(p))) - result.append((record_path, None, None)) - return result - - def list_distinfo_files(self, absolute=False): - """ - Iterates over the ``installed-files.txt`` entries and returns paths for - each line if the path is pointing to a file located in the - ``.egg-info`` directory or one of its subdirectories. - - :parameter absolute: If *absolute* is ``True``, each returned path is - transformed into a local absolute path. Otherwise the - raw value from ``installed-files.txt`` is returned. - :type absolute: boolean - :returns: iterator of paths - """ - record_path = os.path.join(self.path, 'installed-files.txt') - skip = True - with codecs.open(record_path, 'r', encoding='utf-8') as f: - for line in f: - line = line.strip() - if line == './': - skip = False - continue - if not skip: - p = os.path.normpath(os.path.join(self.path, line)) - if p.startswith(self.path): - if absolute: - yield p - else: - yield line - - def __eq__(self, other): - return (isinstance(other, EggInfoDistribution) and - self.path == other.path) - - # See http://docs.python.org/reference/datamodel#object.__hash__ - __hash__ = object.__hash__ - -new_dist_class = InstalledDistribution -old_dist_class = EggInfoDistribution - - -class DependencyGraph(object): - """ - Represents a dependency graph between distributions. - - The dependency relationships are stored in an ``adjacency_list`` that maps - distributions to a list of ``(other, label)`` tuples where ``other`` - is a distribution and the edge is labeled with ``label`` (i.e. the version - specifier, if such was provided). Also, for more efficient traversal, for - every distribution ``x``, a list of predecessors is kept in - ``reverse_list[x]``. An edge from distribution ``a`` to - distribution ``b`` means that ``a`` depends on ``b``. If any missing - dependencies are found, they are stored in ``missing``, which is a - dictionary that maps distributions to a list of requirements that were not - provided by any other distributions. - """ - - def __init__(self): - self.adjacency_list = {} - self.reverse_list = {} - self.missing = {} - - def add_distribution(self, distribution): - """Add the *distribution* to the graph. - - :type distribution: :class:`distutils2.database.InstalledDistribution` - or :class:`distutils2.database.EggInfoDistribution` - """ - self.adjacency_list[distribution] = [] - self.reverse_list[distribution] = [] - #self.missing[distribution] = [] - - def add_edge(self, x, y, label=None): - """Add an edge from distribution *x* to distribution *y* with the given - *label*. - - :type x: :class:`distutils2.database.InstalledDistribution` or - :class:`distutils2.database.EggInfoDistribution` - :type y: :class:`distutils2.database.InstalledDistribution` or - :class:`distutils2.database.EggInfoDistribution` - :type label: ``str`` or ``None`` - """ - self.adjacency_list[x].append((y, label)) - # multiple edges are allowed, so be careful - if x not in self.reverse_list[y]: - self.reverse_list[y].append(x) - - def add_missing(self, distribution, requirement): - """ - Add a missing *requirement* for the given *distribution*. - - :type distribution: :class:`distutils2.database.InstalledDistribution` - or :class:`distutils2.database.EggInfoDistribution` - :type requirement: ``str`` - """ - logger.debug('%s missing %r', distribution, requirement) - self.missing.setdefault(distribution, []).append(requirement) - - def _repr_dist(self, dist): - return '%s %s' % (dist.name, dist.version) - - def repr_node(self, dist, level=1): - """Prints only a subgraph""" - output = [self._repr_dist(dist)] - for other, label in self.adjacency_list[dist]: - dist = self._repr_dist(other) - if label is not None: - dist = '%s [%s]' % (dist, label) - output.append(' ' * level + str(dist)) - suboutput = self.repr_node(other, level + 1) - subs = suboutput.split('\n') - output.extend(subs[1:]) - return '\n'.join(output) - - def to_dot(self, f, skip_disconnected=True): - """Writes a DOT output for the graph to the provided file *f*. - - If *skip_disconnected* is set to ``True``, then all distributions - that are not dependent on any other distribution are skipped. - - :type f: has to support ``file``-like operations - :type skip_disconnected: ``bool`` - """ - disconnected = [] - - f.write("digraph dependencies {\n") - for dist, adjs in self.adjacency_list.items(): - if len(adjs) == 0 and not skip_disconnected: - disconnected.append(dist) - for other, label in adjs: - if not label is None: - f.write('"%s" -> "%s" [label="%s"]\n' % - (dist.name, other.name, label)) - else: - f.write('"%s" -> "%s"\n' % (dist.name, other.name)) - if not skip_disconnected and len(disconnected) > 0: - f.write('subgraph disconnected {\n') - f.write('label = "Disconnected"\n') - f.write('bgcolor = red\n') - - for dist in disconnected: - f.write('"%s"' % dist.name) - f.write('\n') - f.write('}\n') - f.write('}\n') - - def topological_sort(self): - """ - Perform a topological sort of the graph. - :return: A tuple, the first element of which is a topologically sorted - list of distributions, and the second element of which is a - list of distributions that cannot be sorted because they have - circular dependencies and so form a cycle. - """ - result = [] - # Make a shallow copy of the adjacency list - alist = {} - for k, v in self.adjacency_list.items(): - alist[k] = v[:] - while True: - # See what we can remove in this run - to_remove = [] - for k, v in list(alist.items())[:]: - if not v: - to_remove.append(k) - del alist[k] - if not to_remove: - # What's left in alist (if anything) is a cycle. - break - # Remove from the adjacency list of others - for k, v in alist.items(): - alist[k] = [(d, r) for d, r in v if d not in to_remove] - logger.debug('Moving to result: %s', - ['%s (%s)' % (d.name, d.version) for d in to_remove]) - result.extend(to_remove) - return result, list(alist.keys()) - - def __repr__(self): - """Representation of the graph""" - output = [] - for dist, adjs in self.adjacency_list.items(): - output.append(self.repr_node(dist)) - return '\n'.join(output) - - -def make_graph(dists, scheme='default'): - """Makes a dependency graph from the given distributions. - - :parameter dists: a list of distributions - :type dists: list of :class:`distutils2.database.InstalledDistribution` and - :class:`distutils2.database.EggInfoDistribution` instances - :rtype: a :class:`DependencyGraph` instance - """ - scheme = get_scheme(scheme) - graph = DependencyGraph() - provided = {} # maps names to lists of (version, dist) tuples - - # first, build the graph and find out what's provided - for dist in dists: - graph.add_distribution(dist) - - for p in dist.provides: - name, version = parse_name_and_version(p) - logger.debug('Add to provided: %s, %s, %s', name, version, dist) - provided.setdefault(name, []).append((version, dist)) - - # now make the edges - for dist in dists: - requires = (dist.run_requires | dist.meta_requires | - dist.build_requires | dist.dev_requires) - for req in requires: - try: - matcher = scheme.matcher(req) - except UnsupportedVersionError: - # XXX compat-mode if cannot read the version - logger.warning('could not read version %r - using name only', - req) - name = req.split()[0] - matcher = scheme.matcher(name) - - name = matcher.key # case-insensitive - - matched = False - if name in provided: - for version, provider in provided[name]: - try: - match = matcher.match(version) - except UnsupportedVersionError: - match = False - - if match: - graph.add_edge(dist, provider, req) - matched = True - break - if not matched: - graph.add_missing(dist, req) - return graph - - -def get_dependent_dists(dists, dist): - """Recursively generate a list of distributions from *dists* that are - dependent on *dist*. - - :param dists: a list of distributions - :param dist: a distribution, member of *dists* for which we are interested - """ - if dist not in dists: - raise DistlibException('given distribution %r is not a member ' - 'of the list' % dist.name) - graph = make_graph(dists) - - dep = [dist] # dependent distributions - todo = graph.reverse_list[dist] # list of nodes we should inspect - - while todo: - d = todo.pop() - dep.append(d) - for succ in graph.reverse_list[d]: - if succ not in dep: - todo.append(succ) - - dep.pop(0) # remove dist from dep, was there to prevent infinite loops - return dep - - -def get_required_dists(dists, dist): - """Recursively generate a list of distributions from *dists* that are - required by *dist*. - - :param dists: a list of distributions - :param dist: a distribution, member of *dists* for which we are interested - """ - if dist not in dists: - raise DistlibException('given distribution %r is not a member ' - 'of the list' % dist.name) - graph = make_graph(dists) - - req = [] # required distributions - todo = graph.adjacency_list[dist] # list of nodes we should inspect - - while todo: - d = todo.pop()[0] - req.append(d) - for pred in graph.adjacency_list[d]: - if pred not in req: - todo.append(pred) - - return req - - -def make_dist(name, version, **kwargs): - """ - A convenience method for making a dist given just a name and version. - """ - summary = kwargs.pop('summary', 'Placeholder for summary') - md = Metadata(**kwargs) - md.name = name - md.version = version - md.summary = summary or 'Plaeholder for summary' - return Distribution(md) diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/index.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/index.py deleted file mode 100644 index 73037c9..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/index.py +++ /dev/null @@ -1,513 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2013 Vinay Sajip. -# Licensed to the Python Software Foundation under a contributor agreement. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -import hashlib -import logging -import os -import shutil -import subprocess -import tempfile -try: - from threading import Thread -except ImportError: - from dummy_threading import Thread - -from . import DistlibException -from .compat import (HTTPBasicAuthHandler, Request, HTTPPasswordMgr, - urlparse, build_opener, string_types) -from .util import cached_property, zip_dir, ServerProxy - -logger = logging.getLogger(__name__) - -DEFAULT_INDEX = 'https://pypi.python.org/pypi' -DEFAULT_REALM = 'pypi' - -class PackageIndex(object): - """ - This class represents a package index compatible with PyPI, the Python - Package Index. - """ - - boundary = b'----------ThIs_Is_tHe_distlib_index_bouNdaRY_$' - - def __init__(self, url=None): - """ - Initialise an instance. - - :param url: The URL of the index. If not specified, the URL for PyPI is - used. - """ - self.url = url or DEFAULT_INDEX - self.read_configuration() - scheme, netloc, path, params, query, frag = urlparse(self.url) - if params or query or frag or scheme not in ('http', 'https'): - raise DistlibException('invalid repository: %s' % self.url) - self.password_handler = None - self.ssl_verifier = None - self.gpg = None - self.gpg_home = None - self.rpc_proxy = None - with open(os.devnull, 'w') as sink: - for s in ('gpg2', 'gpg'): - try: - rc = subprocess.check_call([s, '--version'], stdout=sink, - stderr=sink) - if rc == 0: - self.gpg = s - break - except OSError: - pass - - def _get_pypirc_command(self): - """ - Get the distutils command for interacting with PyPI configurations. - :return: the command. - """ - from distutils.core import Distribution - from distutils.config import PyPIRCCommand - d = Distribution() - return PyPIRCCommand(d) - - def read_configuration(self): - """ - Read the PyPI access configuration as supported by distutils, getting - PyPI to do the acutal work. This populates ``username``, ``password``, - ``realm`` and ``url`` attributes from the configuration. - """ - # get distutils to do the work - c = self._get_pypirc_command() - c.repository = self.url - cfg = c._read_pypirc() - self.username = cfg.get('username') - self.password = cfg.get('password') - self.realm = cfg.get('realm', 'pypi') - self.url = cfg.get('repository', self.url) - - def save_configuration(self): - """ - Save the PyPI access configuration. You must have set ``username`` and - ``password`` attributes before calling this method. - - Again, distutils is used to do the actual work. - """ - self.check_credentials() - # get distutils to do the work - c = self._get_pypirc_command() - c._store_pypirc(self.username, self.password) - - def check_credentials(self): - """ - Check that ``username`` and ``password`` have been set, and raise an - exception if not. - """ - if self.username is None or self.password is None: - raise DistlibException('username and password must be set') - pm = HTTPPasswordMgr() - _, netloc, _, _, _, _ = urlparse(self.url) - pm.add_password(self.realm, netloc, self.username, self.password) - self.password_handler = HTTPBasicAuthHandler(pm) - - def register(self, metadata): - """ - Register a distribution on PyPI, using the provided metadata. - - :param metadata: A :class:`Metadata` instance defining at least a name - and version number for the distribution to be - registered. - :return: The HTTP response received from PyPI upon submission of the - request. - """ - self.check_credentials() - metadata.validate() - d = metadata.todict() - d[':action'] = 'verify' - request = self.encode_request(d.items(), []) - response = self.send_request(request) - d[':action'] = 'submit' - request = self.encode_request(d.items(), []) - return self.send_request(request) - - def _reader(self, name, stream, outbuf): - """ - Thread runner for reading lines of from a subprocess into a buffer. - - :param name: The logical name of the stream (used for logging only). - :param stream: The stream to read from. This will typically a pipe - connected to the output stream of a subprocess. - :param outbuf: The list to append the read lines to. - """ - while True: - s = stream.readline() - if not s: - break - s = s.decode('utf-8').rstrip() - outbuf.append(s) - logger.debug('%s: %s' % (name, s)) - stream.close() - - def get_sign_command(self, filename, signer, sign_password, - keystore=None): - """ - Return a suitable command for signing a file. - - :param filename: The pathname to the file to be signed. - :param signer: The identifier of the signer of the file. - :param sign_password: The passphrase for the signer's - private key used for signing. - :param keystore: The path to a directory which contains the keys - used in verification. If not specified, the - instance's ``gpg_home`` attribute is used instead. - :return: The signing command as a list suitable to be - passed to :class:`subprocess.Popen`. - """ - cmd = [self.gpg, '--status-fd', '2', '--no-tty'] - if keystore is None: - keystore = self.gpg_home - if keystore: - cmd.extend(['--homedir', keystore]) - if sign_password is not None: - cmd.extend(['--batch', '--passphrase-fd', '0']) - td = tempfile.mkdtemp() - sf = os.path.join(td, os.path.basename(filename) + '.asc') - cmd.extend(['--detach-sign', '--armor', '--local-user', - signer, '--output', sf, filename]) - logger.debug('invoking: %s', ' '.join(cmd)) - return cmd, sf - - def run_command(self, cmd, input_data=None): - """ - Run a command in a child process , passing it any input data specified. - - :param cmd: The command to run. - :param input_data: If specified, this must be a byte string containing - data to be sent to the child process. - :return: A tuple consisting of the subprocess' exit code, a list of - lines read from the subprocess' ``stdout``, and a list of - lines read from the subprocess' ``stderr``. - """ - kwargs = { - 'stdout': subprocess.PIPE, - 'stderr': subprocess.PIPE, - } - if input_data is not None: - kwargs['stdin'] = subprocess.PIPE - stdout = [] - stderr = [] - p = subprocess.Popen(cmd, **kwargs) - # We don't use communicate() here because we may need to - # get clever with interacting with the command - t1 = Thread(target=self._reader, args=('stdout', p.stdout, stdout)) - t1.start() - t2 = Thread(target=self._reader, args=('stderr', p.stderr, stderr)) - t2.start() - if input_data is not None: - p.stdin.write(input_data) - p.stdin.close() - - p.wait() - t1.join() - t2.join() - return p.returncode, stdout, stderr - - def sign_file(self, filename, signer, sign_password, keystore=None): - """ - Sign a file. - - :param filename: The pathname to the file to be signed. - :param signer: The identifier of the signer of the file. - :param sign_password: The passphrase for the signer's - private key used for signing. - :param keystore: The path to a directory which contains the keys - used in signing. If not specified, the instance's - ``gpg_home`` attribute is used instead. - :return: The absolute pathname of the file where the signature is - stored. - """ - cmd, sig_file = self.get_sign_command(filename, signer, sign_password, - keystore) - rc, stdout, stderr = self.run_command(cmd, - sign_password.encode('utf-8')) - if rc != 0: - raise DistlibException('sign command failed with error ' - 'code %s' % rc) - return sig_file - - def upload_file(self, metadata, filename, signer=None, sign_password=None, - filetype='sdist', pyversion='source', keystore=None): - """ - Upload a release file to the index. - - :param metadata: A :class:`Metadata` instance defining at least a name - and version number for the file to be uploaded. - :param filename: The pathname of the file to be uploaded. - :param signer: The identifier of the signer of the file. - :param sign_password: The passphrase for the signer's - private key used for signing. - :param filetype: The type of the file being uploaded. This is the - distutils command which produced that file, e.g. - ``sdist`` or ``bdist_wheel``. - :param pyversion: The version of Python which the release relates - to. For code compatible with any Python, this would - be ``source``, otherwise it would be e.g. ``3.2``. - :param keystore: The path to a directory which contains the keys - used in signing. If not specified, the instance's - ``gpg_home`` attribute is used instead. - :return: The HTTP response received from PyPI upon submission of the - request. - """ - self.check_credentials() - if not os.path.exists(filename): - raise DistlibException('not found: %s' % filename) - metadata.validate() - d = metadata.todict() - sig_file = None - if signer: - if not self.gpg: - logger.warning('no signing program available - not signed') - else: - sig_file = self.sign_file(filename, signer, sign_password, - keystore) - with open(filename, 'rb') as f: - file_data = f.read() - md5_digest = hashlib.md5(file_data).hexdigest() - sha256_digest = hashlib.sha256(file_data).hexdigest() - d.update({ - ':action': 'file_upload', - 'protcol_version': '1', - 'filetype': filetype, - 'pyversion': pyversion, - 'md5_digest': md5_digest, - 'sha256_digest': sha256_digest, - }) - files = [('content', os.path.basename(filename), file_data)] - if sig_file: - with open(sig_file, 'rb') as f: - sig_data = f.read() - files.append(('gpg_signature', os.path.basename(sig_file), - sig_data)) - shutil.rmtree(os.path.dirname(sig_file)) - request = self.encode_request(d.items(), files) - return self.send_request(request) - - def upload_documentation(self, metadata, doc_dir): - """ - Upload documentation to the index. - - :param metadata: A :class:`Metadata` instance defining at least a name - and version number for the documentation to be - uploaded. - :param doc_dir: The pathname of the directory which contains the - documentation. This should be the directory that - contains the ``index.html`` for the documentation. - :return: The HTTP response received from PyPI upon submission of the - request. - """ - self.check_credentials() - if not os.path.isdir(doc_dir): - raise DistlibException('not a directory: %r' % doc_dir) - fn = os.path.join(doc_dir, 'index.html') - if not os.path.exists(fn): - raise DistlibException('not found: %r' % fn) - metadata.validate() - name, version = metadata.name, metadata.version - zip_data = zip_dir(doc_dir).getvalue() - fields = [(':action', 'doc_upload'), - ('name', name), ('version', version)] - files = [('content', name, zip_data)] - request = self.encode_request(fields, files) - return self.send_request(request) - - def get_verify_command(self, signature_filename, data_filename, - keystore=None): - """ - Return a suitable command for verifying a file. - - :param signature_filename: The pathname to the file containing the - signature. - :param data_filename: The pathname to the file containing the - signed data. - :param keystore: The path to a directory which contains the keys - used in verification. If not specified, the - instance's ``gpg_home`` attribute is used instead. - :return: The verifying command as a list suitable to be - passed to :class:`subprocess.Popen`. - """ - cmd = [self.gpg, '--status-fd', '2', '--no-tty'] - if keystore is None: - keystore = self.gpg_home - if keystore: - cmd.extend(['--homedir', keystore]) - cmd.extend(['--verify', signature_filename, data_filename]) - logger.debug('invoking: %s', ' '.join(cmd)) - return cmd - - def verify_signature(self, signature_filename, data_filename, - keystore=None): - """ - Verify a signature for a file. - - :param signature_filename: The pathname to the file containing the - signature. - :param data_filename: The pathname to the file containing the - signed data. - :param keystore: The path to a directory which contains the keys - used in verification. If not specified, the - instance's ``gpg_home`` attribute is used instead. - :return: True if the signature was verified, else False. - """ - if not self.gpg: - raise DistlibException('verification unavailable because gpg ' - 'unavailable') - cmd = self.get_verify_command(signature_filename, data_filename, - keystore) - rc, stdout, stderr = self.run_command(cmd) - if rc not in (0, 1): - raise DistlibException('verify command failed with error ' - 'code %s' % rc) - return rc == 0 - - def download_file(self, url, destfile, digest=None, reporthook=None): - """ - This is a convenience method for downloading a file from an URL. - Normally, this will be a file from the index, though currently - no check is made for this (i.e. a file can be downloaded from - anywhere). - - The method is just like the :func:`urlretrieve` function in the - standard library, except that it allows digest computation to be - done during download and checking that the downloaded data - matched any expected value. - - :param url: The URL of the file to be downloaded (assumed to be - available via an HTTP GET request). - :param destfile: The pathname where the downloaded file is to be - saved. - :param digest: If specified, this must be a (hasher, value) - tuple, where hasher is the algorithm used (e.g. - ``'md5'``) and ``value`` is the expected value. - :param reporthook: The same as for :func:`urlretrieve` in the - standard library. - """ - if digest is None: - digester = None - logger.debug('No digest specified') - else: - if isinstance(digest, (list, tuple)): - hasher, digest = digest - else: - hasher = 'md5' - digester = getattr(hashlib, hasher)() - logger.debug('Digest specified: %s' % digest) - # The following code is equivalent to urlretrieve. - # We need to do it this way so that we can compute the - # digest of the file as we go. - with open(destfile, 'wb') as dfp: - # addinfourl is not a context manager on 2.x - # so we have to use try/finally - sfp = self.send_request(Request(url)) - try: - headers = sfp.info() - blocksize = 8192 - size = -1 - read = 0 - blocknum = 0 - if "content-length" in headers: - size = int(headers["Content-Length"]) - if reporthook: - reporthook(blocknum, blocksize, size) - while True: - block = sfp.read(blocksize) - if not block: - break - read += len(block) - dfp.write(block) - if digester: - digester.update(block) - blocknum += 1 - if reporthook: - reporthook(blocknum, blocksize, size) - finally: - sfp.close() - - # check that we got the whole file, if we can - if size >= 0 and read < size: - raise DistlibException( - 'retrieval incomplete: got only %d out of %d bytes' - % (read, size)) - # if we have a digest, it must match. - if digester: - actual = digester.hexdigest() - if digest != actual: - raise DistlibException('%s digest mismatch for %s: expected ' - '%s, got %s' % (hasher, destfile, - digest, actual)) - logger.debug('Digest verified: %s', digest) - - def send_request(self, req): - """ - Send a standard library :class:`Request` to PyPI and return its - response. - - :param req: The request to send. - :return: The HTTP response from PyPI (a standard library HTTPResponse). - """ - handlers = [] - if self.password_handler: - handlers.append(self.password_handler) - if self.ssl_verifier: - handlers.append(self.ssl_verifier) - opener = build_opener(*handlers) - return opener.open(req) - - def encode_request(self, fields, files): - """ - Encode fields and files for posting to an HTTP server. - - :param fields: The fields to send as a list of (fieldname, value) - tuples. - :param files: The files to send as a list of (fieldname, filename, - file_bytes) tuple. - """ - # Adapted from packaging, which in turn was adapted from - # http://code.activestate.com/recipes/146306 - - parts = [] - boundary = self.boundary - for k, values in fields: - if not isinstance(values, (list, tuple)): - values = [values] - - for v in values: - parts.extend(( - b'--' + boundary, - ('Content-Disposition: form-data; name="%s"' % - k).encode('utf-8'), - b'', - v.encode('utf-8'))) - for key, filename, value in files: - parts.extend(( - b'--' + boundary, - ('Content-Disposition: form-data; name="%s"; filename="%s"' % - (key, filename)).encode('utf-8'), - b'', - value)) - - parts.extend((b'--' + boundary + b'--', b'')) - - body = b'\r\n'.join(parts) - ct = b'multipart/form-data; boundary=' + boundary - headers = { - 'Content-type': ct, - 'Content-length': str(len(body)) - } - return Request(self.url, body, headers) - - def search(self, terms, operator=None): - if isinstance(terms, string_types): - terms = {'name': terms} - if self.rpc_proxy is None: - self.rpc_proxy = ServerProxy(self.url, timeout=3.0) - return self.rpc_proxy.search(terms, operator or 'and') diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/locators.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/locators.py deleted file mode 100644 index ef584d5..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/locators.py +++ /dev/null @@ -1,1264 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012-2015 Vinay Sajip. -# Licensed to the Python Software Foundation under a contributor agreement. -# See LICENSE.txt and CONTRIBUTORS.txt. -# - -import gzip -from io import BytesIO -import json -import logging -import os -import posixpath -import re -try: - import threading -except ImportError: - import dummy_threading as threading -import zlib - -from . import DistlibException -from .compat import (urljoin, urlparse, urlunparse, url2pathname, pathname2url, - queue, quote, unescape, string_types, build_opener, - HTTPRedirectHandler as BaseRedirectHandler, - Request, HTTPError, URLError) -from .database import Distribution, DistributionPath, make_dist -from .metadata import Metadata -from .util import (cached_property, parse_credentials, ensure_slash, - split_filename, get_project_data, parse_requirement, - parse_name_and_version, ServerProxy) -from .version import get_scheme, UnsupportedVersionError -from .wheel import Wheel, is_compatible - -logger = logging.getLogger(__name__) - -HASHER_HASH = re.compile('^(\w+)=([a-f0-9]+)') -CHARSET = re.compile(r';\s*charset\s*=\s*(.*)\s*$', re.I) -HTML_CONTENT_TYPE = re.compile('text/html|application/x(ht)?ml') -DEFAULT_INDEX = 'http://python.org/pypi' - -def get_all_distribution_names(url=None): - """ - Return all distribution names known by an index. - :param url: The URL of the index. - :return: A list of all known distribution names. - """ - if url is None: - url = DEFAULT_INDEX - client = ServerProxy(url, timeout=3.0) - return client.list_packages() - -class RedirectHandler(BaseRedirectHandler): - """ - A class to work around a bug in some Python 3.2.x releases. - """ - # There's a bug in the base version for some 3.2.x - # (e.g. 3.2.2 on Ubuntu Oneiric). If a Location header - # returns e.g. /abc, it bails because it says the scheme '' - # is bogus, when actually it should use the request's - # URL for the scheme. See Python issue #13696. - def http_error_302(self, req, fp, code, msg, headers): - # Some servers (incorrectly) return multiple Location headers - # (so probably same goes for URI). Use first header. - newurl = None - for key in ('location', 'uri'): - if key in headers: - newurl = headers[key] - break - if newurl is None: - return - urlparts = urlparse(newurl) - if urlparts.scheme == '': - newurl = urljoin(req.get_full_url(), newurl) - if hasattr(headers, 'replace_header'): - headers.replace_header(key, newurl) - else: - headers[key] = newurl - return BaseRedirectHandler.http_error_302(self, req, fp, code, msg, - headers) - - http_error_301 = http_error_303 = http_error_307 = http_error_302 - -class Locator(object): - """ - A base class for locators - things that locate distributions. - """ - source_extensions = ('.tar.gz', '.tar.bz2', '.tar', '.zip', '.tgz', '.tbz') - binary_extensions = ('.egg', '.exe', '.whl') - excluded_extensions = ('.pdf',) - - # A list of tags indicating which wheels you want to match. The default - # value of None matches against the tags compatible with the running - # Python. If you want to match other values, set wheel_tags on a locator - # instance to a list of tuples (pyver, abi, arch) which you want to match. - wheel_tags = None - - downloadable_extensions = source_extensions + ('.whl',) - - def __init__(self, scheme='default'): - """ - Initialise an instance. - :param scheme: Because locators look for most recent versions, they - need to know the version scheme to use. This specifies - the current PEP-recommended scheme - use ``'legacy'`` - if you need to support existing distributions on PyPI. - """ - self._cache = {} - self.scheme = scheme - # Because of bugs in some of the handlers on some of the platforms, - # we use our own opener rather than just using urlopen. - self.opener = build_opener(RedirectHandler()) - # If get_project() is called from locate(), the matcher instance - # is set from the requirement passed to locate(). See issue #18 for - # why this can be useful to know. - self.matcher = None - - def clear_cache(self): - self._cache.clear() - - def _get_scheme(self): - return self._scheme - - def _set_scheme(self, value): - self._scheme = value - - scheme = property(_get_scheme, _set_scheme) - - def _get_project(self, name): - """ - For a given project, get a dictionary mapping available versions to Distribution - instances. - - This should be implemented in subclasses. - - If called from a locate() request, self.matcher will be set to a - matcher for the requirement to satisfy, otherwise it will be None. - """ - raise NotImplementedError('Please implement in the subclass') - - def get_distribution_names(self): - """ - Return all the distribution names known to this locator. - """ - raise NotImplementedError('Please implement in the subclass') - - def get_project(self, name): - """ - For a given project, get a dictionary mapping available versions to Distribution - instances. - - This calls _get_project to do all the work, and just implements a caching layer on top. - """ - if self._cache is None: - result = self._get_project(name) - elif name in self._cache: - result = self._cache[name] - else: - result = self._get_project(name) - self._cache[name] = result - return result - - def score_url(self, url): - """ - Give an url a score which can be used to choose preferred URLs - for a given project release. - """ - t = urlparse(url) - basename = posixpath.basename(t.path) - compatible = True - is_wheel = basename.endswith('.whl') - if is_wheel: - compatible = is_compatible(Wheel(basename), self.wheel_tags) - return (t.scheme != 'https', 'pypi.python.org' in t.netloc, - is_wheel, compatible, basename) - - def prefer_url(self, url1, url2): - """ - Choose one of two URLs where both are candidates for distribution - archives for the same version of a distribution (for example, - .tar.gz vs. zip). - - The current implementation favours https:// URLs over http://, archives - from PyPI over those from other locations, wheel compatibility (if a - wheel) and then the archive name. - """ - result = url2 - if url1: - s1 = self.score_url(url1) - s2 = self.score_url(url2) - if s1 > s2: - result = url1 - if result != url2: - logger.debug('Not replacing %r with %r', url1, url2) - else: - logger.debug('Replacing %r with %r', url1, url2) - return result - - def split_filename(self, filename, project_name): - """ - Attempt to split a filename in project name, version and Python version. - """ - return split_filename(filename, project_name) - - def convert_url_to_download_info(self, url, project_name): - """ - See if a URL is a candidate for a download URL for a project (the URL - has typically been scraped from an HTML page). - - If it is, a dictionary is returned with keys "name", "version", - "filename" and "url"; otherwise, None is returned. - """ - def same_project(name1, name2): - name1, name2 = name1.lower(), name2.lower() - if name1 == name2: - result = True - else: - # distribute replaces '-' by '_' in project names, so it - # can tell where the version starts in a filename. - result = name1.replace('_', '-') == name2.replace('_', '-') - return result - - result = None - scheme, netloc, path, params, query, frag = urlparse(url) - if frag.lower().startswith('egg='): - logger.debug('%s: version hint in fragment: %r', - project_name, frag) - m = HASHER_HASH.match(frag) - if m: - algo, digest = m.groups() - else: - algo, digest = None, None - origpath = path - if path and path[-1] == '/': - path = path[:-1] - if path.endswith('.whl'): - try: - wheel = Wheel(path) - if is_compatible(wheel, self.wheel_tags): - if project_name is None: - include = True - else: - include = same_project(wheel.name, project_name) - if include: - result = { - 'name': wheel.name, - 'version': wheel.version, - 'filename': wheel.filename, - 'url': urlunparse((scheme, netloc, origpath, - params, query, '')), - 'python-version': ', '.join( - ['.'.join(list(v[2:])) for v in wheel.pyver]), - } - except Exception as e: - logger.warning('invalid path for wheel: %s', path) - elif path.endswith(self.downloadable_extensions): - path = filename = posixpath.basename(path) - for ext in self.downloadable_extensions: - if path.endswith(ext): - path = path[:-len(ext)] - t = self.split_filename(path, project_name) - if not t: - logger.debug('No match for project/version: %s', path) - else: - name, version, pyver = t - if not project_name or same_project(project_name, name): - result = { - 'name': name, - 'version': version, - 'filename': filename, - 'url': urlunparse((scheme, netloc, origpath, - params, query, '')), - #'packagetype': 'sdist', - } - if pyver: - result['python-version'] = pyver - break - if result and algo: - result['%s_digest' % algo] = digest - return result - - def _get_digest(self, info): - """ - Get a digest from a dictionary by looking at keys of the form - 'algo_digest'. - - Returns a 2-tuple (algo, digest) if found, else None. Currently - looks only for SHA256, then MD5. - """ - result = None - for algo in ('sha256', 'md5'): - key = '%s_digest' % algo - if key in info: - result = (algo, info[key]) - break - return result - - def _update_version_data(self, result, info): - """ - Update a result dictionary (the final result from _get_project) with a - dictionary for a specific version, which typically holds information - gleaned from a filename or URL for an archive for the distribution. - """ - name = info.pop('name') - version = info.pop('version') - if version in result: - dist = result[version] - md = dist.metadata - else: - dist = make_dist(name, version, scheme=self.scheme) - md = dist.metadata - dist.digest = digest = self._get_digest(info) - url = info['url'] - result['digests'][url] = digest - if md.source_url != info['url']: - md.source_url = self.prefer_url(md.source_url, url) - result['urls'].setdefault(version, set()).add(url) - dist.locator = self - result[version] = dist - - def locate(self, requirement, prereleases=False): - """ - Find the most recent distribution which matches the given - requirement. - - :param requirement: A requirement of the form 'foo (1.0)' or perhaps - 'foo (>= 1.0, < 2.0, != 1.3)' - :param prereleases: If ``True``, allow pre-release versions - to be located. Otherwise, pre-release versions - are not returned. - :return: A :class:`Distribution` instance, or ``None`` if no such - distribution could be located. - """ - result = None - r = parse_requirement(requirement) - if r is None: - raise DistlibException('Not a valid requirement: %r' % requirement) - scheme = get_scheme(self.scheme) - self.matcher = matcher = scheme.matcher(r.requirement) - logger.debug('matcher: %s (%s)', matcher, type(matcher).__name__) - versions = self.get_project(r.name) - if len(versions) > 2: # urls and digests keys are present - # sometimes, versions are invalid - slist = [] - vcls = matcher.version_class - for k in versions: - if k in ('urls', 'digests'): - continue - try: - if not matcher.match(k): - logger.debug('%s did not match %r', matcher, k) - else: - if prereleases or not vcls(k).is_prerelease: - slist.append(k) - else: - logger.debug('skipping pre-release ' - 'version %s of %s', k, matcher.name) - except Exception: - logger.warning('error matching %s with %r', matcher, k) - pass # slist.append(k) - if len(slist) > 1: - slist = sorted(slist, key=scheme.key) - if slist: - logger.debug('sorted list: %s', slist) - version = slist[-1] - result = versions[version] - if result: - if r.extras: - result.extras = r.extras - result.download_urls = versions.get('urls', {}).get(version, set()) - d = {} - sd = versions.get('digests', {}) - for url in result.download_urls: - if url in sd: - d[url] = sd[url] - result.digests = d - self.matcher = None - return result - - -class PyPIRPCLocator(Locator): - """ - This locator uses XML-RPC to locate distributions. It therefore - cannot be used with simple mirrors (that only mirror file content). - """ - def __init__(self, url, **kwargs): - """ - Initialise an instance. - - :param url: The URL to use for XML-RPC. - :param kwargs: Passed to the superclass constructor. - """ - super(PyPIRPCLocator, self).__init__(**kwargs) - self.base_url = url - self.client = ServerProxy(url, timeout=3.0) - - def get_distribution_names(self): - """ - Return all the distribution names known to this locator. - """ - return set(self.client.list_packages()) - - def _get_project(self, name): - result = {'urls': {}, 'digests': {}} - versions = self.client.package_releases(name, True) - for v in versions: - urls = self.client.release_urls(name, v) - data = self.client.release_data(name, v) - metadata = Metadata(scheme=self.scheme) - metadata.name = data['name'] - metadata.version = data['version'] - metadata.license = data.get('license') - metadata.keywords = data.get('keywords', []) - metadata.summary = data.get('summary') - dist = Distribution(metadata) - if urls: - info = urls[0] - metadata.source_url = info['url'] - dist.digest = self._get_digest(info) - dist.locator = self - result[v] = dist - for info in urls: - url = info['url'] - digest = self._get_digest(info) - result['urls'].setdefault(v, set()).add(url) - result['digests'][url] = digest - return result - -class PyPIJSONLocator(Locator): - """ - This locator uses PyPI's JSON interface. It's very limited in functionality - and probably not worth using. - """ - def __init__(self, url, **kwargs): - super(PyPIJSONLocator, self).__init__(**kwargs) - self.base_url = ensure_slash(url) - - def get_distribution_names(self): - """ - Return all the distribution names known to this locator. - """ - raise NotImplementedError('Not available from this locator') - - def _get_project(self, name): - result = {'urls': {}, 'digests': {}} - url = urljoin(self.base_url, '%s/json' % quote(name)) - try: - resp = self.opener.open(url) - data = resp.read().decode() # for now - d = json.loads(data) - md = Metadata(scheme=self.scheme) - data = d['info'] - md.name = data['name'] - md.version = data['version'] - md.license = data.get('license') - md.keywords = data.get('keywords', []) - md.summary = data.get('summary') - dist = Distribution(md) - dist.locator = self - urls = d['urls'] - result[md.version] = dist - for info in d['urls']: - url = info['url'] - dist.download_urls.add(url) - dist.digests[url] = self._get_digest(info) - result['urls'].setdefault(md.version, set()).add(url) - result['digests'][url] = self._get_digest(info) - # Now get other releases - for version, infos in d['releases'].items(): - if version == md.version: - continue # already done - omd = Metadata(scheme=self.scheme) - omd.name = md.name - omd.version = version - odist = Distribution(omd) - odist.locator = self - result[version] = odist - for info in infos: - url = info['url'] - odist.download_urls.add(url) - odist.digests[url] = self._get_digest(info) - result['urls'].setdefault(version, set()).add(url) - result['digests'][url] = self._get_digest(info) -# for info in urls: -# md.source_url = info['url'] -# dist.digest = self._get_digest(info) -# dist.locator = self -# for info in urls: -# url = info['url'] -# result['urls'].setdefault(md.version, set()).add(url) -# result['digests'][url] = self._get_digest(info) - except Exception as e: - logger.exception('JSON fetch failed: %s', e) - return result - - -class Page(object): - """ - This class represents a scraped HTML page. - """ - # The following slightly hairy-looking regex just looks for the contents of - # an anchor link, which has an attribute "href" either immediately preceded - # or immediately followed by a "rel" attribute. The attribute values can be - # declared with double quotes, single quotes or no quotes - which leads to - # the length of the expression. - _href = re.compile(""" -(rel\s*=\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\s\n]*))\s+)? -href\s*=\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\s\n]*)) -(\s+rel\s*=\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\s\n]*)))? -""", re.I | re.S | re.X) - _base = re.compile(r"""]+)""", re.I | re.S) - - def __init__(self, data, url): - """ - Initialise an instance with the Unicode page contents and the URL they - came from. - """ - self.data = data - self.base_url = self.url = url - m = self._base.search(self.data) - if m: - self.base_url = m.group(1) - - _clean_re = re.compile(r'[^a-z0-9$&+,/:;=?@.#%_\\|-]', re.I) - - @cached_property - def links(self): - """ - Return the URLs of all the links on a page together with information - about their "rel" attribute, for determining which ones to treat as - downloads and which ones to queue for further scraping. - """ - def clean(url): - "Tidy up an URL." - scheme, netloc, path, params, query, frag = urlparse(url) - return urlunparse((scheme, netloc, quote(path), - params, query, frag)) - - result = set() - for match in self._href.finditer(self.data): - d = match.groupdict('') - rel = (d['rel1'] or d['rel2'] or d['rel3'] or - d['rel4'] or d['rel5'] or d['rel6']) - url = d['url1'] or d['url2'] or d['url3'] - url = urljoin(self.base_url, url) - url = unescape(url) - url = self._clean_re.sub(lambda m: '%%%2x' % ord(m.group(0)), url) - result.add((url, rel)) - # We sort the result, hoping to bring the most recent versions - # to the front - result = sorted(result, key=lambda t: t[0], reverse=True) - return result - - -class SimpleScrapingLocator(Locator): - """ - A locator which scrapes HTML pages to locate downloads for a distribution. - This runs multiple threads to do the I/O; performance is at least as good - as pip's PackageFinder, which works in an analogous fashion. - """ - - # These are used to deal with various Content-Encoding schemes. - decoders = { - 'deflate': zlib.decompress, - 'gzip': lambda b: gzip.GzipFile(fileobj=BytesIO(d)).read(), - 'none': lambda b: b, - } - - def __init__(self, url, timeout=None, num_workers=10, **kwargs): - """ - Initialise an instance. - :param url: The root URL to use for scraping. - :param timeout: The timeout, in seconds, to be applied to requests. - This defaults to ``None`` (no timeout specified). - :param num_workers: The number of worker threads you want to do I/O, - This defaults to 10. - :param kwargs: Passed to the superclass. - """ - super(SimpleScrapingLocator, self).__init__(**kwargs) - self.base_url = ensure_slash(url) - self.timeout = timeout - self._page_cache = {} - self._seen = set() - self._to_fetch = queue.Queue() - self._bad_hosts = set() - self.skip_externals = False - self.num_workers = num_workers - self._lock = threading.RLock() - # See issue #45: we need to be resilient when the locator is used - # in a thread, e.g. with concurrent.futures. We can't use self._lock - # as it is for coordinating our internal threads - the ones created - # in _prepare_threads. - self._gplock = threading.RLock() - - def _prepare_threads(self): - """ - Threads are created only when get_project is called, and terminate - before it returns. They are there primarily to parallelise I/O (i.e. - fetching web pages). - """ - self._threads = [] - for i in range(self.num_workers): - t = threading.Thread(target=self._fetch) - t.setDaemon(True) - t.start() - self._threads.append(t) - - def _wait_threads(self): - """ - Tell all the threads to terminate (by sending a sentinel value) and - wait for them to do so. - """ - # Note that you need two loops, since you can't say which - # thread will get each sentinel - for t in self._threads: - self._to_fetch.put(None) # sentinel - for t in self._threads: - t.join() - self._threads = [] - - def _get_project(self, name): - result = {'urls': {}, 'digests': {}} - with self._gplock: - self.result = result - self.project_name = name - url = urljoin(self.base_url, '%s/' % quote(name)) - self._seen.clear() - self._page_cache.clear() - self._prepare_threads() - try: - logger.debug('Queueing %s', url) - self._to_fetch.put(url) - self._to_fetch.join() - finally: - self._wait_threads() - del self.result - return result - - platform_dependent = re.compile(r'\b(linux-(i\d86|x86_64|arm\w+)|' - r'win(32|-amd64)|macosx-?\d+)\b', re.I) - - def _is_platform_dependent(self, url): - """ - Does an URL refer to a platform-specific download? - """ - return self.platform_dependent.search(url) - - def _process_download(self, url): - """ - See if an URL is a suitable download for a project. - - If it is, register information in the result dictionary (for - _get_project) about the specific version it's for. - - Note that the return value isn't actually used other than as a boolean - value. - """ - if self._is_platform_dependent(url): - info = None - else: - info = self.convert_url_to_download_info(url, self.project_name) - logger.debug('process_download: %s -> %s', url, info) - if info: - with self._lock: # needed because self.result is shared - self._update_version_data(self.result, info) - return info - - def _should_queue(self, link, referrer, rel): - """ - Determine whether a link URL from a referring page and with a - particular "rel" attribute should be queued for scraping. - """ - scheme, netloc, path, _, _, _ = urlparse(link) - if path.endswith(self.source_extensions + self.binary_extensions + - self.excluded_extensions): - result = False - elif self.skip_externals and not link.startswith(self.base_url): - result = False - elif not referrer.startswith(self.base_url): - result = False - elif rel not in ('homepage', 'download'): - result = False - elif scheme not in ('http', 'https', 'ftp'): - result = False - elif self._is_platform_dependent(link): - result = False - else: - host = netloc.split(':', 1)[0] - if host.lower() == 'localhost': - result = False - else: - result = True - logger.debug('should_queue: %s (%s) from %s -> %s', link, rel, - referrer, result) - return result - - def _fetch(self): - """ - Get a URL to fetch from the work queue, get the HTML page, examine its - links for download candidates and candidates for further scraping. - - This is a handy method to run in a thread. - """ - while True: - url = self._to_fetch.get() - try: - if url: - page = self.get_page(url) - if page is None: # e.g. after an error - continue - for link, rel in page.links: - if link not in self._seen: - self._seen.add(link) - if (not self._process_download(link) and - self._should_queue(link, url, rel)): - logger.debug('Queueing %s from %s', link, url) - self._to_fetch.put(link) - finally: - # always do this, to avoid hangs :-) - self._to_fetch.task_done() - if not url: - #logger.debug('Sentinel seen, quitting.') - break - - def get_page(self, url): - """ - Get the HTML for an URL, possibly from an in-memory cache. - - XXX TODO Note: this cache is never actually cleared. It's assumed that - the data won't get stale over the lifetime of a locator instance (not - necessarily true for the default_locator). - """ - # http://peak.telecommunity.com/DevCenter/EasyInstall#package-index-api - scheme, netloc, path, _, _, _ = urlparse(url) - if scheme == 'file' and os.path.isdir(url2pathname(path)): - url = urljoin(ensure_slash(url), 'index.html') - - if url in self._page_cache: - result = self._page_cache[url] - logger.debug('Returning %s from cache: %s', url, result) - else: - host = netloc.split(':', 1)[0] - result = None - if host in self._bad_hosts: - logger.debug('Skipping %s due to bad host %s', url, host) - else: - req = Request(url, headers={'Accept-encoding': 'identity'}) - try: - logger.debug('Fetching %s', url) - resp = self.opener.open(req, timeout=self.timeout) - logger.debug('Fetched %s', url) - headers = resp.info() - content_type = headers.get('Content-Type', '') - if HTML_CONTENT_TYPE.match(content_type): - final_url = resp.geturl() - data = resp.read() - encoding = headers.get('Content-Encoding') - if encoding: - decoder = self.decoders[encoding] # fail if not found - data = decoder(data) - encoding = 'utf-8' - m = CHARSET.search(content_type) - if m: - encoding = m.group(1) - try: - data = data.decode(encoding) - except UnicodeError: - data = data.decode('latin-1') # fallback - result = Page(data, final_url) - self._page_cache[final_url] = result - except HTTPError as e: - if e.code != 404: - logger.exception('Fetch failed: %s: %s', url, e) - except URLError as e: - logger.exception('Fetch failed: %s: %s', url, e) - with self._lock: - self._bad_hosts.add(host) - except Exception as e: - logger.exception('Fetch failed: %s: %s', url, e) - finally: - self._page_cache[url] = result # even if None (failure) - return result - - _distname_re = re.compile(']*>([^<]+)<') - - def get_distribution_names(self): - """ - Return all the distribution names known to this locator. - """ - result = set() - page = self.get_page(self.base_url) - if not page: - raise DistlibException('Unable to get %s' % self.base_url) - for match in self._distname_re.finditer(page.data): - result.add(match.group(1)) - return result - -class DirectoryLocator(Locator): - """ - This class locates distributions in a directory tree. - """ - - def __init__(self, path, **kwargs): - """ - Initialise an instance. - :param path: The root of the directory tree to search. - :param kwargs: Passed to the superclass constructor, - except for: - * recursive - if True (the default), subdirectories are - recursed into. If False, only the top-level directory - is searched, - """ - self.recursive = kwargs.pop('recursive', True) - super(DirectoryLocator, self).__init__(**kwargs) - path = os.path.abspath(path) - if not os.path.isdir(path): - raise DistlibException('Not a directory: %r' % path) - self.base_dir = path - - def should_include(self, filename, parent): - """ - Should a filename be considered as a candidate for a distribution - archive? As well as the filename, the directory which contains it - is provided, though not used by the current implementation. - """ - return filename.endswith(self.downloadable_extensions) - - def _get_project(self, name): - result = {'urls': {}, 'digests': {}} - for root, dirs, files in os.walk(self.base_dir): - for fn in files: - if self.should_include(fn, root): - fn = os.path.join(root, fn) - url = urlunparse(('file', '', - pathname2url(os.path.abspath(fn)), - '', '', '')) - info = self.convert_url_to_download_info(url, name) - if info: - self._update_version_data(result, info) - if not self.recursive: - break - return result - - def get_distribution_names(self): - """ - Return all the distribution names known to this locator. - """ - result = set() - for root, dirs, files in os.walk(self.base_dir): - for fn in files: - if self.should_include(fn, root): - fn = os.path.join(root, fn) - url = urlunparse(('file', '', - pathname2url(os.path.abspath(fn)), - '', '', '')) - info = self.convert_url_to_download_info(url, None) - if info: - result.add(info['name']) - if not self.recursive: - break - return result - -class JSONLocator(Locator): - """ - This locator uses special extended metadata (not available on PyPI) and is - the basis of performant dependency resolution in distlib. Other locators - require archive downloads before dependencies can be determined! As you - might imagine, that can be slow. - """ - def get_distribution_names(self): - """ - Return all the distribution names known to this locator. - """ - raise NotImplementedError('Not available from this locator') - - def _get_project(self, name): - result = {'urls': {}, 'digests': {}} - data = get_project_data(name) - if data: - for info in data.get('files', []): - if info['ptype'] != 'sdist' or info['pyversion'] != 'source': - continue - # We don't store summary in project metadata as it makes - # the data bigger for no benefit during dependency - # resolution - dist = make_dist(data['name'], info['version'], - summary=data.get('summary', - 'Placeholder for summary'), - scheme=self.scheme) - md = dist.metadata - md.source_url = info['url'] - # TODO SHA256 digest - if 'digest' in info and info['digest']: - dist.digest = ('md5', info['digest']) - md.dependencies = info.get('requirements', {}) - dist.exports = info.get('exports', {}) - result[dist.version] = dist - result['urls'].setdefault(dist.version, set()).add(info['url']) - return result - -class DistPathLocator(Locator): - """ - This locator finds installed distributions in a path. It can be useful for - adding to an :class:`AggregatingLocator`. - """ - def __init__(self, distpath, **kwargs): - """ - Initialise an instance. - - :param distpath: A :class:`DistributionPath` instance to search. - """ - super(DistPathLocator, self).__init__(**kwargs) - assert isinstance(distpath, DistributionPath) - self.distpath = distpath - - def _get_project(self, name): - dist = self.distpath.get_distribution(name) - if dist is None: - result = {'urls': {}, 'digests': {}} - else: - result = { - dist.version: dist, - 'urls': {dist.version: set([dist.source_url])}, - 'digests': {dist.version: set([None])} - } - return result - - -class AggregatingLocator(Locator): - """ - This class allows you to chain and/or merge a list of locators. - """ - def __init__(self, *locators, **kwargs): - """ - Initialise an instance. - - :param locators: The list of locators to search. - :param kwargs: Passed to the superclass constructor, - except for: - * merge - if False (the default), the first successful - search from any of the locators is returned. If True, - the results from all locators are merged (this can be - slow). - """ - self.merge = kwargs.pop('merge', False) - self.locators = locators - super(AggregatingLocator, self).__init__(**kwargs) - - def clear_cache(self): - super(AggregatingLocator, self).clear_cache() - for locator in self.locators: - locator.clear_cache() - - def _set_scheme(self, value): - self._scheme = value - for locator in self.locators: - locator.scheme = value - - scheme = property(Locator.scheme.fget, _set_scheme) - - def _get_project(self, name): - result = {} - for locator in self.locators: - d = locator.get_project(name) - if d: - if self.merge: - files = result.get('urls', {}) - digests = result.get('digests', {}) - # next line could overwrite result['urls'], result['digests'] - result.update(d) - df = result.get('urls') - if files and df: - for k, v in files.items(): - if k in df: - df[k] |= v - else: - df[k] = v - dd = result.get('digests') - if digests and dd: - dd.update(digests) - else: - # See issue #18. If any dists are found and we're looking - # for specific constraints, we only return something if - # a match is found. For example, if a DirectoryLocator - # returns just foo (1.0) while we're looking for - # foo (>= 2.0), we'll pretend there was nothing there so - # that subsequent locators can be queried. Otherwise we - # would just return foo (1.0) which would then lead to a - # failure to find foo (>= 2.0), because other locators - # weren't searched. Note that this only matters when - # merge=False. - if self.matcher is None: - found = True - else: - found = False - for k in d: - if self.matcher.match(k): - found = True - break - if found: - result = d - break - return result - - def get_distribution_names(self): - """ - Return all the distribution names known to this locator. - """ - result = set() - for locator in self.locators: - try: - result |= locator.get_distribution_names() - except NotImplementedError: - pass - return result - - -# We use a legacy scheme simply because most of the dists on PyPI use legacy -# versions which don't conform to PEP 426 / PEP 440. -default_locator = AggregatingLocator( - JSONLocator(), - SimpleScrapingLocator('https://pypi.python.org/simple/', - timeout=3.0), - scheme='legacy') - -locate = default_locator.locate - -NAME_VERSION_RE = re.compile(r'(?P[\w-]+)\s*' - r'\(\s*(==\s*)?(?P[^)]+)\)$') - -class DependencyFinder(object): - """ - Locate dependencies for distributions. - """ - - def __init__(self, locator=None): - """ - Initialise an instance, using the specified locator - to locate distributions. - """ - self.locator = locator or default_locator - self.scheme = get_scheme(self.locator.scheme) - - def add_distribution(self, dist): - """ - Add a distribution to the finder. This will update internal information - about who provides what. - :param dist: The distribution to add. - """ - logger.debug('adding distribution %s', dist) - name = dist.key - self.dists_by_name[name] = dist - self.dists[(name, dist.version)] = dist - for p in dist.provides: - name, version = parse_name_and_version(p) - logger.debug('Add to provided: %s, %s, %s', name, version, dist) - self.provided.setdefault(name, set()).add((version, dist)) - - def remove_distribution(self, dist): - """ - Remove a distribution from the finder. This will update internal - information about who provides what. - :param dist: The distribution to remove. - """ - logger.debug('removing distribution %s', dist) - name = dist.key - del self.dists_by_name[name] - del self.dists[(name, dist.version)] - for p in dist.provides: - name, version = parse_name_and_version(p) - logger.debug('Remove from provided: %s, %s, %s', name, version, dist) - s = self.provided[name] - s.remove((version, dist)) - if not s: - del self.provided[name] - - def get_matcher(self, reqt): - """ - Get a version matcher for a requirement. - :param reqt: The requirement - :type reqt: str - :return: A version matcher (an instance of - :class:`distlib.version.Matcher`). - """ - try: - matcher = self.scheme.matcher(reqt) - except UnsupportedVersionError: - # XXX compat-mode if cannot read the version - name = reqt.split()[0] - matcher = self.scheme.matcher(name) - return matcher - - def find_providers(self, reqt): - """ - Find the distributions which can fulfill a requirement. - - :param reqt: The requirement. - :type reqt: str - :return: A set of distribution which can fulfill the requirement. - """ - matcher = self.get_matcher(reqt) - name = matcher.key # case-insensitive - result = set() - provided = self.provided - if name in provided: - for version, provider in provided[name]: - try: - match = matcher.match(version) - except UnsupportedVersionError: - match = False - - if match: - result.add(provider) - break - return result - - def try_to_replace(self, provider, other, problems): - """ - Attempt to replace one provider with another. This is typically used - when resolving dependencies from multiple sources, e.g. A requires - (B >= 1.0) while C requires (B >= 1.1). - - For successful replacement, ``provider`` must meet all the requirements - which ``other`` fulfills. - - :param provider: The provider we are trying to replace with. - :param other: The provider we're trying to replace. - :param problems: If False is returned, this will contain what - problems prevented replacement. This is currently - a tuple of the literal string 'cantreplace', - ``provider``, ``other`` and the set of requirements - that ``provider`` couldn't fulfill. - :return: True if we can replace ``other`` with ``provider``, else - False. - """ - rlist = self.reqts[other] - unmatched = set() - for s in rlist: - matcher = self.get_matcher(s) - if not matcher.match(provider.version): - unmatched.add(s) - if unmatched: - # can't replace other with provider - problems.add(('cantreplace', provider, other, - frozenset(unmatched))) - result = False - else: - # can replace other with provider - self.remove_distribution(other) - del self.reqts[other] - for s in rlist: - self.reqts.setdefault(provider, set()).add(s) - self.add_distribution(provider) - result = True - return result - - def find(self, requirement, meta_extras=None, prereleases=False): - """ - Find a distribution and all distributions it depends on. - - :param requirement: The requirement specifying the distribution to - find, or a Distribution instance. - :param meta_extras: A list of meta extras such as :test:, :build: and - so on. - :param prereleases: If ``True``, allow pre-release versions to be - returned - otherwise, don't return prereleases - unless they're all that's available. - - Return a set of :class:`Distribution` instances and a set of - problems. - - The distributions returned should be such that they have the - :attr:`required` attribute set to ``True`` if they were - from the ``requirement`` passed to ``find()``, and they have the - :attr:`build_time_dependency` attribute set to ``True`` unless they - are post-installation dependencies of the ``requirement``. - - The problems should be a tuple consisting of the string - ``'unsatisfied'`` and the requirement which couldn't be satisfied - by any distribution known to the locator. - """ - - self.provided = {} - self.dists = {} - self.dists_by_name = {} - self.reqts = {} - - meta_extras = set(meta_extras or []) - if ':*:' in meta_extras: - meta_extras.remove(':*:') - # :meta: and :run: are implicitly included - meta_extras |= set([':test:', ':build:', ':dev:']) - - if isinstance(requirement, Distribution): - dist = odist = requirement - logger.debug('passed %s as requirement', odist) - else: - dist = odist = self.locator.locate(requirement, - prereleases=prereleases) - if dist is None: - raise DistlibException('Unable to locate %r' % requirement) - logger.debug('located %s', odist) - dist.requested = True - problems = set() - todo = set([dist]) - install_dists = set([odist]) - while todo: - dist = todo.pop() - name = dist.key # case-insensitive - if name not in self.dists_by_name: - self.add_distribution(dist) - else: - #import pdb; pdb.set_trace() - other = self.dists_by_name[name] - if other != dist: - self.try_to_replace(dist, other, problems) - - ireqts = dist.run_requires | dist.meta_requires - sreqts = dist.build_requires - ereqts = set() - if dist in install_dists: - for key in ('test', 'build', 'dev'): - e = ':%s:' % key - if e in meta_extras: - ereqts |= getattr(dist, '%s_requires' % key) - all_reqts = ireqts | sreqts | ereqts - for r in all_reqts: - providers = self.find_providers(r) - if not providers: - logger.debug('No providers found for %r', r) - provider = self.locator.locate(r, prereleases=prereleases) - # If no provider is found and we didn't consider - # prereleases, consider them now. - if provider is None and not prereleases: - provider = self.locator.locate(r, prereleases=True) - if provider is None: - logger.debug('Cannot satisfy %r', r) - problems.add(('unsatisfied', r)) - else: - n, v = provider.key, provider.version - if (n, v) not in self.dists: - todo.add(provider) - providers.add(provider) - if r in ireqts and dist in install_dists: - install_dists.add(provider) - logger.debug('Adding %s to install_dists', - provider.name_and_version) - for p in providers: - name = p.key - if name not in self.dists_by_name: - self.reqts.setdefault(p, set()).add(r) - else: - other = self.dists_by_name[name] - if other != p: - # see if other can be replaced by p - self.try_to_replace(p, other, problems) - - dists = set(self.dists.values()) - for dist in dists: - dist.build_time_dependency = dist not in install_dists - if dist.build_time_dependency: - logger.debug('%s is a build-time dependency only.', - dist.name_and_version) - logger.debug('find done for %s', odist) - return dists, problems diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/manifest.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/manifest.py deleted file mode 100644 index 21cff45..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/manifest.py +++ /dev/null @@ -1,367 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012-2013 Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -""" -Class representing the list of files in a distribution. - -Equivalent to distutils.filelist, but fixes some problems. -""" -import fnmatch -import logging -import os -import re - -from . import DistlibException -from .compat import fsdecode -from .util import convert_path - - -__all__ = ['Manifest'] - -logger = logging.getLogger(__name__) - -# a \ followed by some spaces + EOL -_COLLAPSE_PATTERN = re.compile('\\\w*\n', re.M) -_COMMENTED_LINE = re.compile('#.*?(?=\n)|\n(?=$)', re.M | re.S) - - -class Manifest(object): - """A list of files built by on exploring the filesystem and filtered by - applying various patterns to what we find there. - """ - - def __init__(self, base=None): - """ - Initialise an instance. - - :param base: The base directory to explore under. - """ - self.base = os.path.abspath(os.path.normpath(base or os.getcwd())) - self.prefix = self.base + os.sep - self.allfiles = None - self.files = set() - - # - # Public API - # - - def findall(self): - """Find all files under the base and set ``allfiles`` to the absolute - pathnames of files found. - """ - from stat import S_ISREG, S_ISDIR, S_ISLNK - - self.allfiles = allfiles = [] - root = self.base - stack = [root] - pop = stack.pop - push = stack.append - - while stack: - root = pop() - names = os.listdir(root) - - for name in names: - fullname = os.path.join(root, name) - - # Avoid excess stat calls -- just one will do, thank you! - stat = os.stat(fullname) - mode = stat.st_mode - if S_ISREG(mode): - allfiles.append(fsdecode(fullname)) - elif S_ISDIR(mode) and not S_ISLNK(mode): - push(fullname) - - def add(self, item): - """ - Add a file to the manifest. - - :param item: The pathname to add. This can be relative to the base. - """ - if not item.startswith(self.prefix): - item = os.path.join(self.base, item) - self.files.add(os.path.normpath(item)) - - def add_many(self, items): - """ - Add a list of files to the manifest. - - :param items: The pathnames to add. These can be relative to the base. - """ - for item in items: - self.add(item) - - def sorted(self, wantdirs=False): - """ - Return sorted files in directory order - """ - - def add_dir(dirs, d): - dirs.add(d) - logger.debug('add_dir added %s', d) - if d != self.base: - parent, _ = os.path.split(d) - assert parent not in ('', '/') - add_dir(dirs, parent) - - result = set(self.files) # make a copy! - if wantdirs: - dirs = set() - for f in result: - add_dir(dirs, os.path.dirname(f)) - result |= dirs - return [os.path.join(*path_tuple) for path_tuple in - sorted(os.path.split(path) for path in result)] - - def clear(self): - """Clear all collected files.""" - self.files = set() - self.allfiles = [] - - def process_directive(self, directive): - """ - Process a directive which either adds some files from ``allfiles`` to - ``files``, or removes some files from ``files``. - - :param directive: The directive to process. This should be in a format - compatible with distutils ``MANIFEST.in`` files: - - http://docs.python.org/distutils/sourcedist.html#commands - """ - # 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 (dirpattern). - action, patterns, thedir, dirpattern = self._parse_directive(directive) - - # 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': - for pattern in patterns: - if not self._include_pattern(pattern, anchor=True): - logger.warning('no files found matching %r', pattern) - - elif action == 'exclude': - for pattern in patterns: - found = self._exclude_pattern(pattern, anchor=True) - #if not found: - # logger.warning('no previously-included files ' - # 'found matching %r', pattern) - - elif action == 'global-include': - for pattern in patterns: - if not self._include_pattern(pattern, anchor=False): - logger.warning('no files found matching %r ' - 'anywhere in distribution', pattern) - - elif action == 'global-exclude': - for pattern in patterns: - found = self._exclude_pattern(pattern, anchor=False) - #if not found: - # logger.warning('no previously-included files ' - # 'matching %r found anywhere in ' - # 'distribution', pattern) - - elif action == 'recursive-include': - for pattern in patterns: - if not self._include_pattern(pattern, prefix=thedir): - logger.warning('no files found matching %r ' - 'under directory %r', pattern, thedir) - - elif action == 'recursive-exclude': - for pattern in patterns: - found = self._exclude_pattern(pattern, prefix=thedir) - #if not found: - # logger.warning('no previously-included files ' - # 'matching %r found under directory %r', - # pattern, thedir) - - elif action == 'graft': - if not self._include_pattern(None, prefix=dirpattern): - logger.warning('no directories found matching %r', - dirpattern) - - elif action == 'prune': - if not self._exclude_pattern(None, prefix=dirpattern): - logger.warning('no previously-included directories found ' - 'matching %r', dirpattern) - else: # pragma: no cover - # This should never happen, as it should be caught in - # _parse_template_line - raise DistlibException( - 'invalid action %r' % action) - - # - # Private API - # - - def _parse_directive(self, directive): - """ - Validate a directive. - :param directive: The directive to validate. - :return: A tuple of action, patterns, thedir, dir_patterns - """ - words = directive.split() - if len(words) == 1 and words[0] not in ('include', 'exclude', - 'global-include', - 'global-exclude', - 'recursive-include', - 'recursive-exclude', - 'graft', 'prune'): - # no action given, let's use the default 'include' - words.insert(0, 'include') - - action = words[0] - patterns = thedir = dir_pattern = None - - if action in ('include', 'exclude', - 'global-include', 'global-exclude'): - if len(words) < 2: - raise DistlibException( - '%r expects ...' % action) - - patterns = [convert_path(word) for word in words[1:]] - - elif action in ('recursive-include', 'recursive-exclude'): - if len(words) < 3: - raise DistlibException( - '%r expects

...' % action) - - thedir = convert_path(words[1]) - patterns = [convert_path(word) for word in words[2:]] - - elif action in ('graft', 'prune'): - if len(words) != 2: - raise DistlibException( - '%r expects a single ' % action) - - dir_pattern = convert_path(words[1]) - - else: - raise DistlibException('unknown action %r' % action) - - return action, patterns, thedir, dir_pattern - - def _include_pattern(self, pattern, anchor=True, prefix=None, - is_regex=False): - """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 True if files are found. - """ - # XXX docstring lying about what the special chars are? - found = False - pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex) - - # delayed loading of allfiles list - if self.allfiles is None: - self.findall() - - for name in self.allfiles: - if pattern_re.search(name): - self.files.add(name) - found = True - return found - - def _exclude_pattern(self, pattern, anchor=True, prefix=None, - is_regex=False): - """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 True if files are - found. - - This API is public to allow e.g. exclusion of SCM subdirs, e.g. when - packaging source distributions - """ - found = False - pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex) - for f in list(self.files): - if pattern_re.search(f): - self.files.remove(f) - found = True - return found - - def _translate_pattern(self, pattern, anchor=True, prefix=None, - is_regex=False): - """Translate a shell-like wildcard pattern to a compiled regular - expression. - - Return the compiled regex. If 'is_regex' true, - then 'pattern' is directly compiled to a regex (if it's a string) - or just returned as-is (assumes it's a regex object). - """ - if is_regex: - if isinstance(pattern, str): - return re.compile(pattern) - else: - return pattern - - if pattern: - pattern_re = self._glob_to_re(pattern) - else: - pattern_re = '' - - base = re.escape(os.path.join(self.base, '')) - if prefix is not None: - # ditch end of pattern character - empty_pattern = self._glob_to_re('') - prefix_re = self._glob_to_re(prefix)[:-len(empty_pattern)] - sep = os.sep - if os.sep == '\\': - sep = r'\\' - pattern_re = '^' + base + sep.join((prefix_re, - '.*' + pattern_re)) - else: # no prefix -- respect anchor flag - if anchor: - pattern_re = '^' + base + pattern_re - - return re.compile(pattern_re) - - def _glob_to_re(self, 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'((? y, - 'gte': lambda x, y: x >= y, - 'in': lambda x, y: x in y, - 'lt': lambda x, y: x < y, - 'lte': lambda x, y: x <= y, - 'not': lambda x: not x, - 'noteq': lambda x, y: x != y, - 'notin': lambda x, y: x not in y, - } - - allowed_values = { - 'sys_platform': sys.platform, - 'python_version': '%s.%s' % sys.version_info[:2], - # parsing sys.platform is not reliable, but there is no other - # way to get e.g. 2.7.2+, and the PEP is defined with sys.version - 'python_full_version': sys.version.split(' ', 1)[0], - 'os_name': os.name, - 'platform_in_venv': str(in_venv()), - 'platform_release': platform.release(), - 'platform_version': platform.version(), - 'platform_machine': platform.machine(), - 'platform_python_implementation': python_implementation(), - } - - def __init__(self, context=None): - """ - Initialise an instance. - - :param context: If specified, names are looked up in this mapping. - """ - self.context = context or {} - self.source = None - - def get_fragment(self, offset): - """ - Get the part of the source which is causing a problem. - """ - fragment_len = 10 - s = '%r' % (self.source[offset:offset + fragment_len]) - if offset + fragment_len < len(self.source): - s += '...' - return s - - def get_handler(self, node_type): - """ - Get a handler for the specified AST node type. - """ - return getattr(self, 'do_%s' % node_type, None) - - def evaluate(self, node, filename=None): - """ - Evaluate a source string or node, using ``filename`` when - displaying errors. - """ - if isinstance(node, string_types): - self.source = node - kwargs = {'mode': 'eval'} - if filename: - kwargs['filename'] = filename - try: - node = ast.parse(node, **kwargs) - except SyntaxError as e: - s = self.get_fragment(e.offset) - raise SyntaxError('syntax error %s' % s) - node_type = node.__class__.__name__.lower() - handler = self.get_handler(node_type) - if handler is None: - if self.source is None: - s = '(source not available)' - else: - s = self.get_fragment(node.col_offset) - raise SyntaxError("don't know how to evaluate %r %s" % ( - node_type, s)) - return handler(node) - - def get_attr_key(self, node): - assert isinstance(node, ast.Attribute), 'attribute node expected' - return '%s.%s' % (node.value.id, node.attr) - - def do_attribute(self, node): - if not isinstance(node.value, ast.Name): - valid = False - else: - key = self.get_attr_key(node) - valid = key in self.context or key in self.allowed_values - if not valid: - raise SyntaxError('invalid expression: %s' % key) - if key in self.context: - result = self.context[key] - else: - result = self.allowed_values[key] - return result - - def do_boolop(self, node): - result = self.evaluate(node.values[0]) - is_or = node.op.__class__ is ast.Or - is_and = node.op.__class__ is ast.And - assert is_or or is_and - if (is_and and result) or (is_or and not result): - for n in node.values[1:]: - result = self.evaluate(n) - if (is_or and result) or (is_and and not result): - break - return result - - def do_compare(self, node): - def sanity_check(lhsnode, rhsnode): - valid = True - if isinstance(lhsnode, ast.Str) and isinstance(rhsnode, ast.Str): - valid = False - #elif (isinstance(lhsnode, ast.Attribute) - # and isinstance(rhsnode, ast.Attribute)): - # klhs = self.get_attr_key(lhsnode) - # krhs = self.get_attr_key(rhsnode) - # valid = klhs != krhs - if not valid: - s = self.get_fragment(node.col_offset) - raise SyntaxError('Invalid comparison: %s' % s) - - lhsnode = node.left - lhs = self.evaluate(lhsnode) - result = True - for op, rhsnode in zip(node.ops, node.comparators): - sanity_check(lhsnode, rhsnode) - op = op.__class__.__name__.lower() - if op not in self.operators: - raise SyntaxError('unsupported operation: %r' % op) - rhs = self.evaluate(rhsnode) - result = self.operators[op](lhs, rhs) - if not result: - break - lhs = rhs - lhsnode = rhsnode - return result - - def do_expression(self, node): - return self.evaluate(node.body) - - def do_name(self, node): - valid = False - if node.id in self.context: - valid = True - result = self.context[node.id] - elif node.id in self.allowed_values: - valid = True - result = self.allowed_values[node.id] - if not valid: - raise SyntaxError('invalid expression: %s' % node.id) - return result - - def do_str(self, node): - return node.s - - -def interpret(marker, execution_context=None): - """ - Interpret a marker and return a result depending on environment. - - :param marker: The marker to interpret. - :type marker: str - :param execution_context: The context used for name lookup. - :type execution_context: mapping - """ - return Evaluator(execution_context).evaluate(marker.strip()) diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/metadata.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/metadata.py deleted file mode 100644 index 55bd75f..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/metadata.py +++ /dev/null @@ -1,1058 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012 The Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -"""Implementation of the Metadata for Python packages PEPs. - -Supports all metadata formats (1.0, 1.1, 1.2, and 2.0 experimental). -""" -from __future__ import unicode_literals - -import codecs -from email import message_from_file -import json -import logging -import re - - -from . import DistlibException, __version__ -from .compat import StringIO, string_types, text_type -from .markers import interpret -from .util import extract_by_key, get_extras -from .version import get_scheme, PEP440_VERSION_RE - -logger = logging.getLogger(__name__) - - -class MetadataMissingError(DistlibException): - """A required metadata is missing""" - - -class MetadataConflictError(DistlibException): - """Attempt to read or write metadata fields that are conflictual.""" - - -class MetadataUnrecognizedVersionError(DistlibException): - """Unknown metadata version number.""" - - -class MetadataInvalidError(DistlibException): - """A metadata value is invalid""" - -# public API of this module -__all__ = ['Metadata', 'PKG_INFO_ENCODING', 'PKG_INFO_PREFERRED_VERSION'] - -# Encoding used for the PKG-INFO files -PKG_INFO_ENCODING = 'utf-8' - -# preferred version. Hopefully will be changed -# to 1.2 once PEP 345 is supported everywhere -PKG_INFO_PREFERRED_VERSION = '1.1' - -_LINE_PREFIX = re.compile('\n \|') -_241_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', - 'Summary', 'Description', - 'Keywords', 'Home-page', 'Author', 'Author-email', - 'License') - -_314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', - 'Supported-Platform', 'Summary', 'Description', - 'Keywords', 'Home-page', 'Author', 'Author-email', - 'License', 'Classifier', 'Download-URL', 'Obsoletes', - 'Provides', 'Requires') - -_314_MARKERS = ('Obsoletes', 'Provides', 'Requires', 'Classifier', - 'Download-URL') - -_345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', - 'Supported-Platform', 'Summary', 'Description', - 'Keywords', 'Home-page', 'Author', 'Author-email', - 'Maintainer', 'Maintainer-email', 'License', - 'Classifier', 'Download-URL', 'Obsoletes-Dist', - 'Project-URL', 'Provides-Dist', 'Requires-Dist', - 'Requires-Python', 'Requires-External') - -_345_MARKERS = ('Provides-Dist', 'Requires-Dist', 'Requires-Python', - 'Obsoletes-Dist', 'Requires-External', 'Maintainer', - 'Maintainer-email', 'Project-URL') - -_426_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', - 'Supported-Platform', 'Summary', 'Description', - 'Keywords', 'Home-page', 'Author', 'Author-email', - 'Maintainer', 'Maintainer-email', 'License', - 'Classifier', 'Download-URL', 'Obsoletes-Dist', - 'Project-URL', 'Provides-Dist', 'Requires-Dist', - 'Requires-Python', 'Requires-External', 'Private-Version', - 'Obsoleted-By', 'Setup-Requires-Dist', 'Extension', - 'Provides-Extra') - -_426_MARKERS = ('Private-Version', 'Provides-Extra', 'Obsoleted-By', - 'Setup-Requires-Dist', 'Extension') - -_ALL_FIELDS = set() -_ALL_FIELDS.update(_241_FIELDS) -_ALL_FIELDS.update(_314_FIELDS) -_ALL_FIELDS.update(_345_FIELDS) -_ALL_FIELDS.update(_426_FIELDS) - -EXTRA_RE = re.compile(r'''extra\s*==\s*("([^"]+)"|'([^']+)')''') - - -def _version2fieldlist(version): - if version == '1.0': - return _241_FIELDS - elif version == '1.1': - return _314_FIELDS - elif version == '1.2': - return _345_FIELDS - elif version == '2.0': - return _426_FIELDS - raise MetadataUnrecognizedVersionError(version) - - -def _best_version(fields): - """Detect the best version depending on the fields used.""" - def _has_marker(keys, markers): - for marker in markers: - if marker in keys: - return True - return False - - keys = [] - for key, value in fields.items(): - if value in ([], 'UNKNOWN', None): - continue - keys.append(key) - - possible_versions = ['1.0', '1.1', '1.2', '2.0'] - - # first let's try to see if a field is not part of one of the version - for key in keys: - if key not in _241_FIELDS and '1.0' in possible_versions: - possible_versions.remove('1.0') - if key not in _314_FIELDS and '1.1' in possible_versions: - possible_versions.remove('1.1') - if key not in _345_FIELDS and '1.2' in possible_versions: - possible_versions.remove('1.2') - if key not in _426_FIELDS and '2.0' in possible_versions: - possible_versions.remove('2.0') - - # possible_version contains qualified versions - if len(possible_versions) == 1: - return possible_versions[0] # found ! - elif len(possible_versions) == 0: - raise MetadataConflictError('Unknown metadata set') - - # let's see if one unique marker is found - is_1_1 = '1.1' in possible_versions and _has_marker(keys, _314_MARKERS) - is_1_2 = '1.2' in possible_versions and _has_marker(keys, _345_MARKERS) - is_2_0 = '2.0' in possible_versions and _has_marker(keys, _426_MARKERS) - if int(is_1_1) + int(is_1_2) + int(is_2_0) > 1: - raise MetadataConflictError('You used incompatible 1.1/1.2/2.0 fields') - - # we have the choice, 1.0, or 1.2, or 2.0 - # - 1.0 has a broken Summary field but works with all tools - # - 1.1 is to avoid - # - 1.2 fixes Summary but has little adoption - # - 2.0 adds more features and is very new - if not is_1_1 and not is_1_2 and not is_2_0: - # we couldn't find any specific marker - if PKG_INFO_PREFERRED_VERSION in possible_versions: - return PKG_INFO_PREFERRED_VERSION - if is_1_1: - return '1.1' - if is_1_2: - return '1.2' - - return '2.0' - -_ATTR2FIELD = { - 'metadata_version': 'Metadata-Version', - 'name': 'Name', - 'version': 'Version', - 'platform': 'Platform', - 'supported_platform': 'Supported-Platform', - 'summary': 'Summary', - 'description': 'Description', - 'keywords': 'Keywords', - 'home_page': 'Home-page', - 'author': 'Author', - 'author_email': 'Author-email', - 'maintainer': 'Maintainer', - 'maintainer_email': 'Maintainer-email', - 'license': 'License', - 'classifier': 'Classifier', - 'download_url': 'Download-URL', - 'obsoletes_dist': 'Obsoletes-Dist', - 'provides_dist': 'Provides-Dist', - 'requires_dist': 'Requires-Dist', - 'setup_requires_dist': 'Setup-Requires-Dist', - 'requires_python': 'Requires-Python', - 'requires_external': 'Requires-External', - 'requires': 'Requires', - 'provides': 'Provides', - 'obsoletes': 'Obsoletes', - 'project_url': 'Project-URL', - 'private_version': 'Private-Version', - 'obsoleted_by': 'Obsoleted-By', - 'extension': 'Extension', - 'provides_extra': 'Provides-Extra', -} - -_PREDICATE_FIELDS = ('Requires-Dist', 'Obsoletes-Dist', 'Provides-Dist') -_VERSIONS_FIELDS = ('Requires-Python',) -_VERSION_FIELDS = ('Version',) -_LISTFIELDS = ('Platform', 'Classifier', 'Obsoletes', - 'Requires', 'Provides', 'Obsoletes-Dist', - 'Provides-Dist', 'Requires-Dist', 'Requires-External', - 'Project-URL', 'Supported-Platform', 'Setup-Requires-Dist', - 'Provides-Extra', 'Extension') -_LISTTUPLEFIELDS = ('Project-URL',) - -_ELEMENTSFIELD = ('Keywords',) - -_UNICODEFIELDS = ('Author', 'Maintainer', 'Summary', 'Description') - -_MISSING = object() - -_FILESAFE = re.compile('[^A-Za-z0-9.]+') - - -def _get_name_and_version(name, version, for_filename=False): - """Return the distribution name with version. - - If for_filename is true, return a filename-escaped form.""" - if for_filename: - # For both name and version any runs of non-alphanumeric or '.' - # characters are replaced with a single '-'. Additionally any - # spaces in the version string become '.' - name = _FILESAFE.sub('-', name) - version = _FILESAFE.sub('-', version.replace(' ', '.')) - return '%s-%s' % (name, version) - - -class LegacyMetadata(object): - """The legacy metadata of a release. - - Supports versions 1.0, 1.1 and 1.2 (auto-detected). You can - instantiate the class with one of these arguments (or none): - - *path*, the path to a metadata file - - *fileobj* give a file-like object with metadata as content - - *mapping* is a dict-like object - - *scheme* is a version scheme name - """ - # TODO document the mapping API and UNKNOWN default key - - def __init__(self, path=None, fileobj=None, mapping=None, - scheme='default'): - if [path, fileobj, mapping].count(None) < 2: - raise TypeError('path, fileobj and mapping are exclusive') - self._fields = {} - self.requires_files = [] - self._dependencies = None - self.scheme = scheme - if path is not None: - self.read(path) - elif fileobj is not None: - self.read_file(fileobj) - elif mapping is not None: - self.update(mapping) - self.set_metadata_version() - - def set_metadata_version(self): - self._fields['Metadata-Version'] = _best_version(self._fields) - - def _write_field(self, fileobj, name, value): - fileobj.write('%s: %s\n' % (name, value)) - - def __getitem__(self, name): - return self.get(name) - - def __setitem__(self, name, value): - return self.set(name, value) - - def __delitem__(self, name): - field_name = self._convert_name(name) - try: - del self._fields[field_name] - except KeyError: - raise KeyError(name) - - def __contains__(self, name): - return (name in self._fields or - self._convert_name(name) in self._fields) - - def _convert_name(self, name): - if name in _ALL_FIELDS: - return name - name = name.replace('-', '_').lower() - return _ATTR2FIELD.get(name, name) - - def _default_value(self, name): - if name in _LISTFIELDS or name in _ELEMENTSFIELD: - return [] - return 'UNKNOWN' - - def _remove_line_prefix(self, value): - return _LINE_PREFIX.sub('\n', value) - - def __getattr__(self, name): - if name in _ATTR2FIELD: - return self[name] - raise AttributeError(name) - - # - # Public API - # - -# dependencies = property(_get_dependencies, _set_dependencies) - - def get_fullname(self, filesafe=False): - """Return the distribution name with version. - - If filesafe is true, return a filename-escaped form.""" - return _get_name_and_version(self['Name'], self['Version'], filesafe) - - def is_field(self, name): - """return True if name is a valid metadata key""" - name = self._convert_name(name) - return name in _ALL_FIELDS - - def is_multi_field(self, name): - name = self._convert_name(name) - return name in _LISTFIELDS - - def read(self, filepath): - """Read the metadata values from a file path.""" - fp = codecs.open(filepath, 'r', encoding='utf-8') - try: - self.read_file(fp) - finally: - fp.close() - - def read_file(self, fileob): - """Read the metadata values from a file object.""" - msg = message_from_file(fileob) - self._fields['Metadata-Version'] = msg['metadata-version'] - - # When reading, get all the fields we can - for field in _ALL_FIELDS: - if field not in msg: - continue - if field in _LISTFIELDS: - # we can have multiple lines - values = msg.get_all(field) - if field in _LISTTUPLEFIELDS and values is not None: - values = [tuple(value.split(',')) for value in values] - self.set(field, values) - else: - # single line - value = msg[field] - if value is not None and value != 'UNKNOWN': - self.set(field, value) - self.set_metadata_version() - - def write(self, filepath, skip_unknown=False): - """Write the metadata fields to filepath.""" - fp = codecs.open(filepath, 'w', encoding='utf-8') - try: - self.write_file(fp, skip_unknown) - finally: - fp.close() - - def write_file(self, fileobject, skip_unknown=False): - """Write the PKG-INFO format data to a file object.""" - self.set_metadata_version() - - for field in _version2fieldlist(self['Metadata-Version']): - values = self.get(field) - if skip_unknown and values in ('UNKNOWN', [], ['UNKNOWN']): - continue - if field in _ELEMENTSFIELD: - self._write_field(fileobject, field, ','.join(values)) - continue - if field not in _LISTFIELDS: - if field == 'Description': - values = values.replace('\n', '\n |') - values = [values] - - if field in _LISTTUPLEFIELDS: - values = [','.join(value) for value in values] - - for value in values: - self._write_field(fileobject, field, value) - - def update(self, other=None, **kwargs): - """Set metadata values from the given iterable `other` and kwargs. - - Behavior is like `dict.update`: If `other` has a ``keys`` method, - they are looped over and ``self[key]`` is assigned ``other[key]``. - Else, ``other`` is an iterable of ``(key, value)`` iterables. - - Keys that don't match a metadata field or that have an empty value are - dropped. - """ - def _set(key, value): - if key in _ATTR2FIELD and value: - self.set(self._convert_name(key), value) - - if not other: - # other is None or empty container - pass - elif hasattr(other, 'keys'): - for k in other.keys(): - _set(k, other[k]) - else: - for k, v in other: - _set(k, v) - - if kwargs: - for k, v in kwargs.items(): - _set(k, v) - - def set(self, name, value): - """Control then set a metadata field.""" - name = self._convert_name(name) - - if ((name in _ELEMENTSFIELD or name == 'Platform') and - not isinstance(value, (list, tuple))): - if isinstance(value, string_types): - value = [v.strip() for v in value.split(',')] - else: - value = [] - elif (name in _LISTFIELDS and - not isinstance(value, (list, tuple))): - if isinstance(value, string_types): - value = [value] - else: - value = [] - - if logger.isEnabledFor(logging.WARNING): - project_name = self['Name'] - - scheme = get_scheme(self.scheme) - if name in _PREDICATE_FIELDS and value is not None: - for v in value: - # check that the values are valid - if not scheme.is_valid_matcher(v.split(';')[0]): - logger.warning( - '%r: %r is not valid (field %r)', - project_name, v, name) - # FIXME this rejects UNKNOWN, is that right? - elif name in _VERSIONS_FIELDS and value is not None: - if not scheme.is_valid_constraint_list(value): - logger.warning('%r: %r is not a valid version (field %r)', - project_name, value, name) - elif name in _VERSION_FIELDS and value is not None: - if not scheme.is_valid_version(value): - logger.warning('%r: %r is not a valid version (field %r)', - project_name, value, name) - - if name in _UNICODEFIELDS: - if name == 'Description': - value = self._remove_line_prefix(value) - - self._fields[name] = value - - def get(self, name, default=_MISSING): - """Get a metadata field.""" - name = self._convert_name(name) - if name not in self._fields: - if default is _MISSING: - default = self._default_value(name) - return default - if name in _UNICODEFIELDS: - value = self._fields[name] - return value - elif name in _LISTFIELDS: - value = self._fields[name] - if value is None: - return [] - res = [] - for val in value: - if name not in _LISTTUPLEFIELDS: - res.append(val) - else: - # That's for Project-URL - res.append((val[0], val[1])) - return res - - elif name in _ELEMENTSFIELD: - value = self._fields[name] - if isinstance(value, string_types): - return value.split(',') - return self._fields[name] - - def check(self, strict=False): - """Check if the metadata is compliant. If strict is True then raise if - no Name or Version are provided""" - self.set_metadata_version() - - # XXX should check the versions (if the file was loaded) - missing, warnings = [], [] - - for attr in ('Name', 'Version'): # required by PEP 345 - if attr not in self: - missing.append(attr) - - if strict and missing != []: - msg = 'missing required metadata: %s' % ', '.join(missing) - raise MetadataMissingError(msg) - - for attr in ('Home-page', 'Author'): - if attr not in self: - missing.append(attr) - - # checking metadata 1.2 (XXX needs to check 1.1, 1.0) - if self['Metadata-Version'] != '1.2': - return missing, warnings - - scheme = get_scheme(self.scheme) - - def are_valid_constraints(value): - for v in value: - if not scheme.is_valid_matcher(v.split(';')[0]): - return False - return True - - for fields, controller in ((_PREDICATE_FIELDS, are_valid_constraints), - (_VERSIONS_FIELDS, - scheme.is_valid_constraint_list), - (_VERSION_FIELDS, - scheme.is_valid_version)): - for field in fields: - value = self.get(field, None) - if value is not None and not controller(value): - warnings.append('Wrong value for %r: %s' % (field, value)) - - return missing, warnings - - def todict(self, skip_missing=False): - """Return fields as a dict. - - Field names will be converted to use the underscore-lowercase style - instead of hyphen-mixed case (i.e. home_page instead of Home-page). - """ - self.set_metadata_version() - - mapping_1_0 = ( - ('metadata_version', 'Metadata-Version'), - ('name', 'Name'), - ('version', 'Version'), - ('summary', 'Summary'), - ('home_page', 'Home-page'), - ('author', 'Author'), - ('author_email', 'Author-email'), - ('license', 'License'), - ('description', 'Description'), - ('keywords', 'Keywords'), - ('platform', 'Platform'), - ('classifier', 'Classifier'), - ('download_url', 'Download-URL'), - ) - - data = {} - for key, field_name in mapping_1_0: - if not skip_missing or field_name in self._fields: - data[key] = self[field_name] - - if self['Metadata-Version'] == '1.2': - mapping_1_2 = ( - ('requires_dist', 'Requires-Dist'), - ('requires_python', 'Requires-Python'), - ('requires_external', 'Requires-External'), - ('provides_dist', 'Provides-Dist'), - ('obsoletes_dist', 'Obsoletes-Dist'), - ('project_url', 'Project-URL'), - ('maintainer', 'Maintainer'), - ('maintainer_email', 'Maintainer-email'), - ) - for key, field_name in mapping_1_2: - if not skip_missing or field_name in self._fields: - if key != 'project_url': - data[key] = self[field_name] - else: - data[key] = [','.join(u) for u in self[field_name]] - - elif self['Metadata-Version'] == '1.1': - mapping_1_1 = ( - ('provides', 'Provides'), - ('requires', 'Requires'), - ('obsoletes', 'Obsoletes'), - ) - for key, field_name in mapping_1_1: - if not skip_missing or field_name in self._fields: - data[key] = self[field_name] - - return data - - def add_requirements(self, requirements): - if self['Metadata-Version'] == '1.1': - # we can't have 1.1 metadata *and* Setuptools requires - for field in ('Obsoletes', 'Requires', 'Provides'): - if field in self: - del self[field] - self['Requires-Dist'] += requirements - - # Mapping API - # TODO could add iter* variants - - def keys(self): - return list(_version2fieldlist(self['Metadata-Version'])) - - def __iter__(self): - for key in self.keys(): - yield key - - def values(self): - return [self[key] for key in self.keys()] - - def items(self): - return [(key, self[key]) for key in self.keys()] - - def __repr__(self): - return '<%s %s %s>' % (self.__class__.__name__, self.name, - self.version) - - -METADATA_FILENAME = 'pydist.json' - - -class Metadata(object): - """ - The metadata of a release. This implementation uses 2.0 (JSON) - metadata where possible. If not possible, it wraps a LegacyMetadata - instance which handles the key-value metadata format. - """ - - METADATA_VERSION_MATCHER = re.compile('^\d+(\.\d+)*$') - - NAME_MATCHER = re.compile('^[0-9A-Z]([0-9A-Z_.-]*[0-9A-Z])?$', re.I) - - VERSION_MATCHER = PEP440_VERSION_RE - - SUMMARY_MATCHER = re.compile('.{1,2047}') - - METADATA_VERSION = '2.0' - - GENERATOR = 'distlib (%s)' % __version__ - - MANDATORY_KEYS = { - 'name': (), - 'version': (), - 'summary': ('legacy',), - } - - INDEX_KEYS = ('name version license summary description author ' - 'author_email keywords platform home_page classifiers ' - 'download_url') - - DEPENDENCY_KEYS = ('extras run_requires test_requires build_requires ' - 'dev_requires provides meta_requires obsoleted_by ' - 'supports_environments') - - SYNTAX_VALIDATORS = { - 'metadata_version': (METADATA_VERSION_MATCHER, ()), - 'name': (NAME_MATCHER, ('legacy',)), - 'version': (VERSION_MATCHER, ('legacy',)), - 'summary': (SUMMARY_MATCHER, ('legacy',)), - } - - __slots__ = ('_legacy', '_data', 'scheme') - - def __init__(self, path=None, fileobj=None, mapping=None, - scheme='default'): - if [path, fileobj, mapping].count(None) < 2: - raise TypeError('path, fileobj and mapping are exclusive') - self._legacy = None - self._data = None - self.scheme = scheme - #import pdb; pdb.set_trace() - if mapping is not None: - try: - self._validate_mapping(mapping, scheme) - self._data = mapping - except MetadataUnrecognizedVersionError: - self._legacy = LegacyMetadata(mapping=mapping, scheme=scheme) - self.validate() - else: - data = None - if path: - with open(path, 'rb') as f: - data = f.read() - elif fileobj: - data = fileobj.read() - if data is None: - # Initialised with no args - to be added - self._data = { - 'metadata_version': self.METADATA_VERSION, - 'generator': self.GENERATOR, - } - else: - if not isinstance(data, text_type): - data = data.decode('utf-8') - try: - self._data = json.loads(data) - self._validate_mapping(self._data, scheme) - except ValueError: - # Note: MetadataUnrecognizedVersionError does not - # inherit from ValueError (it's a DistlibException, - # which should not inherit from ValueError). - # The ValueError comes from the json.load - if that - # succeeds and we get a validation error, we want - # that to propagate - self._legacy = LegacyMetadata(fileobj=StringIO(data), - scheme=scheme) - self.validate() - - common_keys = set(('name', 'version', 'license', 'keywords', 'summary')) - - none_list = (None, list) - none_dict = (None, dict) - - mapped_keys = { - 'run_requires': ('Requires-Dist', list), - 'build_requires': ('Setup-Requires-Dist', list), - 'dev_requires': none_list, - 'test_requires': none_list, - 'meta_requires': none_list, - 'extras': ('Provides-Extra', list), - 'modules': none_list, - 'namespaces': none_list, - 'exports': none_dict, - 'commands': none_dict, - 'classifiers': ('Classifier', list), - 'source_url': ('Download-URL', None), - 'metadata_version': ('Metadata-Version', None), - } - - del none_list, none_dict - - def __getattribute__(self, key): - common = object.__getattribute__(self, 'common_keys') - mapped = object.__getattribute__(self, 'mapped_keys') - if key in mapped: - lk, maker = mapped[key] - if self._legacy: - if lk is None: - result = None if maker is None else maker() - else: - result = self._legacy.get(lk) - else: - value = None if maker is None else maker() - if key not in ('commands', 'exports', 'modules', 'namespaces', - 'classifiers'): - result = self._data.get(key, value) - else: - # special cases for PEP 459 - sentinel = object() - result = sentinel - d = self._data.get('extensions') - if d: - if key == 'commands': - result = d.get('python.commands', value) - elif key == 'classifiers': - d = d.get('python.details') - if d: - result = d.get(key, value) - else: - d = d.get('python.exports') - if d: - result = d.get(key, value) - if result is sentinel: - result = value - elif key not in common: - result = object.__getattribute__(self, key) - elif self._legacy: - result = self._legacy.get(key) - else: - result = self._data.get(key) - return result - - def _validate_value(self, key, value, scheme=None): - if key in self.SYNTAX_VALIDATORS: - pattern, exclusions = self.SYNTAX_VALIDATORS[key] - if (scheme or self.scheme) not in exclusions: - m = pattern.match(value) - if not m: - raise MetadataInvalidError('%r is an invalid value for ' - 'the %r property' % (value, - key)) - - def __setattr__(self, key, value): - self._validate_value(key, value) - common = object.__getattribute__(self, 'common_keys') - mapped = object.__getattribute__(self, 'mapped_keys') - if key in mapped: - lk, _ = mapped[key] - if self._legacy: - if lk is None: - raise NotImplementedError - self._legacy[lk] = value - elif key not in ('commands', 'exports', 'modules', 'namespaces', - 'classifiers'): - self._data[key] = value - else: - # special cases for PEP 459 - d = self._data.setdefault('extensions', {}) - if key == 'commands': - d['python.commands'] = value - elif key == 'classifiers': - d = d.setdefault('python.details', {}) - d[key] = value - else: - d = d.setdefault('python.exports', {}) - d[key] = value - elif key not in common: - object.__setattr__(self, key, value) - else: - if key == 'keywords': - if isinstance(value, string_types): - value = value.strip() - if value: - value = value.split() - else: - value = [] - if self._legacy: - self._legacy[key] = value - else: - self._data[key] = value - - @property - def name_and_version(self): - return _get_name_and_version(self.name, self.version, True) - - @property - def provides(self): - if self._legacy: - result = self._legacy['Provides-Dist'] - else: - result = self._data.setdefault('provides', []) - s = '%s (%s)' % (self.name, self.version) - if s not in result: - result.append(s) - return result - - @provides.setter - def provides(self, value): - if self._legacy: - self._legacy['Provides-Dist'] = value - else: - self._data['provides'] = value - - def get_requirements(self, reqts, extras=None, env=None): - """ - Base method to get dependencies, given a set of extras - to satisfy and an optional environment context. - :param reqts: A list of sometimes-wanted dependencies, - perhaps dependent on extras and environment. - :param extras: A list of optional components being requested. - :param env: An optional environment for marker evaluation. - """ - if self._legacy: - result = reqts - else: - result = [] - extras = get_extras(extras or [], self.extras) - for d in reqts: - if 'extra' not in d and 'environment' not in d: - # unconditional - include = True - else: - if 'extra' not in d: - # Not extra-dependent - only environment-dependent - include = True - else: - include = d.get('extra') in extras - if include: - # Not excluded because of extras, check environment - marker = d.get('environment') - if marker: - include = interpret(marker, env) - if include: - result.extend(d['requires']) - for key in ('build', 'dev', 'test'): - e = ':%s:' % key - if e in extras: - extras.remove(e) - # A recursive call, but it should terminate since 'test' - # has been removed from the extras - reqts = self._data.get('%s_requires' % key, []) - result.extend(self.get_requirements(reqts, extras=extras, - env=env)) - return result - - @property - def dictionary(self): - if self._legacy: - return self._from_legacy() - return self._data - - @property - def dependencies(self): - if self._legacy: - raise NotImplementedError - else: - return extract_by_key(self._data, self.DEPENDENCY_KEYS) - - @dependencies.setter - def dependencies(self, value): - if self._legacy: - raise NotImplementedError - else: - self._data.update(value) - - def _validate_mapping(self, mapping, scheme): - if mapping.get('metadata_version') != self.METADATA_VERSION: - raise MetadataUnrecognizedVersionError() - missing = [] - for key, exclusions in self.MANDATORY_KEYS.items(): - if key not in mapping: - if scheme not in exclusions: - missing.append(key) - if missing: - msg = 'Missing metadata items: %s' % ', '.join(missing) - raise MetadataMissingError(msg) - for k, v in mapping.items(): - self._validate_value(k, v, scheme) - - def validate(self): - if self._legacy: - missing, warnings = self._legacy.check(True) - if missing or warnings: - logger.warning('Metadata: missing: %s, warnings: %s', - missing, warnings) - else: - self._validate_mapping(self._data, self.scheme) - - def todict(self): - if self._legacy: - return self._legacy.todict(True) - else: - result = extract_by_key(self._data, self.INDEX_KEYS) - return result - - def _from_legacy(self): - assert self._legacy and not self._data - result = { - 'metadata_version': self.METADATA_VERSION, - 'generator': self.GENERATOR, - } - lmd = self._legacy.todict(True) # skip missing ones - for k in ('name', 'version', 'license', 'summary', 'description', - 'classifier'): - if k in lmd: - if k == 'classifier': - nk = 'classifiers' - else: - nk = k - result[nk] = lmd[k] - kw = lmd.get('Keywords', []) - if kw == ['']: - kw = [] - result['keywords'] = kw - keys = (('requires_dist', 'run_requires'), - ('setup_requires_dist', 'build_requires')) - for ok, nk in keys: - if ok in lmd and lmd[ok]: - result[nk] = [{'requires': lmd[ok]}] - result['provides'] = self.provides - author = {} - maintainer = {} - return result - - LEGACY_MAPPING = { - 'name': 'Name', - 'version': 'Version', - 'license': 'License', - 'summary': 'Summary', - 'description': 'Description', - 'classifiers': 'Classifier', - } - - def _to_legacy(self): - def process_entries(entries): - reqts = set() - for e in entries: - extra = e.get('extra') - env = e.get('environment') - rlist = e['requires'] - for r in rlist: - if not env and not extra: - reqts.add(r) - else: - marker = '' - if extra: - marker = 'extra == "%s"' % extra - if env: - if marker: - marker = '(%s) and %s' % (env, marker) - else: - marker = env - reqts.add(';'.join((r, marker))) - return reqts - - assert self._data and not self._legacy - result = LegacyMetadata() - nmd = self._data - for nk, ok in self.LEGACY_MAPPING.items(): - if nk in nmd: - result[ok] = nmd[nk] - r1 = process_entries(self.run_requires + self.meta_requires) - r2 = process_entries(self.build_requires + self.dev_requires) - if self.extras: - result['Provides-Extra'] = sorted(self.extras) - result['Requires-Dist'] = sorted(r1) - result['Setup-Requires-Dist'] = sorted(r2) - # TODO: other fields such as contacts - return result - - def write(self, path=None, fileobj=None, legacy=False, skip_unknown=True): - if [path, fileobj].count(None) != 1: - raise ValueError('Exactly one of path and fileobj is needed') - self.validate() - if legacy: - if self._legacy: - legacy_md = self._legacy - else: - legacy_md = self._to_legacy() - if path: - legacy_md.write(path, skip_unknown=skip_unknown) - else: - legacy_md.write_file(fileobj, skip_unknown=skip_unknown) - else: - if self._legacy: - d = self._from_legacy() - else: - d = self._data - if fileobj: - json.dump(d, fileobj, ensure_ascii=True, indent=2, - sort_keys=True) - else: - with codecs.open(path, 'w', 'utf-8') as f: - json.dump(d, f, ensure_ascii=True, indent=2, - sort_keys=True) - - def add_requirements(self, requirements): - if self._legacy: - self._legacy.add_requirements(requirements) - else: - run_requires = self._data.setdefault('run_requires', []) - always = None - for entry in run_requires: - if 'environment' not in entry and 'extra' not in entry: - always = entry - break - if always is None: - always = { 'requires': requirements } - run_requires.insert(0, always) - else: - rset = set(always['requires']) | set(requirements) - always['requires'] = sorted(rset) - - def __repr__(self): - name = self.name or '(no name)' - version = self.version or 'no version' - return '<%s %s %s (%s)>' % (self.__class__.__name__, - self.metadata_version, name, version) diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/resources.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/resources.py deleted file mode 100644 index c8e2f82..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/resources.py +++ /dev/null @@ -1,350 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2013 Vinay Sajip. -# Licensed to the Python Software Foundation under a contributor agreement. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -from __future__ import unicode_literals - -import bisect -import io -import logging -import os -import pkgutil -import shutil -import sys -import types -import zipimport - -from . import DistlibException -from .util import cached_property, get_cache_base, path_to_cache_dir, Cache - -logger = logging.getLogger(__name__) - - -cache = None # created when needed - - -class ResourceCache(Cache): - def __init__(self, base=None): - if base is None: - # Use native string to avoid issues on 2.x: see Python #20140. - base = os.path.join(get_cache_base(), str('resource-cache')) - super(ResourceCache, self).__init__(base) - - def is_stale(self, resource, path): - """ - Is the cache stale for the given resource? - - :param resource: The :class:`Resource` being cached. - :param path: The path of the resource in the cache. - :return: True if the cache is stale. - """ - # Cache invalidation is a hard problem :-) - return True - - def get(self, resource): - """ - Get a resource into the cache, - - :param resource: A :class:`Resource` instance. - :return: The pathname of the resource in the cache. - """ - prefix, path = resource.finder.get_cache_info(resource) - if prefix is None: - result = path - else: - result = os.path.join(self.base, self.prefix_to_dir(prefix), path) - dirname = os.path.dirname(result) - if not os.path.isdir(dirname): - os.makedirs(dirname) - if not os.path.exists(result): - stale = True - else: - stale = self.is_stale(resource, path) - if stale: - # write the bytes of the resource to the cache location - with open(result, 'wb') as f: - f.write(resource.bytes) - return result - - -class ResourceBase(object): - def __init__(self, finder, name): - self.finder = finder - self.name = name - - -class Resource(ResourceBase): - """ - A class representing an in-package resource, such as a data file. This is - not normally instantiated by user code, but rather by a - :class:`ResourceFinder` which manages the resource. - """ - is_container = False # Backwards compatibility - - def as_stream(self): - """ - Get the resource as a stream. - - This is not a property to make it obvious that it returns a new stream - each time. - """ - return self.finder.get_stream(self) - - @cached_property - def file_path(self): - global cache - if cache is None: - cache = ResourceCache() - return cache.get(self) - - @cached_property - def bytes(self): - return self.finder.get_bytes(self) - - @cached_property - def size(self): - return self.finder.get_size(self) - - -class ResourceContainer(ResourceBase): - is_container = True # Backwards compatibility - - @cached_property - def resources(self): - return self.finder.get_resources(self) - - -class ResourceFinder(object): - """ - Resource finder for file system resources. - """ - - if sys.platform.startswith('java'): - skipped_extensions = ('.pyc', '.pyo', '.class') - else: - skipped_extensions = ('.pyc', '.pyo') - - def __init__(self, module): - self.module = module - self.loader = getattr(module, '__loader__', None) - self.base = os.path.dirname(getattr(module, '__file__', '')) - - def _adjust_path(self, path): - return os.path.realpath(path) - - def _make_path(self, resource_name): - # Issue #50: need to preserve type of path on Python 2.x - # like os.path._get_sep - if isinstance(resource_name, bytes): # should only happen on 2.x - sep = b'/' - else: - sep = '/' - parts = resource_name.split(sep) - parts.insert(0, self.base) - result = os.path.join(*parts) - return self._adjust_path(result) - - def _find(self, path): - return os.path.exists(path) - - def get_cache_info(self, resource): - return None, resource.path - - def find(self, resource_name): - path = self._make_path(resource_name) - if not self._find(path): - result = None - else: - if self._is_directory(path): - result = ResourceContainer(self, resource_name) - else: - result = Resource(self, resource_name) - result.path = path - return result - - def get_stream(self, resource): - return open(resource.path, 'rb') - - def get_bytes(self, resource): - with open(resource.path, 'rb') as f: - return f.read() - - def get_size(self, resource): - return os.path.getsize(resource.path) - - def get_resources(self, resource): - def allowed(f): - return (f != '__pycache__' and not - f.endswith(self.skipped_extensions)) - return set([f for f in os.listdir(resource.path) if allowed(f)]) - - def is_container(self, resource): - return self._is_directory(resource.path) - - _is_directory = staticmethod(os.path.isdir) - - def iterator(self, resource_name): - resource = self.find(resource_name) - if resource is not None: - todo = [resource] - while todo: - resource = todo.pop(0) - yield resource - if resource.is_container: - rname = resource.name - for name in resource.resources: - if not rname: - new_name = name - else: - new_name = '/'.join([rname, name]) - child = self.find(new_name) - if child.is_container: - todo.append(child) - else: - yield child - - -class ZipResourceFinder(ResourceFinder): - """ - Resource finder for resources in .zip files. - """ - def __init__(self, module): - super(ZipResourceFinder, self).__init__(module) - archive = self.loader.archive - self.prefix_len = 1 + len(archive) - # PyPy doesn't have a _files attr on zipimporter, and you can't set one - if hasattr(self.loader, '_files'): - self._files = self.loader._files - else: - self._files = zipimport._zip_directory_cache[archive] - self.index = sorted(self._files) - - def _adjust_path(self, path): - return path - - def _find(self, path): - path = path[self.prefix_len:] - if path in self._files: - result = True - else: - if path and path[-1] != os.sep: - path = path + os.sep - i = bisect.bisect(self.index, path) - try: - result = self.index[i].startswith(path) - except IndexError: - result = False - if not result: - logger.debug('_find failed: %r %r', path, self.loader.prefix) - else: - logger.debug('_find worked: %r %r', path, self.loader.prefix) - return result - - def get_cache_info(self, resource): - prefix = self.loader.archive - path = resource.path[1 + len(prefix):] - return prefix, path - - def get_bytes(self, resource): - return self.loader.get_data(resource.path) - - def get_stream(self, resource): - return io.BytesIO(self.get_bytes(resource)) - - def get_size(self, resource): - path = resource.path[self.prefix_len:] - return self._files[path][3] - - def get_resources(self, resource): - path = resource.path[self.prefix_len:] - if path and path[-1] != os.sep: - path += os.sep - plen = len(path) - result = set() - i = bisect.bisect(self.index, path) - while i < len(self.index): - if not self.index[i].startswith(path): - break - s = self.index[i][plen:] - result.add(s.split(os.sep, 1)[0]) # only immediate children - i += 1 - return result - - def _is_directory(self, path): - path = path[self.prefix_len:] - if path and path[-1] != os.sep: - path += os.sep - i = bisect.bisect(self.index, path) - try: - result = self.index[i].startswith(path) - except IndexError: - result = False - return result - -_finder_registry = { - type(None): ResourceFinder, - zipimport.zipimporter: ZipResourceFinder -} - -try: - import _frozen_importlib - _finder_registry[_frozen_importlib.SourceFileLoader] = ResourceFinder - _finder_registry[_frozen_importlib.FileFinder] = ResourceFinder -except (ImportError, AttributeError): - pass - - -def register_finder(loader, finder_maker): - _finder_registry[type(loader)] = finder_maker - -_finder_cache = {} - - -def finder(package): - """ - Return a resource finder for a package. - :param package: The name of the package. - :return: A :class:`ResourceFinder` instance for the package. - """ - if package in _finder_cache: - result = _finder_cache[package] - else: - if package not in sys.modules: - __import__(package) - module = sys.modules[package] - path = getattr(module, '__path__', None) - if path is None: - raise DistlibException('You cannot get a finder for a module, ' - 'only for a package') - loader = getattr(module, '__loader__', None) - finder_maker = _finder_registry.get(type(loader)) - if finder_maker is None: - raise DistlibException('Unable to locate finder for %r' % package) - result = finder_maker(module) - _finder_cache[package] = result - return result - - -_dummy_module = types.ModuleType(str('__dummy__')) - - -def finder_for_path(path): - """ - Return a resource finder for a path, which should represent a container. - - :param path: The path. - :return: A :class:`ResourceFinder` instance for the path. - """ - result = None - # calls any path hooks, gets importer into cache - pkgutil.get_importer(path) - loader = sys.path_importer_cache.get(path) - finder = _finder_registry.get(type(loader)) - if finder: - module = _dummy_module - module.__file__ = os.path.join(path, '') - module.__loader__ = loader - result = finder(module) - return result diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/scripts.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/scripts.py deleted file mode 100644 index 2aa6eb7..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/scripts.py +++ /dev/null @@ -1,365 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2013-2015 Vinay Sajip. -# Licensed to the Python Software Foundation under a contributor agreement. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -from io import BytesIO -import logging -import os -import re -import struct -import sys - -from .compat import sysconfig, detect_encoding, ZipFile -from .resources import finder -from .util import (FileOperator, get_export_entry, convert_path, - get_executable, in_venv) - -logger = logging.getLogger(__name__) - -_DEFAULT_MANIFEST = ''' - - - - - - - - - - - - -'''.strip() - -# check if Python is called on the first line with this expression -FIRST_LINE_RE = re.compile(b'^#!.*pythonw?[0-9.]*([ \t].*)?$') -SCRIPT_TEMPLATE = '''# -*- coding: utf-8 -*- -if __name__ == '__main__': - import sys, re - - def _resolve(module, func): - __import__(module) - mod = sys.modules[module] - parts = func.split('.') - result = getattr(mod, parts.pop(0)) - for p in parts: - result = getattr(result, p) - return result - - try: - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - - func = _resolve('%(module)s', '%(func)s') - rc = func() # None interpreted as 0 - except Exception as e: # only supporting Python >= 2.6 - sys.stderr.write('%%s\\n' %% e) - rc = 1 - sys.exit(rc) -''' - - -class ScriptMaker(object): - """ - A class to copy or create scripts from source scripts or callable - specifications. - """ - script_template = SCRIPT_TEMPLATE - - executable = None # for shebangs - - def __init__(self, source_dir, target_dir, add_launchers=True, - dry_run=False, fileop=None): - self.source_dir = source_dir - self.target_dir = target_dir - self.add_launchers = add_launchers - self.force = False - self.clobber = False - # It only makes sense to set mode bits on POSIX. - self.set_mode = (os.name == 'posix') or (os.name == 'java' and - os._name == 'posix') - self.variants = set(('', 'X.Y')) - self._fileop = fileop or FileOperator(dry_run) - - def _get_alternate_executable(self, executable, options): - if options.get('gui', False) and os.name == 'nt': - dn, fn = os.path.split(executable) - fn = fn.replace('python', 'pythonw') - executable = os.path.join(dn, fn) - return executable - - if sys.platform.startswith('java'): # pragma: no cover - def _is_shell(self, executable): - """ - Determine if the specified executable is a script - (contains a #! line) - """ - try: - with open(executable) as fp: - return fp.read(2) == '#!' - except (OSError, IOError): - logger.warning('Failed to open %s', executable) - return False - - def _fix_jython_executable(self, executable): - if self._is_shell(executable): - # Workaround for Jython is not needed on Linux systems. - import java - - if java.lang.System.getProperty('os.name') == 'Linux': - return executable - elif executable.lower().endswith('jython.exe'): - # Use wrapper exe for Jython on Windows - return executable - return '/usr/bin/env %s' % executable - - def _get_shebang(self, encoding, post_interp=b'', options=None): - enquote = True - if self.executable: - executable = self.executable - enquote = False # assume this will be taken care of - elif not sysconfig.is_python_build(): - executable = get_executable() - elif in_venv(): - executable = os.path.join(sysconfig.get_path('scripts'), - 'python%s' % sysconfig.get_config_var('EXE')) - else: - executable = os.path.join( - sysconfig.get_config_var('BINDIR'), - 'python%s%s' % (sysconfig.get_config_var('VERSION'), - sysconfig.get_config_var('EXE'))) - if options: - executable = self._get_alternate_executable(executable, options) - - if sys.platform.startswith('java'): # pragma: no cover - executable = self._fix_jython_executable(executable) - # Normalise case for Windows - executable = os.path.normcase(executable) - # If the user didn't specify an executable, it may be necessary to - # cater for executable paths with spaces (not uncommon on Windows) - if enquote and ' ' in executable: - executable = '"%s"' % executable - # Issue #51: don't use fsencode, since we later try to - # check that the shebang is decodable using utf-8. - executable = executable.encode('utf-8') - # in case of IronPython, play safe and enable frames support - if (sys.platform == 'cli' and '-X:Frames' not in post_interp - and '-X:FullFrames' not in post_interp): - post_interp += b' -X:Frames' - shebang = b'#!' + executable + post_interp + b'\n' - # Python parser starts to read a script using UTF-8 until - # it gets a #coding:xxx cookie. The shebang has to be the - # first line of a file, the #coding:xxx cookie cannot be - # written before. So the shebang has to be decodable from - # UTF-8. - try: - shebang.decode('utf-8') - except UnicodeDecodeError: - raise ValueError( - 'The shebang (%r) is not decodable from utf-8' % shebang) - # If the script is encoded to a custom encoding (use a - # #coding:xxx cookie), the shebang has to be decodable from - # the script encoding too. - if encoding != 'utf-8': - try: - shebang.decode(encoding) - except UnicodeDecodeError: - raise ValueError( - 'The shebang (%r) is not decodable ' - 'from the script encoding (%r)' % (shebang, encoding)) - return shebang - - def _get_script_text(self, entry): - return self.script_template % dict(module=entry.prefix, - func=entry.suffix) - - manifest = _DEFAULT_MANIFEST - - def get_manifest(self, exename): - base = os.path.basename(exename) - return self.manifest % base - - def _write_script(self, names, shebang, script_bytes, filenames, ext): - use_launcher = self.add_launchers and os.name == 'nt' - linesep = os.linesep.encode('utf-8') - if not use_launcher: - script_bytes = shebang + linesep + script_bytes - else: - if ext == 'py': - launcher = self._get_launcher('t') - else: - launcher = self._get_launcher('w') - stream = BytesIO() - with ZipFile(stream, 'w') as zf: - zf.writestr('__main__.py', script_bytes) - zip_data = stream.getvalue() - script_bytes = launcher + shebang + linesep + zip_data - for name in names: - outname = os.path.join(self.target_dir, name) - if use_launcher: - n, e = os.path.splitext(outname) - if e.startswith('.py'): - outname = n - outname = '%s.exe' % outname - try: - self._fileop.write_binary_file(outname, script_bytes) - except Exception: - # Failed writing an executable - it might be in use. - logger.warning('Failed to write executable - trying to ' - 'use .deleteme logic') - dfname = '%s.deleteme' % outname - if os.path.exists(dfname): - os.remove(dfname) # Not allowed to fail here - os.rename(outname, dfname) # nor here - self._fileop.write_binary_file(outname, script_bytes) - logger.debug('Able to replace executable using ' - '.deleteme logic') - try: - os.remove(dfname) - except Exception: - pass # still in use - ignore error - else: - if os.name == 'nt' and not outname.endswith('.' + ext): - outname = '%s.%s' % (outname, ext) - if os.path.exists(outname) and not self.clobber: - logger.warning('Skipping existing file %s', outname) - continue - self._fileop.write_binary_file(outname, script_bytes) - if self.set_mode: - self._fileop.set_executable_mode([outname]) - filenames.append(outname) - - def _make_script(self, entry, filenames, options=None): - post_interp = b'' - if options: - args = options.get('interpreter_args', []) - if args: - args = ' %s' % ' '.join(args) - post_interp = args.encode('utf-8') - shebang = self._get_shebang('utf-8', post_interp, options=options) - script = self._get_script_text(entry).encode('utf-8') - name = entry.name - scriptnames = set() - if '' in self.variants: - scriptnames.add(name) - if 'X' in self.variants: - scriptnames.add('%s%s' % (name, sys.version[0])) - if 'X.Y' in self.variants: - scriptnames.add('%s-%s' % (name, sys.version[:3])) - if options and options.get('gui', False): - ext = 'pyw' - else: - ext = 'py' - self._write_script(scriptnames, shebang, script, filenames, ext) - - def _copy_script(self, script, filenames): - adjust = False - script = os.path.join(self.source_dir, convert_path(script)) - outname = os.path.join(self.target_dir, os.path.basename(script)) - if not self.force and not self._fileop.newer(script, outname): - logger.debug('not copying %s (up-to-date)', script) - return - - # 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, 'rb') - except IOError: - if not self.dry_run: - raise - f = None - else: - encoding, lines = detect_encoding(f.readline) - f.seek(0) - first_line = f.readline() - if not first_line: - logger.warning('%s: %s is an empty file (skipping)', - self.get_command_name(), script) - return - - match = FIRST_LINE_RE.match(first_line.replace(b'\r\n', b'\n')) - if match: - adjust = True - post_interp = match.group(1) or b'' - - if not adjust: - if f: - f.close() - self._fileop.copy_file(script, outname) - if self.set_mode: - self._fileop.set_executable_mode([outname]) - filenames.append(outname) - else: - logger.info('copying and adjusting %s -> %s', script, - self.target_dir) - if not self._fileop.dry_run: - shebang = self._get_shebang(encoding, post_interp) - if b'pythonw' in first_line: - ext = 'pyw' - else: - ext = 'py' - n = os.path.basename(outname) - self._write_script([n], shebang, f.read(), filenames, ext) - if f: - f.close() - - @property - def dry_run(self): - return self._fileop.dry_run - - @dry_run.setter - def dry_run(self, value): - self._fileop.dry_run = value - - if os.name == 'nt': - # Executable launcher support. - # Launchers are from https://bitbucket.org/vinay.sajip/simple_launcher/ - - def _get_launcher(self, kind): - if struct.calcsize('P') == 8: # 64-bit - bits = '64' - else: - bits = '32' - name = '%s%s.exe' % (kind, bits) - # Issue 31: don't hardcode an absolute package name, but - # determine it relative to the current package - distlib_package = __name__.rsplit('.', 1)[0] - result = finder(distlib_package).find(name).bytes - return result - - # Public API follows - - def make(self, specification, options=None): - """ - Make a script. - - :param specification: The specification, which is either a valid export - entry specification (to make a script from a - callable) or a filename (to make a script by - copying from a source location). - :param options: A dictionary of options controlling script generation. - :return: A list of all absolute pathnames written to. - """ - filenames = [] - entry = get_export_entry(specification) - if entry is None: - self._copy_script(specification, filenames) - else: - self._make_script(entry, filenames, options=options) - return filenames - - def make_multiple(self, specifications, options=None): - """ - Take a list of specifications and make scripts from them, - :param specifications: A list of specifications. - :return: A list of all absolute pathnames written to, - """ - filenames = [] - for specification in specifications: - filenames.extend(self.make(specification, options)) - return filenames diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/t32.exe b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/t32.exe deleted file mode 100644 index e0168c22c57f32e59dc7f64f805c586e959c3ec2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89088 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

cCam5!j}jO7Ps19?sV&U#*qxz<7n$K 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 P24SC;PdV`a$$|d@Alj9? diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/util.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/util.py deleted file mode 100644 index 7555c1e..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/util.py +++ /dev/null @@ -1,1579 +0,0 @@ -# -# Copyright (C) 2012-2014 The Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -import codecs -from collections import deque -import contextlib -import csv -from glob import iglob as std_iglob -import io -import json -import logging -import os -import py_compile -import re -import shutil -import socket -import ssl -import subprocess -import sys -import tarfile -import tempfile -try: - import threading -except ImportError: - import dummy_threading as threading -import time - -from . import DistlibException -from .compat import (string_types, text_type, shutil, raw_input, StringIO, - cache_from_source, urlopen, httplib, xmlrpclib, splittype, - HTTPHandler, HTTPSHandler as BaseHTTPSHandler, - BaseConfigurator, valid_ident, Container, configparser, - URLError, match_hostname, CertificateError, ZipFile) - -logger = logging.getLogger(__name__) - -# -# Requirement parsing code for name + optional constraints + optional extras -# -# e.g. 'foo >= 1.2, < 2.0 [bar, baz]' -# -# The regex can seem a bit hairy, so we build it up out of smaller pieces -# which are manageable. -# - -COMMA = r'\s*,\s*' -COMMA_RE = re.compile(COMMA) - -IDENT = r'(\w|[.-])+' -EXTRA_IDENT = r'(\*|:(\*|\w+):|' + IDENT + ')' -VERSPEC = IDENT + r'\*?' - -RELOP = '([<>=!~]=)|[<>]' - -# -# The first relop is optional - if absent, will be taken as '~=' -# -BARE_CONSTRAINTS = ('(' + RELOP + r')?\s*(' + VERSPEC + ')(' + COMMA + '(' + - RELOP + r')\s*(' + VERSPEC + '))*') - -DIRECT_REF = '(from\s+(?P.*))' - -# -# Either the bare constraints or the bare constraints in parentheses -# -CONSTRAINTS = (r'\(\s*(?P' + BARE_CONSTRAINTS + '|' + DIRECT_REF + - r')\s*\)|(?P' + BARE_CONSTRAINTS + '\s*)') - -EXTRA_LIST = EXTRA_IDENT + '(' + COMMA + EXTRA_IDENT + ')*' -EXTRAS = r'\[\s*(?P' + EXTRA_LIST + r')?\s*\]' -REQUIREMENT = ('(?P' + IDENT + r')\s*(' + EXTRAS + r'\s*)?(\s*' + - CONSTRAINTS + ')?$') -REQUIREMENT_RE = re.compile(REQUIREMENT) - -# -# Used to scan through the constraints -# -RELOP_IDENT = '(?P' + RELOP + r')\s*(?P' + VERSPEC + ')' -RELOP_IDENT_RE = re.compile(RELOP_IDENT) - -def parse_requirement(s): - - def get_constraint(m): - d = m.groupdict() - return d['op'], d['vn'] - - result = None - m = REQUIREMENT_RE.match(s) - if m: - d = m.groupdict() - name = d['dn'] - cons = d['c1'] or d['c2'] - if not d['diref']: - url = None - else: - # direct reference - cons = None - url = d['diref'].strip() - if not cons: - cons = None - constr = '' - rs = d['dn'] - else: - if cons[0] not in '<>!=': - cons = '~=' + cons - iterator = RELOP_IDENT_RE.finditer(cons) - cons = [get_constraint(m) for m in iterator] - rs = '%s (%s)' % (name, ', '.join(['%s %s' % con for con in cons])) - if not d['ex']: - extras = None - else: - extras = COMMA_RE.split(d['ex']) - result = Container(name=name, constraints=cons, extras=extras, - requirement=rs, source=s, url=url) - return result - - -def get_resources_dests(resources_root, rules): - """Find destinations for resources files""" - - def get_rel_path(base, path): - # normalizes and returns a lstripped-/-separated path - base = base.replace(os.path.sep, '/') - path = path.replace(os.path.sep, '/') - assert path.startswith(base) - return path[len(base):].lstrip('/') - - - destinations = {} - for base, suffix, dest in rules: - prefix = os.path.join(resources_root, base) - for abs_base in iglob(prefix): - abs_glob = os.path.join(abs_base, suffix) - for abs_path in iglob(abs_glob): - resource_file = get_rel_path(resources_root, abs_path) - if dest is None: # remove the entry if it was here - destinations.pop(resource_file, None) - else: - rel_path = get_rel_path(abs_base, abs_path) - rel_dest = dest.replace(os.path.sep, '/').rstrip('/') - destinations[resource_file] = rel_dest + '/' + rel_path - return destinations - - -def in_venv(): - if hasattr(sys, 'real_prefix'): - # virtualenv venvs - result = True - else: - # PEP 405 venvs - result = sys.prefix != getattr(sys, 'base_prefix', sys.prefix) - return result - - -def get_executable(): -# The __PYVENV_LAUNCHER__ dance is apparently no longer needed, as -# changes to the stub launcher mean that sys.executable always points -# to the stub on OS X -# if sys.platform == 'darwin' and ('__PYVENV_LAUNCHER__' -# in os.environ): -# result = os.environ['__PYVENV_LAUNCHER__'] -# else: -# result = sys.executable -# return result - return os.path.normcase(sys.executable) - - -def proceed(prompt, allowed_chars, error_prompt=None, default=None): - p = prompt - while True: - s = raw_input(p) - p = prompt - if not s and default: - s = default - if s: - c = s[0].lower() - if c in allowed_chars: - break - if error_prompt: - p = '%c: %s\n%s' % (c, error_prompt, prompt) - return c - - -def extract_by_key(d, keys): - if isinstance(keys, string_types): - keys = keys.split() - result = {} - for key in keys: - if key in d: - result[key] = d[key] - return result - -def read_exports(stream): - if sys.version_info[0] >= 3: - # needs to be a text stream - stream = codecs.getreader('utf-8')(stream) - # Try to load as JSON, falling back on legacy format - data = stream.read() - stream = StringIO(data) - try: - data = json.load(stream) - result = data['extensions']['python.exports']['exports'] - for group, entries in result.items(): - for k, v in entries.items(): - s = '%s = %s' % (k, v) - entry = get_export_entry(s) - assert entry is not None - entries[k] = entry - return result - except Exception: - stream.seek(0, 0) - cp = configparser.ConfigParser() - if hasattr(cp, 'read_file'): - cp.read_file(stream) - else: - cp.readfp(stream) - result = {} - for key in cp.sections(): - result[key] = entries = {} - for name, value in cp.items(key): - s = '%s = %s' % (name, value) - entry = get_export_entry(s) - assert entry is not None - #entry.dist = self - entries[name] = entry - return result - - -def write_exports(exports, stream): - if sys.version_info[0] >= 3: - # needs to be a text stream - stream = codecs.getwriter('utf-8')(stream) - cp = configparser.ConfigParser() - for k, v in exports.items(): - # TODO check k, v for valid values - cp.add_section(k) - for entry in v.values(): - if entry.suffix is None: - s = entry.prefix - else: - s = '%s:%s' % (entry.prefix, entry.suffix) - if entry.flags: - s = '%s [%s]' % (s, ', '.join(entry.flags)) - cp.set(k, entry.name, s) - cp.write(stream) - - -@contextlib.contextmanager -def tempdir(): - td = tempfile.mkdtemp() - try: - yield td - finally: - shutil.rmtree(td) - -@contextlib.contextmanager -def chdir(d): - cwd = os.getcwd() - try: - os.chdir(d) - yield - finally: - os.chdir(cwd) - - -@contextlib.contextmanager -def socket_timeout(seconds=15): - cto = socket.getdefaulttimeout() - try: - socket.setdefaulttimeout(seconds) - yield - finally: - socket.setdefaulttimeout(cto) - - -class cached_property(object): - def __init__(self, func): - self.func = func - #for attr in ('__name__', '__module__', '__doc__'): - # setattr(self, attr, getattr(func, attr, None)) - - def __get__(self, obj, cls=None): - if obj is None: - return self - value = self.func(obj) - object.__setattr__(obj, self.func.__name__, value) - #obj.__dict__[self.func.__name__] = value = self.func(obj) - return value - -def convert_path(pathname): - """Return 'pathname' as a name that will work on the native filesystem. - - The path is split on '/' and put 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 = pathname.split('/') - while os.curdir in paths: - paths.remove(os.curdir) - if not paths: - return os.curdir - return os.path.join(*paths) - - -class FileOperator(object): - def __init__(self, dry_run=False): - self.dry_run = dry_run - self.ensured = set() - self._init_record() - - def _init_record(self): - self.record = False - self.files_written = set() - self.dirs_created = set() - - def record_as_written(self, path): - if self.record: - self.files_written.add(path) - - def newer(self, source, target): - """Tell if the target is newer than the source. - - Returns true if 'source' exists and is more recently modified than - 'target', or if 'source' exists and 'target' doesn't. - - Returns false if both exist and 'target' is the same age or younger - than 'source'. Raise PackagingFileError 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 DistlibException("file '%r' 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 copy_file(self, infile, outfile, check=True): - """Copy a file respecting dry-run and force flags. - """ - self.ensure_dir(os.path.dirname(outfile)) - logger.info('Copying %s to %s', infile, outfile) - if not self.dry_run: - msg = None - if check: - if os.path.islink(outfile): - msg = '%s is a symlink' % outfile - elif os.path.exists(outfile) and not os.path.isfile(outfile): - msg = '%s is a non-regular file' % outfile - if msg: - raise ValueError(msg + ' which would be overwritten') - shutil.copyfile(infile, outfile) - self.record_as_written(outfile) - - def copy_stream(self, instream, outfile, encoding=None): - assert not os.path.isdir(outfile) - self.ensure_dir(os.path.dirname(outfile)) - logger.info('Copying stream %s to %s', instream, outfile) - if not self.dry_run: - if encoding is None: - outstream = open(outfile, 'wb') - else: - outstream = codecs.open(outfile, 'w', encoding=encoding) - try: - shutil.copyfileobj(instream, outstream) - finally: - outstream.close() - self.record_as_written(outfile) - - def write_binary_file(self, path, data): - self.ensure_dir(os.path.dirname(path)) - if not self.dry_run: - with open(path, 'wb') as f: - f.write(data) - self.record_as_written(path) - - def write_text_file(self, path, data, encoding): - self.ensure_dir(os.path.dirname(path)) - if not self.dry_run: - with open(path, 'wb') as f: - f.write(data.encode(encoding)) - self.record_as_written(path) - - def set_mode(self, bits, mask, files): - if os.name == 'posix' or (os.name == 'java' and os._name == 'posix'): - # Set the executable bits (owner, group, and world) on - # all the files specified. - for f in files: - if self.dry_run: - logger.info("changing mode of %s", f) - else: - mode = (os.stat(f).st_mode | bits) & mask - logger.info("changing mode of %s to %o", f, mode) - os.chmod(f, mode) - - set_executable_mode = lambda s, f: s.set_mode(0o555, 0o7777, f) - - def ensure_dir(self, path): - path = os.path.abspath(path) - if path not in self.ensured and not os.path.exists(path): - self.ensured.add(path) - d, f = os.path.split(path) - self.ensure_dir(d) - logger.info('Creating %s' % path) - if not self.dry_run: - os.mkdir(path) - if self.record: - self.dirs_created.add(path) - - def byte_compile(self, path, optimize=False, force=False, prefix=None): - dpath = cache_from_source(path, not optimize) - logger.info('Byte-compiling %s to %s', path, dpath) - if not self.dry_run: - if force or self.newer(path, dpath): - if not prefix: - diagpath = None - else: - assert path.startswith(prefix) - diagpath = path[len(prefix):] - py_compile.compile(path, dpath, diagpath, True) # raise error - self.record_as_written(dpath) - return dpath - - def ensure_removed(self, path): - if os.path.exists(path): - if os.path.isdir(path) and not os.path.islink(path): - logger.debug('Removing directory tree at %s', path) - if not self.dry_run: - shutil.rmtree(path) - if self.record: - if path in self.dirs_created: - self.dirs_created.remove(path) - else: - if os.path.islink(path): - s = 'link' - else: - s = 'file' - logger.debug('Removing %s %s', s, path) - if not self.dry_run: - os.remove(path) - if self.record: - if path in self.files_written: - self.files_written.remove(path) - - def is_writable(self, path): - result = False - while not result: - if os.path.exists(path): - result = os.access(path, os.W_OK) - break - parent = os.path.dirname(path) - if parent == path: - break - path = parent - return result - - def commit(self): - """ - Commit recorded changes, turn off recording, return - changes. - """ - assert self.record - result = self.files_written, self.dirs_created - self._init_record() - return result - - def rollback(self): - if not self.dry_run: - for f in list(self.files_written): - if os.path.exists(f): - os.remove(f) - # dirs should all be empty now, except perhaps for - # __pycache__ subdirs - # reverse so that subdirs appear before their parents - dirs = sorted(self.dirs_created, reverse=True) - for d in dirs: - flist = os.listdir(d) - if flist: - assert flist == ['__pycache__'] - sd = os.path.join(d, flist[0]) - os.rmdir(sd) - os.rmdir(d) # should fail if non-empty - self._init_record() - -def resolve(module_name, dotted_path): - if module_name in sys.modules: - mod = sys.modules[module_name] - else: - mod = __import__(module_name) - if dotted_path is None: - result = mod - else: - parts = dotted_path.split('.') - result = getattr(mod, parts.pop(0)) - for p in parts: - result = getattr(result, p) - return result - - -class ExportEntry(object): - def __init__(self, name, prefix, suffix, flags): - self.name = name - self.prefix = prefix - self.suffix = suffix - self.flags = flags - - @cached_property - def value(self): - return resolve(self.prefix, self.suffix) - - def __repr__(self): - return '' % (self.name, self.prefix, - self.suffix, self.flags) - - def __eq__(self, other): - if not isinstance(other, ExportEntry): - result = False - else: - result = (self.name == other.name and - self.prefix == other.prefix and - self.suffix == other.suffix and - self.flags == other.flags) - return result - - __hash__ = object.__hash__ - - -ENTRY_RE = re.compile(r'''(?P(\w|[-.])+) - \s*=\s*(?P(\w+)([:\.]\w+)*) - \s*(\[\s*(?P\w+(=\w+)?(,\s*\w+(=\w+)?)*)\s*\])? - ''', re.VERBOSE) - - -def get_export_entry(specification): - m = ENTRY_RE.search(specification) - if not m: - result = None - if '[' in specification or ']' in specification: - raise DistlibException('Invalid specification ' - '%r' % specification) - else: - d = m.groupdict() - name = d['name'] - path = d['callable'] - colons = path.count(':') - if colons == 0: - prefix, suffix = path, None - else: - if colons != 1: - raise DistlibException('Invalid specification ' - '%r' % specification) - prefix, suffix = path.split(':') - flags = d['flags'] - if flags is None: - if '[' in specification or ']' in specification: - raise DistlibException('Invalid specification ' - '%r' % specification) - flags = [] - else: - flags = [f.strip() for f in flags.split(',')] - result = ExportEntry(name, prefix, suffix, flags) - return result - - -def get_cache_base(suffix=None): - """ - Return the default base location for distlib caches. If the directory does - not exist, it is created. Use the suffix provided for the base directory, - and default to '.distlib' if it isn't provided. - - On Windows, if LOCALAPPDATA is defined in the environment, then it is - assumed to be a directory, and will be the parent directory of the result. - On POSIX, and on Windows if LOCALAPPDATA is not defined, the user's home - directory - using os.expanduser('~') - will be the parent directory of - the result. - - The result is just the directory '.distlib' in the parent directory as - determined above, or with the name specified with ``suffix``. - """ - if suffix is None: - suffix = '.distlib' - if os.name == 'nt' and 'LOCALAPPDATA' in os.environ: - result = os.path.expandvars('$localappdata') - else: - # Assume posix, or old Windows - result = os.path.expanduser('~') - # we use 'isdir' instead of 'exists', because we want to - # fail if there's a file with that name - if os.path.isdir(result): - usable = os.access(result, os.W_OK) - if not usable: - logger.warning('Directory exists but is not writable: %s', result) - else: - try: - os.makedirs(result) - usable = True - except OSError: - logger.warning('Unable to create %s', result, exc_info=True) - usable = False - if not usable: - result = tempfile.mkdtemp() - logger.warning('Default location unusable, using %s', result) - return os.path.join(result, suffix) - - -def path_to_cache_dir(path): - """ - Convert an absolute path to a directory name for use in a cache. - - The algorithm used is: - - #. On Windows, any ``':'`` in the drive is replaced with ``'---'``. - #. Any occurrence of ``os.sep`` is replaced with ``'--'``. - #. ``'.cache'`` is appended. - """ - d, p = os.path.splitdrive(os.path.abspath(path)) - if d: - d = d.replace(':', '---') - p = p.replace(os.sep, '--') - return d + p + '.cache' - - -def ensure_slash(s): - if not s.endswith('/'): - return s + '/' - return s - - -def parse_credentials(netloc): - username = password = None - if '@' in netloc: - prefix, netloc = netloc.split('@', 1) - if ':' not in prefix: - username = prefix - else: - username, password = prefix.split(':', 1) - return username, password, netloc - - -def get_process_umask(): - result = os.umask(0o22) - os.umask(result) - return result - -def is_string_sequence(seq): - result = True - i = None - for i, s in enumerate(seq): - if not isinstance(s, string_types): - result = False - break - assert i is not None - return result - -PROJECT_NAME_AND_VERSION = re.compile('([a-z0-9_]+([.-][a-z_][a-z0-9_]*)*)-' - '([a-z0-9_.+-]+)', re.I) -PYTHON_VERSION = re.compile(r'-py(\d\.?\d?)') - - -def split_filename(filename, project_name=None): - """ - Extract name, version, python version from a filename (no extension) - - Return name, version, pyver or None - """ - result = None - pyver = None - m = PYTHON_VERSION.search(filename) - if m: - pyver = m.group(1) - filename = filename[:m.start()] - if project_name and len(filename) > len(project_name) + 1: - m = re.match(re.escape(project_name) + r'\b', filename) - if m: - n = m.end() - result = filename[:n], filename[n + 1:], pyver - if result is None: - m = PROJECT_NAME_AND_VERSION.match(filename) - if m: - result = m.group(1), m.group(3), pyver - return result - -# Allow spaces in name because of legacy dists like "Twisted Core" -NAME_VERSION_RE = re.compile(r'(?P[\w .-]+)\s*' - r'\(\s*(?P[^\s)]+)\)$') - -def parse_name_and_version(p): - """ - A utility method used to get name and version from a string. - - From e.g. a Provides-Dist value. - - :param p: A value in a form 'foo (1.0)' - :return: The name and version as a tuple. - """ - m = NAME_VERSION_RE.match(p) - if not m: - raise DistlibException('Ill-formed name/version string: \'%s\'' % p) - d = m.groupdict() - return d['name'].strip().lower(), d['ver'] - -def get_extras(requested, available): - result = set() - requested = set(requested or []) - available = set(available or []) - if '*' in requested: - requested.remove('*') - result |= available - for r in requested: - if r == '-': - result.add(r) - elif r.startswith('-'): - unwanted = r[1:] - if unwanted not in available: - logger.warning('undeclared extra: %s' % unwanted) - if unwanted in result: - result.remove(unwanted) - else: - if r not in available: - logger.warning('undeclared extra: %s' % r) - result.add(r) - return result -# -# Extended metadata functionality -# - -def _get_external_data(url): - result = {} - try: - # urlopen might fail if it runs into redirections, - # because of Python issue #13696. Fixed in locators - # using a custom redirect handler. - resp = urlopen(url) - headers = resp.info() - if headers.get('Content-Type') != 'application/json': - logger.debug('Unexpected response for JSON request') - else: - reader = codecs.getreader('utf-8')(resp) - #data = reader.read().decode('utf-8') - #result = json.loads(data) - result = json.load(reader) - except Exception as e: - logger.exception('Failed to get external data for %s: %s', url, e) - return result - - -def get_project_data(name): - url = ('https://www.red-dove.com/pypi/projects/' - '%s/%s/project.json' % (name[0].upper(), name)) - result = _get_external_data(url) - return result - -def get_package_data(name, version): - url = ('https://www.red-dove.com/pypi/projects/' - '%s/%s/package-%s.json' % (name[0].upper(), name, version)) - return _get_external_data(url) - - -class Cache(object): - """ - A class implementing a cache for resources that need to live in the file system - e.g. shared libraries. This class was moved from resources to here because it - could be used by other modules, e.g. the wheel module. - """ - - def __init__(self, base): - """ - Initialise an instance. - - :param base: The base directory where the cache should be located. - """ - # we use 'isdir' instead of 'exists', because we want to - # fail if there's a file with that name - if not os.path.isdir(base): - os.makedirs(base) - if (os.stat(base).st_mode & 0o77) != 0: - logger.warning('Directory \'%s\' is not private', base) - self.base = os.path.abspath(os.path.normpath(base)) - - def prefix_to_dir(self, prefix): - """ - Converts a resource prefix to a directory name in the cache. - """ - return path_to_cache_dir(prefix) - - def clear(self): - """ - Clear the cache. - """ - not_removed = [] - for fn in os.listdir(self.base): - fn = os.path.join(self.base, fn) - try: - if os.path.islink(fn) or os.path.isfile(fn): - os.remove(fn) - elif os.path.isdir(fn): - shutil.rmtree(fn) - except Exception: - not_removed.append(fn) - return not_removed - - -class EventMixin(object): - """ - A very simple publish/subscribe system. - """ - def __init__(self): - self._subscribers = {} - - def add(self, event, subscriber, append=True): - """ - Add a subscriber for an event. - - :param event: The name of an event. - :param subscriber: The subscriber to be added (and called when the - event is published). - :param append: Whether to append or prepend the subscriber to an - existing subscriber list for the event. - """ - subs = self._subscribers - if event not in subs: - subs[event] = deque([subscriber]) - else: - sq = subs[event] - if append: - sq.append(subscriber) - else: - sq.appendleft(subscriber) - - def remove(self, event, subscriber): - """ - Remove a subscriber for an event. - - :param event: The name of an event. - :param subscriber: The subscriber to be removed. - """ - subs = self._subscribers - if event not in subs: - raise ValueError('No subscribers: %r' % event) - subs[event].remove(subscriber) - - def get_subscribers(self, event): - """ - Return an iterator for the subscribers for an event. - :param event: The event to return subscribers for. - """ - return iter(self._subscribers.get(event, ())) - - def publish(self, event, *args, **kwargs): - """ - Publish a event and return a list of values returned by its - subscribers. - - :param event: The event to publish. - :param args: The positional arguments to pass to the event's - subscribers. - :param kwargs: The keyword arguments to pass to the event's - subscribers. - """ - result = [] - for subscriber in self.get_subscribers(event): - try: - value = subscriber(event, *args, **kwargs) - except Exception: - logger.exception('Exception during event publication') - value = None - result.append(value) - logger.debug('publish %s: args = %s, kwargs = %s, result = %s', - event, args, kwargs, result) - return result - -# -# Simple sequencing -# -class Sequencer(object): - def __init__(self): - self._preds = {} - self._succs = {} - self._nodes = set() # nodes with no preds/succs - - def add_node(self, node): - self._nodes.add(node) - - def remove_node(self, node, edges=False): - if node in self._nodes: - self._nodes.remove(node) - if edges: - for p in set(self._preds.get(node, ())): - self.remove(p, node) - for s in set(self._succs.get(node, ())): - self.remove(node, s) - # Remove empties - for k, v in list(self._preds.items()): - if not v: - del self._preds[k] - for k, v in list(self._succs.items()): - if not v: - del self._succs[k] - - def add(self, pred, succ): - assert pred != succ - self._preds.setdefault(succ, set()).add(pred) - self._succs.setdefault(pred, set()).add(succ) - - def remove(self, pred, succ): - assert pred != succ - try: - preds = self._preds[succ] - succs = self._succs[pred] - except KeyError: - raise ValueError('%r not a successor of anything' % succ) - try: - preds.remove(pred) - succs.remove(succ) - except KeyError: - raise ValueError('%r not a successor of %r' % (succ, pred)) - - def is_step(self, step): - return (step in self._preds or step in self._succs or - step in self._nodes) - - def get_steps(self, final): - if not self.is_step(final): - raise ValueError('Unknown: %r' % final) - result = [] - todo = [] - seen = set() - todo.append(final) - while todo: - step = todo.pop(0) - if step in seen: - # if a step was already seen, - # move it to the end (so it will appear earlier - # when reversed on return) ... but not for the - # final step, as that would be confusing for - # users - if step != final: - result.remove(step) - result.append(step) - else: - seen.add(step) - result.append(step) - preds = self._preds.get(step, ()) - todo.extend(preds) - return reversed(result) - - @property - def strong_connections(self): - #http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm - index_counter = [0] - stack = [] - lowlinks = {} - index = {} - result = [] - - graph = self._succs - - def strongconnect(node): - # set the depth index for this node to the smallest unused index - index[node] = index_counter[0] - lowlinks[node] = index_counter[0] - index_counter[0] += 1 - stack.append(node) - - # Consider successors - try: - successors = graph[node] - except Exception: - successors = [] - for successor in successors: - if successor not in lowlinks: - # Successor has not yet been visited - strongconnect(successor) - lowlinks[node] = min(lowlinks[node],lowlinks[successor]) - elif successor in stack: - # the successor is in the stack and hence in the current - # strongly connected component (SCC) - lowlinks[node] = min(lowlinks[node],index[successor]) - - # If `node` is a root node, pop the stack and generate an SCC - if lowlinks[node] == index[node]: - connected_component = [] - - while True: - successor = stack.pop() - connected_component.append(successor) - if successor == node: break - component = tuple(connected_component) - # storing the result - result.append(component) - - for node in graph: - if node not in lowlinks: - strongconnect(node) - - return result - - @property - def dot(self): - result = ['digraph G {'] - for succ in self._preds: - preds = self._preds[succ] - for pred in preds: - result.append(' %s -> %s;' % (pred, succ)) - for node in self._nodes: - result.append(' %s;' % node) - result.append('}') - return '\n'.join(result) - -# -# Unarchiving functionality for zip, tar, tgz, tbz, whl -# - -ARCHIVE_EXTENSIONS = ('.tar.gz', '.tar.bz2', '.tar', '.zip', - '.tgz', '.tbz', '.whl') - -def unarchive(archive_filename, dest_dir, format=None, check=True): - - def check_path(path): - if not isinstance(path, text_type): - path = path.decode('utf-8') - p = os.path.abspath(os.path.join(dest_dir, path)) - if not p.startswith(dest_dir) or p[plen] != os.sep: - raise ValueError('path outside destination: %r' % p) - - dest_dir = os.path.abspath(dest_dir) - plen = len(dest_dir) - archive = None - if format is None: - if archive_filename.endswith(('.zip', '.whl')): - format = 'zip' - elif archive_filename.endswith(('.tar.gz', '.tgz')): - format = 'tgz' - mode = 'r:gz' - elif archive_filename.endswith(('.tar.bz2', '.tbz')): - format = 'tbz' - mode = 'r:bz2' - elif archive_filename.endswith('.tar'): - format = 'tar' - mode = 'r' - else: - raise ValueError('Unknown format for %r' % archive_filename) - try: - if format == 'zip': - archive = ZipFile(archive_filename, 'r') - if check: - names = archive.namelist() - for name in names: - check_path(name) - else: - archive = tarfile.open(archive_filename, mode) - if check: - names = archive.getnames() - for name in names: - check_path(name) - if format != 'zip' and sys.version_info[0] < 3: - # See Python issue 17153. If the dest path contains Unicode, - # tarfile extraction fails on Python 2.x if a member path name - # contains non-ASCII characters - it leads to an implicit - # bytes -> unicode conversion using ASCII to decode. - for tarinfo in archive.getmembers(): - if not isinstance(tarinfo.name, text_type): - tarinfo.name = tarinfo.name.decode('utf-8') - archive.extractall(dest_dir) - - finally: - if archive: - archive.close() - - -def zip_dir(directory): - """zip a directory tree into a BytesIO object""" - result = io.BytesIO() - dlen = len(directory) - with ZipFile(result, "w") as zf: - for root, dirs, files in os.walk(directory): - for name in files: - full = os.path.join(root, name) - rel = root[dlen:] - dest = os.path.join(rel, name) - zf.write(full, dest) - return result - -# -# Simple progress bar -# - -UNITS = ('', 'K', 'M', 'G','T','P') - - -class Progress(object): - unknown = 'UNKNOWN' - - def __init__(self, minval=0, maxval=100): - assert maxval is None or maxval >= minval - self.min = self.cur = minval - self.max = maxval - self.started = None - self.elapsed = 0 - self.done = False - - def update(self, curval): - assert self.min <= curval - assert self.max is None or curval <= self.max - self.cur = curval - now = time.time() - if self.started is None: - self.started = now - else: - self.elapsed = now - self.started - - def increment(self, incr): - assert incr >= 0 - self.update(self.cur + incr) - - def start(self): - self.update(self.min) - return self - - def stop(self): - if self.max is not None: - self.update(self.max) - self.done = True - - @property - def maximum(self): - return self.unknown if self.max is None else self.max - - @property - def percentage(self): - if self.done: - result = '100 %' - elif self.max is None: - result = ' ?? %' - else: - v = 100.0 * (self.cur - self.min) / (self.max - self.min) - result = '%3d %%' % v - return result - - def format_duration(self, duration): - if (duration <= 0) and self.max is None or self.cur == self.min: - result = '??:??:??' - #elif duration < 1: - # result = '--:--:--' - else: - result = time.strftime('%H:%M:%S', time.gmtime(duration)) - return result - - @property - def ETA(self): - if self.done: - prefix = 'Done' - t = self.elapsed - #import pdb; pdb.set_trace() - else: - prefix = 'ETA ' - if self.max is None: - t = -1 - elif self.elapsed == 0 or (self.cur == self.min): - t = 0 - else: - #import pdb; pdb.set_trace() - t = float(self.max - self.min) - t /= self.cur - self.min - t = (t - 1) * self.elapsed - return '%s: %s' % (prefix, self.format_duration(t)) - - @property - def speed(self): - if self.elapsed == 0: - result = 0.0 - else: - result = (self.cur - self.min) / self.elapsed - for unit in UNITS: - if result < 1000: - break - result /= 1000.0 - return '%d %sB/s' % (result, unit) - -# -# Glob functionality -# - -RICH_GLOB = re.compile(r'\{([^}]*)\}') -_CHECK_RECURSIVE_GLOB = re.compile(r'[^/\\,{]\*\*|\*\*[^/\\,}]') -_CHECK_MISMATCH_SET = re.compile(r'^[^{]*\}|\{[^}]*$') - - -def iglob(path_glob): - """Extended globbing function that supports ** and {opt1,opt2,opt3}.""" - if _CHECK_RECURSIVE_GLOB.search(path_glob): - msg = """invalid glob %r: recursive glob "**" must be used alone""" - raise ValueError(msg % path_glob) - if _CHECK_MISMATCH_SET.search(path_glob): - msg = """invalid glob %r: mismatching set marker '{' or '}'""" - raise ValueError(msg % path_glob) - return _iglob(path_glob) - - -def _iglob(path_glob): - rich_path_glob = RICH_GLOB.split(path_glob, 1) - if len(rich_path_glob) > 1: - assert len(rich_path_glob) == 3, rich_path_glob - prefix, set, suffix = rich_path_glob - for item in set.split(','): - for path in _iglob(''.join((prefix, item, suffix))): - yield path - else: - if '**' not in path_glob: - for item in std_iglob(path_glob): - yield item - else: - prefix, radical = path_glob.split('**', 1) - if prefix == '': - prefix = '.' - if radical == '': - radical = '*' - else: - # we support both - radical = radical.lstrip('/') - radical = radical.lstrip('\\') - for path, dir, files in os.walk(prefix): - path = os.path.normpath(path) - for fn in _iglob(os.path.join(path, radical)): - yield fn - - - -# -# HTTPSConnection which verifies certificates/matches domains -# - -class HTTPSConnection(httplib.HTTPSConnection): - ca_certs = None # set this to the path to the certs file (.pem) - check_domain = True # only used if ca_certs is not None - - # noinspection PyPropertyAccess - def connect(self): - sock = socket.create_connection((self.host, self.port), self.timeout) - if getattr(self, '_tunnel_host', False): - self.sock = sock - self._tunnel() - - if not hasattr(ssl, 'SSLContext'): - # For 2.x - if self.ca_certs: - cert_reqs = ssl.CERT_REQUIRED - else: - cert_reqs = ssl.CERT_NONE - self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, - cert_reqs=cert_reqs, - ssl_version=ssl.PROTOCOL_SSLv23, - ca_certs=self.ca_certs) - else: - context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - context.options |= ssl.OP_NO_SSLv2 - if self.cert_file: - context.load_cert_chain(self.cert_file, self.key_file) - kwargs = {} - if self.ca_certs: - context.verify_mode = ssl.CERT_REQUIRED - context.load_verify_locations(cafile=self.ca_certs) - if getattr(ssl, 'HAS_SNI', False): - kwargs['server_hostname'] = self.host - self.sock = context.wrap_socket(sock, **kwargs) - if self.ca_certs and self.check_domain: - try: - match_hostname(self.sock.getpeercert(), self.host) - logger.debug('Host verified: %s', self.host) - except CertificateError: - self.sock.shutdown(socket.SHUT_RDWR) - self.sock.close() - raise - -class HTTPSHandler(BaseHTTPSHandler): - def __init__(self, ca_certs, check_domain=True): - BaseHTTPSHandler.__init__(self) - self.ca_certs = ca_certs - self.check_domain = check_domain - - def _conn_maker(self, *args, **kwargs): - """ - This is called to create a connection instance. Normally you'd - pass a connection class to do_open, but it doesn't actually check for - a class, and just expects a callable. As long as we behave just as a - constructor would have, we should be OK. If it ever changes so that - we *must* pass a class, we'll create an UnsafeHTTPSConnection class - which just sets check_domain to False in the class definition, and - choose which one to pass to do_open. - """ - result = HTTPSConnection(*args, **kwargs) - if self.ca_certs: - result.ca_certs = self.ca_certs - result.check_domain = self.check_domain - return result - - def https_open(self, req): - try: - return self.do_open(self._conn_maker, req) - except URLError as e: - if 'certificate verify failed' in str(e.reason): - raise CertificateError('Unable to verify server certificate ' - 'for %s' % req.host) - else: - raise - -# -# To prevent against mixing HTTP traffic with HTTPS (examples: A Man-In-The- -# Middle proxy using HTTP listens on port 443, or an index mistakenly serves -# HTML containing a http://xyz link when it should be https://xyz), -# you can use the following handler class, which does not allow HTTP traffic. -# -# It works by inheriting from HTTPHandler - so build_opener won't add a -# handler for HTTP itself. -# -class HTTPSOnlyHandler(HTTPSHandler, HTTPHandler): - def http_open(self, req): - raise URLError('Unexpected HTTP request on what should be a secure ' - 'connection: %s' % req) - -# -# XML-RPC with timeouts -# - -_ver_info = sys.version_info[:2] - -if _ver_info == (2, 6): - class HTTP(httplib.HTTP): - def __init__(self, host='', port=None, **kwargs): - if port == 0: # 0 means use port 0, not the default port - port = None - self._setup(self._connection_class(host, port, **kwargs)) - - - class HTTPS(httplib.HTTPS): - def __init__(self, host='', port=None, **kwargs): - if port == 0: # 0 means use port 0, not the default port - port = None - self._setup(self._connection_class(host, port, **kwargs)) - - -class Transport(xmlrpclib.Transport): - def __init__(self, timeout, use_datetime=0): - self.timeout = timeout - xmlrpclib.Transport.__init__(self, use_datetime) - - def make_connection(self, host): - h, eh, x509 = self.get_host_info(host) - if _ver_info == (2, 6): - result = HTTP(h, timeout=self.timeout) - else: - if not self._connection or host != self._connection[0]: - self._extra_headers = eh - self._connection = host, httplib.HTTPConnection(h) - result = self._connection[1] - return result - -class SafeTransport(xmlrpclib.SafeTransport): - def __init__(self, timeout, use_datetime=0): - self.timeout = timeout - xmlrpclib.SafeTransport.__init__(self, use_datetime) - - def make_connection(self, host): - h, eh, kwargs = self.get_host_info(host) - if not kwargs: - kwargs = {} - kwargs['timeout'] = self.timeout - if _ver_info == (2, 6): - result = HTTPS(host, None, **kwargs) - else: - if not self._connection or host != self._connection[0]: - self._extra_headers = eh - self._connection = host, httplib.HTTPSConnection(h, None, - **kwargs) - result = self._connection[1] - return result - - -class ServerProxy(xmlrpclib.ServerProxy): - def __init__(self, uri, **kwargs): - self.timeout = timeout = kwargs.pop('timeout', None) - # The above classes only come into play if a timeout - # is specified - if timeout is not None: - scheme, _ = splittype(uri) - use_datetime = kwargs.get('use_datetime', 0) - if scheme == 'https': - tcls = SafeTransport - else: - tcls = Transport - kwargs['transport'] = t = tcls(timeout, use_datetime=use_datetime) - self.transport = t - xmlrpclib.ServerProxy.__init__(self, uri, **kwargs) - -# -# CSV functionality. This is provided because on 2.x, the csv module can't -# handle Unicode. However, we need to deal with Unicode in e.g. RECORD files. -# - -def _csv_open(fn, mode, **kwargs): - if sys.version_info[0] < 3: - mode += 'b' - else: - kwargs['newline'] = '' - return open(fn, mode, **kwargs) - - -class CSVBase(object): - defaults = { - 'delimiter': str(','), # The strs are used because we need native - 'quotechar': str('"'), # str in the csv API (2.x won't take - 'lineterminator': str('\n') # Unicode) - } - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.stream.close() - - -class CSVReader(CSVBase): - def __init__(self, **kwargs): - if 'stream' in kwargs: - stream = kwargs['stream'] - if sys.version_info[0] >= 3: - # needs to be a text stream - stream = codecs.getreader('utf-8')(stream) - self.stream = stream - else: - self.stream = _csv_open(kwargs['path'], 'r') - self.reader = csv.reader(self.stream, **self.defaults) - - def __iter__(self): - return self - - def next(self): - result = next(self.reader) - if sys.version_info[0] < 3: - for i, item in enumerate(result): - if not isinstance(item, text_type): - result[i] = item.decode('utf-8') - return result - - __next__ = next - -class CSVWriter(CSVBase): - def __init__(self, fn, **kwargs): - self.stream = _csv_open(fn, 'w') - self.writer = csv.writer(self.stream, **self.defaults) - - def writerow(self, row): - if sys.version_info[0] < 3: - r = [] - for item in row: - if isinstance(item, text_type): - item = item.encode('utf-8') - r.append(item) - row = r - self.writer.writerow(row) - -# -# Configurator functionality -# - -class Configurator(BaseConfigurator): - - value_converters = dict(BaseConfigurator.value_converters) - value_converters['inc'] = 'inc_convert' - - def __init__(self, config, base=None): - super(Configurator, self).__init__(config) - self.base = base or os.getcwd() - - def configure_custom(self, config): - def convert(o): - if isinstance(o, (list, tuple)): - result = type(o)([convert(i) for i in o]) - elif isinstance(o, dict): - if '()' in o: - result = self.configure_custom(o) - else: - result = {} - for k in o: - result[k] = convert(o[k]) - else: - result = self.convert(o) - return result - - c = config.pop('()') - if not callable(c): - c = self.resolve(c) - props = config.pop('.', None) - # Check for valid identifiers - args = config.pop('[]', ()) - if args: - args = tuple([convert(o) for o in args]) - items = [(k, convert(config[k])) for k in config if valid_ident(k)] - kwargs = dict(items) - result = c(*args, **kwargs) - if props: - for n, v in props.items(): - setattr(result, n, convert(v)) - return result - - def __getitem__(self, key): - result = self.config[key] - if isinstance(result, dict) and '()' in result: - self.config[key] = result = self.configure_custom(result) - return result - - def inc_convert(self, value): - """Default converter for the inc:// protocol.""" - if not os.path.isabs(value): - value = os.path.join(self.base, value) - with codecs.open(value, 'r', encoding='utf-8') as f: - result = json.load(f) - return result - -# -# Mixin for running subprocesses and capturing their output -# - -class SubprocessMixin(object): - def __init__(self, verbose=False, progress=None): - self.verbose = verbose - self.progress = progress - - def reader(self, stream, context): - """ - Read lines from a subprocess' output stream and either pass to a progress - callable (if specified) or write progress information to sys.stderr. - """ - progress = self.progress - verbose = self.verbose - while True: - s = stream.readline() - if not s: - break - if progress is not None: - progress(s, context) - else: - if not verbose: - sys.stderr.write('.') - else: - sys.stderr.write(s.decode('utf-8')) - sys.stderr.flush() - stream.close() - - def run_command(self, cmd, **kwargs): - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, **kwargs) - t1 = threading.Thread(target=self.reader, args=(p.stdout, 'stdout')) - t1.start() - t2 = threading.Thread(target=self.reader, args=(p.stderr, 'stderr')) - t2.start() - p.wait() - t1.join() - t2.join() - if self.progress is not None: - self.progress('done.', 'main') - elif self.verbose: - sys.stderr.write('done.\n') - return p diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/version.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/version.py deleted file mode 100644 index d9c438a..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/version.py +++ /dev/null @@ -1,742 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012-2014 The Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -""" -Implementation of a flexible versioning scheme providing support for PEP-386, -distribute-compatible and semantic versioning. -""" - -import logging -import re - -from .compat import string_types - -__all__ = ['NormalizedVersion', 'NormalizedMatcher', - 'LegacyVersion', 'LegacyMatcher', - 'SemanticVersion', 'SemanticMatcher', - 'UnsupportedVersionError', 'get_scheme'] - -logger = logging.getLogger(__name__) - - -class UnsupportedVersionError(ValueError): - """This is an unsupported version.""" - pass - - -class Version(object): - def __init__(self, s): - self._string = s = s.strip() - self._parts = parts = self.parse(s) - assert isinstance(parts, tuple) - assert len(parts) > 0 - - def parse(self, s): - raise NotImplementedError('please implement in a subclass') - - def _check_compatible(self, other): - if type(self) != type(other): - raise TypeError('cannot compare %r and %r' % (self, other)) - - def __eq__(self, other): - self._check_compatible(other) - return self._parts == other._parts - - def __ne__(self, other): - return not self.__eq__(other) - - def __lt__(self, other): - self._check_compatible(other) - return self._parts < other._parts - - def __gt__(self, other): - return not (self.__lt__(other) or self.__eq__(other)) - - def __le__(self, other): - return self.__lt__(other) or self.__eq__(other) - - def __ge__(self, other): - return self.__gt__(other) or self.__eq__(other) - - # See http://docs.python.org/reference/datamodel#object.__hash__ - def __hash__(self): - return hash(self._parts) - - def __repr__(self): - return "%s('%s')" % (self.__class__.__name__, self._string) - - def __str__(self): - return self._string - - @property - def is_prerelease(self): - raise NotImplementedError('Please implement in subclasses.') - - -class Matcher(object): - version_class = None - - dist_re = re.compile(r"^(\w[\s\w'.-]*)(\((.*)\))?") - comp_re = re.compile(r'^(<=|>=|<|>|!=|={2,3}|~=)?\s*([^\s,]+)$') - num_re = re.compile(r'^\d+(\.\d+)*$') - - # value is either a callable or the name of a method - _operators = { - '<': lambda v, c, p: v < c, - '>': lambda v, c, p: v > c, - '<=': lambda v, c, p: v == c or v < c, - '>=': lambda v, c, p: v == c or v > c, - '==': lambda v, c, p: v == c, - '===': lambda v, c, p: v == c, - # by default, compatible => >=. - '~=': lambda v, c, p: v == c or v > c, - '!=': lambda v, c, p: v != c, - } - - def __init__(self, s): - if self.version_class is None: - raise ValueError('Please specify a version class') - self._string = s = s.strip() - m = self.dist_re.match(s) - if not m: - raise ValueError('Not valid: %r' % s) - groups = m.groups('') - self.name = groups[0].strip() - self.key = self.name.lower() # for case-insensitive comparisons - clist = [] - if groups[2]: - constraints = [c.strip() for c in groups[2].split(',')] - for c in constraints: - m = self.comp_re.match(c) - if not m: - raise ValueError('Invalid %r in %r' % (c, s)) - groups = m.groups() - op = groups[0] or '~=' - s = groups[1] - if s.endswith('.*'): - if op not in ('==', '!='): - raise ValueError('\'.*\' not allowed for ' - '%r constraints' % op) - # Could be a partial version (e.g. for '2.*') which - # won't parse as a version, so keep it as a string - vn, prefix = s[:-2], True - if not self.num_re.match(vn): - # Just to check that vn is a valid version - self.version_class(vn) - else: - # Should parse as a version, so we can create an - # instance for the comparison - vn, prefix = self.version_class(s), False - clist.append((op, vn, prefix)) - self._parts = tuple(clist) - - def match(self, version): - """ - Check if the provided version matches the constraints. - - :param version: The version to match against this instance. - :type version: Strring or :class:`Version` instance. - """ - if isinstance(version, string_types): - version = self.version_class(version) - for operator, constraint, prefix in self._parts: - f = self._operators.get(operator) - if isinstance(f, string_types): - f = getattr(self, f) - if not f: - msg = ('%r not implemented ' - 'for %s' % (operator, self.__class__.__name__)) - raise NotImplementedError(msg) - if not f(version, constraint, prefix): - return False - return True - - @property - def exact_version(self): - result = None - if len(self._parts) == 1 and self._parts[0][0] in ('==', '==='): - result = self._parts[0][1] - return result - - def _check_compatible(self, other): - if type(self) != type(other) or self.name != other.name: - raise TypeError('cannot compare %s and %s' % (self, other)) - - def __eq__(self, other): - self._check_compatible(other) - return self.key == other.key and self._parts == other._parts - - def __ne__(self, other): - return not self.__eq__(other) - - # See http://docs.python.org/reference/datamodel#object.__hash__ - def __hash__(self): - return hash(self.key) + hash(self._parts) - - def __repr__(self): - return "%s(%r)" % (self.__class__.__name__, self._string) - - def __str__(self): - return self._string - - -PEP440_VERSION_RE = re.compile(r'^v?(\d+!)?(\d+(\.\d+)*)((a|b|c|rc)(\d+))?' - r'(\.(post)(\d+))?(\.(dev)(\d+))?' - r'(\+([a-zA-Z\d]+(\.[a-zA-Z\d]+)?))?$') - - -def _pep_440_key(s): - s = s.strip() - m = PEP440_VERSION_RE.match(s) - if not m: - raise UnsupportedVersionError('Not a valid version: %s' % s) - groups = m.groups() - nums = tuple(int(v) for v in groups[1].split('.')) - while len(nums) > 1 and nums[-1] == 0: - nums = nums[:-1] - - if not groups[0]: - epoch = 0 - else: - epoch = int(groups[0]) - pre = groups[4:6] - post = groups[7:9] - dev = groups[10:12] - local = groups[13] - if pre == (None, None): - pre = () - else: - pre = pre[0], int(pre[1]) - if post == (None, None): - post = () - else: - post = post[0], int(post[1]) - if dev == (None, None): - dev = () - else: - dev = dev[0], int(dev[1]) - if local is None: - local = () - else: - parts = [] - for part in local.split('.'): - # to ensure that numeric compares as > lexicographic, avoid - # comparing them directly, but encode a tuple which ensures - # correct sorting - if part.isdigit(): - part = (1, int(part)) - else: - part = (0, part) - parts.append(part) - local = tuple(parts) - if not pre: - # either before pre-release, or final release and after - if not post and dev: - # before pre-release - pre = ('a', -1) # to sort before a0 - else: - pre = ('z',) # to sort after all pre-releases - # now look at the state of post and dev. - if not post: - post = ('_',) # sort before 'a' - if not dev: - dev = ('final',) - - #print('%s -> %s' % (s, m.groups())) - return epoch, nums, pre, post, dev, local - - -_normalized_key = _pep_440_key - - -class NormalizedVersion(Version): - """A rational version. - - Good: - 1.2 # equivalent to "1.2.0" - 1.2.0 - 1.2a1 - 1.2.3a2 - 1.2.3b1 - 1.2.3c1 - 1.2.3.4 - TODO: fill this out - - Bad: - 1 # mininum two numbers - 1.2a # release level must have a release serial - 1.2.3b - """ - def parse(self, s): - result = _normalized_key(s) - # _normalized_key loses trailing zeroes in the release - # clause, since that's needed to ensure that X.Y == X.Y.0 == X.Y.0.0 - # However, PEP 440 prefix matching needs it: for example, - # (~= 1.4.5.0) matches differently to (~= 1.4.5.0.0). - m = PEP440_VERSION_RE.match(s) # must succeed - groups = m.groups() - self._release_clause = tuple(int(v) for v in groups[1].split('.')) - return result - - PREREL_TAGS = set(['a', 'b', 'c', 'rc', 'dev']) - - @property - def is_prerelease(self): - return any(t[0] in self.PREREL_TAGS for t in self._parts if t) - - -def _match_prefix(x, y): - x = str(x) - y = str(y) - if x == y: - return True - if not x.startswith(y): - return False - n = len(y) - return x[n] == '.' - - -class NormalizedMatcher(Matcher): - version_class = NormalizedVersion - - # value is either a callable or the name of a method - _operators = { - '~=': '_match_compatible', - '<': '_match_lt', - '>': '_match_gt', - '<=': '_match_le', - '>=': '_match_ge', - '==': '_match_eq', - '===': '_match_arbitrary', - '!=': '_match_ne', - } - - def _adjust_local(self, version, constraint, prefix): - if prefix: - strip_local = '+' not in constraint and version._parts[-1] - else: - # both constraint and version are - # NormalizedVersion instances. - # If constraint does not have a local component, - # ensure the version doesn't, either. - strip_local = not constraint._parts[-1] and version._parts[-1] - if strip_local: - s = version._string.split('+', 1)[0] - version = self.version_class(s) - return version, constraint - - def _match_lt(self, version, constraint, prefix): - version, constraint = self._adjust_local(version, constraint, prefix) - if version >= constraint: - return False - release_clause = constraint._release_clause - pfx = '.'.join([str(i) for i in release_clause]) - return not _match_prefix(version, pfx) - - def _match_gt(self, version, constraint, prefix): - version, constraint = self._adjust_local(version, constraint, prefix) - if version <= constraint: - return False - release_clause = constraint._release_clause - pfx = '.'.join([str(i) for i in release_clause]) - return not _match_prefix(version, pfx) - - def _match_le(self, version, constraint, prefix): - version, constraint = self._adjust_local(version, constraint, prefix) - return version <= constraint - - def _match_ge(self, version, constraint, prefix): - version, constraint = self._adjust_local(version, constraint, prefix) - return version >= constraint - - def _match_eq(self, version, constraint, prefix): - version, constraint = self._adjust_local(version, constraint, prefix) - if not prefix: - result = (version == constraint) - else: - result = _match_prefix(version, constraint) - return result - - def _match_arbitrary(self, version, constraint, prefix): - return str(version) == str(constraint) - - def _match_ne(self, version, constraint, prefix): - version, constraint = self._adjust_local(version, constraint, prefix) - if not prefix: - result = (version != constraint) - else: - result = not _match_prefix(version, constraint) - return result - - def _match_compatible(self, version, constraint, prefix): - version, constraint = self._adjust_local(version, constraint, prefix) - if version == constraint: - return True - if version < constraint: - return False -# if not prefix: -# return True - release_clause = constraint._release_clause - if len(release_clause) > 1: - release_clause = release_clause[:-1] - pfx = '.'.join([str(i) for i in release_clause]) - return _match_prefix(version, pfx) - -_REPLACEMENTS = ( - (re.compile('[.+-]$'), ''), # remove trailing puncts - (re.compile(r'^[.](\d)'), r'0.\1'), # .N -> 0.N at start - (re.compile('^[.-]'), ''), # remove leading puncts - (re.compile(r'^\((.*)\)$'), r'\1'), # remove parentheses - (re.compile(r'^v(ersion)?\s*(\d+)'), r'\2'), # remove leading v(ersion) - (re.compile(r'^r(ev)?\s*(\d+)'), r'\2'), # remove leading v(ersion) - (re.compile('[.]{2,}'), '.'), # multiple runs of '.' - (re.compile(r'\b(alfa|apha)\b'), 'alpha'), # misspelt alpha - (re.compile(r'\b(pre-alpha|prealpha)\b'), - 'pre.alpha'), # standardise - (re.compile(r'\(beta\)$'), 'beta'), # remove parentheses -) - -_SUFFIX_REPLACEMENTS = ( - (re.compile('^[:~._+-]+'), ''), # remove leading puncts - (re.compile('[,*")([\]]'), ''), # remove unwanted chars - (re.compile('[~:+_ -]'), '.'), # replace illegal chars - (re.compile('[.]{2,}'), '.'), # multiple runs of '.' - (re.compile(r'\.$'), ''), # trailing '.' -) - -_NUMERIC_PREFIX = re.compile(r'(\d+(\.\d+)*)') - - -def _suggest_semantic_version(s): - """ - Try to suggest a semantic form for a version for which - _suggest_normalized_version couldn't come up with anything. - """ - result = s.strip().lower() - for pat, repl in _REPLACEMENTS: - result = pat.sub(repl, result) - if not result: - result = '0.0.0' - - # Now look for numeric prefix, and separate it out from - # the rest. - #import pdb; pdb.set_trace() - m = _NUMERIC_PREFIX.match(result) - if not m: - prefix = '0.0.0' - suffix = result - else: - prefix = m.groups()[0].split('.') - prefix = [int(i) for i in prefix] - while len(prefix) < 3: - prefix.append(0) - if len(prefix) == 3: - suffix = result[m.end():] - else: - suffix = '.'.join([str(i) for i in prefix[3:]]) + result[m.end():] - prefix = prefix[:3] - prefix = '.'.join([str(i) for i in prefix]) - suffix = suffix.strip() - if suffix: - #import pdb; pdb.set_trace() - # massage the suffix. - for pat, repl in _SUFFIX_REPLACEMENTS: - suffix = pat.sub(repl, suffix) - - if not suffix: - result = prefix - else: - sep = '-' if 'dev' in suffix else '+' - result = prefix + sep + suffix - if not is_semver(result): - result = None - return result - - -def _suggest_normalized_version(s): - """Suggest a normalized version close to the given version string. - - If you have a version string that isn't rational (i.e. NormalizedVersion - doesn't like it) then you might be able to get an equivalent (or close) - rational version from this function. - - This does a number of simple normalizations to the given string, based - on observation of versions currently in use on PyPI. Given a dump of - those version during PyCon 2009, 4287 of them: - - 2312 (53.93%) match NormalizedVersion without change - with the automatic suggestion - - 3474 (81.04%) match when using this suggestion method - - @param s {str} An irrational version string. - @returns A rational version string, or None, if couldn't determine one. - """ - try: - _normalized_key(s) - return s # already rational - except UnsupportedVersionError: - pass - - rs = s.lower() - - # part of this could use maketrans - for orig, repl in (('-alpha', 'a'), ('-beta', 'b'), ('alpha', 'a'), - ('beta', 'b'), ('rc', 'c'), ('-final', ''), - ('-pre', 'c'), - ('-release', ''), ('.release', ''), ('-stable', ''), - ('+', '.'), ('_', '.'), (' ', ''), ('.final', ''), - ('final', '')): - rs = rs.replace(orig, repl) - - # if something ends with dev or pre, we add a 0 - rs = re.sub(r"pre$", r"pre0", rs) - rs = re.sub(r"dev$", r"dev0", rs) - - # if we have something like "b-2" or "a.2" at the end of the - # version, that is pobably beta, alpha, etc - # let's remove the dash or dot - rs = re.sub(r"([abc]|rc)[\-\.](\d+)$", r"\1\2", rs) - - # 1.0-dev-r371 -> 1.0.dev371 - # 0.1-dev-r79 -> 0.1.dev79 - rs = re.sub(r"[\-\.](dev)[\-\.]?r?(\d+)$", r".\1\2", rs) - - # Clean: 2.0.a.3, 2.0.b1, 0.9.0~c1 - rs = re.sub(r"[.~]?([abc])\.?", r"\1", rs) - - # Clean: v0.3, v1.0 - if rs.startswith('v'): - rs = rs[1:] - - # Clean leading '0's on numbers. - #TODO: unintended side-effect on, e.g., "2003.05.09" - # PyPI stats: 77 (~2%) better - rs = re.sub(r"\b0+(\d+)(?!\d)", r"\1", rs) - - # Clean a/b/c with no version. E.g. "1.0a" -> "1.0a0". Setuptools infers - # zero. - # PyPI stats: 245 (7.56%) better - rs = re.sub(r"(\d+[abc])$", r"\g<1>0", rs) - - # the 'dev-rNNN' tag is a dev tag - rs = re.sub(r"\.?(dev-r|dev\.r)\.?(\d+)$", r".dev\2", rs) - - # clean the - when used as a pre delimiter - rs = re.sub(r"-(a|b|c)(\d+)$", r"\1\2", rs) - - # a terminal "dev" or "devel" can be changed into ".dev0" - rs = re.sub(r"[\.\-](dev|devel)$", r".dev0", rs) - - # a terminal "dev" can be changed into ".dev0" - rs = re.sub(r"(?![\.\-])dev$", r".dev0", rs) - - # a terminal "final" or "stable" can be removed - rs = re.sub(r"(final|stable)$", "", rs) - - # The 'r' and the '-' tags are post release tags - # 0.4a1.r10 -> 0.4a1.post10 - # 0.9.33-17222 -> 0.9.33.post17222 - # 0.9.33-r17222 -> 0.9.33.post17222 - rs = re.sub(r"\.?(r|-|-r)\.?(\d+)$", r".post\2", rs) - - # Clean 'r' instead of 'dev' usage: - # 0.9.33+r17222 -> 0.9.33.dev17222 - # 1.0dev123 -> 1.0.dev123 - # 1.0.git123 -> 1.0.dev123 - # 1.0.bzr123 -> 1.0.dev123 - # 0.1a0dev.123 -> 0.1a0.dev123 - # PyPI stats: ~150 (~4%) better - rs = re.sub(r"\.?(dev|git|bzr)\.?(\d+)$", r".dev\2", rs) - - # Clean '.pre' (normalized from '-pre' above) instead of 'c' usage: - # 0.2.pre1 -> 0.2c1 - # 0.2-c1 -> 0.2c1 - # 1.0preview123 -> 1.0c123 - # PyPI stats: ~21 (0.62%) better - rs = re.sub(r"\.?(pre|preview|-c)(\d+)$", r"c\g<2>", rs) - - # Tcl/Tk uses "px" for their post release markers - rs = re.sub(r"p(\d+)$", r".post\1", rs) - - try: - _normalized_key(rs) - except UnsupportedVersionError: - rs = None - return rs - -# -# Legacy version processing (distribute-compatible) -# - -_VERSION_PART = re.compile(r'([a-z]+|\d+|[\.-])', re.I) -_VERSION_REPLACE = { - 'pre': 'c', - 'preview': 'c', - '-': 'final-', - 'rc': 'c', - 'dev': '@', - '': None, - '.': None, -} - - -def _legacy_key(s): - def get_parts(s): - result = [] - for p in _VERSION_PART.split(s.lower()): - p = _VERSION_REPLACE.get(p, p) - if p: - if '0' <= p[:1] <= '9': - p = p.zfill(8) - else: - p = '*' + p - result.append(p) - result.append('*final') - return result - - result = [] - for p in get_parts(s): - if p.startswith('*'): - if p < '*final': - while result and result[-1] == '*final-': - result.pop() - while result and result[-1] == '00000000': - result.pop() - result.append(p) - return tuple(result) - - -class LegacyVersion(Version): - def parse(self, s): - return _legacy_key(s) - - @property - def is_prerelease(self): - result = False - for x in self._parts: - if (isinstance(x, string_types) and x.startswith('*') and - x < '*final'): - result = True - break - return result - - -class LegacyMatcher(Matcher): - version_class = LegacyVersion - - _operators = dict(Matcher._operators) - _operators['~='] = '_match_compatible' - - numeric_re = re.compile('^(\d+(\.\d+)*)') - - def _match_compatible(self, version, constraint, prefix): - if version < constraint: - return False - m = self.numeric_re.match(str(constraint)) - if not m: - logger.warning('Cannot compute compatible match for version %s ' - ' and constraint %s', version, constraint) - return True - s = m.groups()[0] - if '.' in s: - s = s.rsplit('.', 1)[0] - return _match_prefix(version, s) - -# -# Semantic versioning -# - -_SEMVER_RE = re.compile(r'^(\d+)\.(\d+)\.(\d+)' - r'(-[a-z0-9]+(\.[a-z0-9-]+)*)?' - r'(\+[a-z0-9]+(\.[a-z0-9-]+)*)?$', re.I) - - -def is_semver(s): - return _SEMVER_RE.match(s) - - -def _semantic_key(s): - def make_tuple(s, absent): - if s is None: - result = (absent,) - else: - parts = s[1:].split('.') - # We can't compare ints and strings on Python 3, so fudge it - # by zero-filling numeric values so simulate a numeric comparison - result = tuple([p.zfill(8) if p.isdigit() else p for p in parts]) - return result - - m = is_semver(s) - if not m: - raise UnsupportedVersionError(s) - groups = m.groups() - major, minor, patch = [int(i) for i in groups[:3]] - # choose the '|' and '*' so that versions sort correctly - pre, build = make_tuple(groups[3], '|'), make_tuple(groups[5], '*') - return (major, minor, patch), pre, build - - -class SemanticVersion(Version): - def parse(self, s): - return _semantic_key(s) - - @property - def is_prerelease(self): - return self._parts[1][0] != '|' - - -class SemanticMatcher(Matcher): - version_class = SemanticVersion - - -class VersionScheme(object): - def __init__(self, key, matcher, suggester=None): - self.key = key - self.matcher = matcher - self.suggester = suggester - - def is_valid_version(self, s): - try: - self.matcher.version_class(s) - result = True - except UnsupportedVersionError: - result = False - return result - - def is_valid_matcher(self, s): - try: - self.matcher(s) - result = True - except UnsupportedVersionError: - result = False - return result - - def is_valid_constraint_list(self, s): - """ - Used for processing some metadata fields - """ - return self.is_valid_matcher('dummy_name (%s)' % s) - - def suggest(self, s): - if self.suggester is None: - result = None - else: - result = self.suggester(s) - return result - -_SCHEMES = { - 'normalized': VersionScheme(_normalized_key, NormalizedMatcher, - _suggest_normalized_version), - 'legacy': VersionScheme(_legacy_key, LegacyMatcher, lambda self, s: s), - 'semantic': VersionScheme(_semantic_key, SemanticMatcher, - _suggest_semantic_version), -} - -_SCHEMES['default'] = _SCHEMES['normalized'] - - -def get_scheme(name): - if name not in _SCHEMES: - raise ValueError('unknown scheme name: %r' % name) - return _SCHEMES[name] diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/w32.exe b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/w32.exe deleted file mode 100644 index f27573a1eac23fc0ddbc2e056e3c099d32da1681..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85504 zcmeFae|%I$mN$I+N0LtH*BqZg>PMaYv}HE1#9c?y{rEApA_72`#tyED;4~&I}7UNdkXHpr=a}i>Vlu# zyZX*6v$L}blc@KMTJzh}Ve9$SZ&l&{KL0ho*_mg~|CPUgeSUzypFaO7?Z{$_U=_Sg9FX!+X8s;}QKazPp9NtK1qv*} zlYR>P&A&#A@PtDUwzmtyq`yfT`8ngGziFE`L8vrI8woZPzEZk#qlB*s&*DLJQC+FA zNBk=ggjHA8ufAQnT@Wt490_gs&BSjPek1;QQS_B2n9zMC5_<6?oTu;`@y`nkSJtnq zzXNf+uBfwc3qE>A03qlleD!y(xfg)xIfwucIKH_TRtRv{BlZ9P_x}P1mS{bJQ1KtV zf{|C=<`uNw9a8o@A<`y~kMv8|gytY6VB~p`w9`zGCWQ8m5`?f2atRh8uW zh>x~~wxLd{+~a4rQM9k8$k!K6Ly19Tdd#GOie^)w7(tD4aAuL*T_krEoxb1d?hiv8 zP_b!dQK(Z5yBGy=^qmvi&YTGC0)9U`f1dLtT0YlUu}sgY(_AkdK|-Bpw3JcliLLuW zx2e8fLe&OTny)vwk~eKY>oxLn(d5ddLf9I%pgc&6!*Ap*Bsu7f^vg~oZw>(@(q&79 z)@jNbm#r~7)^g#MGQ$FLOahd<&1*JzccQ6>^pq)%2i4}n6ZnE?ptamaO^sS!ILXMH zMTMM*mKVDG;k9^e^oKL6jl7wNhGaRFO@*$tavG58R(D(IJzmu@sA|);!WQbC#extF z@|=>H(}A3!J`VT!0K}+#MF41L)%aPxhXgiPl?rEQC9?q*?l<1|BXKqBL(9bMg}En* zlg}d?aDHPZhS&#YVlhwrCo{3nOkBfWHWL@}#QV)eOX&46ULjUqxEvi8{k#%op_qIs zYo@=ZrUs2zV@M#%$a5hL!Q4=YWB3s;Xn;b;LTvs{VlUWHU_yakexlnz8p8P|Ui5DM zS%}ZjHjbtjJv|siw9D+yN6?2CgYR0Ix7{nevI{`fXk>kQw88;BA?^|C!0o9@VwyA| z?C`Tw5dB~fO34YZ0pkNM2JgDtBK;)Luktdsp$v#?Q0a8kDc4O4$``xa>Xf1ss;Q~D^JWXk{2N(OUJz z@I2jTsTJzfW|=YtgVEjet}A_oL*R3s`>cr8jfVCa!ltOKzc&w;TkT4{yWv&HH>@5=o}?Z*;Yuf_}bPJ$Xa1>_oU z!S5t$hcqrQQ9sb-16|}K&>c9IupP2RDPK)gy2=q?&tME4YS_?GkmP3@6BuH+5E)!d zjNMc*V>hph{UZ$Rff{xO!-;aRxQ4xt);z)rQR^d~Y#Ov>>*kknztR7I%L;4Pk2d+RhtHI1uIp|V--7z1H z!UjW=LZNrF$C1B-#@fRoq^LtPXp*DJ4vZaR8OuX`#;s6`**1ia-A<}g^~mdy$Zc% zxOco+g#gQ&3_^MX z?EOiC5MVwqF~DBo;eX}NUm;6?HRB24TQOW~)Ix;va%nk{!;;lFrgYjpva`M?RVAhD z)RcLGAdL^vn=QKp1%k*dP7g%|*(1|1NeiJ4AwM2$2a!wa_|`y8=ofPk;{w3mN~G;y zh(}OMcskdKS_aTqjiXA;?isBAN-682a#pU8CWa`)zCtD{$r+}R9_*r6Vqv%-Mye9Sd|MA_I=h*C3* zcTId0l|oTkdrD3#^_`G%2v6-%)pvqp)oPFG&&GV+Yruo1hVG4cts4!2)Tq&k5x#D_ z{%OqDwTT0CH6{VNh5@=bfGN%esEpF!66DKbyw*_8#E#mFzz&j{edwu_E;$gpfMPq? zZy*+C(}Srr&t$(t*Fd*PN*iMNEcCHdEX}aO0#nWJ4tyel{X_DT%RKw=66zlgHjNrA zWPl9zJBYv$o=Ouh=?WyHxDp`?EY4dF&O)YSREF z;ONj!!hZ#a!P*zjR#>pDcQ9S-3Afz4->iyWNC?rAzvDHt|(2j1BaAd%@h(i zRNxtO|Cca3g|7HLf6>sd=T@`-MF8xd5f>A%?0{e{tL-?#|6#V|tOmumXtx$R+$UR? z7dp=zumMII*P5jquw4D7RIf0LbhQ~Pf37fl{g@iD=fwvXxMvVE*iT#0Fel#|Ng zMGpDvWgP_jUs{&?&DV^ zerRR%dSh8f^!mY-^gPd>19J(0&)OpFYM$Feo)&b01n*RufCV`}K zt-=n5mx(Q3BUU@-IZ=;gpQm9!eCQQK)EL*$oKa4&hkhssmuVulaK0uTl?ez^t2wC9@~bLm6NgyA-2ZOh8{0;y)#*Ma}{( zR@4C&%dU8{8ROD>!p=}JY0(=2?(SFR?o!z${jgNdl`b!p^W`fzb`jXIpmQ*?=MeJ4 z819n|xduUZ8@n0#F`DKx2h3AJm3WzdfwX);dI$@d;ei-43L1!Yo~@j+nW8q74NC@; zc^m4Aj7c$D49*HdU8&C@W8^*Dv6ogW^tsL@?(sRa>|6Vx`S;l8>61xkge_5@15YDw zwW)4w7t_jtepSv(+LJm$>2X#=Xwefr=THSbd#H8~BM7;R--%K%3o5??B=@3viPDvJ ztm0SN!Q#dd?La2kQMAAwpN^20q227zP85Bp*7o%uut{^Y z_uIcs({dku0?Q@k)2Z#BruUa$ZEuvuX~#TA*SWOb#%r@=%lzv-@7I5WJR}eDM6DxE zqgwOvjbF0)Lv+R;LR|j>r$uajftPNN9G4vzFX@XvMW3|^O->ZG+YYp!OG8P~Nsm*R zm|bZ$UTQH)y`PV+=m4|K9tW|N3$z6ebZXlnJ+pCkmTWV84zH)Z{`8pzPN4vkF)xW6 z?=^-gb&h(_P0AE$C-Ar-$*uX0s1Kl?k_L4+a*GY*%E|b z^Yz($11nZy(FB?FlT5w{t%*ss&w)816m1^61rbTH`vxm7Drp9Z$RiLXKK9ec<&bTd zJ-##F`wwL1^SuuV+7vaK?`ajzrxn@72&0Ld@ZP0#eTiYyqEYKv^a=C=DCO4k5j^l?vHq%luBq?~7{nsP?0BA-}bYRdo{RfIDA>;(Fc`!ISC zdbs##dvuKSOX-OfT=Ra4OR50Q&;e2ebtH z5aJ$Svo9AgT4!?6ckzaQ$I!=U6_cQ5NBLPARuxL!B+ymo6lh4~72Qr1{RnuKs%|Wp z_;fqfy3%mT7ZC)in~kEqQZ`3{Df{P$?g+4_FjAV;Wphx`k&R6{MSl-y1MF*pGApQ* zO)|WKMNVV0FkK^#HDGKuNB+nAXygZROGCSexOpfe>iZ?;;cKBW-2J5`hcF|QM+IOo zgXMA!BKKC^Mmh&&c?BsAI#a)9#~g&4_EHS(A;_P2qyPij!#wrEclyzT53HLj~6Irw$kVamp z4c69!pp89Qf@y9pYREpGm4tGzy9kOcy*e3@$pRD+wy-Ox!k$hk!_Ve(m_MKi`+Wy3 zQaY64A>9_vf+->pqPnoLUt@La>nfGI<#azg{0-Jmy?E$X!X&6Uv`n??6s)Q@KxG8M z>pPj|I|Xp1p<5vM-x2&fcqG?eny-spiuG3qYXQk|nojb`MN`iVG}g`;0+dpAAwBa7 z=s9^3JxlWGS(b}u-L^b0e`U|&ugNa{N^|npbO(Q3VaMy&KTVsBm*x|8&g5_V&SJbV z8tj}y-+Z+kOWR0tf&X?;;?9})ilr6cnQ0f=VrhjuHEFz2BPTFP+~Mf;3g%MW$ZMn~ zSPLMqbunrbgg(sMgvii)?O0aiZA4HhBLIv8#Cn1W5pL6Z2_cgJf>F!`tQ|Yr(3*j8 z?g~gi2G^i^x~H=tL+jj0DPg;x%_a=NoloX)>-&_jJ)o9Q8k>4SLRxsj(iIr%Un0DE z+75zOomQp2faZZ`w}0&wHhmr*TmgszK-6dl+7oG-Jwn5R_O0^S)b`KPHG2llLmUtl z%$#JadKI!?-*mPS88*GW66X63RyPydF=e!}LPuaFpus4ivRDQQ*|2uu_4D-BPiq=n zi?TON(B3XO)P6QiX?HDV8dOr#BB#)Zs_9uuX92odGuV<^0bqPk61ffIls1>2tpG3# zY)zFWJZ1&Z%54SUBxOlX5|D$}9AnkgGG1VQ(<-O2#W0H6QBjU)4*EH|y_vUVMBXY4 zNKWN!Zo}AQ9!_NT-vP(8cSkPlY3}3I7)+pX2h=5f>XL-Iq*u3*RZ5v#Ad#&}N!%_K zD~WpP5+$)gx`=Is`bg^8%Mf(8#c#I?!YdYZ1U=h*QmGoS=$Wr%LW>}1HO-6e!}DtD zJO{+)_Yobvf6L1P7#}$-Hc!I0xTj4?REt0TM*)qoMPUVEb3cL#8ztRRDa}_{zI27c zvZRZ#J`f{2kfYR>5F#0VMamCp2G zAhckaEOP@RWl0NlBS(P!*^|s7!}gm6GBEDz^I+EO<;fi*lUYOW$VYl0cgv5@ZJ}J})hG0?=^^uVq7R|u5L`E*gTrxxzU{PSC zm0Qt^u~w*bYE@2kqg|b?Zgi*{C#jV#zTgVGLPtMFtph;mKFLjWP)>F}ajzYqRX~@A zYZWp22DrhsN7TNnG+$b#37VItOO?+M+vR!Dit|dswP8%O0)11!o)}idV)G-ZT*jm(eu$0^nCn1dhR|- z&wWSmtlRczg1@3Y{Pp-D{)!yruczAh>pxz_>(@Vx^x~!Y?9nQ_8YRdAUxX1a5Vo?{sVg4DQj+i8B}c!c5z;6j)*5+akb^YaYK^YHT|#nm zlDo}M|5yyuBMAOb%V0Cs{uT{v(%5;**(>V5idOzrIXikoPB?oh8qEIIBS@?5NGnIa za8A&3XkyzX?Mj=Ywu9wkN`k7S?@gS>D2%ucmX?YdFr%Ewv5fs0*|8*AtUB0(2nMln z`YPUPF-9xXwnNX*_8)qM)v$DtIANPmT~p|a;#bs#-5)M7S7Ar_b-#KigJA$FG&w=S zZY@mNt9Meq4y~$pwTdMkn7R`ER{O8o#i=4pn_5pkH@9f(9PSb_e%EN}ojwCoC}nGl?6!B@&e^Prf%HXAt-@h`m(jP+(eJg_nR*yaA6>%K>H%#T1~R5r^(f~C zrIpbegs6R)ws321w0tWp>Af13jtQ8FbF~i`6@@}Ak+zNAEekYXLOX#{<+mFf3_&W? zFzk&a;f>Es5(1orYuU^6?dvmZ*FmNm{L>GE!A+%itouoqe3?@A1m+WhR1l&!`wJFv z%0aT^h}sfNsctdyC|)^;b*d9F>=Dp|@w;@XQyRl}1ZuQ*wL|Qm%xG9sNGtvgRkQwv zszOdxuU6?m1usWV+AlRqtDR!=%?KpXzRBhxDLx)CM`)Mw);PK(nR#}oE@3ahNp6(q zK!x0gSjDFXwmL%j##*Pb)@7{CWphylbjw-}gKDVOy%-q;_)siFrpt``CK>nT8~4p% zc}c(nc40}Nrds=)w(Z=<-TiP`Cb}Zzol(tV*%}goh+S9c4rut$e;nUvw%^?TznRwErLNTSEI8y!KG7RfR5=u z3Fos+Ecj@PiJ4ip!vUr>y`+P%?*tN^16k`YBqx2j!+jGdIWb+c@>mlyw zCjKsn-bZIJh~yrif@$v;-9J{bd?`4u)H$$ozChiat8QM~x%Cj3JHK=5O^|~5v5JuE zEDR0VY&kKM_pJ3HBX1WFq#9!`;KNSlApmTXV;EE`)=-z-;Xqb|jrD8T*XVph8i1OQ zJpyt%P%P*G`a%$jJ!L1G$OEK@&7C=;glY)$-$5D;k8*Y`3guc+riDFGD3D=12;1bf zU>fH|$&nHKL0ja*ON%8)NMXI&3%Zp>c0)~vLm)fx7sR^zQPK;DUrC%s!E6f(;^jEP zF7{6ZLn&b6#xAh&7qDJ|X1Mn>Cr}Tqq7a3^s-q zuWIwF-2C#HUzO(9kIb*-WzsX!Qbs@mHyRc0pq{mpQg%>p zh^0}+BiBG0xpeTnW{2FF>^Wj{yCA@fM0xzi`?Q?gg$OqFV+cbDW!Fk*yfEH3VUole zCO(r`vuo}&iRERm=OE;0$~&|&Ql_EkY+&Hnj1P>XJ5#;7JSERZFCLQT;tS;&;J`DH zWO*iavleoqfJp^DmI(YfdX zyOOZi%hl{I4`NQ>JLoyFu5zz{)j0y#PqcM-I_gDiC=Rgoppv^-jEl~9A$Bg0U6qWL ze%NkU{n1%_lLIU{JU}sOWt@E|o`9 zG+9Kjd(gaRPLOYCu#$9sU~kt)@D!m(&G&kWV46ozjG*Z8-$B85)7UeE6g01j`VfWT zaiSPA>ObX(XfjvjNLuzSWK01O^XAyvn`U!^{+BS7nkN0qeDRS3+JTYFJ=4blJk%=Z z*ba$%=H*rg#69<=yN}mI%N?}4JyC0LYL!mU+4@Y(`fVS=gCy&ErELcG_TYfVC&I(4 z$0H`b@L;G7Y&F-CJHR@@uk?^3YH|UYzyfk;wTP7@lnDWaxZ(bCu+v;9-3q#{;2RTW zil3)AAjH>d-okb^^~_PF%aR;JMy@&ek`wk-82a7En`pbEjn{m{R1P~hBNnO23^XyO z1c%4@deP< zD?eYFBuReC*iBVN+`kOP{Ve1vfD`?8WT;`2W^+(|MK%44-w#%W`;5HVpqNyNgk_K+ z&2zW4Iv2ETOLG8MUFoC+lEYg@OZ9pNKTImXAB|9&zoqsZoBJd1FcpE`-bT1!##upj zoQqD79S5v`2ecFGr96BbpbxNpYLe~pxDauiO$SbMX)_Ta>rM0>}hh4J%f-sTlZ`EHA%onOu$Zf`eS}PD38bH zx&fDe=x!$>8x2uQoAgs zCJM0aSZ%95n7y3AryoR#*&JmiDos8y)S^EGcb~>KGy7Ukm8Sot+I=-S3_8>ZH z2r-UoKa}oZ&tSk(E9{8v_pY^K&0V?Hib5=UmgWFvubmQcrh~8IFx>q84m|bqlrXac zWamM1ze?O5>cErGf%91cY02gJuaaPo04&*8(NWP)o6rr6>(*ytU5>yOJw0l_4*h$m zV?z}EBl~gyeffIo%UQfH8@{eocdo_k+w9KY)7QO2iM+47cwetm%Qp}Hoz6aInD&oh zm_Zf)o6i1Q)M{jBH;^OQ*)=4wFY*07oqg0lp|k&NxU=8DI;kjh_FDETLg?(b^3Kiy zLjWWJ>X)h?QJa!`o z8b|d06}H;=w+L}J99;U7)~)mfRNGhgZP5ZA~rvW031>tlotoswFF6Bs5ro`G{b{ZA?7X@ z;{$ulf#@8*o6bh#8yz!9oiZc1GT9?rz4pQf=R7E9(8hNGCM=t|yO5km)ws}$2&1Q# zV=S_ZFIwiQIeIQll9etOHnB6I2I}nOD3jVMS9&ICOSqN~4=z=GJ?fHfXrGB}Cb*;& z2y8UoF@ftobc6;>>7eF3r#Cq~C5_nnub;}SfKc-pgIUQ0WEz6hZ59Dq>qOOR$c4Y@T<;=5!$GZ^zd0c~}WcYn@U_ zYk6^@we4u4#WyJKZ>tR3gVOj)IY&Ei<|yf3<a#G>@0W z1)=-DU{$+DJ8%s97A|c3NQ4{tFd8FXc?u6 z(fOE1(=u86(yXu$tzwH&Ex(pw%t|-%4z z_X~|;GuabCt5s|!vkm4!S&g17IjzxQ*KLgj=d{{h^1|y-YcU(?^PCWsV<;FirdG?G z31ai_@G%ExeOheu=YhxZpHZT(uhMg9U4C?)g**gDDeYDyb=tCY8T{9OV)$I3*~hpe zrg0(Fa+YaW!pH&cFhROb%jgHGl~OKtkFunfI&IlnMr)PPvM@bOpYEycmD72`6KE&H zbPm0~jCv{>0PuFe&j&%JK9~4l1;kFz(=yDud#RFEJ+0LO;^Cp|>jfJusH7M!{|#8`I~7D zcsFOW7hn>K36~?Q{tq|`CEIN$bgw4%mtTb{O`qR#>s4t=!n!H5b*v_~+?q3ezLK!X zsjo}t7oE_@oH_9r_OvhtJ6LEAuNjuhMYX-h7>&!=@$bcadidNFc>}k}vr?Y(L9$6H zRXx~J>%}yh%v4*BA__}5C|5C}q4~j|xMIGwi?C4) zmrW%UG=I^&uH-BpgMKasee!O(ogd#F%WeXcc{uCKkHNK0y^?FpaahpQkA@2@^uB|s z6R7_<^%y!1EfXB<2PA56y(R7X3SigeFbiRt7Q}gxuk_!C$1P25;$tJ$NqeY~$& zN@MS|xlJC|^lc+h)aNK=8!=eI<1M~9fcd+2R{7Rmf7O`}l}~Jvv*=h$h7z+Vaf{rq z9cu4#*xKpk!s`v?&$jlsRZ2hoED&dzaGw(#3V^k+ywGlPM(J6I6E81d3t?@WR|tE< z1uFuqEE}8)qRX~pvkT%NT489|PIkea+?$(^;GP5Pu2I_3l*)5PUCe6;S!$&XfvG}P zr}tufxLYcJsFe`B(&ml&&oy;&!{Yn(Z&laSl~#Q!Hs|o(%{=X5vyFoJyvq*QI`$JJ z9Vh>2lU4hulnY_Qk6(KdxQIgbI2xObk8<=B-`5{%5$v#IE-^<5u1Lar)#`0w-GtHxt?4MXgVe>hfb4fV5ex! z#Oy<=f|t2G3M@McmVt^g?F?w*Rx zv^X#-9EvYtUtqwW|JcE{#ANn?Q>LC1G!l4gP)J&V9% z>7;JvE9Y$Dwh%%FZ*wE>2&$aaCy)%ipD&MTwj5x&i>VvqngJKfg}rrX@~2nfJ^+l( z=pCT+Js{ACQaW8o$FRs43?@4L%#K_^!a9*p{*q3jrcS|a3HHW<^GWY+S4j8-noK~3 zAx-xDDN~dE67Qk1>?@cZ;sKdIZ4p1Nol^Hj62 z@6%H%l1x3-O=!*DNRFL!Nl$cIw`qSAF9YY#nxFQwl!Rw5%!-EquK>wpu)P=i6!VQEqV{si?O2G}OF zF?A_^sA4J%27(vG=Hf^vrq%Grz6EeFm``k@_JZ;X=Y|TX4K|&`07FM`)rM2pox2Qb zj&=kuaP3o22zQSo*S^`(3JqogxaI{=jmUd|54w+EuPzxdJ?QMaV7=~dS8z0Fi9;Uk zXEzdM)D@-}7zf6eHaO&5Ozb7m&wiLpl5Lsr25%T(G{vsao88#0>*DCRTj0aI5IFtN zE`hkcjUTJO4+t1&II0k5Cc?rV`#^R$;C6qeayAAi}?ctF%FjoY~(< zQwj^FqBtEfsoz_UMFd>WoB$15uzP8vJV6{chMDjTnPDLQen>oqqU3y3OMsg&>sBN6 zyD}f_gwW%7ndGct>_cJ#`Uc-R0sCE{N@D+c#1D0WUHDK61okN2!(D)gyr2uHNw9l{ zz}RR6|0iAGF{;MMF5s+Ye*jZy>qQsYq#=yoC-VPD18G9jZ0@slxw6q^lM6L(ZdpOvKaQ93$}Xl?PT4ei zWt0it$LJ_V40-}v0x;o(CIx6`h8*YJZAk){f++*-{ff<3(=fDXIlQ~H_8J_Z#w5}i zeQ7%w=!w;T+0@QM?d$C3*=qEb49)Mr`6pO&ZRgvBHHxZS!(vb*V#8+MV#0N8F~r!t-_W>avHi2_k34DpphP z(KnYN&HQen?|aIyCNjUNef1S(aK<*jBlNwfESma$kiO@Z{WSGWD-Qk2vY)5ETj_gB z*=}nxKQan>PT33ejl)H&L5N_iUkxkx@u0eSH8cw+LuHhfoxsK& z7=8wu###xT7=e~a+n;z3=c3c+6l}oUM!FILT{vf&oCyQHfje!qv*L?we)h=C5D9S9 zQci`W{IxK!&06QsT zKpB)fdhG&C6>O&);iYuQ;3Tlt4)nO`M2(>Q0DI0yP-Vyv+CK;(DrEj&nEudy-U*kA`j21q0s7=bG&h2y9)v>V1HqMUGTQ!#@v)cx10)*i3 z`4oc6o!yWswS?h`Ws8k>N4~MnP1Vk7?6Gx&Fztl9-}4b)+H9yRbxW}6;TDr(Igxz# z;_90&zy$(YBw#1#1C;RrdIpXH z4zPwc8VKY8T*z~Z%7k>%T}2cg+VAINx%fV;a%X}IT6N89i$3+f@(Q$!fx$96(jjG@ zIl7ZhKk0X3ae{*K`Usyq;KnUhdA)?M*YxY5cMt!jdpV3eMsU79x3AaT>p3H5?7tb9 zbywuH?9@85M=yZEw97TBSLII3XWmy!s1&}ZrA*&ME3M?10EbXo$4y6#pg6Es^#fe= zfM#Al6%0+Fkmy!s!>C|J65DZ40H(fgm=jcUk_9Au)=QYkHwe>SsFD9Mu8zOKh50jK z`ZJ8lq|AV5W+_ZB|3k{!ho;Vr-+g7R#U7j*J<<)Sj zc7{)&N+<1-e5u0}m~#CFgEOB9;XG}(V&ra`k(#!dMp`?8o~7%)fA6Vu8LR zH3OqXJT2CnK?TjXCO{D;=L1U5EEtOWeXd5_yoKv5T51Q?+C?$AQ{O8zV%Fnx$z#s=T!J?PV@Ij)lw@zLG8(Z{ zt903lI$lENwwLi}l;&4TGb*J5b`OkLYQBu#22Je}v!V_)W&or7*AjROymFuI+mCDcI_P>*s!m~lKqw~U10j0@K~0FSGS#zIHUROW zPSqRZ=mAV)C+b%f-^Jo#8%py&1x)Xbb#ulC(xsdm} z8Goc*^WBNKx%eDR89$eUrXVZkltDelvAP09U8yygK>LD%MtBP=`{Ula7p|H1zB z7S%f&bn8!;3-&5wXu)1(I0*V0_LLXRlCHs(X6o>%e%ka2!hqd)*wV7lYX43;lB4C; z!p4Hema6lOcb>0osWRj({p~Q-KMm;tgRIh8Y}*3=WxYvN1&8qQY&mFZnyr8)$&W;a zQ@U{j1DJB>39NFWz7rJtId(+MDbfTOIZsTG$7-?1U|hb2eNurYKInwx9^eT^9g9}Sp->FMta$07UOUKI21tGj7=4qG8vDmc;(q)*} z<24OmR`Uxl`m)0X5@|TVFs0KsXwmaAvhSs1j$8_|5NFlxcnZnRD>gp|8Fw3?!;2NH z7zJvJ2W>x+~`niyGzC~?1U z&}~$T%~SAEDMl9HMLW5JnDATUWAKH`8*vQ?`?8Rj;~I59I#RWE3iH|L`!B2b?o7WTf6ILkbPz?gf((g-^E;iE=+oWK*8F|S8loX+ve>?-lL03+K{2T z`@kk+3&OY)l2jE`(a@gB^f$oBzgJGdAQ-j~Vit_=z`7S2^&QD%+hU>*t#G6|F3WQ+64q|k}8lr)&x}dAjN*gBO zXoD|z`W7@a?f817H(*K`>Fq)?sCBaCbk73atJ0Mk$MYZ{@HhY(8;zN}Q3Bk%am!9= zL$@@ew4n>$h-P~bbGy=$?S>Y!H}V=YsJWP zC~9<6+++DpjoNvQK-Y1i>!{Sh={iu=b|vSUaPUJ5xKgGU+Rvah1X_fakPhNX z9?;j(8m!J^#cn~nRXJeQKSiXtC#$HPUv&yU(j}z)L+maukUQASYC)*QbOYxMzk7b{ zYHUvAYLx@-Lo9t4KR@Qu{4;LR{Drr$TyR4<==jd@F*+1iUg%olha+n*3Q3-aOrC|K zdqwT$Nk>4E_TRi{AgT9_2O5a z==TcxsAK?0oa#*ub-rEwv2)2{|I%P>a2c#r#?cP;d#F~h)e#=YUO+I|pN8|yf>jzF zwuI2_yzq?tgv<&Doe2Hs@1Y6Ie^_AEz=}*Od|Wf6wQI+0ou0w<4o^aS@Cj&W+^PT? z>nEjlmd4ful+Q%vQ_(ZHVx^oGzvp_Kl8<4`6y#j&AYmT~)~fo;PCsQ7KDsOH#gXNg zDN%{r>*1JYvmG)DBM0wByB0>&Q061}ZNsk_ zzfJf__^rWjHGW$8!`*86PrLDEcr(0v@b1C87w=xY`|$3=JAros?*Y6AqV_1NF4%f) zi4->ss`MfJ-ouX(ZWs}8bMSVm@yM`Q`(zAgynrKMM+z2~XAVR+l@27^pm4Yivd^D> zY5?UfT!T`KGarJ}13$(}^oF4}Icv5_5w(dQNq`{W?W+)O#_u`&S}Saq9BWx%Q@-Hb z`;v3-_ajgfZAqBnw)(=Ve92p(Wd!8*5pbvhYM5-ZFKo(})Ux7(WNR6b1Gohcq&U$~x!eJNfplE7`(zE)1oxIL#R^jjX;&``j*e`lIu8SU{U1XBi#UMsBH?3y9FBhnLCV->W-JG0ueS9dzOKL=78fY|7695- znrgh(hzF*p>{mSMX!0w{k+tEAJ%}I%N^L9gzwA&ysxYzimqZhhd+S^*5MQJu76c&f z7~VY8wp+}$9j#@6`cWVPk~E8eN>>g@W3&bK;poW}t;Bd!#{w*eJ}+ov7?*Ien~UbG zfL81|Bh9E$XR|P7&~#jGBJR~f5T|T|I5IZKk9@&HcpV1$pcY%fx0d+TSx?i1a_4K< zD*FU8DqO+O-DxY zO6QsY3!*(>R3E-8%?fVl`vE-#qZrO5cXwRzBnB1~!R*pS3WN7orG)D-JNDY`Fw5;7 z!=H3>NXOpM6sF^XS}z}<>FWJSHGa11BiiS|R7Pu8H`~?C4t2A${S()y_ULBUv(G;J z5*?DmfC=EDw_l@?y*1a;;_}`spNVdrjL-c7k8>byk$fg~Sf{CH5=J|COvugmAa<{cK^IQ16*fZ*DjeG&n&Is*17Qmcc9DV#tM2IgQ5?{1= z4s94$)b901AIYZlaKSC?ub8ER#Mb#1%pkG<@jj+w>z&ca05YLGKguRhIJx1#>lgE> z+f*YSv1r+vq2wB5s%ASN`pUubB*4H(fDoCGIM5~zR7iZ==A&ZB#UZD0VftiO>$WsP ztBz`|*YsOVHpU{|K=Usk*nRji9@ZYEm}qkjWwITO z-d3QT8^0l|abeD6S9EcKo~?X4euI-f3!;m=TCnQx6oh%6cj`M+cYK_Cik}T}h7OTz zX6%D(`e2FF5~ge}SSw9dwm>#7(l&&WVtMo#Q!J+fxC7@WA8t>IB|vbKnx};OgI|M= zF#$$hQi(8RqhFXuDFf`clz#^SsS8555uXBbH$X|Tr&d6a3_*Vw;)?=qCHuFj*RWWD z6|q2P$Wvlz6a*WvW#EA9%&r}PebrnB=yR08^YWOHAa;Q0CzZhg zc?=dWa7Q0b)DKc#OfnM6sVxykY^p7PpDH+)Q=FwduVk2q=28f$XDR_^^kA%0lT`+S-OOYTdB`9Hhck;?;;eH zziiEE#ywLI06~1Q0zKt${27EtpgH_U)TF8#XnuUS7~b;H|MZ(}qZeVMMkl*Wd~q%| z6>&wNudB6j4iX*Zp2@&wS>Q>m{~UuMrj@jfcN7h0;1an`2adbj!G!v_76Wau`Q&sV zu)DDo52vg1ojCLuRm*|swmR*qI<=VAIc?S(<*&5U{0wIN1$4^Bg|^9d+*-N5pU`hM z1Tj(!rbp*bd5K1pMu)?DgM1dFHX9ARz^Ya|VDiPCDyGgdRn-Hes`P&=Eg?A(Bew!E zZ7-w_Nqzkr-Vt&`>=Sf^!IzL))n%~R(4us2z$r#o$7w4=XmfTSIxlX(^vt)5%{9~% z1?co_0{pIn+6i3l+FXIims&s@x`cM_^i#?u{O=yH7m$&(br%{jLJg$Jrwlp+p6n%~ zwTe)g*-!jz>%Rh6T@k9*%BW`;AM{tOh1>P#$kv}mBZozdV2VTs%17-7D0d&2Z{Ils z^}`h-J7@B@b7wK$bf-W!3~3FnI&I;67ye#=ZxW)tI*u+PrHqtzLw4)J{7Ee>#pk?8 zh?@!2qZ**F@=3$Aw9Fo$v`-D*Ylp}l%X{+>;cr2w1l7sZv8#;_Qau_h67*sa8+jGU z9r|?I*C}W^XI8hG{ep6_tFih{dNA6RJG;mV!d^sNM{28jO!zztpzVUOG}<@>Rj6E2 zInbY-$zxyQ9BR^V@pA;x$hCA`CKP`1w3!RN2;;GprBjiq`<$`xJkxFiI;pVLqO_B| zFES(KFG(8-(I*Q>yfn+p{BGu>O0VHQptQp-Z?QBQdLBvSoqgAIChn>*oi^CRN&w{A*eq3ZHV_U-|2nB-f-a)i@d`!9wh>$+bIEq6N zly?VFMJYH)O)0SA_wYocgx81SU~j?yIN#I76KN(k)Zr}{NR!qfuE;T7CC|_0vFCQD zjC+2Bv`+4dLB|fsBL#m~ME{faew}iyAf>}9bF)JqtRF3^%r$Wt^AA zZsGxCV7C#*q?_u$n@gP~bk%llz&y-%9EbUq@WXt3=1KeL=3&0EZ0Zm(9WM|u`k!E* z<8)Z{qcBILsIubL)C0K3OU~E6CaV<@lanOo2OvhDrhQfPwYbNbUZ=t^2O@Eb@@C0) zldO~TBc0%(#Z2UWnqagMB3uXV4Eu3#>BhmOaT@39R4dyKB9b+U!-LA#}fPqIIJe$VeZX@fd65J)6WkvmkxQ#X~f!(wfBo)TXR51(O5uK4zcn*Vx>4t zfc~nMMroD=R4_wg~JNDhHNedQ(6TBms-8a9s#3pPqH%CkaLvlF2_#Ho4c-Kn-NK%TmC>7MBuF0 zfSQpymeB>EDZ5v)Gj+&e{d2I5YcpU#M z6Em&-2XKw2RH-nVG^?mnDy+oO7<`D4!${5CP2lnU2r5wu+T*_;3R~j;if|K;Z-mm0 z|6(Y~8rKkR{PuErCOoIqebo5cmH~AiQGzb4t{DQgpW&Aa#&1K6#%1EiZCT>}H*l%J zQBy|Z*AehjR4*a!PU5}vLcEkncyl>k`ZD4Uj*-G6G17PZuUJhsetUzor19I3RNnaQ z8Y#c=+YMsm4~RD_L~iBrP6G3+k;lzXMndPCZ5V$RNhV8N@qZZ#7sUS&;a1z6Yvd`7 z4_IcwNv*@0%nKGJ^WF=XIc^SdwF&VQ@z&Ua7UL2UuOf)mVzZClcZ^Ek^zsNh5d;Z^aSGa@KH?#zhYaH7*15;us)it4Fncq%V|% zlbSvQO9WUz%vxi=)9m)uM#;h?Y%tikkNW*x_zNhsAvy$5ISk;rLLQxLP}B~(fH+ni zCq;t4>PFA#(|GEaD{LK%0Z<4?t5=Xv{{0+C;;Z0KSz2 z*cW$3-UGtomI(dPgBTzF(UL-ZG+@xs$RI{8BK$EN`z?_2O@{QhV=g4VwqQWFQ}=sJ z9}7NGr0p>bn#YHMCPt2Lxo8uNddcpz9W;Ndosi*%pX6RjIJhKC zP`FM$!$s&qsn9w`#pLvhInh!1H2zu|>R@o?6lvR%PRY_08t>(Bg{i4#R#Zo6FIFEn z1p}9#pDo>-ZsR;{$yucDi~3F%byg$^10Qg2FHqu-?%^rj0ny6P-fk={mX;d4_iOyw zX({&V-W%{2{^0zAc_?PtUl(x=cPydL;Hqy}2bii)&$yux&}m-4eq+L#MJfB9L{Z>5 zZC9Gzjo4a(ra*+0X*Smt`UEl&Cclbw9M-_Lq?raiPxA}nojHmZ@j4VGXLeNc{&pvh zASd+6BS)8A1vj&Ns3&C~DF*{LdKp_jHg*#(ZQrly`8Xe}xV-qIT!pX+$Y2VXBN&vf zG=p{^-$&)>e9sl-+Oipg)PBV zL%3onH{|#;tY>Y=LH>vIN7G=mz}^3Y@+20f*aCswJWNA}_HKL!WExiwJ3RczVf_Sl zeG={mLvZX37;5xm+yN;%hc6c37R>+Nj)uwo!mI4cCpZ)9XSblP7aXI(l{X_Um!ZF? z3JFtjrfEr+KAyb}v?ezg*{ndENpi|$<)rTBJEbk@VpoG0{zq3HrXtKm;NEV8S;rM4 zmublcz!?fPGV8x+sF}^5#dwy&1&>a&{1)RQm^_s&MWNV7nu}L*;q}RrAOou`4In1N z2dkr#%!7|M^N%{TE}UIxJ$&@6`gkF5wnVSP69?LG(%`H`{sHU(XO7X~fXVDz!UcYR zjCT_Kg9yea19yMYw-3%Cc&5hn~QlU=CWe*V^$D=zwnb`Zxoxi;e%a? zy+O^p27msf62n{pO2r`)zh*OLWoTdFkHWTNeT0*(V)H6Md%lvKvpH#Evmf8ME*$CF z_m-t@!1-o`e33QxeLm!b(FT7YUysntqSDk8<~VJE!`GV zHbT?pwfbkZEa_{h`bJqb8_s{EQ1qL`{q25s6sr?D!f>q?r80}&v{k{)$?G{JZhZ=f z0UIetJdUBXHc+pyvq{Y^*Mo4x_ zcN3e$ZT&XTxsU3P!Tv2s<`7PD7ad00>FdkB0P%nFjD*A@Zrgg%r?Za|?bN^ytA*7JbS-gNgDaY2YiDglJcHP&6)Iu@5;JWh>< zKYc5YGU@0Pvb`19r>tliG{$0&<_}u0nWYH#Hbf&c0F5@}NWQ-r=TmVU&cb;CYr-}U z#dQ>Mg@7~r;)83z{`mAE(qYx71|30kCDN3qs6&8ulX4PSqJ0GsKVRH4*7lL@ZIgZl z^iQztrdADSFRN4YHC`=Sr)4*xFrRg*%huVnk0J)CW_$mi*6eQdo4>8u?G!h%W(%lh zblt6Hsz0-jQ#;5M86`1HR%}GI&L*qn(H`Z(zGsYuOTF!Fsv7S9r%L_Z>O2jF_J7)Y z6M!hI^?&>zptyo%iDo$>F6B1BFf+`s3<4@BisG6JqJW|Z2s18S6$~s5F}-zfS(fEe zwq7fjHWQcB%v{pStea+5gIH3TQc~~l^EvOlFd&-M{r>L%_y6|7nRDK=KF@QW^PJ^5 z?>Tv8As0uEoI0W<=6$7=I0S5HY3TrD+hd2E$|aTTz_d*J?&DYJpNcJJZkyW%!#avAU)c^MP}Tz9P!i zJX_#(Ohu3;Z79rb7@5e5DKxj2Uo8bX%N}R?4j_edADl%x`7K?G5(!8TDJsUQ+Tsb$ z_wJQSGQX+aPuqm^V??j{Ms}&1);UvV2YD%vg;~Mk$Iw#iv z!`+>3!<-wO18Rbt6{|pj&$Ja$*JfTUjN-Tt53izAHdn4te!Hy)W1QE5cdL!^UBojo zM>?lbul9zv8rvItL+HW9)_{@DM7S}2t2xsu0`IkFT4CvR*L}9Yz=CibEaU`2Bb^=8 z#EKmm`MG7}RWG9pZ#0~dhi~y}nbA>1kRLW7qrIwILi7gQ?hrk9MMgODuFyUnsylRV z)4Y?o71-(Q491enKTV(&L}iS}=dtrE7wB=k)|?wkaFSKT1suE7%5~IME08ea0#xKL za1)sXV_$#k{K|QUGf+nrx}ttwzs_k{f(_u%H+U2^ZdB2dcTgfh+d!~|yb490p?S2J zoG;0bL&z`)@*V*76F;+c9f8T639J$x#$~@LY`mY{&wLv<7x-YKk*Zw5_x;#Q;Mz7_ zh&{O2c@Q?bjpH^oQe)pOt)PN&-+X`(OU1i#3-lJ;#kL#tl*e<-=az-V&*Qb|CyxbP z(9O-$g}fg&9$U|M4g4Jg|Sfkm*sFZ*c|$ zl53|#`JHe(UwDK~2>rF(MWOA4;JDO^U~Fh$NoClLkK+U@ai?CL(tHZzh_6))iN_SLvtg?EL4r}7JPl4SXr`U9}4B&pIt;DI(FWls_o@=>FSuHk33$M zSN_$WxI2>Do12$8xrLR1XLQaU1{kW{;W0o^vr=L12!{Cr%#3C!M7sOF8-q_*~ z4RvD|VXmQCiqTX{q2L(bt<)_gVZX^gL2rC2+z8qwY(S%W$!}T|{1?D~jMOh3Zb-j0 z2Lnzwc|u(zrjF1rQSmpwMQQ1#%jixvALH+1XZXA5dHGu%Y8 z4ffDEGahD|Rd|>BrBQfw%|m{Eh?Czkgh>6;n{a6QrEjn#3Ej`H_Cvl~+hTbPK}$BD zlfS#=?*{(<;}m`~tRMOouS0xX_~7}|l5J1GFHENJT{;Ke(Eel;RZ;)5wZ8smGxJjQ zKYDll551}X8A6g)HSxW-CGvsx=eZ{_yMgwH=yI_W){;dkzA7D53aFGJ1j9$K#bBj_sy~>}faeI`nhI^s(M@tap%b7yHmM?-cqX^oc9wj)( z%1f&p0)mOel8l;6p!}g{Ij1;Skb#q`nyoJ7j|>W9N~NeALp@i<1PYO38XlKP)*c+Dt^%5t>!{K@5w z?zQ|Wc&h~QD}SWMtt(#!xBQC4=xCQwRM5!axB=^zu7sdb`3y#`3QoNVZPf@=7uvT~!ig)r@QXtNmn=i}dl!-982*a#&+vL_5wTVEKJUO&%|ute4er`7 zM-!KS$u_1g!jVDV+esww(nXnrPGzZ*vDHf+W1+sqKS5StlR$Hq-h-Y+>j{Y{*~}Lx z2bZ-5K0I0g2YbV%iVrB#p+j#DMTP9Ra0rDW5eVDH#Pbf9e~OHyj_4%dr+(-kgxlG~ zxA+3O3zF$|#K0Fp050TWKMlUkhml-k{B>~K`z~Iz4|eIIP58z5ofgi*!>>>_va2hV z;aG4aMU$NU<(LtxjdOjMY~Bd3iY6ILWSAOb$s*#Vik@;KU~p>_a$P}ck3v+k)@YBI z#(o2)9JTyW{vD>WMe7N$DE}I6HyS267kxtJIm{^39eoK_!R#KtMODxpy(RsjJNo(; z%A-tsHg!jVQg^flVJbNav6RhnC%M`JC|NPGMlhfjow1i>6E2>Eig1xoYK$mdaTp#o zMpDpv?v+A~Y+ZhdH6sNMbVbY`lF-FPqL5IoL^RLON@A)?lB>%DJsNTn%`Q7Tt5 zlZt`Xeb_B5xwK^8!k^Z{Z-J@wB~{B)4z4Sak{ntdignNxTAo_EV>KIE9x^EtmUz0f zJiCzNa(I@+K+E$W9Ii@-J_j#S%fmD(dthCLtX3*hjB?lVJjTXCEzcJ~M{0SP3ZLh= zvcqK$wOXExqHUxB)jXfL$8b~gL`gLdGv%s&|0S}$jw){lK3=k!S?`toC**{v2$ZUx zzd>@4=T~uL#7zMQkx-4*4Y6Fct5P455j3BNnA7w)EOF5RWLP3IEGip{_k(!Ht%LY2 zAB9LRzCzBZLU)cC|mjZaMV%8ItGFpyT$`pB-|wf1Coca_M^duC$5157~qr<`B#+58FgH zm>Do>2vhgGVU{`y3kqXYy-EI1_4911MKl$OFOEDc3U8%2LS0upa1WW|wj!L<>&IOr zjvJGwU8wL$p7vvfXY#a*%1s@1AoC_mIy4R`8(VR+^QomAuw$eroG-#zq~nr~dMXw6 z^6t!rKnP$aJPF*b&-QmO;8w5i80t*u%YM1<-EmR1dxGc~GG~(4+a%t~$ zA`DnK->Zq^%!RY!gDXF6zZmO-15@8C@xtw*xEyD|X{>jZBQC%FysLMT*V0)JoxH*v7qlJkE{hINbZt0=WnU}LyzBfdSgw1vb2>p$wLrzNcy?vyy~%x}BLhSS-7lsz`@W;~t^ z=bK_5cE!JUeC>^cEmTf8gbk0_>*!LA?jhrha_&Q?L#leYFFvv?YTS^9?0 zjI}&W7rXFrc;fQYV6n2rXec;e?eecUC}ARAR4Kv*q$dHR+k)^7&ghz8=NYUnSDd)& z$;XYc6zX9=nC#5rgiC(yAP*b&um>eO&qLDk9LPX`11dIG71&%6#%Ba)z*4x&u$}X3 zlz=Z>aP#kexLi;*usR$Ipw!jj)htVGVp!qB>J3+{cCV5vR`?eD!hIv!6c6{f6;hRF z65mi~4XZPbPgf6N#rJl$1{bru21IeP@;M31PgACI7LciRJg3&2(POmDvjDD0^S zfx?XJwYX8mX>9kdyw7KGi^jHMxmWrJ3`1J)X(XIqBCfXSd=HNb)7IYjp+s{mzd2Xg zf!=uBA?Ij;H5%M;;)5$M;RVT?II2PqKaYMm=)vvdiSFzpcmv&pFmGPgW4DcTTGaCF5!hPR^-gUZiP&c4q3K~LVT63wsn z=lk`jyya)##e2Yi1wOd1O@15u2G{eGaRTE_dY}dNnFtAkO%tGOTj$dNM1|kE3eFON zUgw=%Q#tuzDK|kTQiOmO^O_ZSS%1j$D%pjF^gUSP!zmv=&f@@4RV>?$D_Q!S#sx<~ z(L*JUN^H1blp}x!*Uves!3G)#;{Za)C-VGyrwQd2nY|s&o$Vzs&~AyMgUS-eg^F#~ z%LOy%q1gQCKpLDW4>9}k--@DL4dYuJ3#MW*?_;jZ#?ccg`wWe)X zmzx+$+o*$qX6l{|&x7|xOM5!J(>>L1~QtErvmTAa@Ib$i(->wj`jwoK zI{ZvvztRL|2)qhL!K)wzUO5>y{A4HLXVyggEXYN`6!;b7z^`C7{0a(kOScpv&(iJu zO>nHm&f0j~WOUXGQmn0ec?C^MXZe*D_$4^b7k%!F`^9(Qa06U%e)E#HrTE^qz$+em z{_qWfr@bkUa_HAT-f?O41bo;2I-08Jak$6+p(Q)D2sbZoDVX48O9ut|^gzbGo;z-Nr}>UC<;}35QRCZ0^SyvhT5>QK!#UWQ?1}b1%gcEw8yVsh z-Sg6J;rv?Ke$JE9ZsYt&+WyW%w2jVv@>S<7lXjrZoFk+?+?got(atz&k8?&y zd!jQ`+G);S(w^$IK8Dk&-u#?6$Dws&hvOvwiKf>oM)tS zF`XYv=TbTkO6PJqcS$Fez|L2t^IDmr&bXEmL#N+(;p^9AYTorTUd(#elv zoe#k&L2kjfB{G1Y@HrPqXB#^6rPH6zsnW@%W#@S5)X_OiIs@tKFP+`#442NHbOuSM zp3bh)X`u5K=`_>nC!OJRdP}E`&Y!0f|5!TDOXmPO&%h}`9>li~Wk3?0?@H%zI?JSU zG@YBJa~z$|O6Np6SHlTOrj1S1W@jH$(%9-PkF3DC4f7CXjJ#@W+^?7x!)Kc6gH3}I zT|T2#AHCIkvCF5Q^qFO_hAx#pBb^5N)Gf%j_$+D%2W4Bm(_HCVsX6&sy{Ec-s_~s0 z%5P)!&T{#jRek)e-nlNHwtGC_dvq$yOS-t1Dd^V{*fmZK%E}u23kJ;+I+~u=e z^$E9nKj`vVp!(RX-VeKcvQ(c~tM@9G&z-8z0IT;CE}sF?XVxHV=sM{$(rKiRhJBsA z1SKQ<)v5f^1s!o>S;_u*vp=qzM5lGJ=pCg5$5#!o?ws#|sgFO-3=JC}=xEOQChmy$ zS`rsn5=u2QwZh#w{_=-vm^yB+w^6$oQ#k_h-6y`FuEep2-2FHV-V0*Xt0FJq5WPH8 zX>62F1iE%H`$i{EVJq1Um3fD~;sBa*1rDmelnKD$)pW1mnJ`6V*x!1AXL?=;8-Kz6 zJoJ?~qS7B_@~AVEhEB2g6l*oqfB{c(vKm1Skv`=9R-E;>1Htkb&_y_E>-Lg39X+3i zXINa7@BM4x0N@?m6UysuO6FJLM!&vpz#9p?b;s#< zoR%wqR}ZI0#3+mcQADMLUj+|?=z!$pu<<&FS8{SiV|*YjZ*r>|1;PfZn+k!!DCZ%J zJ1}m%;N(RxIH_PvY5ExqY_OIT@}9F>8W)mWgJk3K?iaHSOCYIRTL};U#L_< z<22jgUiV|FuB`jZQ|i|}KW?_aUg{N7O|+MSsL@b*+-{OHeF<^%wt?hx@^#NHG; zR@%IV(Iz(y%rat^i7&EmJ_^^``mK~iaQ=u4)O{Pyv&_r2eZzGY9>;`8)zx}=w$8a9 z;nM;pEYUl&;o_c?MXm!c$^nnE7#FM%?8fSGuyUJ7IQ+FZdbmpyTMSJeH4;P8#5O~d zmyB;Ax14Zy9TK*|&2YYpAaO9?_OZTe-?qe~;x%>ZS5$SE@1i7xU=~)KPy4d(J&?Hy zQHgt4qEbGVDR~VsC&(@y>fRu1NXKPs z)!d_-=z|TqH<=+0z#6By_vanAy(1hZawO>0V;^p>KHPa<$?h%!{At~n*Q{j6mCp;oj)9^ordCL9h5sB`>XsbZsi{B>Lj$v5?oaWukqE+7eCU<4Z}^P&1=Y3(WGQo z7t+uDs?s)47T|^;T!q6^+&Oh-^Q4D50ak9J$mhNwetGV?4 zP7mMbyaFq}!vG)M8~kzF!+niq&>j!pwO)bw-(odxw+>%4)J`CZz(%+ zs;JCk*QK2RUfBKb!=a8I$mVMRfJC2O+S!Qy>oQ7s+9LuE!gmkze;fI4!?*kui#3R@ z55E#cBGv+D`bosTEA0pAMa<+DcF&|~o>NhzZL02s4NDN!XuNCLh<0gB$&QWjzhcCt z-ms!}Dm+57#Vo9K`QS!4e7qPXSb%TT$Yks~YyOTs5tPP`qOH-d+_^=^ zdg$8h%zaJl-GE(ZK!&3REnnv~wtO+WQKPRcd*Rvz*B;9$+yH|+xQ>LpV>xAS`Wl!~ z$!m1!2udMFl_1aR5yfu?s;@9 zf|M=~0^$E1j~-K+NSGv;X)tqO?t^(8W)sX|m~$|Vz7)bA#sHH5GXW+WW&zA{m?vOf zh1n1DE6fdF2@wF(8^!`N2xbC|9p)aGM_{(V9D{Mfh_8`9j149UW*m$irWj^9%;PZ6 z!)$>$2=f`t1(+6?hxx;Fg$aghu7aokX z)kNv@x=pn0Ui)4X;O2Pfv(_W{%2q!CCigR#gZKm`CogVJradVyXL5Rez7R7+zL+d> zM4m{;UvH5nvhXK_PO*tOFq83zXkvsIF8YaH!tCY_5=Jpd#KDK*gGIcE5ko|*^cjfX zVepGXj1UowoMYh{B;)qW%I}w#o-SY~r`t!SW;vw0zneQcD=TL*Bj*W+$QE{y2}sk0 z4kizOgjXl?YAKpYdpPnQB9igv9!CvL24sUp{{})(*GQEpqGgOLQ_8G?hf(N(MTlU2 zy^s&qrty~!m~vt3U~=&50Hp|HBA|!|JUU6)H0hTip`Ib*P6amkaHZmxDQ1XCp!r<* zq#=(ygl3B=c*{l%Vm?dez*sj_5^PQ4_ZNXtybNe9e2(OvX`Zx(X99d8-PFB|Wq24SKPxq$Rcg}IVa z*%C%_4^yf9qW;#VjFm7YA_v0NTh=aXT&wTkn)=R04x~Uj;*nZYfU6EAV&yjC6SZeDpSeR<^)8M$i z`kRfi8ZPn5I&?43_y@{kOJW=SBjttGl$Q&hRO@~g^2$S=4$v*Pm}Hu$TgRYdPlEK&#ce9-|DF!~Qt~^^zlLL#e^O zG#Br5Q;M^9Vo#@1hP{U>-PJVYu3B1a9}VRwh!6!zhFY$yvy=bc$pH1MaFR>UlK7|x|*#5A~_S!@{*txLrX*c#_V)GTO<$G-M134S)+vpFwBP{dV zHb9E}cH2ZJ*r#@4JO=ws*mGe&0sAi4#jvYk&x6ecoN=%dW!qr?$TpK9aUKaj;;l-B z7|{cNImJ9{f#%by|uk;$Ie~5-`=x#-#h!?J@DSaLx+#NfArV~AAWTF;}f5J`tQ$9 zp8EXs7iYfw>T75D*@|=De0#p~yYGLv@Z-fxRX_cFx%wB}8|Bf+)62VY6Q8Ednzv}# z%Ga;;4L7#A>E^cn?b_ec;nv$a>N*8<4(!skTld@V=+U!R?>_pV;1ENo(PR#@Si>VC zqim^@Ca0xmOqrTFZF<&>?3~=0dHHt7tl4ws-ZggI_z5W!uO9xldGi+({I~J{ZS(m&=XK zz%_2@H_A9JHHS}{>#rwz@kG}jXDw-hK671vLWcB_{(Yn$(@?TgP~ zjK8=ht6yRdal!o$1?gI2a`XS>QFBx>1OxmuZw$8wkt zXPBJra_*zT-Vbk?ZtueZEo0=n`He#PX~=8CvkB*MHctm1ipR}|-aNtQo^+&_R zrcX|vF)3YE_~4vbHSQsk?K$*LPS3S#p3#mej(h-?;K-7BBsj8VMMmf5Wy(5C&6_Oi zFMU#;BQ;NrlbS7^C`TZFfqa>#KwiuTCR-$?&K1Z5cAn^$K1n2`W{c!hyCW|R0eJf5 zWlGoZsgAsSm*1%LwCr@(%W#M4O3cZYp~()HooZ)Vfph}#1>yGh+Mnh2rON%7$`aq2`oP>AHt!Q+D%qKWYFf#rigzRIU@ zVc|W63ky+z=RJk@++Enl+Z!b;TC~U;^GAJQQsH96?%vIuG^!BkQAkqKVkFdcFI-%R zR073JojTRWr^%e$+}XLgSLFX^yYZ`c6W7&^ORd0QNCN5*0s*fB6&VuTJ1q;$Sz9l| zGiRjdIPB5jt5kbxmM$(YFDFlznXMa?>d2lv6+E8@>BFaAYGzh?n$Di1%gIg8)}_x$ zpX{)wPRb(FkI1HjVHw~bU23*2H5ZZ65TC684AR>zPF{Lynl2+RX9i-+n7)b1h4X2oX0Y z7Y$0Krb;oypD`m9v;)3K6Uvw<#R07X

OXP&)nf^INfn@Yjmk!&Z!Yw)omj5_8RgdSy- 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 diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/w64.exe b/virtualenv/lib/python3.5/site-packages/pip/_vendor/distlib/w64.exe deleted file mode 100644 index fd37d9ee468d5fcab4ccd51d4e85c48607efd310..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94208 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%0A+m!ns>B!NUlDz;pPF&Aoq22e z{pwH&>~rKn2L~Cb0{zKEQ-}*D19>CvPi0OvBM6KA8wvp2DhA^HX)>5WK0bn4(SFsT z_&{T8xTqDvwuFnk4m>p7m{pBYz#C^%G)aZrREYnGS{;ogVl2mnk-zuoDfF~NJ6&4< z7~;>)s22rr65gf_CCJX8Ok9~6W^jUWBtpEf4~Wmd)C(d^Te!y%hI2}EWJS??04l3` zV%#x^EQJKrMWjzBjd78p9k4PwhJy>*NvNbeGJI)Hx)pvv+@e6<2y`gd-v^E&n#`?^ z&zN=^^5#@y8A0(|^el#yjG_qknI?Iqn|AwZjQUHpsEOWjF12=`R4emv{peEqmRI)pjfvE3MFF=s2j@%(iZ8^qs5 zM`=s!Yy>l0(1H~n#{s-i0+WRP6F2ly1rAzc&8uAtA(&+~;5uBEyrRi)$!pvAAV|i< z&mH~kMi$3Mwe zd7%OaOJ_bo=B3cGvfHV;5tRN2f`%4?*B;zq7OFZ}%)UPBIDP}w)Wa={s4dF}cM@`^`Y z-jj4*BpY^xZNmL*Jp9@iu4=>^5|iW=vHk(%Doxx$lQ0WvrAv-Y0=X#o*-6^ussI@s z&pryloW7T&zsJ()AEv)groSmWHFJCd)Arx%AZanx>~J<=8tSb_-nU+P zmEpM?sGVoaI4hOce3Co=jNjpW>jpF-6|LKmN_Gh`{RZC+$wLUiSx^OC5LtL};+A|H zX-fBoVhj&_0Gn8Dn2l2WxEMg5flF{DTL+d`Yp1RL^kX%pQ zZy8zj)I6<9PtBKO*~Fky(e#6>sfBWVGa6cT4#70lY!%xhol#_Am+DlDHmf_18(tuS z5RiIS;M2%4TZ8y1ylj{uQ0i#WX0QM?`4HN9(@l^Ax$-KIiv)_BO}{XY;l~a?IKwdw zW}&IYkSdNg1bx$tYZc+fO?iP(u7Qiv>?)cB{_iu=2*dq&XfR6G1~}1H$1gXs;+JPI zn5183CIneONP~qH5gt*&dLGRt`pBE#zrrFP<3cgD)Czv2X+uEEu8`lHoHB-Ds_=1( zw0;#;2s=V-G7ia5CLi18gD(8a9}UMvt>%bUYv4`<_wNU@#nY~EGSWZkR{Zd(yY>Va z>TG%*Ht`hY(W8ECV>SUd5vb?e>)V##H!C0*(VJ6PpKW+53!a;a3B`Jf{KFcbtg$h#Ujz<%Ec}SiCbD( zKmtM`5ZtR&rYP8Gh-qWHmF>>dG}@-NiDoWkF0D>0mDMGjqD`sH^Z$O&`TZ^z#KxI- z-v9f5KmYl`xzE|p^E~G{`-aLM=fzn2$D*5t`#^R>8x5@kqef_L@Uc~5vhTO0UsWJJ zSD(?fcq7t*8KdgZ-M6#rw?f4;vqE+F6yiN_`wQLgQ||e`?iC5c+(9ZYzz~+|R9yQ* zW}#Xoe;gOg7&yne{4$WH@^2(_E2u1xA~y`#bo^C|D~yI1m2qH58aAOFf7Q>Wyx1B% z7?h7a7=UM5~SM(WTlq z*|_|8c|RiT>dD8Cbj+ICpO1SPjcAmxV6(zr&tIxlQf#(B5waa^n*(99bi0KX^+X{i z4sPzxMs4{R?!HajmRE| z?`}lMONwhee)C?TA5<+<95-qUe#BZgc9voW-?-@ISFnWg!7bAPkl zS6u=Y{FYvO{^ZS-`lUz()DLyr?79YJac7IcO({5dOCfO7m%>mJvYm}~%_8R^`l-KC zdH97`IqIjH(e$+IiW3qw8-0Y8@pPzs1DgdJtjOTmxMW_%;y^4g)<^1qHkTb(3~-Ia zZ;Y!yeurVBLB+{foJ>;dGj9ad|6Oa^)gRRwOZ^AbARhwj4{IyG`n}K)rE>nv;m>UT zq$O8>ZBj$?jQacG(euvz-Y(cx&?d&a@2tN8GTXezhX>(s{FU9Pc+?zodV!hj>xX;p zQeiuwe&YNIj?BXcb7LIqHjbZE+JG|(n9ar9L_`cGAlo_w z%SmKR3v==uLkj%{6X)YmMYcWz%i}Bh)__Ql4Y60+gs15~5=R8ea@rBd$$-%9Qp#ALt=r9=i-5gHKq8(@ulun+nfo`?7wW3?FVN%RAiS@q0}}5S@A(V~8@=vgXgM(00Y7QgI1KSQ zRwVA@%-xQYI7j(aUmh^!S%-{toMyD&?6TsWQk?%x^gEt-=oC)x_^C5IIM0cGy1EnS zZaiLT#Z7jhxXJEyEYA3Op8gGG?RC$K=+m&v{2HnvBys@~!CRMg@E*upZJvg;=Oh+d zxq1h=#VvHT6s(#6D|}vXX;)%`U3XUNx>saGPbEp#sv8jsy;__mJ#MYysuJ$!Oc4Sc zz;?HfP`u{gL0xNAI$Y>wc@=7cn{fcB;^$!OG=qB@5_l35lRRN-uUym}uibI!se9Ur zw1L_7tq3R3+d|Jj2TnvRs{td2eV*YRl_UeV9+t4SV2w=}kLuW8;^o-cVB>*3yGoztcxO&>fh=BQ#mMhErSTN56?KMsxr< zgN7Ug*l@qN6Ep0*y2V;`F{41Z41G`x#2v1YwLrVaODU!>#S4NMWw zY>Raj*02P+TMo<>Uk}N#D9Q12_rXg|*e-`XY{7Y;C(&+Qw~NPhxP3c~_wWPwcps}C zuJ!a8j-`$Scz4gk>L)jn_A{v=9PXymNR*rM0} z0DiE@TbCa(iE_fP@^~h)MqvUDbXD&1V+OmihSSZ?eTHhkA@|+wz{WCMa*pkXOMgB^ z3ST)hg#l+lp&gk-p-w+_W(tRbkk%9?kiu{{sLbM0wOzfj!!laJCxFe28qt!X5J;Qa z7{~4pm9a{N4QCs{@=`pGn1e-CU7}fBofy38L8QBs7i(DHkb;izZlRQ?*^ zp6q$x4zpSHJO?fAI^2r>sf>7OBBN{A#~Q|oI@qRAz>DGP>g>mm7|D1VgHqLr|DfSv zvAtk&r6p;lz=D~fA!8oxE+xjw| z?yjs$Z0PKn>kaN{T&GrWx$vg?n~|K?wei%Ku{+?`C5Vh29PB0FbTm%RS+{&=UA`RU zliQdMJ_nj=hV5U0?n}*}FCI}%t!oVXZO_1olaLti9rQd#f9RCX)i*`n38T+Vk?H=u zK5Xz$tNsYLM8*$XGR{xWrZHfVibd)uvwfqS(K5>9-;WX(GCoh%BFdgdlp|^AWJEcT z220B*zke3O;o-eKc#S;8|J)CcC$p!tlJTG+$BW^ZD8ShFfPHHK>^#Q@v*F<=5&J^W z<)z09&{{0UlbnSE2jViza!e0cdEXtjG6q_o!xVlkj;%Lz!a))V`Lkcw-SBz zK)k=GPP)Da^gM3>F}0_JMYCcdvx2YFRTrw~265O`-ThJ>8oC$+)H*BoS)3Py);@rl z#C3eB0NKyGx|`STXBu~st6lbu>NF*G6~5`}!YQIo4jl9z#I>V#sG9q6njLEboUhMU zrxe%=D2GgEU~5lJI=YmHJzs$AG~AA+_Sp~MG--S5b0Eau5ue+nCea&>N%XCdJJIkL z>vPyXKeNtL2NSC_%=3W2^g2iN$`H03l|Ne+$J!IVTNJ}<6+i$^9^6)oWrgQC7J)G1 ztT0$BBg)3>fat1scFtYOz)rkqJJ=CF&*HLGD+?lFtvU}CERtw62K)7cVfI8~X;0rO zcp9ec)%(E@8!pvz)Hq=J5Lo` z5P6<|glM4Ki9Kl_ppTvij3=UrzjTnOF!v8(>yOVlfl6-tG1tF*_9B)1i!q&fZK|7R zD>mY7qwMG5WM2TzX!lR}z%DRPXQK+Q;o7bX}^jg#f=uh}8M)gLzyr-}d zt5FeLjq17$M|F(FDs}b*3sU>fVnK>o+j>39hNc(mQFZMobpiKX51>YmhtN0mu1A$S zS7KJNCLPz*U^(hLT!At$1M-56fOP(sOA7B!*8Nlu6w)}(HL zg)z(wQf^$_*{F)s2BSDpNatXDgf{^ySax5>oHFL!-b}9kB^l>_FgJ!thr~SGVPvi9 z2Y*=Csm1bD&Bd2GYOd^;f_2t3JSNG@Q=3q*z{pqg>@lw(^A|>-H*|cawzEE$7F2iI z63-4S@o;O-TRNk8#Rab5wp!`gkHVu?dZsE3R(iNSQ?2xDR+{P7svQWb zR(rTYP}y`D-p=J}&wAyK)gBJs9H>bh+cDe`oX0K1;lcJm{`js$Yt;y}445A}8f2|J zj$F^f*kF!#3b#H2t|`^+Q!003b3PX|kp~x;OGU9NMh5O!)(y)>j+)}P@51%em{!Mv z5&EPJYaQ0@@t9WPbdrOw@Ad9d%}jdT)9|65-K=h^&txTZVwYMv@=xygId0)|rd0Pq z6UB9-CU4rwRi9g{rh^(t5AvT&Ca>Pi*tmMLIttz$@!hOdVbEBg!%?Q0YdqN~?wqd0 zc6ki)GkiH&1mvPrwpx^WoFUzY(?|4It_{n7LgY2}zcx6*QcXFzx^N{EM>cY1DnuT{s#O>^ zU!gEz-W#h{uVBvta<~3*43EtvsbhLcN-sx&dnGS(aW%Q7z=jFd>lWoz)=ouZTR3nI zm#4_yD;usc*QbtNH&yv|bo>(cpjKb#&2di$^nMjbtyL9Z37VC}y?m3dDj{ zAVx`r-$krrSj4JRi&%)Y^*_-0^~Cd#F7bHa z9>Wr;UUxBG#=%QhT z{ti|o-lCl2aa@cqjioGHNvGGTPTjyMiP|_uFmsJs$5JIgQD81+9af(1@%5zYrNsCI zwW4*5*D|xpDLOv{>b?r}_O z=m65wlr^(+Ham{x$uTD!F((j>xtLYGS1o6~>v{A9IhMSYBV818%-H!XW_<)l1j6GO z_-*HoP@c9?XpPYM@W2cD(89^Z*|TQEul5({zyOGoi(06+KRfyoWC~;ApPtO$VqS15YXr zZEoP>Wv^B?rMNOGoAO;r+X@jYjs!)j7rpWDy>)pwLZB=k>sTKM9WIs*Qf|2K6crX7 zLhAV*7^;S_`Y)hC3sZlD7I3oW*(>AEb9VzM_rnSmg0xfi_0Pcv9Y-6ESf(-@f3()$ z1;?#yvXL5^>ziq0g{+M{w!f7%u{N@H;uRC3#`(Fn$%IXf-KGt^nhrX2D7aUF4JAe) z$T&Tvi>@YDjNu|Y1AkJPP=5f`IZ*p;s2e>YRaq*6Rkg(O%U0wh0#u(ui|teoFQ|2? zEw38uQqFo#&)KWhx|Fk?6OcN-bM3lv^obAsIpp0+ZW#dwu|$R9F}of+fLIypl`6z* zu2faf8#2s}YZ))BY#QJiwT)#888%=WdmqqrRpOnnLub+~L>kmEl~FfL!mp(vk^B!t z^<25%uVJ)f<;)f2Ng;pCRjSW4Wx7)l#)=3s#ADg{>?W#+*-ccv!sSim8pe9<(Q6BI zkH?~@>S3mDFvdyMJDt@v?A~(d8BoB&x_)3Rx;>Z`VmH`#R>-rj%G+bT1X{fvsb!B9 z_cuLx`W`gyKf^I$42Cii?Pw+NK+zrVaAu)LR3A2IY0;M~l za(rh9lEpm;1a!le|Bl#s7^U7+YY5o}!tl)fHWWI{tc@PYco=eJFFb#X38UT$S9CCi zXB4!RHlNohy!R4e=El2bruWRLvv|Ps+Jw-j*8$H0EEECH$Dv2{qize3!1Dv*`5Rsw z;I*%~e|cP_M2?T2TSRn+_@LXf4RrbH*)r5}Dhg+1h(C7e1LJEd$z6qU1+=GOY#<9> zMsuDi!gHDS?Zx3i($Cnb;y_S8xe=cgX$cEqWBcnGEb)%(S%{!`5+HUBFBEnZ}SZy<4$fKxKTyvOT3p; zb0x1r{S}PiG9fnEu}Xx^VPLifhZ|}F?m#lAa0XV&L~BhoT+`;BNUiSG$ccoi?;viN>BzQa6quV+0DFsM064w%ZEb9u%hA0F}8^P$RsOQEx24*U>Km#f>s zaV2<<-HAb9SnTe^4#AaKA*carXR8<*-rez40J})oQp95fxU9pty#n`j)b7TtsRc8G zm!o5birRrL=2!H*ts}7V41x@EcB$nA7sMq|FD2_cqcG*h^~mf&vrGe47mqRyw6tO5X~#{ccKSs+-J+GA_i7`t68o7 z--HZ8-r};}hlfJ8)MdSxTZ`~4MdH}ye3=&qJ=fg_L}EzN#bft6cn&N^O`+GwvFL#{ zay?h*m2cK(iF~dPRYBT7n;i#waE_hSdAVEyBH|A82{ls{2p#X ze_clW9oeGKakz^w2>1%4ZGFw@VO1+&drjr9bqii%=XyJAJb%8CG82NB^rWg$PpNv_ zQv*i~9dO@PH1c|{XAI1E@A@5&%XGM3JM>Zxya@4y=5txC?k6=)jDI~^@@~e9EO^~` z{zvS6dbsn%l>s|HzLe*g1zTk`-dX(-Zgphcw0Z|Hlo2)%XWz~Rj+$9PkVmYL;odIb zz#Hh1KO;TwFEZ)z9E7$SF6xX?A(zcK1Vat1H)iOYuAdhbAnkzXW5kciFdU3cNkB1q zC)t|52i6yT3{eGkA=$mrduEA;|Ta*IfYtL*(#O`k^M$S~UaG28+L8+^kAi90Hy=;_QhxkUzl-!*~`{ zx(9juya{=_L#uM7KO*H)4kl03HY-HVmn;r=BD|5GIK{=7dIHscq;WHJ@3pIN-KyUD zonmbL#$xyD6K{4{;;}<|jwQ&i*1q&}a0b(8FCVfW{slK}BtnvA1H#tDn>Pe**@`B_ z{aQF=#tXLG&WROimY@o>AFtz9A`!n7W)W{`h;3!ROxgQ2M8cOPXh}nu=?)}d6JLP` zkKKW4_bT=UpLoA#?I2MrL;#Ush6bVGWS;`1)7{_NYJ}V4s;#hw@$`Wk5jb41 zKG!a&;oR!UcvCOgrf2ch#Yky2$v8}bs?6hWRkQX8=xT@Hrzc7de{Q=H}4vb8TIh1al_*QOOb+17vMIt@ntuhRymVPE0(`)X*Q9fzk z?N3`bHXR`>d5x69$ZyV?9!0Nvx@vTA&Y?Ob$n*SFWZ2{|&t|QO^la1`o9BM5iT2#C zHL;!=rRnHdt}PNhi?qh+Dbtz^&(&Hp+mo#|S)SQilkb_LHSwNFT2tZ~uQlbKIHjqs zpa?{3{R--PX+7FH;R)0FJE?D{^&6;f$|eQX8>v60^_!@#)B3H{zpeGP)bG{$z0|*` z^@ph6r1c!9c^=mKI_mG#dJpxhw7!x03axLV-lg>@Qo@t3^+D9n(fTmzGqgUEdWY8A zsE^nBXzI_^dK})wnO3cjr@pJ!CsH4z^^`@=$t*=XH^q1wwVt~qJV&*@ocbeLUqStT ztzSWXt=6xh{u!;mllqNXpHKaIt=~xf8m-?%eU;X4rM_J2YpE~P`n}X=Y5gJUXK4Kf z>YZADg!*w>Uq^kc)_bTQsP&E1M{0c&^&wi%c}|be`XK6m%v5{`qu!(Sk<@>v^)~7c zX?-;HyR<%*`mI_YPyG{GpGf@%t>-JcT(R=>o-szru7@CZ>RN}sBgMb(Y}@XW7Mn8j4JQ0 zyymjr!I=j3OZ8U|FRtS87XENw8d~EnT!U_@1an1JW6MA*@I zk}o-^`iiX45(|3CI8`rOSYKu`@YHF^=h_Ezm?RT|K8RJ%n#7pAQ7g8{^W9!KKaa<)z_|AGuJ3!2Y=5y-X8y<0~R$4}^M?Cd);1>v=rwMnSz@_9M z9D6d;&I?OP*t>9yNp!H&%P2+rmF(`3cJ@v=_{RATvB%$}|8ml=jtzG*>3<~*!p zs)1~zG0Gvz(J*d+kD;`!K z@$lyeA0AhvSMNghqoDZLdTzrM4dlfvGk9Jc8);36+1rES>x#gm&{?<)6DvD*UYrsI z5>Wbl1>w!v$SKTZVNVhAea-ZLCf~EX`JQO!i*`*I@o}%#dX=BZ$2-9!=6fRZJ(iiv z%w`pd(vEVA2e?!YC!bO|Jln|O3?qlxA1+a=BB(>Nn7?YQgT+e-Ixa`hJBzZAu(~Lo z+lt(JTMfK7L;XnTF_VD><(ZHej1?-E z=^aLP4i>D-pF#}iuE%e~pn`i<7NqjUz0Rz(@FX9G=e*t|kYn!i5R=~FL~|p1eUuXWzgf3nkqt7#YhRnsphp^e6>W~{PcaRHNg2<$)yVtlk!UuK?_7qP zMqI#LPkZwrGL>3=JQ#g^Cyq&aE>W)i!S{x`(en6Ciz{m74ME3uhGE?amTDX3XQ!Mi z{Z~$p#Jgs2tE~IBa<3m=Hq#GnkMPW!O9s@UH*>_*$#bbTWx<4Znh$uA-&KRlAkN}^ z@s5;uz$^%<>-&bQae``kSj;tHXo~SNs(*FTK-~0+ccGU5eQ}hd`c;HK{5HsGYM52| znhhw_kE0x%lDN$0)G1dVh$$v=u<7#}tPlI{`1B9i*${}y`O%pm)Q;mI-8o&Oj)RQb zPjq=8;+V?Gq%agdTSKpx(5Xbpo-q)SB57D+>f19-C7!)ev8@y^tqH(Ms&+_l5lo$gDpRUgxMvz#Y(1cDOxmus4@ zdr7V7+97Z0XVRLt^p_^B$RW480Zlj{0(#cDNj-8X?TUnuHekt6N3; zlZ39guf{UAU9kIHP=FgSVCVkExGL1$m)o+e+8sSay5rstM2)A=fz=w^{OadAAM`jA z5X0q8yu#&7a0Car)1XBk-w_<<#@w78J#x(^*gow_$?TGL0Q-MHZvnbe#Kq_wZkE)aqoo5kxsE=HcE zntAqVtBgAAlTkR~gM6v<1T|;a0z81(D3NVOcI{{gA!|&opM74fU@#DY>Iy=~N)MBo^Jy(fgi<3GE&_FnB+vD_m9vEXxC^+~qXia0|UwSzre*ZteK_6dvq| zn9@ag!4_-m>8!>5ft;f5j9oumNx=qS-sY09v-F!EUfC}PErVw{s7n2=#;@jVqPk(j ziFbMN;DYBqjE2{+@S)r0b*X%*0@$HxQm4{AH)E-_g&*|E7&=Rh)#(!J8yYULo=I)R zOVOx4Tpi?jW^Jn&Z7Rml+F6`J{k}7H*q?^ejakAKgbScgVutNBSAB=xr#?=KST9BT zUdkOl?p`O)EosdWB9zww*pA+}G#=~Awbpezs`1wvCo*u%(dN+2LFcA}q8+##v(I(N zu*?PXde!NPp2MFvhxMkR!+eAFffn3g-c;U*+tf#+!%|Xt zV;o*VaL&cLf?AHk+SaNCx_ZZ*>Rgr5cd7?_<{N3W$V$z&n_H*B+|nE`Zqq3k!sD57 zW~U2$oLc3RS__Nvai<{u=lfsG0h^UQQ6YvKFwuaQ88F{~*BfxP0UtJCtpPtY;P(a$ z3e)ipG~ieRUTnZC4OnEr3Inb&;6?*JZ@_O1=*NR&_&OV~j{%1oaGU`zHei+kT?SlZ zz$Xp3(}3?9u+f0+IveR2aHs(%8t`fZUT?r#4fvn|HyQ9{1MW585d(f>z+Vj5zKc$; zmjQ>$1`OddD?Z=5M*jL(wW-~3E+3K+;_VAHjIGk}nM@5^ z2a0<`+gA*0+r71ans5I&d?q2g$yY&@|rNS+Wgi914#av;7D#ahuwW%}d!y9e=)lOjk_hBG!w=MQ3nDw;iF= zg-@|zEe z%Am`}FGI`+#|y=Eu*pFjrEo10^I$514^qEC#n2oV-3ydUHo_H%>kWU!unz_|%=qaq z2kvu~d#;hD4XL?R{B*Y=-C~t0@hQO{W7HuE;8KMAwShCFQe!=++q#H1`+rEKzPnBo(8SpYw|z}Y6E#R%9IBDQm2%0qlbFq0d^ zi8ho3@-rLibWRm194SEzrDaC{HivX5oYD~k@fxmjm-1xh_b6|E7a<06AQ%3~t$Co; zh7?K=cCMm2&q$*XP*Y1@FkbC4A3ja&nySz|8z% z9%vWMY4VJC4*zeF50f5~Z?RrFOq@*qwM9XWm+zVzCO<}@zA(!hb3a>^5=|FNTU&A2 zlnhdiO`MwfJ4&4IjnBmA?DBIV(rP=!w)0f;VH9c&6aTYMk0py`_FqYFj5oa!$f%Zq z1&FH@ak|03LU8T$l4O?6W{#Qo$9dyBd;Bwjc@ZS79O=4HhRGq*M2R$Wu{kv}zekD- zyy>---^IvP=9jKjS-y)^ZNXYI7j-0Sty~p@DMu#M^o(pJPsEBbvVPEY4(l(w`nSAi;%=ehy zzp!JvKNh5oVpD@QcQDKuhFSM&U}>1c4EGIRYyaVfIngjN?Fk{U{eT`pf_g;p1gJH(vocd-PW-RupZ_St5zs)e)40Auj z9D7u|mmB6V!;A?D^)-I3-LE&yhYT~%BkSv`EU7G!x<{D?-BpkfN{PlI*yvL-{^9Bm@4F+f8T<lYI`hMmh$@ca4&O zh4{UY!A?sh8R2xlwI5;+78xyK8;kh<^Z9bX29C7+i$=Yq|61C&ZE|8;=I{MgiPQgD z`d=!V|19F{{(NItCYt~JFs3@2KQsJ)q(QXGedcoh|7{7dEcO2BTlN3(ubG2{%Ph@* zewMTQGsCwn)&Gp`KPmxCsVn}>6lrSKhZ*k({9}r>kJkRrj@o8lVWL^Db$lnH`KwsE ztg>qPO@COi^5*JQHLGt~v-Z|MuDk8_JMO&e?t9kXd*A&V9(eGfhaY+Lv5kNF^W#ta z<;lNp+Wgeh&pi9wmaW^Kf8oWKUfy22W9KWoUfsQC@4nYw-~YyegNF{k`PSR-y!+mf zzrFv#haY|XN!_QPeSY+dFTe8Cf8B8G@85je_}%wE{P@%H6HPz=^6Sap@H(x<&%a$j z`@o(_t4z(IqDM4vM>=G88~FQ0S8m6=&*cE4fK zjf$&Y5t$t{r?I6bG?VF z5ax&7WwqF6;Qg>+tA)7+X0wk;Ppey*Z)s)5_Ldg@alojB`PNqEKejSIF!Ren|CxX1qTWw8{y56hHrJu2#y@Ns$KMELKf%6(F+0Ch z=s6c=el&AjXnuCpkK`Pe{y6hginQ_#^Cb9XZhxGIjIXNS=Ap>G#*Pl#7cOv@lPZ z>nf)6^xP7c>0o!ybC&_xRCl3@Jk?#KGTvTNTEIL=&n}(o&F9>!O5NF|UdE?T}&2VYiWiI<%SHXhZjN%eEg%lscX*(UANXP0z_PpGQ#pOEW zOyp=XMpL83D2&7$nB`AX;i8etl@hW>p|O63NI|fq=H?iWL3t-xH2T7~O01A(s_nLB#a@SH-U;%d&P z83prmi`_0eJmH&^?aD5+C6|^Km)Z)7Y-!ow0l8eZjQ}WY%4CwEwbg7 z=gxJzvac#s1qB{v7STZWJjjgbp=K9Yp?lbbdh*SOH%k9ho)kT6ZxJ2akQS^LHadoHKl)(cu>sxbn%$GFNt~iv6F8wwXVQ zN`nsUX=+Ws%Sc$ur!T#VQeXc$xr)WUevE9HIb+f=y^`tcU!^=`zz|!uK?QTiH#AZ> z-G9F!U|nHh@j{i~2;C|hbOxLjuDRs28Q?Vk*`@Q`^K*+_Wwz+t1t@t1dA8j7C9dnv zX)|~WJg>^NnT0YNh@u?idWDFBVw;~kzu0KX`intm-TR~0Mrec1*Nl0w>5l1tzGL5) z#V>D}bnCpzhN5Zx23SC1(%3m{Kg#A@0^z!D4%V63kd)0SE0|wWn44K>)FX4s&x@Ng zEw?Z?yDWFkMKe>TD`&Ho8D5g3YZ=Y6-}_~n;a!46mz)sMC9b3BGR=A@w6lB`=5=tEWv&vcvSmXOGk_72!t(NgGJXktLQo^tg%yF$f4lcppw9>_8FG; zexm&}zl`vxU=g*eqlj_==5!EIcmpVETErpZ%J`q?FT|@*2aNc`6>fnFH`7nSARM}f z@|b?QwijJS;NY>Ayp0fC!E2EvURbB;d?PO&9f^y>N1;D_5C(iv!#jxHIlDyfxK~7P%gdru zZAeK+bO1c)r`4gYwsZv#a=`x?9l#6dr-iAWi6zia1X}J<{AIjKMFfcm7gSE5hyYI_ zMupdgpKj;Pmxl9&I0w~)4K(xXfHOSpCN}frPjLGS6yqig?;b3==X4U?<3dIEXzZYfe(Ym~I0$v25ns4Z-jL6J@Y8J^(u0~~_!&bz)FLxXmv)f%K+$ECRpmLuyf_|b zhoH)7aiHQII=d*&7v6*X2-nt(muDCm@nUA?`Q>oeS-deW*=vCyW}_QS{82 zDtgYy5Iy6jh@O^Ip-YU;mqZ|CQE5WvkvCDu8$;%6E#%=N!AbLF*(b%Of{E)Ra zv?L^}V{9;FB%JZUe^1m8Jx6tK)KqJ}F+Wyaf=5!J-Zbd8^y(;jxgtfc8QmeT-9#@- zXQ9I&F3Jhwfy@}W8k}YFuLh@kwnKU2VYwe=lzUeQcmO^CUzGVqlkd#8{#OW*2i0Jt zUq45PB{26iWIsH-y$DCR@KLPUn$!E_N+JBQZT>vNpQU$*=GYK!bP#=9&x$@d&xk&8Pm4a5O(M*w8%j_&XgmTHt!5mr zEymjqOHkLEar6xmVR4u@Ep4v1S+}4#i+@ya$5smQA(R;xf~dM6st@Y4TRYZuI22eL zP|_~TKf^DUaXRT983Y-I0>2}{@5oVIOQK>sioS6b#C(P~5ftgDiReZN+En`TOy`b05Y`_xr@xFGzHrVHKTG7CV=!8aRve#F8GC zv0W&qE|k-pP?R;4w_CgFwy)GLR+m|nRmf!|{aCe4R1Ii~A&)al?= zSMZAMoRVjly=^z;XcuG{^?DTQbwh^h%=~`-DIq?9syFgms<0>oDVbH8UHyN3BpW%94^^8=K(OsaC%jOQ83Xrn5l0e&JN4l7i6=(;o7 zj?TAs%uw}YXYintpXf9yI5uinXmVdyXYe>2^<|jolGN$e;Krc3_J`Wl`WZ5>zf@*5N=Fgqb}`^{OdBhQ)%mPDj!uiE5daW)~7m_SR&9qB94fsI+cWGg=APd zSVRZb+np&3!N3!6l$Hfu$27O)r(*=)uNe zr=g`t=-N=1rz}inDqJSw>6Q=^L#$1QL0^X{0c*3}XRurGnIfglpa1Mb*1Y=9K4i^@ z|5x@Q_qF(L_pPyDo-Rqx8>C^xH%lyTH$B&Po)7aVdhSo;TPBs}=B5=~Rm$njjUq|S zYZx1cF{!s(#pNz7#bDIjP8<|4E4#ooskn4H2Em27MojbJvnaO|!_B1PqO#(`+$2|N zVKN4KMsve8i*lxy6ci;DyMgC7h}W0TZ-VcIxsd5r z3E6!m0$je#GO4f(VslA$A?DyOrwJ_5rb}s3Sye&4`AFL9KBa3$KIcYLz?a$dud`Fc z12O-xUZ!Y)4vVYP z3v;m^bBj^>=`af?BoJ#-2DvASsJADfFLfbfnUb7NeF!8Mc~+34>LRRchz~W-AvHp5 zP~nZr4Zff9F{7%2k9FjsPt9@#a?)Lv&*Ue%^YV~M7*nYjr{(Gl&Sr?@qMRvt^d!Vo zVq=iV5-!9D|Fop^>=MmoNZM#E5k~C;i~kQkKZC|m4}LQ2t{5TSxWe{k9!`Rrq$fJ{ zIhNMu7Q0fyOxH6*rlVW-GyCy%p??!MU;F>)|HFa*aNz7Yz%thj$}CS9vMD`=h9VLw z04fv;>%?kbN+4heRFDBX7?At0>BhY`rW@mBSVAil(_mFVJMPQIuv;nG_k*JS7$}<2 z+$nRCVMe8|!b~&lryG#9Fyp@zifMD%mGR7nvO%F5SC7=8>!k1}9rRxTMVyx!a2X(J z!8DU{uL5K|*x#d8&M{S^%ntw(zlWii-eXYow*`tcaf*@d??KT$5=VJocl@pKX>D$u{{OFLT>9c|d&z@!Rr(yjzYG3v=j%V(hwIns z^EW<|?hW5+em?k}hU7QD3RV{X#*cLbKh|%)U+k|s-E$2XZNPyBv>C9M0V53aj<#uFN^qXzuYfO`$N!GJ3a=*weYx&C+S zv(9Nb?r0tV|Fk>#@VmSi-8TMa{S*76=KH3fG%PXbjXk&RaINY8_n5=Z`04m z>Hkm1a^}MZ8nZL+9{iui{NI=U8AZSt)t^xWZ2vwS{vV3zf4N9(7^dqFi(fkq)5OCV z@MSH#ZdpHr#gBfXH4i+Z;nMr-PEwb+xI)2=@W11s_aCxp=hJ?dp3+u{27LA`{o4)y z&%yt}2ai73Lwxa|=Rs`tX!UvHU;KayF%<*UsqbI;zD;DlfA#yLTKUHK?yVyq*ZnNS z$i+J3A){YZYd~COsQS|n8~wfEh=EEN^>gDW&9AqU{ylJs@%?DTd&G$MpM`8&h-d3I zhV<|glLI)^{jYy0<*!5S#~!@>fTJgf0jB_2}VW>s0e;Y8O zueOf_JOD*{j{$bF2~h<g!pETKeihc;I3_am%P)xTDu-$n=*bp`h zFq#VbSiq4`=R%(dXorf0-T}B5Dh_(WDd%gx$Bw+tU&;p(e1WbTp{Nn&!P>hrC2}4i#nV~PS3$Yn$4#L&}j(0$opicy> zgkn5ZfbSdn4*?e>>p05+ubc!Kga0hRjTb?Np(or8#XQ;zI5P$L3;k@spP`6Im#l0(MK&@k9dVrVH^S?DGMizgU-x7Xd$+3E6HBJOO{b1bcX(KMB}>md0}+;Nws% zM^6AQz6|@?;im$y+vVCm67U363GAByubrdqU4XSv#EtL??Av=7ezpR-t~7WEcz!12 z0rv5L#ZdHL0=OB9yu$roV!xp$T%WDwhcMzQ9Zw{nbFP+W!tS}c%tius%7Y*B2e92d z-~>J47N~gQ26$mU&d))g2>6Pj-vyXbpzYHDk3-FYpC-T!*P?7dPgsfx%JtB@03U^7 z9`W6Rm&&qTmGpcwW} zz|ckD1N32l>#0XwM7U}(=*0EJgp-yaPoZ}L9)a2bKZNPakRI$a0Ebth%tMd+*2HWm z@|)!^Puu|(20V|*wC*f|xelK9u&EOT{ z=>@nMY9nxa2C(urwp1cj%^I@&;1vnjw@yq~x1d4cW1f2MY#?t|K z-zMZQ!fpUe->mtc0r(446YNg{mOQ0#AdGk#@`-Yk2Ez$dq( zEr5O#V6R%;#t{zQq3xpqzkdaMhMyk+Z{CG=ANZ^S{Q6bo1@y-NuilL_sL&Sz#_mOa zKu_p^Qtb%fy-+2v-vBt`HPA>ufHhF7Xb+h2I_QEv3vkGO@D}<+z@MNtLEi*8`VDM1 zgdX?(iA$hJBhM`GtigKJ8-zR;Ks_P%=|7A%nvi?(X-~*K>eLf*e>wGp+!Ibc;X*^t zec{~eO?$$>7<%sSe$&tsa$hq25O%@-N$R;bnR^_mC*)pW>Iu2GmwH0((IuXQ+#gGO zLhi$)o{)PisVD4f=(*2wf}s~@@wHQa{DnVYG{mP9UT~ZJ#E-?p0Ww{L8XvAFz=`)Ks370&xXBej$DAcB&gY3yBO^< zm}tl;E(1 zzLaMe8fgjE93p0j@cL6DF~{sbNQ%hE1n z0KO)ge_K8(JZ=9$_*ez+i2qM_kBrwIl)34RgAezAV!!fBcZ54;A1CpaMpKCLe{lbS zhi2?=I(e|7mS*rr{x)-a(@Et_|KM-^`X;HI75^E9M?2HMx+D6Cc2@B#+!#6ITVZ^) z$|z3utzA;*UooKqRh5tOhu#9EMB@yQ?)2vyj`6gmmcU+C2n&=yR3MZUs;{J+he6q( z{*j!=#l;C6lo!*dPZ!r;f4#!Zl<_rd)`&m<`Oo5+XP!|q{_eZ)iZ8zS!Yk(`Tpr$p zI&{;PKuY=zB{#_D^0td5+rQnOcTKTaf-K70j`vKqH)KK*u37TUPnpj_v*f-n@XFAy zc{lF+V&=@5+w;=m9tX_4CiU7WQa+n07q1+${qmWaVu^fc`?E6{-!{C0(Fn8r`-u~q zgp%SL&?t7KA|G|oo~>fK_Vt52IswF#rW~# zh24((V^dNT@1{nIz`Tn<#Q6Lv{4<~1qC9gt$q8&V{_jcJnirI`AO6lG8|Ka=9}ucVk;C&g9A zq*%IisaUykrC7Umt+?ZkJH%ag-6htqUoSRn*dQKxn>K9{&p!LCs>@z{@kR00 zE1Sf!@1%IPQHobzeO2t+w@2$vluT& zip%9xah<$Y+$qB4T7q%F8q9xe!hQ*apVx@CQihA05q>?w zKZ)?Q2>&L+AN2`87~vB$u+y>xW3Dy0BW05ie?s`3jp+L#{1Jrz7~wxh_fL3lRRga3OCVDdfFVh5YNaLhe|LI5!LV#o^}g=zL_fL-_Ux z-vQx+5gzqVBRVnC)>+64M+!M-s*u-TE94z(g?w(akZ&Ju4lg>14AC9^oql2s?#A1M z+e!~Y@*8p2uMEFT$dM&NPQ6LUYu5|8_9-DZ?-la!CqChA2!9^Jry=}R2w#rys}cTT zgnt_0Uq<*n2#++^eu(g2Abg`Y{JFTfWinzYKn#CC438j&U5MdR#LyTn#rGqn_;IQf z$FG&*#9AqS-Ymthhov`sPlO+a@DmVz8p6*-_yq{R0^#opmpBV5#WPc-*m8jxvt zaHPN)|0&Qo9GNla(8EO+*$ns8^rYm}35Y&9$v$DCJ@Z_87&NGVKf^sGJ<*YTD;W)6r4M?VV}mDP*1#JuD6MGyWu%gvqtcagjiQCh$+i zKQbX5EKW~OO;G&KsO&w-5RVCC?e^LGcOns)}g({67B?sL@_;e0tBhq-G2U<*wG#QgF2_cF=--X zIW8_Kso6aPPCSy-=G^d}LM7f)i5b770NcW@(5Z6>QIQU2YK)@0^ zhIg8hnUp>u0kY3|tE^qpWUZJ`ht5SURE1XmmHylk#L-&Gw)%1vVnVC_ z-0$~O%>LZ8Y134HWO43A-oD3UC?Qi+k?5N8Eewz2bof9uN;d{IKdPJpJ_3sz3Pr^Un+R72c_ROx%P1#wPR? zcJ10F4jee3`UXco`$T;9*=OSD(W9cFp+Ouwc1(Q#-M6Z5@Y7E}iQj(vO{_g3#b)#s z4*%*?&yMJahVFbcbSRf==Axm)#NWYN(9k_9!sRn!qQ-Y4@dQn9yDmkpb_C= z)^kE(?$K|+kRk9J9@ck6%!nA#tN+mG5xs*)gu_Fp(9k};`VER6(J?r>k6~f6MGqYj z6ciGTFz0mc6xt)Q`_K^`gMxxP1O$YfW3~2Z*S^Ql-W`L2X)z+KZ$zLaus{5c7}2{! z0ORi#>DL9Ojst=_bcn$?px>aL{=MLeAiZHm`Z2w_4jB+LVnoak;E(i&#>5PaiRl-k z=<9{ghOb{gWfV)SxVt$J9?@4;$^zKdM|;x`{Ue;{tL6j+y5}Mb$|7v|{V#of2#p@Q zK#$$40-$Hg|2MufQU7~s6W@+d5qf5V_C{JRVOy zX#MofH{ZN($BrFKCQh6<8u2indO>xE3Wp*t%-3K;QBNMzts7KtsP34n7~Ry=^b7Q8 zIL{jYDDe9r%3vJhIRE_f2NOTwrSO04wbvx(NG0%-Teogicw-Jpe);8>^3b6}5_1a5 zAH$%JK>MQzbN}Yen{V8*Wy_7|_9a(VR!%7?DRHb`y*dN^YT|YdR805o-A7|?O}@k0Mk;s3)AKS=at)(#jjU<`P;`s=U1mYCD^^7-JwgYs{G`xIB|ENH-dvMd2z#J}JzDF?o&i^W-C5B{UgkY@c)`A2&ssm%N!B>twHQ~sGBlq<@H zNejz3<&1LAvSC7&3x3l-mGWZHkP7*q1b&l-@rR_m;0;YfEXo4r$z}9*<(>8D*?bCr z)WvHt$3F)7u$twJbxT`xP~Ls>#FQ&S@}KT(7Z{fHjPG~JQIt{A@R5`$pdlGFZ2G&e zk2C7OgUj7#ASUYPpMREUXId!IU@DW2w(`WJ#g~p>fBjV+-gd8iWKpWT``QWe_Tof^ z*kxZzITMexPOXzNoizN-D9@0Yab|gDorLntI%zP<0n76+$P>%-DXg=#L4(2{`MnBr z7yVJMSCJOhhlC~#gp_;Ab!$3I`J${-mOk14jC^e2IQfu!yu7dMLPY}!xT0RlOAQ(_ zK9MpFI5|Osw>*;uqdX61orF4d5bC6UprP+pUAH2drLAaC`1kMM-&_Bqjb}T5T7Izn zvOO^KgXMu{vz!or)O)h_jvV>;b>rlt3&+a`LBqYEfnPT2&pDuBHtP5ppGip?%<@bc z%<{}SY2+U8{S_(CAr0WaZJU%+P*34I&=&rv@0I+ctgU8$h-J>C!=#0I!1lm5PfS_} zi9hSfXP4ULlQ$&DKZAxxK*Iwrjeps!eiFNoIK_4Q6>J4Q6>} zofQ3o!v92T{8`S}zM!AwRiwdGt?4k!iZ311lLmfUmRum8S~ONZd3}QXQ#oi@Fkb%D z__cfw#hEl@f(ERy$yq+-nROD&vmIrDby7U)B(~3Hoit>-lmj&Wt?Q*I;*b9Qsxf26 z^hY11igd7EB&5uc4)%EnNek`R)|&k?y0N`wpMl@=6&J|o7GEGYgNDC=hK-=%#k-2- zkKaOg&f=>Fo%4|=@ob+#gW1Oz^0E%xn*XdXO!*%>cI;s0g{fFxi8pa0?j|j)`&r*} zT*G>kZ57)#elIVJm)k(Yvx~>dO^Xub6QH4WdA<#G(%SiUx$2sUaz#Ostelr5m*hBP zwfi#p@q33PY4Gi1sPc?DiC=Lf z%8Co+OQ2yZXn5vE(15bQ@=O|7o>?c|g?g1VtRW3oPn3Vi2Mu`+xi}|T(Lg-e$6)(x z_A$nweZzN}{Ikwr8_a$L)y9n*<>QY(F4-?Nm6;!ezgJE$FDnn-mo0Zxo-bcq3K~!r zo(2tnHOe#VqzBv=%6m&Mly{a)kn4&PGFSq&O)0u9SR!;PSUU+X@`l_(qdPOE>2 zKV(74KjgZKwA^&lP4bB+o>26dG!UMN4$?%~Vpz}Nr{&J7^JOh)cmXu1@(dbSCz<7W z1L~ypr4!^GC5iHnpkXy=xEVAoha4@_&r*F`|YIsbjRKD)m2Gydu6z;KGO&2@Vnu_me6^;f zb)L}7I)P>3AARrbdeYm+V0o@F%5$r5zuW&I{>*!))5(00fBMs(RNsqz8q5#K1q&8< zY4|-lelJgm59_37SSS6X@(ddIwZZGQtfI&#?6ui}x>F7rGDK!(W=ibMknGo$m6b`C z%OzK>TBXW0rhHVr!@f{kw2=2~8(3GdFU0;R#{>LWo)13imM4F~c;lf3s(tqDW87tw z=QSt`{Mtg+w8LD56@C2~Ff06r4I6eIw)Pa^>5T^Tqg6gU_~3(b%9JS*dy8aEO^w8w zl3cfLox+FXd-9t!uq|LaLAj#h7=|>kKBXM8EhLY2RXgOHj}ial^0kK-H1{!37TCvN zd1jq-cX>L||A*r*%>AvzQs`334`h8U#{FZk59SG!VF@>hHz6d-grs@$!^2|EPw>c zdzE}~c_P|p-N#`2{P>MYa?2m*$q!zCP9Fd1r?-&bXFdOby_B-5s_F;qQIgA+E&J)R z%Py0Jg@uam7*{G;A`L7TocAGaq@y)0oP%IHOu1(tiDiZJ5!*4Iq#gT6Y$r%d8y{Hk z^T*7ue|G+daiQ#Pz#Qc#H{5W;DdLHJqe`(%n=}j^I#gosn#u>Z8I*bUeM~xtFY%|$ zlTMBe2w5IjMpz!qJRzhEvTtIxJsf*;{0w>dr{+IdwkZFQr3bKI>}{4)tcc4+ix#PT zAPuZnF}Eyd&z`O9nFpl7RHVTi_i{|hJ~ri^coI^ENSi5Nv}d1+eQwkxw_@(;JnS>P zg=2_+1%Jvt6=jL@&7_IAan2cg?^O9sN=lN6iHQ=sQ&c|ConcHG2u-;%^TaGCEFZ+( zgp?zW87Nom2Qu%>`3>OD<+c#0v-wp03A$Hd37|iCSjF=E(n~KX8pt2c8=`zD8nUyq zWm;OAk}a&sEBwi8@|?5~Z+YwxSv8iRgsaAiOBZ{ zG4JF7(p>Z5y3W~rs{dfhAp1WiUy08rpM0Y5LEcLAEx4;#l?UXvguE#kU>ij~(?1o> zq=EG)dCL0#si&TjPd@piY6JiJ*T1T8oFf3AJgD2QKpVLTxbKABAAmI1JfpC7OHF zKTH#|QJhh-lom2JKn_jFzX~S)!AZ_N_r34?p7WgNJm)#j^L)?y zUUUuejm$wm^MHBDm>?&N0r4!(yTo_uWsDdP)^qju$D$j(2~K#k$gebo#@MOX(%dTT^wHAq?0@ll zGktJ+(e=gkff9bBo3wUYKLMFyt&Q>*S~-S(#>UwY;5x`XvINhWL(&=TqGKYokI)~L ze{@82JjNRn`bCU=$&w{T`*N*(JDx{Nu0xiPb$(|JfOdzE$VYndHfXo>(}weZwf1}u zxnvEZAIw4cg#JL+u^vUo1l}Gzc+l+Hwadyg{C1gsBRk9;>?V$p8R}y#kj~8L)kPEK zJG7JTg`ViT2>mY82bZrmCe)!l(Y79BjC<%C^deh_q&w-0qh0ptz6r{Ef$A%tHvXge zW&K~R-<#38xkTj4YCiF~~=!M?}-px ze@ah`#DC}mYbW*#`VTo^J!0*I$M~G^o^ikyaO1!+Iv-t&9+OXDaSiqPPSZ|5to%o1 zW2~IJV>fT3C9=*j*Dw~yJbb2)$hzd{vTTGwjTP%Edn|5cZGyfVrBCPr_8|N(Gi|W< zfqfdcolKh+mqY8j`Xh9= zQN4~2hvmTSl&vA1rch1_%gJFmH7xH5%XnB;hGlD5nnF2=vQ+dWlxHhXaG%x`-HLrn zMxL)}D{7>lR8|z+TvU!GjzLt$#sgK|xQVuki+YvG3$i&%s)}U*oXy#DSS@Y&Jx9jPyEZ0bUhmA>!te`qcEr}WZE+2>t~lhw%vo~!F;D3{3IIJZI=2RIqA(AkRLf_Z}%A3tx*9~70- z^GKw#y8c?})6(Id+8joIq9gH_pn>c#jL_!4EWLVOI`^3L=4(_8W(wX2&IP_gOdNdZ z?F+{AsqZ&|^~TZDiYp`)d#Z*8Y$tqA)<^U@YZ1B{TNXQob9^T~Caem~6RZu4hy4p+ zRNy<{{$OmRYjs|~$MFH=gEq)tsAK(QUBl0%UF>Lh687KPPK6o^pWtO*SL_zN53KB! zq3GFhzXM`L<-xX(KZuP$h6XbFoeWP{zs~&qq{%#8ZE*?W;iP3}gm;}T;HHa21Gq1H zAc*aQ`8s(7?*(TpSNZm6nT)fh$bU`B&aH+HM+@VR4Gb-;Kd(PuZ)4hE&cx(h`_S+W z(E#oVes1MaG=Q~%@gR?2RA8OpgpX>DDD{S85@#J(+@(R!-_@};lN}A%9Pk9&`sGaz zS*#CyhBzXLw#i_x;KyKoQF&x93m6Sp9~cwz_}O3CTQ9oyv4b4G$hwN1=Il2|3wID# zCKl)^o(blwXX(t7nqyHKkjLsV@~Hj$c22OD26-HV)5U3DcuG=nh3Y6Bw2hoolEB-* zNWcrhsSf_A>4uo$=?{!)J|)akG_aqCIRR!%a{b4y(0?#Dw6?a^VS|z#9mGxG1&R1N zSQ8irSQ$7I_y#x`7!%kA7#aA|w`&UdhfmcSXt44q+|^;<)E8|Z9YDsmAxG(e7RLXL zEtLkm>wst=rb%oZj0JfF=K@~=YqS_w*#5@HAE7BbC!9Ra5+9UC#vj{EI7Cv#_MPMA%sVGEC&tL5<^=Lc8n0m||M=s?If&`P zWBe=4MeA=dH=)UmPjqY;i{Cz5Wrp58ZqEJf#1(neoB+Q@9(Qkgl;+1>|D{{8x8t-g zEaI<~l~{G_EjF!pDwu8CwpsrUn$U~P1L%MUj1RmyKX}soe(x&ti>K$T{Zw(NI$e%q{CwaUhUwMWv%E}ZWJ&*2CB z$G<}s;0N@NP1LFDj!L$oYwf7^IS?-PHO+hL2eQ_K%YZG(&NABfZTs!~FX$k{59k;> zHqghqh3>#FRrOy`#=g5=isOUI{x}Vm2ri-LObzi@XjrpmjpaM~fOU|%oeaQQL^&K9HcI6JNQj37a1g$4z9ucfKC^?Vhqp=+y^c2 z0=SUauLGKALdar<4xNxDR4I0Q?!yMo` z==h9CMp~B4g~|Vef^W z3$XfOg8im#Qk?#e<$IL>i~$+li|%8b^-c)n?~LMM&!`UKClgIPYf?19%>25Me!C`J zm*RS6chbo7y74ygLV1#M>?ShTxqITegOzbZZ#n zES-KL+8B76_CFJ6{g3Jxko;X>9^xA#uP@67StPrTeT|j!t#-=~RC?9b!L`UVHk`9( z+?+y}eN%oDJ`*v7qcUqguYH|L&OVNTAJ7(a4ZTE0Ub&Z)lzV~?{A$4@v%iHO@2fnB zZekumE4Bl&-S^9v%(IOJ+ps3|-|!#tU-1?2Rm$WmJukYzTJg!D9r>r-?4||Q#yKw^ zY`18p4t#NZFJck+efXU-<#!UJ#-@U9^cD#p1|RBY&#f`k5l!z&#S+sYj)2bw{}?CM zAnYL0>)(CY+FSS^_#XH^*t+-|xfh->)PWy9Uvw~jdiRXQxzSox-QNB-@=%fPbTwo7mp8l2 zfv4u#{oF6MeA&G9T88HJ#=t_-vn$qCLw_MR=xuB+#shsCrG@XTe)KeSQxCk*c{`t2vxz5hFMc*_x3HK|_fpTMsku2t%CX5| zj;Xv>cGqw{`5vyFq(EjOQKWK;edC(mg;`WM;(co$(mAe~X5Y3pS?3BzylZWW-e|;8 z!oF$k!{L=W(ls9muT0pttWAxTC)4Rv{j${?5-s(s8`85%);2dhn66ows!yixtFNtT zZcH~Wf8xHH#`*`7>H7QE%_vFKCmU*)r_$~p24|JbxWBBV;$t68B+8#?UYoZ6MR=37 zJy5t$ccxP{YxTE=8*DuZrSj&~nzd>r^>|ft?K=Gv-ilOu)D$1vi)IIvy~|K_Bs$AF zJ2Tyx{h6N3;Y@F)FVmkH$P8wNx`(@)vMt%R?AGkgY%+ zV0I`woQ?U@{35^DPxz&NnLpE??a%kC{KfuKf2H5#xA<-TR)448?sxj#{(is5KkWDW z1OA{tk&4+et4U?><4V!3I#qFiw76O-Q~dlDF^-w)N[^-]+) --(?P\d+[^-]*) -(-(?P\d+[^-]*))? --(?P\w+\d+(\.\w+\d+)*) --(?P\w+) --(?P\w+(\.\w+)*) -\.whl$ -''', re.IGNORECASE | re.VERBOSE) - -NAME_VERSION_RE = re.compile(r''' -(?P[^-]+) --(?P\d+[^-]*) -(-(?P\d+[^-]*))?$ -''', re.IGNORECASE | re.VERBOSE) - -SHEBANG_RE = re.compile(br'\s*#![^\r\n]*') -SHEBANG_DETAIL_RE = re.compile(br'^(\s*#!("[^"]+"|\S+))\s+(.*)$') -SHEBANG_PYTHON = b'#!python' -SHEBANG_PYTHONW = b'#!pythonw' - -if os.sep == '/': - to_posix = lambda o: o -else: - to_posix = lambda o: o.replace(os.sep, '/') - - -class Mounter(object): - def __init__(self): - self.impure_wheels = {} - self.libs = {} - - def add(self, pathname, extensions): - self.impure_wheels[pathname] = extensions - self.libs.update(extensions) - - def remove(self, pathname): - extensions = self.impure_wheels.pop(pathname) - for k, v in extensions: - if k in self.libs: - del self.libs[k] - - def find_module(self, fullname, path=None): - if fullname in self.libs: - result = self - else: - result = None - return result - - def load_module(self, fullname): - if fullname in sys.modules: - result = sys.modules[fullname] - else: - if fullname not in self.libs: - raise ImportError('unable to find extension for %s' % fullname) - result = imp.load_dynamic(fullname, self.libs[fullname]) - result.__loader__ = self - parts = fullname.rsplit('.', 1) - if len(parts) > 1: - result.__package__ = parts[0] - return result - -_hook = Mounter() - - -class Wheel(object): - """ - Class to build and install from Wheel files (PEP 427). - """ - - wheel_version = (1, 1) - hash_kind = 'sha256' - - def __init__(self, filename=None, sign=False, verify=False): - """ - Initialise an instance using a (valid) filename. - """ - self.sign = sign - self.should_verify = verify - self.buildver = '' - self.pyver = [PYVER] - self.abi = ['none'] - self.arch = ['any'] - self.dirname = os.getcwd() - if filename is None: - self.name = 'dummy' - self.version = '0.1' - self._filename = self.filename - else: - m = NAME_VERSION_RE.match(filename) - if m: - info = m.groupdict('') - self.name = info['nm'] - # Reinstate the local version separator - self.version = info['vn'].replace('_', '-') - self.buildver = info['bn'] - self._filename = self.filename - else: - dirname, filename = os.path.split(filename) - m = FILENAME_RE.match(filename) - if not m: - raise DistlibException('Invalid name or ' - 'filename: %r' % filename) - if dirname: - self.dirname = os.path.abspath(dirname) - self._filename = filename - info = m.groupdict('') - self.name = info['nm'] - self.version = info['vn'] - self.buildver = info['bn'] - self.pyver = info['py'].split('.') - self.abi = info['bi'].split('.') - self.arch = info['ar'].split('.') - - @property - def filename(self): - """ - Build and return a filename from the various components. - """ - if self.buildver: - buildver = '-' + self.buildver - else: - buildver = '' - pyver = '.'.join(self.pyver) - abi = '.'.join(self.abi) - arch = '.'.join(self.arch) - # replace - with _ as a local version separator - version = self.version.replace('-', '_') - return '%s-%s%s-%s-%s-%s.whl' % (self.name, version, buildver, - pyver, abi, arch) - - @property - def exists(self): - path = os.path.join(self.dirname, self.filename) - return os.path.isfile(path) - - @property - def tags(self): - for pyver in self.pyver: - for abi in self.abi: - for arch in self.arch: - yield pyver, abi, arch - - @cached_property - def metadata(self): - pathname = os.path.join(self.dirname, self.filename) - name_ver = '%s-%s' % (self.name, self.version) - info_dir = '%s.dist-info' % name_ver - wrapper = codecs.getreader('utf-8') - with ZipFile(pathname, 'r') as zf: - wheel_metadata = self.get_wheel_metadata(zf) - wv = wheel_metadata['Wheel-Version'].split('.', 1) - file_version = tuple([int(i) for i in wv]) - if file_version < (1, 1): - fn = 'METADATA' - else: - fn = METADATA_FILENAME - try: - metadata_filename = posixpath.join(info_dir, fn) - with zf.open(metadata_filename) as bf: - wf = wrapper(bf) - result = Metadata(fileobj=wf) - except KeyError: - raise ValueError('Invalid wheel, because %s is ' - 'missing' % fn) - return result - - def get_wheel_metadata(self, zf): - name_ver = '%s-%s' % (self.name, self.version) - info_dir = '%s.dist-info' % name_ver - metadata_filename = posixpath.join(info_dir, 'WHEEL') - with zf.open(metadata_filename) as bf: - wf = codecs.getreader('utf-8')(bf) - message = message_from_file(wf) - return dict(message) - - @cached_property - def info(self): - pathname = os.path.join(self.dirname, self.filename) - with ZipFile(pathname, 'r') as zf: - result = self.get_wheel_metadata(zf) - return result - - def process_shebang(self, data): - m = SHEBANG_RE.match(data) - if m: - end = m.end() - shebang, data_after_shebang = data[:end], data[end:] - # Preserve any arguments after the interpreter - if b'pythonw' in shebang.lower(): - shebang_python = SHEBANG_PYTHONW - else: - shebang_python = SHEBANG_PYTHON - m = SHEBANG_DETAIL_RE.match(shebang) - if m: - args = b' ' + m.groups()[-1] - else: - args = b'' - shebang = shebang_python + args - data = shebang + data_after_shebang - else: - cr = data.find(b'\r') - lf = data.find(b'\n') - if cr < 0 or cr > lf: - term = b'\n' - else: - if data[cr:cr + 2] == b'\r\n': - term = b'\r\n' - else: - term = b'\r' - data = SHEBANG_PYTHON + term + data - return data - - def get_hash(self, data, hash_kind=None): - if hash_kind is None: - hash_kind = self.hash_kind - try: - hasher = getattr(hashlib, hash_kind) - except AttributeError: - raise DistlibException('Unsupported hash algorithm: %r' % hash_kind) - result = hasher(data).digest() - result = base64.urlsafe_b64encode(result).rstrip(b'=').decode('ascii') - return hash_kind, result - - def write_record(self, records, record_path, base): - with CSVWriter(record_path) as writer: - for row in records: - writer.writerow(row) - p = to_posix(os.path.relpath(record_path, base)) - writer.writerow((p, '', '')) - - def write_records(self, info, libdir, archive_paths): - records = [] - distinfo, info_dir = info - hasher = getattr(hashlib, self.hash_kind) - for ap, p in archive_paths: - with open(p, 'rb') as f: - data = f.read() - digest = '%s=%s' % self.get_hash(data) - size = os.path.getsize(p) - records.append((ap, digest, size)) - - p = os.path.join(distinfo, 'RECORD') - self.write_record(records, p, libdir) - ap = to_posix(os.path.join(info_dir, 'RECORD')) - archive_paths.append((ap, p)) - - def build_zip(self, pathname, archive_paths): - with ZipFile(pathname, 'w', zipfile.ZIP_DEFLATED) as zf: - for ap, p in archive_paths: - logger.debug('Wrote %s to %s in wheel', p, ap) - zf.write(p, ap) - - def build(self, paths, tags=None, wheel_version=None): - """ - Build a wheel from files in specified paths, and use any specified tags - when determining the name of the wheel. - """ - if tags is None: - tags = {} - - libkey = list(filter(lambda o: o in paths, ('purelib', 'platlib')))[0] - if libkey == 'platlib': - is_pure = 'false' - default_pyver = [IMPVER] - default_abi = [ABI] - default_arch = [ARCH] - else: - is_pure = 'true' - default_pyver = [PYVER] - default_abi = ['none'] - default_arch = ['any'] - - self.pyver = tags.get('pyver', default_pyver) - self.abi = tags.get('abi', default_abi) - self.arch = tags.get('arch', default_arch) - - libdir = paths[libkey] - - name_ver = '%s-%s' % (self.name, self.version) - data_dir = '%s.data' % name_ver - info_dir = '%s.dist-info' % name_ver - - archive_paths = [] - - # First, stuff which is not in site-packages - for key in ('data', 'headers', 'scripts'): - if key not in paths: - continue - path = paths[key] - if os.path.isdir(path): - for root, dirs, files in os.walk(path): - for fn in files: - p = fsdecode(os.path.join(root, fn)) - rp = os.path.relpath(p, path) - ap = to_posix(os.path.join(data_dir, key, rp)) - archive_paths.append((ap, p)) - if key == 'scripts' and not p.endswith('.exe'): - with open(p, 'rb') as f: - data = f.read() - data = self.process_shebang(data) - with open(p, 'wb') as f: - f.write(data) - - # Now, stuff which is in site-packages, other than the - # distinfo stuff. - path = libdir - distinfo = None - for root, dirs, files in os.walk(path): - if root == path: - # At the top level only, save distinfo for later - # and skip it for now - for i, dn in enumerate(dirs): - dn = fsdecode(dn) - if dn.endswith('.dist-info'): - distinfo = os.path.join(root, dn) - del dirs[i] - break - assert distinfo, '.dist-info directory expected, not found' - - for fn in files: - # comment out next suite to leave .pyc files in - if fsdecode(fn).endswith(('.pyc', '.pyo')): - continue - p = os.path.join(root, fn) - rp = to_posix(os.path.relpath(p, path)) - archive_paths.append((rp, p)) - - # Now distinfo. Assumed to be flat, i.e. os.listdir is enough. - files = os.listdir(distinfo) - for fn in files: - if fn not in ('RECORD', 'INSTALLER', 'SHARED', 'WHEEL'): - p = fsdecode(os.path.join(distinfo, fn)) - ap = to_posix(os.path.join(info_dir, fn)) - archive_paths.append((ap, p)) - - wheel_metadata = [ - 'Wheel-Version: %d.%d' % (wheel_version or self.wheel_version), - 'Generator: distlib %s' % __version__, - 'Root-Is-Purelib: %s' % is_pure, - ] - for pyver, abi, arch in self.tags: - wheel_metadata.append('Tag: %s-%s-%s' % (pyver, abi, arch)) - p = os.path.join(distinfo, 'WHEEL') - with open(p, 'w') as f: - f.write('\n'.join(wheel_metadata)) - ap = to_posix(os.path.join(info_dir, 'WHEEL')) - archive_paths.append((ap, p)) - - # Now, at last, RECORD. - # Paths in here are archive paths - nothing else makes sense. - self.write_records((distinfo, info_dir), libdir, archive_paths) - # Now, ready to build the zip file - pathname = os.path.join(self.dirname, self.filename) - self.build_zip(pathname, archive_paths) - return pathname - - def install(self, paths, maker, **kwargs): - """ - Install a wheel to the specified paths. If kwarg ``warner`` is - specified, it should be a callable, which will be called with two - tuples indicating the wheel version of this software and the wheel - version in the file, if there is a discrepancy in the versions. - This can be used to issue any warnings to raise any exceptions. - If kwarg ``lib_only`` is True, only the purelib/platlib files are - installed, and the headers, scripts, data and dist-info metadata are - not written. - - The return value is a :class:`InstalledDistribution` instance unless - ``options.lib_only`` is True, in which case the return value is ``None``. - """ - - dry_run = maker.dry_run - warner = kwargs.get('warner') - lib_only = kwargs.get('lib_only', False) - - pathname = os.path.join(self.dirname, self.filename) - name_ver = '%s-%s' % (self.name, self.version) - data_dir = '%s.data' % name_ver - info_dir = '%s.dist-info' % name_ver - - metadata_name = posixpath.join(info_dir, METADATA_FILENAME) - wheel_metadata_name = posixpath.join(info_dir, 'WHEEL') - record_name = posixpath.join(info_dir, 'RECORD') - - wrapper = codecs.getreader('utf-8') - - with ZipFile(pathname, 'r') as zf: - with zf.open(wheel_metadata_name) as bwf: - wf = wrapper(bwf) - message = message_from_file(wf) - wv = message['Wheel-Version'].split('.', 1) - file_version = tuple([int(i) for i in wv]) - if (file_version != self.wheel_version) and warner: - warner(self.wheel_version, file_version) - - if message['Root-Is-Purelib'] == 'true': - libdir = paths['purelib'] - else: - libdir = paths['platlib'] - - records = {} - with zf.open(record_name) as bf: - with CSVReader(stream=bf) as reader: - for row in reader: - p = row[0] - records[p] = row - - data_pfx = posixpath.join(data_dir, '') - info_pfx = posixpath.join(info_dir, '') - script_pfx = posixpath.join(data_dir, 'scripts', '') - - # make a new instance rather than a copy of maker's, - # as we mutate it - fileop = FileOperator(dry_run=dry_run) - fileop.record = True # so we can rollback if needed - - bc = not sys.dont_write_bytecode # Double negatives. Lovely! - - outfiles = [] # for RECORD writing - - # for script copying/shebang processing - workdir = tempfile.mkdtemp() - # set target dir later - # we default add_launchers to False, as the - # Python Launcher should be used instead - maker.source_dir = workdir - maker.target_dir = None - try: - for zinfo in zf.infolist(): - arcname = zinfo.filename - if isinstance(arcname, text_type): - u_arcname = arcname - else: - u_arcname = arcname.decode('utf-8') - # The signature file won't be in RECORD, - # and we don't currently don't do anything with it - if u_arcname.endswith('/RECORD.jws'): - continue - row = records[u_arcname] - if row[2] and str(zinfo.file_size) != row[2]: - raise DistlibException('size mismatch for ' - '%s' % u_arcname) - if row[1]: - kind, value = row[1].split('=', 1) - with zf.open(arcname) as bf: - data = bf.read() - _, digest = self.get_hash(data, kind) - if digest != value: - raise DistlibException('digest mismatch for ' - '%s' % arcname) - - if lib_only and u_arcname.startswith((info_pfx, data_pfx)): - logger.debug('lib_only: skipping %s', u_arcname) - continue - is_script = (u_arcname.startswith(script_pfx) - and not u_arcname.endswith('.exe')) - - if u_arcname.startswith(data_pfx): - _, where, rp = u_arcname.split('/', 2) - outfile = os.path.join(paths[where], convert_path(rp)) - else: - # meant for site-packages. - if u_arcname in (wheel_metadata_name, record_name): - continue - outfile = os.path.join(libdir, convert_path(u_arcname)) - if not is_script: - with zf.open(arcname) as bf: - fileop.copy_stream(bf, outfile) - outfiles.append(outfile) - # Double check the digest of the written file - if not dry_run and row[1]: - with open(outfile, 'rb') as bf: - data = bf.read() - _, newdigest = self.get_hash(data, kind) - if newdigest != digest: - raise DistlibException('digest mismatch ' - 'on write for ' - '%s' % outfile) - if bc and outfile.endswith('.py'): - try: - pyc = fileop.byte_compile(outfile) - outfiles.append(pyc) - except Exception: - # Don't give up if byte-compilation fails, - # but log it and perhaps warn the user - logger.warning('Byte-compilation failed', - exc_info=True) - else: - fn = os.path.basename(convert_path(arcname)) - workname = os.path.join(workdir, fn) - with zf.open(arcname) as bf: - fileop.copy_stream(bf, workname) - - dn, fn = os.path.split(outfile) - maker.target_dir = dn - filenames = maker.make(fn) - fileop.set_executable_mode(filenames) - outfiles.extend(filenames) - - if lib_only: - logger.debug('lib_only: returning None') - dist = None - else: - # Generate scripts - - # Try to get pydist.json so we can see if there are - # any commands to generate. If this fails (e.g. because - # of a legacy wheel), log a warning but don't give up. - commands = None - file_version = self.info['Wheel-Version'] - if file_version == '1.0': - # Use legacy info - ep = posixpath.join(info_dir, 'entry_points.txt') - try: - with zf.open(ep) as bwf: - epdata = read_exports(bwf) - commands = {} - for key in ('console', 'gui'): - k = '%s_scripts' % key - if k in epdata: - commands['wrap_%s' % key] = d = {} - for v in epdata[k].values(): - s = '%s:%s' % (v.prefix, v.suffix) - if v.flags: - s += ' %s' % v.flags - d[v.name] = s - except Exception: - logger.warning('Unable to read legacy script ' - 'metadata, so cannot generate ' - 'scripts') - else: - try: - with zf.open(metadata_name) as bwf: - wf = wrapper(bwf) - commands = json.load(wf).get('extensions') - if commands: - commands = commands.get('python.commands') - except Exception: - logger.warning('Unable to read JSON metadata, so ' - 'cannot generate scripts') - if commands: - console_scripts = commands.get('wrap_console', {}) - gui_scripts = commands.get('wrap_gui', {}) - if console_scripts or gui_scripts: - script_dir = paths.get('scripts', '') - if not os.path.isdir(script_dir): - raise ValueError('Valid script path not ' - 'specified') - maker.target_dir = script_dir - for k, v in console_scripts.items(): - script = '%s = %s' % (k, v) - filenames = maker.make(script) - fileop.set_executable_mode(filenames) - - if gui_scripts: - options = {'gui': True } - for k, v in gui_scripts.items(): - script = '%s = %s' % (k, v) - filenames = maker.make(script, options) - fileop.set_executable_mode(filenames) - - p = os.path.join(libdir, info_dir) - dist = InstalledDistribution(p) - - # Write SHARED - paths = dict(paths) # don't change passed in dict - del paths['purelib'] - del paths['platlib'] - paths['lib'] = libdir - p = dist.write_shared_locations(paths, dry_run) - if p: - outfiles.append(p) - - # Write RECORD - dist.write_installed_files(outfiles, paths['prefix'], - dry_run) - return dist - except Exception: # pragma: no cover - logger.exception('installation failed.') - fileop.rollback() - raise - finally: - shutil.rmtree(workdir) - - def _get_dylib_cache(self): - global cache - if cache is None: - # Use native string to avoid issues on 2.x: see Python #20140. - base = os.path.join(get_cache_base(), str('dylib-cache'), - sys.version[:3]) - cache = Cache(base) - return cache - - def _get_extensions(self): - pathname = os.path.join(self.dirname, self.filename) - name_ver = '%s-%s' % (self.name, self.version) - info_dir = '%s.dist-info' % name_ver - arcname = posixpath.join(info_dir, 'EXTENSIONS') - wrapper = codecs.getreader('utf-8') - result = [] - with ZipFile(pathname, 'r') as zf: - try: - with zf.open(arcname) as bf: - wf = wrapper(bf) - extensions = json.load(wf) - cache = self._get_dylib_cache() - prefix = cache.prefix_to_dir(pathname) - cache_base = os.path.join(cache.base, prefix) - if not os.path.isdir(cache_base): - os.makedirs(cache_base) - for name, relpath in extensions.items(): - dest = os.path.join(cache_base, convert_path(relpath)) - if not os.path.exists(dest): - extract = True - else: - file_time = os.stat(dest).st_mtime - file_time = datetime.datetime.fromtimestamp(file_time) - info = zf.getinfo(relpath) - wheel_time = datetime.datetime(*info.date_time) - extract = wheel_time > file_time - if extract: - zf.extract(relpath, cache_base) - result.append((name, dest)) - except KeyError: - pass - return result - - def is_compatible(self): - """ - Determine if a wheel is compatible with the running system. - """ - return is_compatible(self) - - def is_mountable(self): - """ - Determine if a wheel is asserted as mountable by its metadata. - """ - return True # for now - metadata details TBD - - def mount(self, append=False): - pathname = os.path.abspath(os.path.join(self.dirname, self.filename)) - if not self.is_compatible(): - msg = 'Wheel %s not compatible with this Python.' % pathname - raise DistlibException(msg) - if not self.is_mountable(): - msg = 'Wheel %s is marked as not mountable.' % pathname - raise DistlibException(msg) - if pathname in sys.path: - logger.debug('%s already in path', pathname) - else: - if append: - sys.path.append(pathname) - else: - sys.path.insert(0, pathname) - extensions = self._get_extensions() - if extensions: - if _hook not in sys.meta_path: - sys.meta_path.append(_hook) - _hook.add(pathname, extensions) - - def unmount(self): - pathname = os.path.abspath(os.path.join(self.dirname, self.filename)) - if pathname not in sys.path: - logger.debug('%s not in path', pathname) - else: - sys.path.remove(pathname) - if pathname in _hook.impure_wheels: - _hook.remove(pathname) - if not _hook.impure_wheels: - if _hook in sys.meta_path: - sys.meta_path.remove(_hook) - - def verify(self): - pathname = os.path.join(self.dirname, self.filename) - name_ver = '%s-%s' % (self.name, self.version) - data_dir = '%s.data' % name_ver - info_dir = '%s.dist-info' % name_ver - - metadata_name = posixpath.join(info_dir, METADATA_FILENAME) - wheel_metadata_name = posixpath.join(info_dir, 'WHEEL') - record_name = posixpath.join(info_dir, 'RECORD') - - wrapper = codecs.getreader('utf-8') - - with ZipFile(pathname, 'r') as zf: - with zf.open(wheel_metadata_name) as bwf: - wf = wrapper(bwf) - message = message_from_file(wf) - wv = message['Wheel-Version'].split('.', 1) - file_version = tuple([int(i) for i in wv]) - # TODO version verification - - records = {} - with zf.open(record_name) as bf: - with CSVReader(stream=bf) as reader: - for row in reader: - p = row[0] - records[p] = row - - for zinfo in zf.infolist(): - arcname = zinfo.filename - if isinstance(arcname, text_type): - u_arcname = arcname - else: - u_arcname = arcname.decode('utf-8') - if '..' in u_arcname: - raise DistlibException('invalid entry in ' - 'wheel: %r' % u_arcname) - - # The signature file won't be in RECORD, - # and we don't currently don't do anything with it - if u_arcname.endswith('/RECORD.jws'): - continue - row = records[u_arcname] - if row[2] and str(zinfo.file_size) != row[2]: - raise DistlibException('size mismatch for ' - '%s' % u_arcname) - if row[1]: - kind, value = row[1].split('=', 1) - with zf.open(arcname) as bf: - data = bf.read() - _, digest = self.get_hash(data, kind) - if digest != value: - raise DistlibException('digest mismatch for ' - '%s' % arcname) - - def update(self, modifier, dest_dir=None, **kwargs): - """ - Update the contents of a wheel in a generic way. The modifier should - be a callable which expects a dictionary argument: its keys are - archive-entry paths, and its values are absolute filesystem paths - where the contents the corresponding archive entries can be found. The - modifier is free to change the contents of the files pointed to, add - new entries and remove entries, before returning. This method will - extract the entire contents of the wheel to a temporary location, call - the modifier, and then use the passed (and possibly updated) - dictionary to write a new wheel. If ``dest_dir`` is specified, the new - wheel is written there -- otherwise, the original wheel is overwritten. - - The modifier should return True if it updated the wheel, else False. - This method returns the same value the modifier returns. - """ - - def get_version(path_map, info_dir): - version = path = None - key = '%s/%s' % (info_dir, METADATA_FILENAME) - if key not in path_map: - key = '%s/PKG-INFO' % info_dir - if key in path_map: - path = path_map[key] - version = Metadata(path=path).version - return version, path - - def update_version(version, path): - updated = None - try: - v = NormalizedVersion(version) - i = version.find('-') - if i < 0: - updated = '%s+1' % version - else: - parts = [int(s) for s in version[i + 1:].split('.')] - parts[-1] += 1 - updated = '%s+%s' % (version[:i], - '.'.join(str(i) for i in parts)) - except UnsupportedVersionError: - logger.debug('Cannot update non-compliant (PEP-440) ' - 'version %r', version) - if updated: - md = Metadata(path=path) - md.version = updated - legacy = not path.endswith(METADATA_FILENAME) - md.write(path=path, legacy=legacy) - logger.debug('Version updated from %r to %r', version, - updated) - - pathname = os.path.join(self.dirname, self.filename) - name_ver = '%s-%s' % (self.name, self.version) - info_dir = '%s.dist-info' % name_ver - record_name = posixpath.join(info_dir, 'RECORD') - with tempdir() as workdir: - with ZipFile(pathname, 'r') as zf: - path_map = {} - for zinfo in zf.infolist(): - arcname = zinfo.filename - if isinstance(arcname, text_type): - u_arcname = arcname - else: - u_arcname = arcname.decode('utf-8') - if u_arcname == record_name: - continue - if '..' in u_arcname: - raise DistlibException('invalid entry in ' - 'wheel: %r' % u_arcname) - zf.extract(zinfo, workdir) - path = os.path.join(workdir, convert_path(u_arcname)) - path_map[u_arcname] = path - - # Remember the version. - original_version, _ = get_version(path_map, info_dir) - # Files extracted. Call the modifier. - modified = modifier(path_map, **kwargs) - if modified: - # Something changed - need to build a new wheel. - current_version, path = get_version(path_map, info_dir) - if current_version and (current_version == original_version): - # Add or update local version to signify changes. - update_version(current_version, path) - # Decide where the new wheel goes. - if dest_dir is None: - fd, newpath = tempfile.mkstemp(suffix='.whl', - prefix='wheel-update-', - dir=workdir) - os.close(fd) - else: - if not os.path.isdir(dest_dir): - raise DistlibException('Not a directory: %r' % dest_dir) - newpath = os.path.join(dest_dir, self.filename) - archive_paths = list(path_map.items()) - distinfo = os.path.join(workdir, info_dir) - info = distinfo, info_dir - self.write_records(info, workdir, archive_paths) - self.build_zip(newpath, archive_paths) - if dest_dir is None: - shutil.copyfile(newpath, pathname) - return modified - -def compatible_tags(): - """ - Return (pyver, abi, arch) tuples compatible with this Python. - """ - versions = [VER_SUFFIX] - major = VER_SUFFIX[0] - for minor in range(sys.version_info[1] - 1, - 1, -1): - versions.append(''.join([major, str(minor)])) - - abis = [] - for suffix, _, _ in imp.get_suffixes(): - if suffix.startswith('.abi'): - abis.append(suffix.split('.', 2)[1]) - abis.sort() - if ABI != 'none': - abis.insert(0, ABI) - abis.append('none') - result = [] - - arches = [ARCH] - if sys.platform == 'darwin': - m = re.match('(\w+)_(\d+)_(\d+)_(\w+)$', ARCH) - if m: - name, major, minor, arch = m.groups() - minor = int(minor) - matches = [arch] - if arch in ('i386', 'ppc'): - matches.append('fat') - if arch in ('i386', 'ppc', 'x86_64'): - matches.append('fat3') - if arch in ('ppc64', 'x86_64'): - matches.append('fat64') - if arch in ('i386', 'x86_64'): - matches.append('intel') - if arch in ('i386', 'x86_64', 'intel', 'ppc', 'ppc64'): - matches.append('universal') - while minor >= 0: - for match in matches: - s = '%s_%s_%s_%s' % (name, major, minor, match) - if s != ARCH: # already there - arches.append(s) - minor -= 1 - - # Most specific - our Python version, ABI and arch - for abi in abis: - for arch in arches: - result.append((''.join((IMP_PREFIX, versions[0])), abi, arch)) - - # where no ABI / arch dependency, but IMP_PREFIX dependency - for i, version in enumerate(versions): - result.append((''.join((IMP_PREFIX, version)), 'none', 'any')) - if i == 0: - result.append((''.join((IMP_PREFIX, version[0])), 'none', 'any')) - - # no IMP_PREFIX, ABI or arch dependency - for i, version in enumerate(versions): - result.append((''.join(('py', version)), 'none', 'any')) - if i == 0: - result.append((''.join(('py', version[0])), 'none', 'any')) - return set(result) - - -COMPATIBLE_TAGS = compatible_tags() - -del compatible_tags - - -def is_compatible(wheel, tags=None): - if not isinstance(wheel, Wheel): - wheel = Wheel(wheel) # assume it's a filename - result = False - if tags is None: - tags = COMPATIBLE_TAGS - for ver, abi, arch in tags: - if ver in wheel.pyver and abi in wheel.abi and arch in wheel.arch: - result = True - break - return result diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/__init__.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/__init__.py deleted file mode 100644 index d4b3d71..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -""" -HTML parsing library based on the WHATWG "HTML5" -specification. The parser is designed to be compatible with existing -HTML found in the wild and implements well-defined error recovery that -is largely compatible with modern desktop web browsers. - -Example usage: - -import html5lib -f = open("my_document.html") -tree = html5lib.parse(f) -""" - -from __future__ import absolute_import, division, unicode_literals - -from .html5parser import HTMLParser, parse, parseFragment -from .treebuilders import getTreeBuilder -from .treewalkers import getTreeWalker -from .serializer import serialize - -__all__ = ["HTMLParser", "parse", "parseFragment", "getTreeBuilder", - "getTreeWalker", "serialize"] -__version__ = "1.0b5" diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/constants.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/constants.py deleted file mode 100644 index d938e0a..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/constants.py +++ /dev/null @@ -1,3102 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -import string - -EOF = None - -E = { - "null-character": - "Null character in input stream, replaced with U+FFFD.", - "invalid-codepoint": - "Invalid codepoint in stream.", - "incorrectly-placed-solidus": - "Solidus (/) incorrectly placed in tag.", - "incorrect-cr-newline-entity": - "Incorrect CR newline entity, replaced with LF.", - "illegal-windows-1252-entity": - "Entity used with illegal number (windows-1252 reference).", - "cant-convert-numeric-entity": - "Numeric entity couldn't be converted to character " - "(codepoint U+%(charAsInt)08x).", - "illegal-codepoint-for-numeric-entity": - "Numeric entity represents an illegal codepoint: " - "U+%(charAsInt)08x.", - "numeric-entity-without-semicolon": - "Numeric entity didn't end with ';'.", - "expected-numeric-entity-but-got-eof": - "Numeric entity expected. Got end of file instead.", - "expected-numeric-entity": - "Numeric entity expected but none found.", - "named-entity-without-semicolon": - "Named entity didn't end with ';'.", - "expected-named-entity": - "Named entity expected. Got none.", - "attributes-in-end-tag": - "End tag contains unexpected attributes.", - 'self-closing-flag-on-end-tag': - "End tag contains unexpected self-closing flag.", - "expected-tag-name-but-got-right-bracket": - "Expected tag name. Got '>' instead.", - "expected-tag-name-but-got-question-mark": - "Expected tag name. Got '?' instead. (HTML doesn't " - "support processing instructions.)", - "expected-tag-name": - "Expected tag name. Got something else instead", - "expected-closing-tag-but-got-right-bracket": - "Expected closing tag. Got '>' instead. Ignoring ''.", - "expected-closing-tag-but-got-eof": - "Expected closing tag. Unexpected end of file.", - "expected-closing-tag-but-got-char": - "Expected closing tag. Unexpected character '%(data)s' found.", - "eof-in-tag-name": - "Unexpected end of file in the tag name.", - "expected-attribute-name-but-got-eof": - "Unexpected end of file. Expected attribute name instead.", - "eof-in-attribute-name": - "Unexpected end of file in attribute name.", - "invalid-character-in-attribute-name": - "Invalid character in attribute name", - "duplicate-attribute": - "Dropped duplicate attribute on tag.", - "expected-end-of-tag-name-but-got-eof": - "Unexpected end of file. Expected = or end of tag.", - "expected-attribute-value-but-got-eof": - "Unexpected end of file. Expected attribute value.", - "expected-attribute-value-but-got-right-bracket": - "Expected attribute value. Got '>' instead.", - 'equals-in-unquoted-attribute-value': - "Unexpected = in unquoted attribute", - 'unexpected-character-in-unquoted-attribute-value': - "Unexpected character in unquoted attribute", - "invalid-character-after-attribute-name": - "Unexpected character after attribute name.", - "unexpected-character-after-attribute-value": - "Unexpected character after attribute value.", - "eof-in-attribute-value-double-quote": - "Unexpected end of file in attribute value (\").", - "eof-in-attribute-value-single-quote": - "Unexpected end of file in attribute value (').", - "eof-in-attribute-value-no-quotes": - "Unexpected end of file in attribute value.", - "unexpected-EOF-after-solidus-in-tag": - "Unexpected end of file in tag. Expected >", - "unexpected-character-after-solidus-in-tag": - "Unexpected character after / in tag. Expected >", - "expected-dashes-or-doctype": - "Expected '--' or 'DOCTYPE'. Not found.", - "unexpected-bang-after-double-dash-in-comment": - "Unexpected ! after -- in comment", - "unexpected-space-after-double-dash-in-comment": - "Unexpected space after -- in comment", - "incorrect-comment": - "Incorrect comment.", - "eof-in-comment": - "Unexpected end of file in comment.", - "eof-in-comment-end-dash": - "Unexpected end of file in comment (-)", - "unexpected-dash-after-double-dash-in-comment": - "Unexpected '-' after '--' found in comment.", - "eof-in-comment-double-dash": - "Unexpected end of file in comment (--).", - "eof-in-comment-end-space-state": - "Unexpected end of file in comment.", - "eof-in-comment-end-bang-state": - "Unexpected end of file in comment.", - "unexpected-char-in-comment": - "Unexpected character in comment found.", - "need-space-after-doctype": - "No space after literal string 'DOCTYPE'.", - "expected-doctype-name-but-got-right-bracket": - "Unexpected > character. Expected DOCTYPE name.", - "expected-doctype-name-but-got-eof": - "Unexpected end of file. Expected DOCTYPE name.", - "eof-in-doctype-name": - "Unexpected end of file in DOCTYPE name.", - "eof-in-doctype": - "Unexpected end of file in DOCTYPE.", - "expected-space-or-right-bracket-in-doctype": - "Expected space or '>'. Got '%(data)s'", - "unexpected-end-of-doctype": - "Unexpected end of DOCTYPE.", - "unexpected-char-in-doctype": - "Unexpected character in DOCTYPE.", - "eof-in-innerhtml": - "XXX innerHTML EOF", - "unexpected-doctype": - "Unexpected DOCTYPE. Ignored.", - "non-html-root": - "html needs to be the first start tag.", - "expected-doctype-but-got-eof": - "Unexpected End of file. Expected DOCTYPE.", - "unknown-doctype": - "Erroneous DOCTYPE.", - "expected-doctype-but-got-chars": - "Unexpected non-space characters. Expected DOCTYPE.", - "expected-doctype-but-got-start-tag": - "Unexpected start tag (%(name)s). Expected DOCTYPE.", - "expected-doctype-but-got-end-tag": - "Unexpected end tag (%(name)s). Expected DOCTYPE.", - "end-tag-after-implied-root": - "Unexpected end tag (%(name)s) after the (implied) root element.", - "expected-named-closing-tag-but-got-eof": - "Unexpected end of file. Expected end tag (%(name)s).", - "two-heads-are-not-better-than-one": - "Unexpected start tag head in existing head. Ignored.", - "unexpected-end-tag": - "Unexpected end tag (%(name)s). Ignored.", - "unexpected-start-tag-out-of-my-head": - "Unexpected start tag (%(name)s) that can be in head. Moved.", - "unexpected-start-tag": - "Unexpected start tag (%(name)s).", - "missing-end-tag": - "Missing end tag (%(name)s).", - "missing-end-tags": - "Missing end tags (%(name)s).", - "unexpected-start-tag-implies-end-tag": - "Unexpected start tag (%(startName)s) " - "implies end tag (%(endName)s).", - "unexpected-start-tag-treated-as": - "Unexpected start tag (%(originalName)s). Treated as %(newName)s.", - "deprecated-tag": - "Unexpected start tag %(name)s. Don't use it!", - "unexpected-start-tag-ignored": - "Unexpected start tag %(name)s. Ignored.", - "expected-one-end-tag-but-got-another": - "Unexpected end tag (%(gotName)s). " - "Missing end tag (%(expectedName)s).", - "end-tag-too-early": - "End tag (%(name)s) seen too early. Expected other end tag.", - "end-tag-too-early-named": - "Unexpected end tag (%(gotName)s). Expected end tag (%(expectedName)s).", - "end-tag-too-early-ignored": - "End tag (%(name)s) seen too early. Ignored.", - "adoption-agency-1.1": - "End tag (%(name)s) violates step 1, " - "paragraph 1 of the adoption agency algorithm.", - "adoption-agency-1.2": - "End tag (%(name)s) violates step 1, " - "paragraph 2 of the adoption agency algorithm.", - "adoption-agency-1.3": - "End tag (%(name)s) violates step 1, " - "paragraph 3 of the adoption agency algorithm.", - "adoption-agency-4.4": - "End tag (%(name)s) violates step 4, " - "paragraph 4 of the adoption agency algorithm.", - "unexpected-end-tag-treated-as": - "Unexpected end tag (%(originalName)s). Treated as %(newName)s.", - "no-end-tag": - "This element (%(name)s) has no end tag.", - "unexpected-implied-end-tag-in-table": - "Unexpected implied end tag (%(name)s) in the table phase.", - "unexpected-implied-end-tag-in-table-body": - "Unexpected implied end tag (%(name)s) in the table body phase.", - "unexpected-char-implies-table-voodoo": - "Unexpected non-space characters in " - "table context caused voodoo mode.", - "unexpected-hidden-input-in-table": - "Unexpected input with type hidden in table context.", - "unexpected-form-in-table": - "Unexpected form in table context.", - "unexpected-start-tag-implies-table-voodoo": - "Unexpected start tag (%(name)s) in " - "table context caused voodoo mode.", - "unexpected-end-tag-implies-table-voodoo": - "Unexpected end tag (%(name)s) in " - "table context caused voodoo mode.", - "unexpected-cell-in-table-body": - "Unexpected table cell start tag (%(name)s) " - "in the table body phase.", - "unexpected-cell-end-tag": - "Got table cell end tag (%(name)s) " - "while required end tags are missing.", - "unexpected-end-tag-in-table-body": - "Unexpected end tag (%(name)s) in the table body phase. Ignored.", - "unexpected-implied-end-tag-in-table-row": - "Unexpected implied end tag (%(name)s) in the table row phase.", - "unexpected-end-tag-in-table-row": - "Unexpected end tag (%(name)s) in the table row phase. Ignored.", - "unexpected-select-in-select": - "Unexpected select start tag in the select phase " - "treated as select end tag.", - "unexpected-input-in-select": - "Unexpected input start tag in the select phase.", - "unexpected-start-tag-in-select": - "Unexpected start tag token (%(name)s in the select phase. " - "Ignored.", - "unexpected-end-tag-in-select": - "Unexpected end tag (%(name)s) in the select phase. Ignored.", - "unexpected-table-element-start-tag-in-select-in-table": - "Unexpected table element start tag (%(name)s) in the select in table phase.", - "unexpected-table-element-end-tag-in-select-in-table": - "Unexpected table element end tag (%(name)s) in the select in table phase.", - "unexpected-char-after-body": - "Unexpected non-space characters in the after body phase.", - "unexpected-start-tag-after-body": - "Unexpected start tag token (%(name)s)" - " in the after body phase.", - "unexpected-end-tag-after-body": - "Unexpected end tag token (%(name)s)" - " in the after body phase.", - "unexpected-char-in-frameset": - "Unexpected characters in the frameset phase. Characters ignored.", - "unexpected-start-tag-in-frameset": - "Unexpected start tag token (%(name)s)" - " in the frameset phase. Ignored.", - "unexpected-frameset-in-frameset-innerhtml": - "Unexpected end tag token (frameset) " - "in the frameset phase (innerHTML).", - "unexpected-end-tag-in-frameset": - "Unexpected end tag token (%(name)s)" - " in the frameset phase. Ignored.", - "unexpected-char-after-frameset": - "Unexpected non-space characters in the " - "after frameset phase. Ignored.", - "unexpected-start-tag-after-frameset": - "Unexpected start tag (%(name)s)" - " in the after frameset phase. Ignored.", - "unexpected-end-tag-after-frameset": - "Unexpected end tag (%(name)s)" - " in the after frameset phase. Ignored.", - "unexpected-end-tag-after-body-innerhtml": - "Unexpected end tag after body(innerHtml)", - "expected-eof-but-got-char": - "Unexpected non-space characters. Expected end of file.", - "expected-eof-but-got-start-tag": - "Unexpected start tag (%(name)s)" - ". Expected end of file.", - "expected-eof-but-got-end-tag": - "Unexpected end tag (%(name)s)" - ". Expected end of file.", - "eof-in-table": - "Unexpected end of file. Expected table content.", - "eof-in-select": - "Unexpected end of file. Expected select content.", - "eof-in-frameset": - "Unexpected end of file. Expected frameset content.", - "eof-in-script-in-script": - "Unexpected end of file. Expected script content.", - "eof-in-foreign-lands": - "Unexpected end of file. Expected foreign content", - "non-void-element-with-trailing-solidus": - "Trailing solidus not allowed on element %(name)s", - "unexpected-html-element-in-foreign-content": - "Element %(name)s not allowed in a non-html context", - "unexpected-end-tag-before-html": - "Unexpected end tag (%(name)s) before html.", - "XXX-undefined-error": - "Undefined error (this sucks and should be fixed)", -} - -namespaces = { - "html": "http://www.w3.org/1999/xhtml", - "mathml": "http://www.w3.org/1998/Math/MathML", - "svg": "http://www.w3.org/2000/svg", - "xlink": "http://www.w3.org/1999/xlink", - "xml": "http://www.w3.org/XML/1998/namespace", - "xmlns": "http://www.w3.org/2000/xmlns/" -} - -scopingElements = frozenset([ - (namespaces["html"], "applet"), - (namespaces["html"], "caption"), - (namespaces["html"], "html"), - (namespaces["html"], "marquee"), - (namespaces["html"], "object"), - (namespaces["html"], "table"), - (namespaces["html"], "td"), - (namespaces["html"], "th"), - (namespaces["mathml"], "mi"), - (namespaces["mathml"], "mo"), - (namespaces["mathml"], "mn"), - (namespaces["mathml"], "ms"), - (namespaces["mathml"], "mtext"), - (namespaces["mathml"], "annotation-xml"), - (namespaces["svg"], "foreignObject"), - (namespaces["svg"], "desc"), - (namespaces["svg"], "title"), -]) - -formattingElements = frozenset([ - (namespaces["html"], "a"), - (namespaces["html"], "b"), - (namespaces["html"], "big"), - (namespaces["html"], "code"), - (namespaces["html"], "em"), - (namespaces["html"], "font"), - (namespaces["html"], "i"), - (namespaces["html"], "nobr"), - (namespaces["html"], "s"), - (namespaces["html"], "small"), - (namespaces["html"], "strike"), - (namespaces["html"], "strong"), - (namespaces["html"], "tt"), - (namespaces["html"], "u") -]) - -specialElements = frozenset([ - (namespaces["html"], "address"), - (namespaces["html"], "applet"), - (namespaces["html"], "area"), - (namespaces["html"], "article"), - (namespaces["html"], "aside"), - (namespaces["html"], "base"), - (namespaces["html"], "basefont"), - (namespaces["html"], "bgsound"), - (namespaces["html"], "blockquote"), - (namespaces["html"], "body"), - (namespaces["html"], "br"), - (namespaces["html"], "button"), - (namespaces["html"], "caption"), - (namespaces["html"], "center"), - (namespaces["html"], "col"), - (namespaces["html"], "colgroup"), - (namespaces["html"], "command"), - (namespaces["html"], "dd"), - (namespaces["html"], "details"), - (namespaces["html"], "dir"), - (namespaces["html"], "div"), - (namespaces["html"], "dl"), - (namespaces["html"], "dt"), - (namespaces["html"], "embed"), - (namespaces["html"], "fieldset"), - (namespaces["html"], "figure"), - (namespaces["html"], "footer"), - (namespaces["html"], "form"), - (namespaces["html"], "frame"), - (namespaces["html"], "frameset"), - (namespaces["html"], "h1"), - (namespaces["html"], "h2"), - (namespaces["html"], "h3"), - (namespaces["html"], "h4"), - (namespaces["html"], "h5"), - (namespaces["html"], "h6"), - (namespaces["html"], "head"), - (namespaces["html"], "header"), - (namespaces["html"], "hr"), - (namespaces["html"], "html"), - (namespaces["html"], "iframe"), - # Note that image is commented out in the spec as "this isn't an - # element that can end up on the stack, so it doesn't matter," - (namespaces["html"], "image"), - (namespaces["html"], "img"), - (namespaces["html"], "input"), - (namespaces["html"], "isindex"), - (namespaces["html"], "li"), - (namespaces["html"], "link"), - (namespaces["html"], "listing"), - (namespaces["html"], "marquee"), - (namespaces["html"], "menu"), - (namespaces["html"], "meta"), - (namespaces["html"], "nav"), - (namespaces["html"], "noembed"), - (namespaces["html"], "noframes"), - (namespaces["html"], "noscript"), - (namespaces["html"], "object"), - (namespaces["html"], "ol"), - (namespaces["html"], "p"), - (namespaces["html"], "param"), - (namespaces["html"], "plaintext"), - (namespaces["html"], "pre"), - (namespaces["html"], "script"), - (namespaces["html"], "section"), - (namespaces["html"], "select"), - (namespaces["html"], "style"), - (namespaces["html"], "table"), - (namespaces["html"], "tbody"), - (namespaces["html"], "td"), - (namespaces["html"], "textarea"), - (namespaces["html"], "tfoot"), - (namespaces["html"], "th"), - (namespaces["html"], "thead"), - (namespaces["html"], "title"), - (namespaces["html"], "tr"), - (namespaces["html"], "ul"), - (namespaces["html"], "wbr"), - (namespaces["html"], "xmp"), - (namespaces["svg"], "foreignObject") -]) - -htmlIntegrationPointElements = frozenset([ - (namespaces["mathml"], "annotaion-xml"), - (namespaces["svg"], "foreignObject"), - (namespaces["svg"], "desc"), - (namespaces["svg"], "title") -]) - -mathmlTextIntegrationPointElements = frozenset([ - (namespaces["mathml"], "mi"), - (namespaces["mathml"], "mo"), - (namespaces["mathml"], "mn"), - (namespaces["mathml"], "ms"), - (namespaces["mathml"], "mtext") -]) - -adjustForeignAttributes = { - "xlink:actuate": ("xlink", "actuate", namespaces["xlink"]), - "xlink:arcrole": ("xlink", "arcrole", namespaces["xlink"]), - "xlink:href": ("xlink", "href", namespaces["xlink"]), - "xlink:role": ("xlink", "role", namespaces["xlink"]), - "xlink:show": ("xlink", "show", namespaces["xlink"]), - "xlink:title": ("xlink", "title", namespaces["xlink"]), - "xlink:type": ("xlink", "type", namespaces["xlink"]), - "xml:base": ("xml", "base", namespaces["xml"]), - "xml:lang": ("xml", "lang", namespaces["xml"]), - "xml:space": ("xml", "space", namespaces["xml"]), - "xmlns": (None, "xmlns", namespaces["xmlns"]), - "xmlns:xlink": ("xmlns", "xlink", namespaces["xmlns"]) -} - -unadjustForeignAttributes = dict([((ns, local), qname) for qname, (prefix, local, ns) in - adjustForeignAttributes.items()]) - -spaceCharacters = frozenset([ - "\t", - "\n", - "\u000C", - " ", - "\r" -]) - -tableInsertModeElements = frozenset([ - "table", - "tbody", - "tfoot", - "thead", - "tr" -]) - -asciiLowercase = frozenset(string.ascii_lowercase) -asciiUppercase = frozenset(string.ascii_uppercase) -asciiLetters = frozenset(string.ascii_letters) -digits = frozenset(string.digits) -hexDigits = frozenset(string.hexdigits) - -asciiUpper2Lower = dict([(ord(c), ord(c.lower())) - for c in string.ascii_uppercase]) - -# Heading elements need to be ordered -headingElements = ( - "h1", - "h2", - "h3", - "h4", - "h5", - "h6" -) - -voidElements = frozenset([ - "base", - "command", - "event-source", - "link", - "meta", - "hr", - "br", - "img", - "embed", - "param", - "area", - "col", - "input", - "source", - "track" -]) - -cdataElements = frozenset(['title', 'textarea']) - -rcdataElements = frozenset([ - 'style', - 'script', - 'xmp', - 'iframe', - 'noembed', - 'noframes', - 'noscript' -]) - -booleanAttributes = { - "": frozenset(["irrelevant"]), - "style": frozenset(["scoped"]), - "img": frozenset(["ismap"]), - "audio": frozenset(["autoplay", "controls"]), - "video": frozenset(["autoplay", "controls"]), - "script": frozenset(["defer", "async"]), - "details": frozenset(["open"]), - "datagrid": frozenset(["multiple", "disabled"]), - "command": frozenset(["hidden", "disabled", "checked", "default"]), - "hr": frozenset(["noshade"]), - "menu": frozenset(["autosubmit"]), - "fieldset": frozenset(["disabled", "readonly"]), - "option": frozenset(["disabled", "readonly", "selected"]), - "optgroup": frozenset(["disabled", "readonly"]), - "button": frozenset(["disabled", "autofocus"]), - "input": frozenset(["disabled", "readonly", "required", "autofocus", "checked", "ismap"]), - "select": frozenset(["disabled", "readonly", "autofocus", "multiple"]), - "output": frozenset(["disabled", "readonly"]), -} - -# entitiesWindows1252 has to be _ordered_ and needs to have an index. It -# therefore can't be a frozenset. -entitiesWindows1252 = ( - 8364, # 0x80 0x20AC EURO SIGN - 65533, # 0x81 UNDEFINED - 8218, # 0x82 0x201A SINGLE LOW-9 QUOTATION MARK - 402, # 0x83 0x0192 LATIN SMALL LETTER F WITH HOOK - 8222, # 0x84 0x201E DOUBLE LOW-9 QUOTATION MARK - 8230, # 0x85 0x2026 HORIZONTAL ELLIPSIS - 8224, # 0x86 0x2020 DAGGER - 8225, # 0x87 0x2021 DOUBLE DAGGER - 710, # 0x88 0x02C6 MODIFIER LETTER CIRCUMFLEX ACCENT - 8240, # 0x89 0x2030 PER MILLE SIGN - 352, # 0x8A 0x0160 LATIN CAPITAL LETTER S WITH CARON - 8249, # 0x8B 0x2039 SINGLE LEFT-POINTING ANGLE QUOTATION MARK - 338, # 0x8C 0x0152 LATIN CAPITAL LIGATURE OE - 65533, # 0x8D UNDEFINED - 381, # 0x8E 0x017D LATIN CAPITAL LETTER Z WITH CARON - 65533, # 0x8F UNDEFINED - 65533, # 0x90 UNDEFINED - 8216, # 0x91 0x2018 LEFT SINGLE QUOTATION MARK - 8217, # 0x92 0x2019 RIGHT SINGLE QUOTATION MARK - 8220, # 0x93 0x201C LEFT DOUBLE QUOTATION MARK - 8221, # 0x94 0x201D RIGHT DOUBLE QUOTATION MARK - 8226, # 0x95 0x2022 BULLET - 8211, # 0x96 0x2013 EN DASH - 8212, # 0x97 0x2014 EM DASH - 732, # 0x98 0x02DC SMALL TILDE - 8482, # 0x99 0x2122 TRADE MARK SIGN - 353, # 0x9A 0x0161 LATIN SMALL LETTER S WITH CARON - 8250, # 0x9B 0x203A SINGLE RIGHT-POINTING ANGLE QUOTATION MARK - 339, # 0x9C 0x0153 LATIN SMALL LIGATURE OE - 65533, # 0x9D UNDEFINED - 382, # 0x9E 0x017E LATIN SMALL LETTER Z WITH CARON - 376 # 0x9F 0x0178 LATIN CAPITAL LETTER Y WITH DIAERESIS -) - -xmlEntities = frozenset(['lt;', 'gt;', 'amp;', 'apos;', 'quot;']) - -entities = { - "AElig": "\xc6", - "AElig;": "\xc6", - "AMP": "&", - "AMP;": "&", - "Aacute": "\xc1", - "Aacute;": "\xc1", - "Abreve;": "\u0102", - "Acirc": "\xc2", - "Acirc;": "\xc2", - "Acy;": "\u0410", - "Afr;": "\U0001d504", - "Agrave": "\xc0", - "Agrave;": "\xc0", - "Alpha;": "\u0391", - "Amacr;": "\u0100", - "And;": "\u2a53", - "Aogon;": "\u0104", - "Aopf;": "\U0001d538", - "ApplyFunction;": "\u2061", - "Aring": "\xc5", - "Aring;": "\xc5", - "Ascr;": "\U0001d49c", - "Assign;": "\u2254", - "Atilde": "\xc3", - "Atilde;": "\xc3", - "Auml": "\xc4", - "Auml;": "\xc4", - "Backslash;": "\u2216", - "Barv;": "\u2ae7", - "Barwed;": "\u2306", - "Bcy;": "\u0411", - "Because;": "\u2235", - "Bernoullis;": "\u212c", - "Beta;": "\u0392", - "Bfr;": "\U0001d505", - "Bopf;": "\U0001d539", - "Breve;": "\u02d8", - "Bscr;": "\u212c", - "Bumpeq;": "\u224e", - "CHcy;": "\u0427", - "COPY": "\xa9", - "COPY;": "\xa9", - "Cacute;": "\u0106", - "Cap;": "\u22d2", - "CapitalDifferentialD;": "\u2145", - "Cayleys;": "\u212d", - "Ccaron;": "\u010c", - "Ccedil": "\xc7", - "Ccedil;": "\xc7", - "Ccirc;": "\u0108", - "Cconint;": "\u2230", - "Cdot;": "\u010a", - "Cedilla;": "\xb8", - "CenterDot;": "\xb7", - "Cfr;": "\u212d", - "Chi;": "\u03a7", - "CircleDot;": "\u2299", - "CircleMinus;": "\u2296", - "CirclePlus;": "\u2295", - "CircleTimes;": "\u2297", - "ClockwiseContourIntegral;": "\u2232", - "CloseCurlyDoubleQuote;": "\u201d", - "CloseCurlyQuote;": "\u2019", - "Colon;": "\u2237", - "Colone;": "\u2a74", - "Congruent;": "\u2261", - "Conint;": "\u222f", - "ContourIntegral;": "\u222e", - "Copf;": "\u2102", - "Coproduct;": "\u2210", - "CounterClockwiseContourIntegral;": "\u2233", - "Cross;": "\u2a2f", - "Cscr;": "\U0001d49e", - "Cup;": "\u22d3", - "CupCap;": "\u224d", - "DD;": "\u2145", - "DDotrahd;": "\u2911", - "DJcy;": "\u0402", - "DScy;": "\u0405", - "DZcy;": "\u040f", - "Dagger;": "\u2021", - "Darr;": "\u21a1", - "Dashv;": "\u2ae4", - "Dcaron;": "\u010e", - "Dcy;": "\u0414", - "Del;": "\u2207", - "Delta;": "\u0394", - "Dfr;": "\U0001d507", - "DiacriticalAcute;": "\xb4", - "DiacriticalDot;": "\u02d9", - "DiacriticalDoubleAcute;": "\u02dd", - "DiacriticalGrave;": "`", - "DiacriticalTilde;": "\u02dc", - "Diamond;": "\u22c4", - "DifferentialD;": "\u2146", - "Dopf;": "\U0001d53b", - "Dot;": "\xa8", - "DotDot;": "\u20dc", - "DotEqual;": "\u2250", - "DoubleContourIntegral;": "\u222f", - "DoubleDot;": "\xa8", - "DoubleDownArrow;": "\u21d3", - "DoubleLeftArrow;": "\u21d0", - "DoubleLeftRightArrow;": "\u21d4", - "DoubleLeftTee;": "\u2ae4", - "DoubleLongLeftArrow;": "\u27f8", - "DoubleLongLeftRightArrow;": "\u27fa", - "DoubleLongRightArrow;": "\u27f9", - "DoubleRightArrow;": "\u21d2", - "DoubleRightTee;": "\u22a8", - "DoubleUpArrow;": "\u21d1", - "DoubleUpDownArrow;": "\u21d5", - "DoubleVerticalBar;": "\u2225", - "DownArrow;": "\u2193", - "DownArrowBar;": "\u2913", - "DownArrowUpArrow;": "\u21f5", - "DownBreve;": "\u0311", - "DownLeftRightVector;": "\u2950", - "DownLeftTeeVector;": "\u295e", - "DownLeftVector;": "\u21bd", - "DownLeftVectorBar;": "\u2956", - "DownRightTeeVector;": "\u295f", - "DownRightVector;": "\u21c1", - "DownRightVectorBar;": "\u2957", - "DownTee;": "\u22a4", - "DownTeeArrow;": "\u21a7", - "Downarrow;": "\u21d3", - "Dscr;": "\U0001d49f", - "Dstrok;": "\u0110", - "ENG;": "\u014a", - "ETH": "\xd0", - "ETH;": "\xd0", - "Eacute": "\xc9", - "Eacute;": "\xc9", - "Ecaron;": "\u011a", - "Ecirc": "\xca", - "Ecirc;": "\xca", - "Ecy;": "\u042d", - "Edot;": "\u0116", - "Efr;": "\U0001d508", - "Egrave": "\xc8", - "Egrave;": "\xc8", - "Element;": "\u2208", - "Emacr;": "\u0112", - "EmptySmallSquare;": "\u25fb", - "EmptyVerySmallSquare;": "\u25ab", - "Eogon;": "\u0118", - "Eopf;": "\U0001d53c", - "Epsilon;": "\u0395", - "Equal;": "\u2a75", - "EqualTilde;": "\u2242", - "Equilibrium;": "\u21cc", - "Escr;": "\u2130", - "Esim;": "\u2a73", - "Eta;": "\u0397", - "Euml": "\xcb", - "Euml;": "\xcb", - "Exists;": "\u2203", - "ExponentialE;": "\u2147", - "Fcy;": "\u0424", - "Ffr;": "\U0001d509", - "FilledSmallSquare;": "\u25fc", - "FilledVerySmallSquare;": "\u25aa", - "Fopf;": "\U0001d53d", - "ForAll;": "\u2200", - "Fouriertrf;": "\u2131", - "Fscr;": "\u2131", - "GJcy;": "\u0403", - "GT": ">", - "GT;": ">", - "Gamma;": "\u0393", - "Gammad;": "\u03dc", - "Gbreve;": "\u011e", - "Gcedil;": "\u0122", - "Gcirc;": "\u011c", - "Gcy;": "\u0413", - "Gdot;": "\u0120", - "Gfr;": "\U0001d50a", - "Gg;": "\u22d9", - "Gopf;": "\U0001d53e", - "GreaterEqual;": "\u2265", - "GreaterEqualLess;": "\u22db", - "GreaterFullEqual;": "\u2267", - "GreaterGreater;": "\u2aa2", - "GreaterLess;": "\u2277", - "GreaterSlantEqual;": "\u2a7e", - "GreaterTilde;": "\u2273", - "Gscr;": "\U0001d4a2", - "Gt;": "\u226b", - "HARDcy;": "\u042a", - "Hacek;": "\u02c7", - "Hat;": "^", - "Hcirc;": "\u0124", - "Hfr;": "\u210c", - "HilbertSpace;": "\u210b", - "Hopf;": "\u210d", - "HorizontalLine;": "\u2500", - "Hscr;": "\u210b", - "Hstrok;": "\u0126", - "HumpDownHump;": "\u224e", - "HumpEqual;": "\u224f", - "IEcy;": "\u0415", - "IJlig;": "\u0132", - "IOcy;": "\u0401", - "Iacute": "\xcd", - "Iacute;": "\xcd", - "Icirc": "\xce", - "Icirc;": "\xce", - "Icy;": "\u0418", - "Idot;": "\u0130", - "Ifr;": "\u2111", - "Igrave": "\xcc", - "Igrave;": "\xcc", - "Im;": "\u2111", - "Imacr;": "\u012a", - "ImaginaryI;": "\u2148", - "Implies;": "\u21d2", - "Int;": "\u222c", - "Integral;": "\u222b", - "Intersection;": "\u22c2", - "InvisibleComma;": "\u2063", - "InvisibleTimes;": "\u2062", - "Iogon;": "\u012e", - "Iopf;": "\U0001d540", - "Iota;": "\u0399", - "Iscr;": "\u2110", - "Itilde;": "\u0128", - "Iukcy;": "\u0406", - "Iuml": "\xcf", - "Iuml;": "\xcf", - "Jcirc;": "\u0134", - "Jcy;": "\u0419", - "Jfr;": "\U0001d50d", - "Jopf;": "\U0001d541", - "Jscr;": "\U0001d4a5", - "Jsercy;": "\u0408", - "Jukcy;": "\u0404", - "KHcy;": "\u0425", - "KJcy;": "\u040c", - "Kappa;": "\u039a", - "Kcedil;": "\u0136", - "Kcy;": "\u041a", - "Kfr;": "\U0001d50e", - "Kopf;": "\U0001d542", - "Kscr;": "\U0001d4a6", - "LJcy;": "\u0409", - "LT": "<", - "LT;": "<", - "Lacute;": "\u0139", - "Lambda;": "\u039b", - "Lang;": "\u27ea", - "Laplacetrf;": "\u2112", - "Larr;": "\u219e", - "Lcaron;": "\u013d", - "Lcedil;": "\u013b", - "Lcy;": "\u041b", - "LeftAngleBracket;": "\u27e8", - "LeftArrow;": "\u2190", - "LeftArrowBar;": "\u21e4", - "LeftArrowRightArrow;": "\u21c6", - "LeftCeiling;": "\u2308", - "LeftDoubleBracket;": "\u27e6", - "LeftDownTeeVector;": "\u2961", - "LeftDownVector;": "\u21c3", - "LeftDownVectorBar;": "\u2959", - "LeftFloor;": "\u230a", - "LeftRightArrow;": "\u2194", - "LeftRightVector;": "\u294e", - "LeftTee;": "\u22a3", - "LeftTeeArrow;": "\u21a4", - "LeftTeeVector;": "\u295a", - "LeftTriangle;": "\u22b2", - "LeftTriangleBar;": "\u29cf", - "LeftTriangleEqual;": "\u22b4", - "LeftUpDownVector;": "\u2951", - "LeftUpTeeVector;": "\u2960", - "LeftUpVector;": "\u21bf", - "LeftUpVectorBar;": "\u2958", - "LeftVector;": "\u21bc", - "LeftVectorBar;": "\u2952", - "Leftarrow;": "\u21d0", - "Leftrightarrow;": "\u21d4", - "LessEqualGreater;": "\u22da", - "LessFullEqual;": "\u2266", - "LessGreater;": "\u2276", - "LessLess;": "\u2aa1", - "LessSlantEqual;": "\u2a7d", - "LessTilde;": "\u2272", - "Lfr;": "\U0001d50f", - "Ll;": "\u22d8", - "Lleftarrow;": "\u21da", - "Lmidot;": "\u013f", - "LongLeftArrow;": "\u27f5", - "LongLeftRightArrow;": "\u27f7", - "LongRightArrow;": "\u27f6", - "Longleftarrow;": "\u27f8", - "Longleftrightarrow;": "\u27fa", - "Longrightarrow;": "\u27f9", - "Lopf;": "\U0001d543", - "LowerLeftArrow;": "\u2199", - "LowerRightArrow;": "\u2198", - "Lscr;": "\u2112", - "Lsh;": "\u21b0", - "Lstrok;": "\u0141", - "Lt;": "\u226a", - "Map;": "\u2905", - "Mcy;": "\u041c", - "MediumSpace;": "\u205f", - "Mellintrf;": "\u2133", - "Mfr;": "\U0001d510", - "MinusPlus;": "\u2213", - "Mopf;": "\U0001d544", - "Mscr;": "\u2133", - "Mu;": "\u039c", - "NJcy;": "\u040a", - "Nacute;": "\u0143", - "Ncaron;": "\u0147", - "Ncedil;": "\u0145", - "Ncy;": "\u041d", - "NegativeMediumSpace;": "\u200b", - "NegativeThickSpace;": "\u200b", - "NegativeThinSpace;": "\u200b", - "NegativeVeryThinSpace;": "\u200b", - "NestedGreaterGreater;": "\u226b", - "NestedLessLess;": "\u226a", - "NewLine;": "\n", - "Nfr;": "\U0001d511", - "NoBreak;": "\u2060", - "NonBreakingSpace;": "\xa0", - "Nopf;": "\u2115", - "Not;": "\u2aec", - "NotCongruent;": "\u2262", - "NotCupCap;": "\u226d", - "NotDoubleVerticalBar;": "\u2226", - "NotElement;": "\u2209", - "NotEqual;": "\u2260", - "NotEqualTilde;": "\u2242\u0338", - "NotExists;": "\u2204", - "NotGreater;": "\u226f", - "NotGreaterEqual;": "\u2271", - "NotGreaterFullEqual;": "\u2267\u0338", - "NotGreaterGreater;": "\u226b\u0338", - "NotGreaterLess;": "\u2279", - "NotGreaterSlantEqual;": "\u2a7e\u0338", - "NotGreaterTilde;": "\u2275", - "NotHumpDownHump;": "\u224e\u0338", - "NotHumpEqual;": "\u224f\u0338", - "NotLeftTriangle;": "\u22ea", - "NotLeftTriangleBar;": "\u29cf\u0338", - "NotLeftTriangleEqual;": "\u22ec", - "NotLess;": "\u226e", - "NotLessEqual;": "\u2270", - "NotLessGreater;": "\u2278", - "NotLessLess;": "\u226a\u0338", - "NotLessSlantEqual;": "\u2a7d\u0338", - "NotLessTilde;": "\u2274", - "NotNestedGreaterGreater;": "\u2aa2\u0338", - "NotNestedLessLess;": "\u2aa1\u0338", - "NotPrecedes;": "\u2280", - "NotPrecedesEqual;": "\u2aaf\u0338", - "NotPrecedesSlantEqual;": "\u22e0", - "NotReverseElement;": "\u220c", - "NotRightTriangle;": "\u22eb", - "NotRightTriangleBar;": "\u29d0\u0338", - "NotRightTriangleEqual;": "\u22ed", - "NotSquareSubset;": "\u228f\u0338", - "NotSquareSubsetEqual;": "\u22e2", - "NotSquareSuperset;": "\u2290\u0338", - "NotSquareSupersetEqual;": "\u22e3", - "NotSubset;": "\u2282\u20d2", - "NotSubsetEqual;": "\u2288", - "NotSucceeds;": "\u2281", - "NotSucceedsEqual;": "\u2ab0\u0338", - "NotSucceedsSlantEqual;": "\u22e1", - "NotSucceedsTilde;": "\u227f\u0338", - "NotSuperset;": "\u2283\u20d2", - "NotSupersetEqual;": "\u2289", - "NotTilde;": "\u2241", - "NotTildeEqual;": "\u2244", - "NotTildeFullEqual;": "\u2247", - "NotTildeTilde;": "\u2249", - "NotVerticalBar;": "\u2224", - "Nscr;": "\U0001d4a9", - "Ntilde": "\xd1", - "Ntilde;": "\xd1", - "Nu;": "\u039d", - "OElig;": "\u0152", - "Oacute": "\xd3", - "Oacute;": "\xd3", - "Ocirc": "\xd4", - "Ocirc;": "\xd4", - "Ocy;": "\u041e", - "Odblac;": "\u0150", - "Ofr;": "\U0001d512", - "Ograve": "\xd2", - "Ograve;": "\xd2", - "Omacr;": "\u014c", - "Omega;": "\u03a9", - "Omicron;": "\u039f", - "Oopf;": "\U0001d546", - "OpenCurlyDoubleQuote;": "\u201c", - "OpenCurlyQuote;": "\u2018", - "Or;": "\u2a54", - "Oscr;": "\U0001d4aa", - "Oslash": "\xd8", - "Oslash;": "\xd8", - "Otilde": "\xd5", - "Otilde;": "\xd5", - "Otimes;": "\u2a37", - "Ouml": "\xd6", - "Ouml;": "\xd6", - "OverBar;": "\u203e", - "OverBrace;": "\u23de", - "OverBracket;": "\u23b4", - "OverParenthesis;": "\u23dc", - "PartialD;": "\u2202", - "Pcy;": "\u041f", - "Pfr;": "\U0001d513", - "Phi;": "\u03a6", - "Pi;": "\u03a0", - "PlusMinus;": "\xb1", - "Poincareplane;": "\u210c", - "Popf;": "\u2119", - "Pr;": "\u2abb", - "Precedes;": "\u227a", - "PrecedesEqual;": "\u2aaf", - "PrecedesSlantEqual;": "\u227c", - "PrecedesTilde;": "\u227e", - "Prime;": "\u2033", - "Product;": "\u220f", - "Proportion;": "\u2237", - "Proportional;": "\u221d", - "Pscr;": "\U0001d4ab", - "Psi;": "\u03a8", - "QUOT": "\"", - "QUOT;": "\"", - "Qfr;": "\U0001d514", - "Qopf;": "\u211a", - "Qscr;": "\U0001d4ac", - "RBarr;": "\u2910", - "REG": "\xae", - "REG;": "\xae", - "Racute;": "\u0154", - "Rang;": "\u27eb", - "Rarr;": "\u21a0", - "Rarrtl;": "\u2916", - "Rcaron;": "\u0158", - "Rcedil;": "\u0156", - "Rcy;": "\u0420", - "Re;": "\u211c", - "ReverseElement;": "\u220b", - "ReverseEquilibrium;": "\u21cb", - "ReverseUpEquilibrium;": "\u296f", - "Rfr;": "\u211c", - "Rho;": "\u03a1", - "RightAngleBracket;": "\u27e9", - "RightArrow;": "\u2192", - "RightArrowBar;": "\u21e5", - "RightArrowLeftArrow;": "\u21c4", - "RightCeiling;": "\u2309", - "RightDoubleBracket;": "\u27e7", - "RightDownTeeVector;": "\u295d", - "RightDownVector;": "\u21c2", - "RightDownVectorBar;": "\u2955", - "RightFloor;": "\u230b", - "RightTee;": "\u22a2", - "RightTeeArrow;": "\u21a6", - "RightTeeVector;": "\u295b", - "RightTriangle;": "\u22b3", - "RightTriangleBar;": "\u29d0", - "RightTriangleEqual;": "\u22b5", - "RightUpDownVector;": "\u294f", - "RightUpTeeVector;": "\u295c", - "RightUpVector;": "\u21be", - "RightUpVectorBar;": "\u2954", - "RightVector;": "\u21c0", - "RightVectorBar;": "\u2953", - "Rightarrow;": "\u21d2", - "Ropf;": "\u211d", - "RoundImplies;": "\u2970", - "Rrightarrow;": "\u21db", - "Rscr;": "\u211b", - "Rsh;": "\u21b1", - "RuleDelayed;": "\u29f4", - "SHCHcy;": "\u0429", - "SHcy;": "\u0428", - "SOFTcy;": "\u042c", - "Sacute;": "\u015a", - "Sc;": "\u2abc", - "Scaron;": "\u0160", - "Scedil;": "\u015e", - "Scirc;": "\u015c", - "Scy;": "\u0421", - "Sfr;": "\U0001d516", - "ShortDownArrow;": "\u2193", - "ShortLeftArrow;": "\u2190", - "ShortRightArrow;": "\u2192", - "ShortUpArrow;": "\u2191", - "Sigma;": "\u03a3", - "SmallCircle;": "\u2218", - "Sopf;": "\U0001d54a", - "Sqrt;": "\u221a", - "Square;": "\u25a1", - "SquareIntersection;": "\u2293", - "SquareSubset;": "\u228f", - "SquareSubsetEqual;": "\u2291", - "SquareSuperset;": "\u2290", - "SquareSupersetEqual;": "\u2292", - "SquareUnion;": "\u2294", - "Sscr;": "\U0001d4ae", - "Star;": "\u22c6", - "Sub;": "\u22d0", - "Subset;": "\u22d0", - "SubsetEqual;": "\u2286", - "Succeeds;": "\u227b", - "SucceedsEqual;": "\u2ab0", - "SucceedsSlantEqual;": "\u227d", - "SucceedsTilde;": "\u227f", - "SuchThat;": "\u220b", - "Sum;": "\u2211", - "Sup;": "\u22d1", - "Superset;": "\u2283", - "SupersetEqual;": "\u2287", - "Supset;": "\u22d1", - "THORN": "\xde", - "THORN;": "\xde", - "TRADE;": "\u2122", - "TSHcy;": "\u040b", - "TScy;": "\u0426", - "Tab;": "\t", - "Tau;": "\u03a4", - "Tcaron;": "\u0164", - "Tcedil;": "\u0162", - "Tcy;": "\u0422", - "Tfr;": "\U0001d517", - "Therefore;": "\u2234", - "Theta;": "\u0398", - "ThickSpace;": "\u205f\u200a", - "ThinSpace;": "\u2009", - "Tilde;": "\u223c", - "TildeEqual;": "\u2243", - "TildeFullEqual;": "\u2245", - "TildeTilde;": "\u2248", - "Topf;": "\U0001d54b", - "TripleDot;": "\u20db", - "Tscr;": "\U0001d4af", - "Tstrok;": "\u0166", - "Uacute": "\xda", - "Uacute;": "\xda", - "Uarr;": "\u219f", - "Uarrocir;": "\u2949", - "Ubrcy;": "\u040e", - "Ubreve;": "\u016c", - "Ucirc": "\xdb", - "Ucirc;": "\xdb", - "Ucy;": "\u0423", - "Udblac;": "\u0170", - "Ufr;": "\U0001d518", - "Ugrave": "\xd9", - "Ugrave;": "\xd9", - "Umacr;": "\u016a", - "UnderBar;": "_", - "UnderBrace;": "\u23df", - "UnderBracket;": "\u23b5", - "UnderParenthesis;": "\u23dd", - "Union;": "\u22c3", - "UnionPlus;": "\u228e", - "Uogon;": "\u0172", - "Uopf;": "\U0001d54c", - "UpArrow;": "\u2191", - "UpArrowBar;": "\u2912", - "UpArrowDownArrow;": "\u21c5", - "UpDownArrow;": "\u2195", - "UpEquilibrium;": "\u296e", - "UpTee;": "\u22a5", - "UpTeeArrow;": "\u21a5", - "Uparrow;": "\u21d1", - "Updownarrow;": "\u21d5", - "UpperLeftArrow;": "\u2196", - "UpperRightArrow;": "\u2197", - "Upsi;": "\u03d2", - "Upsilon;": "\u03a5", - "Uring;": "\u016e", - "Uscr;": "\U0001d4b0", - "Utilde;": "\u0168", - "Uuml": "\xdc", - "Uuml;": "\xdc", - "VDash;": "\u22ab", - "Vbar;": "\u2aeb", - "Vcy;": "\u0412", - "Vdash;": "\u22a9", - "Vdashl;": "\u2ae6", - "Vee;": "\u22c1", - "Verbar;": "\u2016", - "Vert;": "\u2016", - "VerticalBar;": "\u2223", - "VerticalLine;": "|", - "VerticalSeparator;": "\u2758", - "VerticalTilde;": "\u2240", - "VeryThinSpace;": "\u200a", - "Vfr;": "\U0001d519", - "Vopf;": "\U0001d54d", - "Vscr;": "\U0001d4b1", - "Vvdash;": "\u22aa", - "Wcirc;": "\u0174", - "Wedge;": "\u22c0", - "Wfr;": "\U0001d51a", - "Wopf;": "\U0001d54e", - "Wscr;": "\U0001d4b2", - "Xfr;": "\U0001d51b", - "Xi;": "\u039e", - "Xopf;": "\U0001d54f", - "Xscr;": "\U0001d4b3", - "YAcy;": "\u042f", - "YIcy;": "\u0407", - "YUcy;": "\u042e", - "Yacute": "\xdd", - "Yacute;": "\xdd", - "Ycirc;": "\u0176", - "Ycy;": "\u042b", - "Yfr;": "\U0001d51c", - "Yopf;": "\U0001d550", - "Yscr;": "\U0001d4b4", - "Yuml;": "\u0178", - "ZHcy;": "\u0416", - "Zacute;": "\u0179", - "Zcaron;": "\u017d", - "Zcy;": "\u0417", - "Zdot;": "\u017b", - "ZeroWidthSpace;": "\u200b", - "Zeta;": "\u0396", - "Zfr;": "\u2128", - "Zopf;": "\u2124", - "Zscr;": "\U0001d4b5", - "aacute": "\xe1", - "aacute;": "\xe1", - "abreve;": "\u0103", - "ac;": "\u223e", - "acE;": "\u223e\u0333", - "acd;": "\u223f", - "acirc": "\xe2", - "acirc;": "\xe2", - "acute": "\xb4", - "acute;": "\xb4", - "acy;": "\u0430", - "aelig": "\xe6", - "aelig;": "\xe6", - "af;": "\u2061", - "afr;": "\U0001d51e", - "agrave": "\xe0", - "agrave;": "\xe0", - "alefsym;": "\u2135", - "aleph;": "\u2135", - "alpha;": "\u03b1", - "amacr;": "\u0101", - "amalg;": "\u2a3f", - "amp": "&", - "amp;": "&", - "and;": "\u2227", - "andand;": "\u2a55", - "andd;": "\u2a5c", - "andslope;": "\u2a58", - "andv;": "\u2a5a", - "ang;": "\u2220", - "ange;": "\u29a4", - "angle;": "\u2220", - "angmsd;": "\u2221", - "angmsdaa;": "\u29a8", - "angmsdab;": "\u29a9", - "angmsdac;": "\u29aa", - "angmsdad;": "\u29ab", - "angmsdae;": "\u29ac", - "angmsdaf;": "\u29ad", - "angmsdag;": "\u29ae", - "angmsdah;": "\u29af", - "angrt;": "\u221f", - "angrtvb;": "\u22be", - "angrtvbd;": "\u299d", - "angsph;": "\u2222", - "angst;": "\xc5", - "angzarr;": "\u237c", - "aogon;": "\u0105", - "aopf;": "\U0001d552", - "ap;": "\u2248", - "apE;": "\u2a70", - "apacir;": "\u2a6f", - "ape;": "\u224a", - "apid;": "\u224b", - "apos;": "'", - "approx;": "\u2248", - "approxeq;": "\u224a", - "aring": "\xe5", - "aring;": "\xe5", - "ascr;": "\U0001d4b6", - "ast;": "*", - "asymp;": "\u2248", - "asympeq;": "\u224d", - "atilde": "\xe3", - "atilde;": "\xe3", - "auml": "\xe4", - "auml;": "\xe4", - "awconint;": "\u2233", - "awint;": "\u2a11", - "bNot;": "\u2aed", - "backcong;": "\u224c", - "backepsilon;": "\u03f6", - "backprime;": "\u2035", - "backsim;": "\u223d", - "backsimeq;": "\u22cd", - "barvee;": "\u22bd", - "barwed;": "\u2305", - "barwedge;": "\u2305", - "bbrk;": "\u23b5", - "bbrktbrk;": "\u23b6", - "bcong;": "\u224c", - "bcy;": "\u0431", - "bdquo;": "\u201e", - "becaus;": "\u2235", - "because;": "\u2235", - "bemptyv;": "\u29b0", - "bepsi;": "\u03f6", - "bernou;": "\u212c", - "beta;": "\u03b2", - "beth;": "\u2136", - "between;": "\u226c", - "bfr;": "\U0001d51f", - "bigcap;": "\u22c2", - "bigcirc;": "\u25ef", - "bigcup;": "\u22c3", - "bigodot;": "\u2a00", - "bigoplus;": "\u2a01", - "bigotimes;": "\u2a02", - "bigsqcup;": "\u2a06", - "bigstar;": "\u2605", - "bigtriangledown;": "\u25bd", - "bigtriangleup;": "\u25b3", - "biguplus;": "\u2a04", - "bigvee;": "\u22c1", - "bigwedge;": "\u22c0", - "bkarow;": "\u290d", - "blacklozenge;": "\u29eb", - "blacksquare;": "\u25aa", - "blacktriangle;": "\u25b4", - "blacktriangledown;": "\u25be", - "blacktriangleleft;": "\u25c2", - "blacktriangleright;": "\u25b8", - "blank;": "\u2423", - "blk12;": "\u2592", - "blk14;": "\u2591", - "blk34;": "\u2593", - "block;": "\u2588", - "bne;": "=\u20e5", - "bnequiv;": "\u2261\u20e5", - "bnot;": "\u2310", - "bopf;": "\U0001d553", - "bot;": "\u22a5", - "bottom;": "\u22a5", - "bowtie;": "\u22c8", - "boxDL;": "\u2557", - "boxDR;": "\u2554", - "boxDl;": "\u2556", - "boxDr;": "\u2553", - "boxH;": "\u2550", - "boxHD;": "\u2566", - "boxHU;": "\u2569", - "boxHd;": "\u2564", - "boxHu;": "\u2567", - "boxUL;": "\u255d", - "boxUR;": "\u255a", - "boxUl;": "\u255c", - "boxUr;": "\u2559", - "boxV;": "\u2551", - "boxVH;": "\u256c", - "boxVL;": "\u2563", - "boxVR;": "\u2560", - "boxVh;": "\u256b", - "boxVl;": "\u2562", - "boxVr;": "\u255f", - "boxbox;": "\u29c9", - "boxdL;": "\u2555", - "boxdR;": "\u2552", - "boxdl;": "\u2510", - "boxdr;": "\u250c", - "boxh;": "\u2500", - "boxhD;": "\u2565", - "boxhU;": "\u2568", - "boxhd;": "\u252c", - "boxhu;": "\u2534", - "boxminus;": "\u229f", - "boxplus;": "\u229e", - "boxtimes;": "\u22a0", - "boxuL;": "\u255b", - "boxuR;": "\u2558", - "boxul;": "\u2518", - "boxur;": "\u2514", - "boxv;": "\u2502", - "boxvH;": "\u256a", - "boxvL;": "\u2561", - "boxvR;": "\u255e", - "boxvh;": "\u253c", - "boxvl;": "\u2524", - "boxvr;": "\u251c", - "bprime;": "\u2035", - "breve;": "\u02d8", - "brvbar": "\xa6", - "brvbar;": "\xa6", - "bscr;": "\U0001d4b7", - "bsemi;": "\u204f", - "bsim;": "\u223d", - "bsime;": "\u22cd", - "bsol;": "\\", - "bsolb;": "\u29c5", - "bsolhsub;": "\u27c8", - "bull;": "\u2022", - "bullet;": "\u2022", - "bump;": "\u224e", - "bumpE;": "\u2aae", - "bumpe;": "\u224f", - "bumpeq;": "\u224f", - "cacute;": "\u0107", - "cap;": "\u2229", - "capand;": "\u2a44", - "capbrcup;": "\u2a49", - "capcap;": "\u2a4b", - "capcup;": "\u2a47", - "capdot;": "\u2a40", - "caps;": "\u2229\ufe00", - "caret;": "\u2041", - "caron;": "\u02c7", - "ccaps;": "\u2a4d", - "ccaron;": "\u010d", - "ccedil": "\xe7", - "ccedil;": "\xe7", - "ccirc;": "\u0109", - "ccups;": "\u2a4c", - "ccupssm;": "\u2a50", - "cdot;": "\u010b", - "cedil": "\xb8", - "cedil;": "\xb8", - "cemptyv;": "\u29b2", - "cent": "\xa2", - "cent;": "\xa2", - "centerdot;": "\xb7", - "cfr;": "\U0001d520", - "chcy;": "\u0447", - "check;": "\u2713", - "checkmark;": "\u2713", - "chi;": "\u03c7", - "cir;": "\u25cb", - "cirE;": "\u29c3", - "circ;": "\u02c6", - "circeq;": "\u2257", - "circlearrowleft;": "\u21ba", - "circlearrowright;": "\u21bb", - "circledR;": "\xae", - "circledS;": "\u24c8", - "circledast;": "\u229b", - "circledcirc;": "\u229a", - "circleddash;": "\u229d", - "cire;": "\u2257", - "cirfnint;": "\u2a10", - "cirmid;": "\u2aef", - "cirscir;": "\u29c2", - "clubs;": "\u2663", - "clubsuit;": "\u2663", - "colon;": ":", - "colone;": "\u2254", - "coloneq;": "\u2254", - "comma;": ",", - "commat;": "@", - "comp;": "\u2201", - "compfn;": "\u2218", - "complement;": "\u2201", - "complexes;": "\u2102", - "cong;": "\u2245", - "congdot;": "\u2a6d", - "conint;": "\u222e", - "copf;": "\U0001d554", - "coprod;": "\u2210", - "copy": "\xa9", - "copy;": "\xa9", - "copysr;": "\u2117", - "crarr;": "\u21b5", - "cross;": "\u2717", - "cscr;": "\U0001d4b8", - "csub;": "\u2acf", - "csube;": "\u2ad1", - "csup;": "\u2ad0", - "csupe;": "\u2ad2", - "ctdot;": "\u22ef", - "cudarrl;": "\u2938", - "cudarrr;": "\u2935", - "cuepr;": "\u22de", - "cuesc;": "\u22df", - "cularr;": "\u21b6", - "cularrp;": "\u293d", - "cup;": "\u222a", - "cupbrcap;": "\u2a48", - "cupcap;": "\u2a46", - "cupcup;": "\u2a4a", - "cupdot;": "\u228d", - "cupor;": "\u2a45", - "cups;": "\u222a\ufe00", - "curarr;": "\u21b7", - "curarrm;": "\u293c", - "curlyeqprec;": "\u22de", - "curlyeqsucc;": "\u22df", - "curlyvee;": "\u22ce", - "curlywedge;": "\u22cf", - "curren": "\xa4", - "curren;": "\xa4", - "curvearrowleft;": "\u21b6", - "curvearrowright;": "\u21b7", - "cuvee;": "\u22ce", - "cuwed;": "\u22cf", - "cwconint;": "\u2232", - "cwint;": "\u2231", - "cylcty;": "\u232d", - "dArr;": "\u21d3", - "dHar;": "\u2965", - "dagger;": "\u2020", - "daleth;": "\u2138", - "darr;": "\u2193", - "dash;": "\u2010", - "dashv;": "\u22a3", - "dbkarow;": "\u290f", - "dblac;": "\u02dd", - "dcaron;": "\u010f", - "dcy;": "\u0434", - "dd;": "\u2146", - "ddagger;": "\u2021", - "ddarr;": "\u21ca", - "ddotseq;": "\u2a77", - "deg": "\xb0", - "deg;": "\xb0", - "delta;": "\u03b4", - "demptyv;": "\u29b1", - "dfisht;": "\u297f", - "dfr;": "\U0001d521", - "dharl;": "\u21c3", - "dharr;": "\u21c2", - "diam;": "\u22c4", - "diamond;": "\u22c4", - "diamondsuit;": "\u2666", - "diams;": "\u2666", - "die;": "\xa8", - "digamma;": "\u03dd", - "disin;": "\u22f2", - "div;": "\xf7", - "divide": "\xf7", - "divide;": "\xf7", - "divideontimes;": "\u22c7", - "divonx;": "\u22c7", - "djcy;": "\u0452", - "dlcorn;": "\u231e", - "dlcrop;": "\u230d", - "dollar;": "$", - "dopf;": "\U0001d555", - "dot;": "\u02d9", - "doteq;": "\u2250", - "doteqdot;": "\u2251", - "dotminus;": "\u2238", - "dotplus;": "\u2214", - "dotsquare;": "\u22a1", - "doublebarwedge;": "\u2306", - "downarrow;": "\u2193", - "downdownarrows;": "\u21ca", - "downharpoonleft;": "\u21c3", - "downharpoonright;": "\u21c2", - "drbkarow;": "\u2910", - "drcorn;": "\u231f", - "drcrop;": "\u230c", - "dscr;": "\U0001d4b9", - "dscy;": "\u0455", - "dsol;": "\u29f6", - "dstrok;": "\u0111", - "dtdot;": "\u22f1", - "dtri;": "\u25bf", - "dtrif;": "\u25be", - "duarr;": "\u21f5", - "duhar;": "\u296f", - "dwangle;": "\u29a6", - "dzcy;": "\u045f", - "dzigrarr;": "\u27ff", - "eDDot;": "\u2a77", - "eDot;": "\u2251", - "eacute": "\xe9", - "eacute;": "\xe9", - "easter;": "\u2a6e", - "ecaron;": "\u011b", - "ecir;": "\u2256", - "ecirc": "\xea", - "ecirc;": "\xea", - "ecolon;": "\u2255", - "ecy;": "\u044d", - "edot;": "\u0117", - "ee;": "\u2147", - "efDot;": "\u2252", - "efr;": "\U0001d522", - "eg;": "\u2a9a", - "egrave": "\xe8", - "egrave;": "\xe8", - "egs;": "\u2a96", - "egsdot;": "\u2a98", - "el;": "\u2a99", - "elinters;": "\u23e7", - "ell;": "\u2113", - "els;": "\u2a95", - "elsdot;": "\u2a97", - "emacr;": "\u0113", - "empty;": "\u2205", - "emptyset;": "\u2205", - "emptyv;": "\u2205", - "emsp13;": "\u2004", - "emsp14;": "\u2005", - "emsp;": "\u2003", - "eng;": "\u014b", - "ensp;": "\u2002", - "eogon;": "\u0119", - "eopf;": "\U0001d556", - "epar;": "\u22d5", - "eparsl;": "\u29e3", - "eplus;": "\u2a71", - "epsi;": "\u03b5", - "epsilon;": "\u03b5", - "epsiv;": "\u03f5", - "eqcirc;": "\u2256", - "eqcolon;": "\u2255", - "eqsim;": "\u2242", - "eqslantgtr;": "\u2a96", - "eqslantless;": "\u2a95", - "equals;": "=", - "equest;": "\u225f", - "equiv;": "\u2261", - "equivDD;": "\u2a78", - "eqvparsl;": "\u29e5", - "erDot;": "\u2253", - "erarr;": "\u2971", - "escr;": "\u212f", - "esdot;": "\u2250", - "esim;": "\u2242", - "eta;": "\u03b7", - "eth": "\xf0", - "eth;": "\xf0", - "euml": "\xeb", - "euml;": "\xeb", - "euro;": "\u20ac", - "excl;": "!", - "exist;": "\u2203", - "expectation;": "\u2130", - "exponentiale;": "\u2147", - "fallingdotseq;": "\u2252", - "fcy;": "\u0444", - "female;": "\u2640", - "ffilig;": "\ufb03", - "fflig;": "\ufb00", - "ffllig;": "\ufb04", - "ffr;": "\U0001d523", - "filig;": "\ufb01", - "fjlig;": "fj", - "flat;": "\u266d", - "fllig;": "\ufb02", - "fltns;": "\u25b1", - "fnof;": "\u0192", - "fopf;": "\U0001d557", - "forall;": "\u2200", - "fork;": "\u22d4", - "forkv;": "\u2ad9", - "fpartint;": "\u2a0d", - "frac12": "\xbd", - "frac12;": "\xbd", - "frac13;": "\u2153", - "frac14": "\xbc", - "frac14;": "\xbc", - "frac15;": "\u2155", - "frac16;": "\u2159", - "frac18;": "\u215b", - "frac23;": "\u2154", - "frac25;": "\u2156", - "frac34": "\xbe", - "frac34;": "\xbe", - "frac35;": "\u2157", - "frac38;": "\u215c", - "frac45;": "\u2158", - "frac56;": "\u215a", - "frac58;": "\u215d", - "frac78;": "\u215e", - "frasl;": "\u2044", - "frown;": "\u2322", - "fscr;": "\U0001d4bb", - "gE;": "\u2267", - "gEl;": "\u2a8c", - "gacute;": "\u01f5", - "gamma;": "\u03b3", - "gammad;": "\u03dd", - "gap;": "\u2a86", - "gbreve;": "\u011f", - "gcirc;": "\u011d", - "gcy;": "\u0433", - "gdot;": "\u0121", - "ge;": "\u2265", - "gel;": "\u22db", - "geq;": "\u2265", - "geqq;": "\u2267", - "geqslant;": "\u2a7e", - "ges;": "\u2a7e", - "gescc;": "\u2aa9", - "gesdot;": "\u2a80", - "gesdoto;": "\u2a82", - "gesdotol;": "\u2a84", - "gesl;": "\u22db\ufe00", - "gesles;": "\u2a94", - "gfr;": "\U0001d524", - "gg;": "\u226b", - "ggg;": "\u22d9", - "gimel;": "\u2137", - "gjcy;": "\u0453", - "gl;": "\u2277", - "glE;": "\u2a92", - "gla;": "\u2aa5", - "glj;": "\u2aa4", - "gnE;": "\u2269", - "gnap;": "\u2a8a", - "gnapprox;": "\u2a8a", - "gne;": "\u2a88", - "gneq;": "\u2a88", - "gneqq;": "\u2269", - "gnsim;": "\u22e7", - "gopf;": "\U0001d558", - "grave;": "`", - "gscr;": "\u210a", - "gsim;": "\u2273", - "gsime;": "\u2a8e", - "gsiml;": "\u2a90", - "gt": ">", - "gt;": ">", - "gtcc;": "\u2aa7", - "gtcir;": "\u2a7a", - "gtdot;": "\u22d7", - "gtlPar;": "\u2995", - "gtquest;": "\u2a7c", - "gtrapprox;": "\u2a86", - "gtrarr;": "\u2978", - "gtrdot;": "\u22d7", - "gtreqless;": "\u22db", - "gtreqqless;": "\u2a8c", - "gtrless;": "\u2277", - "gtrsim;": "\u2273", - "gvertneqq;": "\u2269\ufe00", - "gvnE;": "\u2269\ufe00", - "hArr;": "\u21d4", - "hairsp;": "\u200a", - "half;": "\xbd", - "hamilt;": "\u210b", - "hardcy;": "\u044a", - "harr;": "\u2194", - "harrcir;": "\u2948", - "harrw;": "\u21ad", - "hbar;": "\u210f", - "hcirc;": "\u0125", - "hearts;": "\u2665", - "heartsuit;": "\u2665", - "hellip;": "\u2026", - "hercon;": "\u22b9", - "hfr;": "\U0001d525", - "hksearow;": "\u2925", - "hkswarow;": "\u2926", - "hoarr;": "\u21ff", - "homtht;": "\u223b", - "hookleftarrow;": "\u21a9", - "hookrightarrow;": "\u21aa", - "hopf;": "\U0001d559", - "horbar;": "\u2015", - "hscr;": "\U0001d4bd", - "hslash;": "\u210f", - "hstrok;": "\u0127", - "hybull;": "\u2043", - "hyphen;": "\u2010", - "iacute": "\xed", - "iacute;": "\xed", - "ic;": "\u2063", - "icirc": "\xee", - "icirc;": "\xee", - "icy;": "\u0438", - "iecy;": "\u0435", - "iexcl": "\xa1", - "iexcl;": "\xa1", - "iff;": "\u21d4", - "ifr;": "\U0001d526", - "igrave": "\xec", - "igrave;": "\xec", - "ii;": "\u2148", - "iiiint;": "\u2a0c", - "iiint;": "\u222d", - "iinfin;": "\u29dc", - "iiota;": "\u2129", - "ijlig;": "\u0133", - "imacr;": "\u012b", - "image;": "\u2111", - "imagline;": "\u2110", - "imagpart;": "\u2111", - "imath;": "\u0131", - "imof;": "\u22b7", - "imped;": "\u01b5", - "in;": "\u2208", - "incare;": "\u2105", - "infin;": "\u221e", - "infintie;": "\u29dd", - "inodot;": "\u0131", - "int;": "\u222b", - "intcal;": "\u22ba", - "integers;": "\u2124", - "intercal;": "\u22ba", - "intlarhk;": "\u2a17", - "intprod;": "\u2a3c", - "iocy;": "\u0451", - "iogon;": "\u012f", - "iopf;": "\U0001d55a", - "iota;": "\u03b9", - "iprod;": "\u2a3c", - "iquest": "\xbf", - "iquest;": "\xbf", - "iscr;": "\U0001d4be", - "isin;": "\u2208", - "isinE;": "\u22f9", - "isindot;": "\u22f5", - "isins;": "\u22f4", - "isinsv;": "\u22f3", - "isinv;": "\u2208", - "it;": "\u2062", - "itilde;": "\u0129", - "iukcy;": "\u0456", - "iuml": "\xef", - "iuml;": "\xef", - "jcirc;": "\u0135", - "jcy;": "\u0439", - "jfr;": "\U0001d527", - "jmath;": "\u0237", - "jopf;": "\U0001d55b", - "jscr;": "\U0001d4bf", - "jsercy;": "\u0458", - "jukcy;": "\u0454", - "kappa;": "\u03ba", - "kappav;": "\u03f0", - "kcedil;": "\u0137", - "kcy;": "\u043a", - "kfr;": "\U0001d528", - "kgreen;": "\u0138", - "khcy;": "\u0445", - "kjcy;": "\u045c", - "kopf;": "\U0001d55c", - "kscr;": "\U0001d4c0", - "lAarr;": "\u21da", - "lArr;": "\u21d0", - "lAtail;": "\u291b", - "lBarr;": "\u290e", - "lE;": "\u2266", - "lEg;": "\u2a8b", - "lHar;": "\u2962", - "lacute;": "\u013a", - "laemptyv;": "\u29b4", - "lagran;": "\u2112", - "lambda;": "\u03bb", - "lang;": "\u27e8", - "langd;": "\u2991", - "langle;": "\u27e8", - "lap;": "\u2a85", - "laquo": "\xab", - "laquo;": "\xab", - "larr;": "\u2190", - "larrb;": "\u21e4", - "larrbfs;": "\u291f", - "larrfs;": "\u291d", - "larrhk;": "\u21a9", - "larrlp;": "\u21ab", - "larrpl;": "\u2939", - "larrsim;": "\u2973", - "larrtl;": "\u21a2", - "lat;": "\u2aab", - "latail;": "\u2919", - "late;": "\u2aad", - "lates;": "\u2aad\ufe00", - "lbarr;": "\u290c", - "lbbrk;": "\u2772", - "lbrace;": "{", - "lbrack;": "[", - "lbrke;": "\u298b", - "lbrksld;": "\u298f", - "lbrkslu;": "\u298d", - "lcaron;": "\u013e", - "lcedil;": "\u013c", - "lceil;": "\u2308", - "lcub;": "{", - "lcy;": "\u043b", - "ldca;": "\u2936", - "ldquo;": "\u201c", - "ldquor;": "\u201e", - "ldrdhar;": "\u2967", - "ldrushar;": "\u294b", - "ldsh;": "\u21b2", - "le;": "\u2264", - "leftarrow;": "\u2190", - "leftarrowtail;": "\u21a2", - "leftharpoondown;": "\u21bd", - "leftharpoonup;": "\u21bc", - "leftleftarrows;": "\u21c7", - "leftrightarrow;": "\u2194", - "leftrightarrows;": "\u21c6", - "leftrightharpoons;": "\u21cb", - "leftrightsquigarrow;": "\u21ad", - "leftthreetimes;": "\u22cb", - "leg;": "\u22da", - "leq;": "\u2264", - "leqq;": "\u2266", - "leqslant;": "\u2a7d", - "les;": "\u2a7d", - "lescc;": "\u2aa8", - "lesdot;": "\u2a7f", - "lesdoto;": "\u2a81", - "lesdotor;": "\u2a83", - "lesg;": "\u22da\ufe00", - "lesges;": "\u2a93", - "lessapprox;": "\u2a85", - "lessdot;": "\u22d6", - "lesseqgtr;": "\u22da", - "lesseqqgtr;": "\u2a8b", - "lessgtr;": "\u2276", - "lesssim;": "\u2272", - "lfisht;": "\u297c", - "lfloor;": "\u230a", - "lfr;": "\U0001d529", - "lg;": "\u2276", - "lgE;": "\u2a91", - "lhard;": "\u21bd", - "lharu;": "\u21bc", - "lharul;": "\u296a", - "lhblk;": "\u2584", - "ljcy;": "\u0459", - "ll;": "\u226a", - "llarr;": "\u21c7", - "llcorner;": "\u231e", - "llhard;": "\u296b", - "lltri;": "\u25fa", - "lmidot;": "\u0140", - "lmoust;": "\u23b0", - "lmoustache;": "\u23b0", - "lnE;": "\u2268", - "lnap;": "\u2a89", - "lnapprox;": "\u2a89", - "lne;": "\u2a87", - "lneq;": "\u2a87", - "lneqq;": "\u2268", - "lnsim;": "\u22e6", - "loang;": "\u27ec", - "loarr;": "\u21fd", - "lobrk;": "\u27e6", - "longleftarrow;": "\u27f5", - "longleftrightarrow;": "\u27f7", - "longmapsto;": "\u27fc", - "longrightarrow;": "\u27f6", - "looparrowleft;": "\u21ab", - "looparrowright;": "\u21ac", - "lopar;": "\u2985", - "lopf;": "\U0001d55d", - "loplus;": "\u2a2d", - "lotimes;": "\u2a34", - "lowast;": "\u2217", - "lowbar;": "_", - "loz;": "\u25ca", - "lozenge;": "\u25ca", - "lozf;": "\u29eb", - "lpar;": "(", - "lparlt;": "\u2993", - "lrarr;": "\u21c6", - "lrcorner;": "\u231f", - "lrhar;": "\u21cb", - "lrhard;": "\u296d", - "lrm;": "\u200e", - "lrtri;": "\u22bf", - "lsaquo;": "\u2039", - "lscr;": "\U0001d4c1", - "lsh;": "\u21b0", - "lsim;": "\u2272", - "lsime;": "\u2a8d", - "lsimg;": "\u2a8f", - "lsqb;": "[", - "lsquo;": "\u2018", - "lsquor;": "\u201a", - "lstrok;": "\u0142", - "lt": "<", - "lt;": "<", - "ltcc;": "\u2aa6", - "ltcir;": "\u2a79", - "ltdot;": "\u22d6", - "lthree;": "\u22cb", - "ltimes;": "\u22c9", - "ltlarr;": "\u2976", - "ltquest;": "\u2a7b", - "ltrPar;": "\u2996", - "ltri;": "\u25c3", - "ltrie;": "\u22b4", - "ltrif;": "\u25c2", - "lurdshar;": "\u294a", - "luruhar;": "\u2966", - "lvertneqq;": "\u2268\ufe00", - "lvnE;": "\u2268\ufe00", - "mDDot;": "\u223a", - "macr": "\xaf", - "macr;": "\xaf", - "male;": "\u2642", - "malt;": "\u2720", - "maltese;": "\u2720", - "map;": "\u21a6", - "mapsto;": "\u21a6", - "mapstodown;": "\u21a7", - "mapstoleft;": "\u21a4", - "mapstoup;": "\u21a5", - "marker;": "\u25ae", - "mcomma;": "\u2a29", - "mcy;": "\u043c", - "mdash;": "\u2014", - "measuredangle;": "\u2221", - "mfr;": "\U0001d52a", - "mho;": "\u2127", - "micro": "\xb5", - "micro;": "\xb5", - "mid;": "\u2223", - "midast;": "*", - "midcir;": "\u2af0", - "middot": "\xb7", - "middot;": "\xb7", - "minus;": "\u2212", - "minusb;": "\u229f", - "minusd;": "\u2238", - "minusdu;": "\u2a2a", - "mlcp;": "\u2adb", - "mldr;": "\u2026", - "mnplus;": "\u2213", - "models;": "\u22a7", - "mopf;": "\U0001d55e", - "mp;": "\u2213", - "mscr;": "\U0001d4c2", - "mstpos;": "\u223e", - "mu;": "\u03bc", - "multimap;": "\u22b8", - "mumap;": "\u22b8", - "nGg;": "\u22d9\u0338", - "nGt;": "\u226b\u20d2", - "nGtv;": "\u226b\u0338", - "nLeftarrow;": "\u21cd", - "nLeftrightarrow;": "\u21ce", - "nLl;": "\u22d8\u0338", - "nLt;": "\u226a\u20d2", - "nLtv;": "\u226a\u0338", - "nRightarrow;": "\u21cf", - "nVDash;": "\u22af", - "nVdash;": "\u22ae", - "nabla;": "\u2207", - "nacute;": "\u0144", - "nang;": "\u2220\u20d2", - "nap;": "\u2249", - "napE;": "\u2a70\u0338", - "napid;": "\u224b\u0338", - "napos;": "\u0149", - "napprox;": "\u2249", - "natur;": "\u266e", - "natural;": "\u266e", - "naturals;": "\u2115", - "nbsp": "\xa0", - "nbsp;": "\xa0", - "nbump;": "\u224e\u0338", - "nbumpe;": "\u224f\u0338", - "ncap;": "\u2a43", - "ncaron;": "\u0148", - "ncedil;": "\u0146", - "ncong;": "\u2247", - "ncongdot;": "\u2a6d\u0338", - "ncup;": "\u2a42", - "ncy;": "\u043d", - "ndash;": "\u2013", - "ne;": "\u2260", - "neArr;": "\u21d7", - "nearhk;": "\u2924", - "nearr;": "\u2197", - "nearrow;": "\u2197", - "nedot;": "\u2250\u0338", - "nequiv;": "\u2262", - "nesear;": "\u2928", - "nesim;": "\u2242\u0338", - "nexist;": "\u2204", - "nexists;": "\u2204", - "nfr;": "\U0001d52b", - "ngE;": "\u2267\u0338", - "nge;": "\u2271", - "ngeq;": "\u2271", - "ngeqq;": "\u2267\u0338", - "ngeqslant;": "\u2a7e\u0338", - "nges;": "\u2a7e\u0338", - "ngsim;": "\u2275", - "ngt;": "\u226f", - "ngtr;": "\u226f", - "nhArr;": "\u21ce", - "nharr;": "\u21ae", - "nhpar;": "\u2af2", - "ni;": "\u220b", - "nis;": "\u22fc", - "nisd;": "\u22fa", - "niv;": "\u220b", - "njcy;": "\u045a", - "nlArr;": "\u21cd", - "nlE;": "\u2266\u0338", - "nlarr;": "\u219a", - "nldr;": "\u2025", - "nle;": "\u2270", - "nleftarrow;": "\u219a", - "nleftrightarrow;": "\u21ae", - "nleq;": "\u2270", - "nleqq;": "\u2266\u0338", - "nleqslant;": "\u2a7d\u0338", - "nles;": "\u2a7d\u0338", - "nless;": "\u226e", - "nlsim;": "\u2274", - "nlt;": "\u226e", - "nltri;": "\u22ea", - "nltrie;": "\u22ec", - "nmid;": "\u2224", - "nopf;": "\U0001d55f", - "not": "\xac", - "not;": "\xac", - "notin;": "\u2209", - "notinE;": "\u22f9\u0338", - "notindot;": "\u22f5\u0338", - "notinva;": "\u2209", - "notinvb;": "\u22f7", - "notinvc;": "\u22f6", - "notni;": "\u220c", - "notniva;": "\u220c", - "notnivb;": "\u22fe", - "notnivc;": "\u22fd", - "npar;": "\u2226", - "nparallel;": "\u2226", - "nparsl;": "\u2afd\u20e5", - "npart;": "\u2202\u0338", - "npolint;": "\u2a14", - "npr;": "\u2280", - "nprcue;": "\u22e0", - "npre;": "\u2aaf\u0338", - "nprec;": "\u2280", - "npreceq;": "\u2aaf\u0338", - "nrArr;": "\u21cf", - "nrarr;": "\u219b", - "nrarrc;": "\u2933\u0338", - "nrarrw;": "\u219d\u0338", - "nrightarrow;": "\u219b", - "nrtri;": "\u22eb", - "nrtrie;": "\u22ed", - "nsc;": "\u2281", - "nsccue;": "\u22e1", - "nsce;": "\u2ab0\u0338", - "nscr;": "\U0001d4c3", - "nshortmid;": "\u2224", - "nshortparallel;": "\u2226", - "nsim;": "\u2241", - "nsime;": "\u2244", - "nsimeq;": "\u2244", - "nsmid;": "\u2224", - "nspar;": "\u2226", - "nsqsube;": "\u22e2", - "nsqsupe;": "\u22e3", - "nsub;": "\u2284", - "nsubE;": "\u2ac5\u0338", - "nsube;": "\u2288", - "nsubset;": "\u2282\u20d2", - "nsubseteq;": "\u2288", - "nsubseteqq;": "\u2ac5\u0338", - "nsucc;": "\u2281", - "nsucceq;": "\u2ab0\u0338", - "nsup;": "\u2285", - "nsupE;": "\u2ac6\u0338", - "nsupe;": "\u2289", - "nsupset;": "\u2283\u20d2", - "nsupseteq;": "\u2289", - "nsupseteqq;": "\u2ac6\u0338", - "ntgl;": "\u2279", - "ntilde": "\xf1", - "ntilde;": "\xf1", - "ntlg;": "\u2278", - "ntriangleleft;": "\u22ea", - "ntrianglelefteq;": "\u22ec", - "ntriangleright;": "\u22eb", - "ntrianglerighteq;": "\u22ed", - "nu;": "\u03bd", - "num;": "#", - "numero;": "\u2116", - "numsp;": "\u2007", - "nvDash;": "\u22ad", - "nvHarr;": "\u2904", - "nvap;": "\u224d\u20d2", - "nvdash;": "\u22ac", - "nvge;": "\u2265\u20d2", - "nvgt;": ">\u20d2", - "nvinfin;": "\u29de", - "nvlArr;": "\u2902", - "nvle;": "\u2264\u20d2", - "nvlt;": "<\u20d2", - "nvltrie;": "\u22b4\u20d2", - "nvrArr;": "\u2903", - "nvrtrie;": "\u22b5\u20d2", - "nvsim;": "\u223c\u20d2", - "nwArr;": "\u21d6", - "nwarhk;": "\u2923", - "nwarr;": "\u2196", - "nwarrow;": "\u2196", - "nwnear;": "\u2927", - "oS;": "\u24c8", - "oacute": "\xf3", - "oacute;": "\xf3", - "oast;": "\u229b", - "ocir;": "\u229a", - "ocirc": "\xf4", - "ocirc;": "\xf4", - "ocy;": "\u043e", - "odash;": "\u229d", - "odblac;": "\u0151", - "odiv;": "\u2a38", - "odot;": "\u2299", - "odsold;": "\u29bc", - "oelig;": "\u0153", - "ofcir;": "\u29bf", - "ofr;": "\U0001d52c", - "ogon;": "\u02db", - "ograve": "\xf2", - "ograve;": "\xf2", - "ogt;": "\u29c1", - "ohbar;": "\u29b5", - "ohm;": "\u03a9", - "oint;": "\u222e", - "olarr;": "\u21ba", - "olcir;": "\u29be", - "olcross;": "\u29bb", - "oline;": "\u203e", - "olt;": "\u29c0", - "omacr;": "\u014d", - "omega;": "\u03c9", - "omicron;": "\u03bf", - "omid;": "\u29b6", - "ominus;": "\u2296", - "oopf;": "\U0001d560", - "opar;": "\u29b7", - "operp;": "\u29b9", - "oplus;": "\u2295", - "or;": "\u2228", - "orarr;": "\u21bb", - "ord;": "\u2a5d", - "order;": "\u2134", - "orderof;": "\u2134", - "ordf": "\xaa", - "ordf;": "\xaa", - "ordm": "\xba", - "ordm;": "\xba", - "origof;": "\u22b6", - "oror;": "\u2a56", - "orslope;": "\u2a57", - "orv;": "\u2a5b", - "oscr;": "\u2134", - "oslash": "\xf8", - "oslash;": "\xf8", - "osol;": "\u2298", - "otilde": "\xf5", - "otilde;": "\xf5", - "otimes;": "\u2297", - "otimesas;": "\u2a36", - "ouml": "\xf6", - "ouml;": "\xf6", - "ovbar;": "\u233d", - "par;": "\u2225", - "para": "\xb6", - "para;": "\xb6", - "parallel;": "\u2225", - "parsim;": "\u2af3", - "parsl;": "\u2afd", - "part;": "\u2202", - "pcy;": "\u043f", - "percnt;": "%", - "period;": ".", - "permil;": "\u2030", - "perp;": "\u22a5", - "pertenk;": "\u2031", - "pfr;": "\U0001d52d", - "phi;": "\u03c6", - "phiv;": "\u03d5", - "phmmat;": "\u2133", - "phone;": "\u260e", - "pi;": "\u03c0", - "pitchfork;": "\u22d4", - "piv;": "\u03d6", - "planck;": "\u210f", - "planckh;": "\u210e", - "plankv;": "\u210f", - "plus;": "+", - "plusacir;": "\u2a23", - "plusb;": "\u229e", - "pluscir;": "\u2a22", - "plusdo;": "\u2214", - "plusdu;": "\u2a25", - "pluse;": "\u2a72", - "plusmn": "\xb1", - "plusmn;": "\xb1", - "plussim;": "\u2a26", - "plustwo;": "\u2a27", - "pm;": "\xb1", - "pointint;": "\u2a15", - "popf;": "\U0001d561", - "pound": "\xa3", - "pound;": "\xa3", - "pr;": "\u227a", - "prE;": "\u2ab3", - "prap;": "\u2ab7", - "prcue;": "\u227c", - "pre;": "\u2aaf", - "prec;": "\u227a", - "precapprox;": "\u2ab7", - "preccurlyeq;": "\u227c", - "preceq;": "\u2aaf", - "precnapprox;": "\u2ab9", - "precneqq;": "\u2ab5", - "precnsim;": "\u22e8", - "precsim;": "\u227e", - "prime;": "\u2032", - "primes;": "\u2119", - "prnE;": "\u2ab5", - "prnap;": "\u2ab9", - "prnsim;": "\u22e8", - "prod;": "\u220f", - "profalar;": "\u232e", - "profline;": "\u2312", - "profsurf;": "\u2313", - "prop;": "\u221d", - "propto;": "\u221d", - "prsim;": "\u227e", - "prurel;": "\u22b0", - "pscr;": "\U0001d4c5", - "psi;": "\u03c8", - "puncsp;": "\u2008", - "qfr;": "\U0001d52e", - "qint;": "\u2a0c", - "qopf;": "\U0001d562", - "qprime;": "\u2057", - "qscr;": "\U0001d4c6", - "quaternions;": "\u210d", - "quatint;": "\u2a16", - "quest;": "?", - "questeq;": "\u225f", - "quot": "\"", - "quot;": "\"", - "rAarr;": "\u21db", - "rArr;": "\u21d2", - "rAtail;": "\u291c", - "rBarr;": "\u290f", - "rHar;": "\u2964", - "race;": "\u223d\u0331", - "racute;": "\u0155", - "radic;": "\u221a", - "raemptyv;": "\u29b3", - "rang;": "\u27e9", - "rangd;": "\u2992", - "range;": "\u29a5", - "rangle;": "\u27e9", - "raquo": "\xbb", - "raquo;": "\xbb", - "rarr;": "\u2192", - "rarrap;": "\u2975", - "rarrb;": "\u21e5", - "rarrbfs;": "\u2920", - "rarrc;": "\u2933", - "rarrfs;": "\u291e", - "rarrhk;": "\u21aa", - "rarrlp;": "\u21ac", - "rarrpl;": "\u2945", - "rarrsim;": "\u2974", - "rarrtl;": "\u21a3", - "rarrw;": "\u219d", - "ratail;": "\u291a", - "ratio;": "\u2236", - "rationals;": "\u211a", - "rbarr;": "\u290d", - "rbbrk;": "\u2773", - "rbrace;": "}", - "rbrack;": "]", - "rbrke;": "\u298c", - "rbrksld;": "\u298e", - "rbrkslu;": "\u2990", - "rcaron;": "\u0159", - "rcedil;": "\u0157", - "rceil;": "\u2309", - "rcub;": "}", - "rcy;": "\u0440", - "rdca;": "\u2937", - "rdldhar;": "\u2969", - "rdquo;": "\u201d", - "rdquor;": "\u201d", - "rdsh;": "\u21b3", - "real;": "\u211c", - "realine;": "\u211b", - "realpart;": "\u211c", - "reals;": "\u211d", - "rect;": "\u25ad", - "reg": "\xae", - "reg;": "\xae", - "rfisht;": "\u297d", - "rfloor;": "\u230b", - "rfr;": "\U0001d52f", - "rhard;": "\u21c1", - "rharu;": "\u21c0", - "rharul;": "\u296c", - "rho;": "\u03c1", - "rhov;": "\u03f1", - "rightarrow;": "\u2192", - "rightarrowtail;": "\u21a3", - "rightharpoondown;": "\u21c1", - "rightharpoonup;": "\u21c0", - "rightleftarrows;": "\u21c4", - "rightleftharpoons;": "\u21cc", - "rightrightarrows;": "\u21c9", - "rightsquigarrow;": "\u219d", - "rightthreetimes;": "\u22cc", - "ring;": "\u02da", - "risingdotseq;": "\u2253", - "rlarr;": "\u21c4", - "rlhar;": "\u21cc", - "rlm;": "\u200f", - "rmoust;": "\u23b1", - "rmoustache;": "\u23b1", - "rnmid;": "\u2aee", - "roang;": "\u27ed", - "roarr;": "\u21fe", - "robrk;": "\u27e7", - "ropar;": "\u2986", - "ropf;": "\U0001d563", - "roplus;": "\u2a2e", - "rotimes;": "\u2a35", - "rpar;": ")", - "rpargt;": "\u2994", - "rppolint;": "\u2a12", - "rrarr;": "\u21c9", - "rsaquo;": "\u203a", - "rscr;": "\U0001d4c7", - "rsh;": "\u21b1", - "rsqb;": "]", - "rsquo;": "\u2019", - "rsquor;": "\u2019", - "rthree;": "\u22cc", - "rtimes;": "\u22ca", - "rtri;": "\u25b9", - "rtrie;": "\u22b5", - "rtrif;": "\u25b8", - "rtriltri;": "\u29ce", - "ruluhar;": "\u2968", - "rx;": "\u211e", - "sacute;": "\u015b", - "sbquo;": "\u201a", - "sc;": "\u227b", - "scE;": "\u2ab4", - "scap;": "\u2ab8", - "scaron;": "\u0161", - "sccue;": "\u227d", - "sce;": "\u2ab0", - "scedil;": "\u015f", - "scirc;": "\u015d", - "scnE;": "\u2ab6", - "scnap;": "\u2aba", - "scnsim;": "\u22e9", - "scpolint;": "\u2a13", - "scsim;": "\u227f", - "scy;": "\u0441", - "sdot;": "\u22c5", - "sdotb;": "\u22a1", - "sdote;": "\u2a66", - "seArr;": "\u21d8", - "searhk;": "\u2925", - "searr;": "\u2198", - "searrow;": "\u2198", - "sect": "\xa7", - "sect;": "\xa7", - "semi;": ";", - "seswar;": "\u2929", - "setminus;": "\u2216", - "setmn;": "\u2216", - "sext;": "\u2736", - "sfr;": "\U0001d530", - "sfrown;": "\u2322", - "sharp;": "\u266f", - "shchcy;": "\u0449", - "shcy;": "\u0448", - "shortmid;": "\u2223", - "shortparallel;": "\u2225", - "shy": "\xad", - "shy;": "\xad", - "sigma;": "\u03c3", - "sigmaf;": "\u03c2", - "sigmav;": "\u03c2", - "sim;": "\u223c", - "simdot;": "\u2a6a", - "sime;": "\u2243", - "simeq;": "\u2243", - "simg;": "\u2a9e", - "simgE;": "\u2aa0", - "siml;": "\u2a9d", - "simlE;": "\u2a9f", - "simne;": "\u2246", - "simplus;": "\u2a24", - "simrarr;": "\u2972", - "slarr;": "\u2190", - "smallsetminus;": "\u2216", - "smashp;": "\u2a33", - "smeparsl;": "\u29e4", - "smid;": "\u2223", - "smile;": "\u2323", - "smt;": "\u2aaa", - "smte;": "\u2aac", - "smtes;": "\u2aac\ufe00", - "softcy;": "\u044c", - "sol;": "/", - "solb;": "\u29c4", - "solbar;": "\u233f", - "sopf;": "\U0001d564", - "spades;": "\u2660", - "spadesuit;": "\u2660", - "spar;": "\u2225", - "sqcap;": "\u2293", - "sqcaps;": "\u2293\ufe00", - "sqcup;": "\u2294", - "sqcups;": "\u2294\ufe00", - "sqsub;": "\u228f", - "sqsube;": "\u2291", - "sqsubset;": "\u228f", - "sqsubseteq;": "\u2291", - "sqsup;": "\u2290", - "sqsupe;": "\u2292", - "sqsupset;": "\u2290", - "sqsupseteq;": "\u2292", - "squ;": "\u25a1", - "square;": "\u25a1", - "squarf;": "\u25aa", - "squf;": "\u25aa", - "srarr;": "\u2192", - "sscr;": "\U0001d4c8", - "ssetmn;": "\u2216", - "ssmile;": "\u2323", - "sstarf;": "\u22c6", - "star;": "\u2606", - "starf;": "\u2605", - "straightepsilon;": "\u03f5", - "straightphi;": "\u03d5", - "strns;": "\xaf", - "sub;": "\u2282", - "subE;": "\u2ac5", - "subdot;": "\u2abd", - "sube;": "\u2286", - "subedot;": "\u2ac3", - "submult;": "\u2ac1", - "subnE;": "\u2acb", - "subne;": "\u228a", - "subplus;": "\u2abf", - "subrarr;": "\u2979", - "subset;": "\u2282", - "subseteq;": "\u2286", - "subseteqq;": "\u2ac5", - "subsetneq;": "\u228a", - "subsetneqq;": "\u2acb", - "subsim;": "\u2ac7", - "subsub;": "\u2ad5", - "subsup;": "\u2ad3", - "succ;": "\u227b", - "succapprox;": "\u2ab8", - "succcurlyeq;": "\u227d", - "succeq;": "\u2ab0", - "succnapprox;": "\u2aba", - "succneqq;": "\u2ab6", - "succnsim;": "\u22e9", - "succsim;": "\u227f", - "sum;": "\u2211", - "sung;": "\u266a", - "sup1": "\xb9", - "sup1;": "\xb9", - "sup2": "\xb2", - "sup2;": "\xb2", - "sup3": "\xb3", - "sup3;": "\xb3", - "sup;": "\u2283", - "supE;": "\u2ac6", - "supdot;": "\u2abe", - "supdsub;": "\u2ad8", - "supe;": "\u2287", - "supedot;": "\u2ac4", - "suphsol;": "\u27c9", - "suphsub;": "\u2ad7", - "suplarr;": "\u297b", - "supmult;": "\u2ac2", - "supnE;": "\u2acc", - "supne;": "\u228b", - "supplus;": "\u2ac0", - "supset;": "\u2283", - "supseteq;": "\u2287", - "supseteqq;": "\u2ac6", - "supsetneq;": "\u228b", - "supsetneqq;": "\u2acc", - "supsim;": "\u2ac8", - "supsub;": "\u2ad4", - "supsup;": "\u2ad6", - "swArr;": "\u21d9", - "swarhk;": "\u2926", - "swarr;": "\u2199", - "swarrow;": "\u2199", - "swnwar;": "\u292a", - "szlig": "\xdf", - "szlig;": "\xdf", - "target;": "\u2316", - "tau;": "\u03c4", - "tbrk;": "\u23b4", - "tcaron;": "\u0165", - "tcedil;": "\u0163", - "tcy;": "\u0442", - "tdot;": "\u20db", - "telrec;": "\u2315", - "tfr;": "\U0001d531", - "there4;": "\u2234", - "therefore;": "\u2234", - "theta;": "\u03b8", - "thetasym;": "\u03d1", - "thetav;": "\u03d1", - "thickapprox;": "\u2248", - "thicksim;": "\u223c", - "thinsp;": "\u2009", - "thkap;": "\u2248", - "thksim;": "\u223c", - "thorn": "\xfe", - "thorn;": "\xfe", - "tilde;": "\u02dc", - "times": "\xd7", - "times;": "\xd7", - "timesb;": "\u22a0", - "timesbar;": "\u2a31", - "timesd;": "\u2a30", - "tint;": "\u222d", - "toea;": "\u2928", - "top;": "\u22a4", - "topbot;": "\u2336", - "topcir;": "\u2af1", - "topf;": "\U0001d565", - "topfork;": "\u2ada", - "tosa;": "\u2929", - "tprime;": "\u2034", - "trade;": "\u2122", - "triangle;": "\u25b5", - "triangledown;": "\u25bf", - "triangleleft;": "\u25c3", - "trianglelefteq;": "\u22b4", - "triangleq;": "\u225c", - "triangleright;": "\u25b9", - "trianglerighteq;": "\u22b5", - "tridot;": "\u25ec", - "trie;": "\u225c", - "triminus;": "\u2a3a", - "triplus;": "\u2a39", - "trisb;": "\u29cd", - "tritime;": "\u2a3b", - "trpezium;": "\u23e2", - "tscr;": "\U0001d4c9", - "tscy;": "\u0446", - "tshcy;": "\u045b", - "tstrok;": "\u0167", - "twixt;": "\u226c", - "twoheadleftarrow;": "\u219e", - "twoheadrightarrow;": "\u21a0", - "uArr;": "\u21d1", - "uHar;": "\u2963", - "uacute": "\xfa", - "uacute;": "\xfa", - "uarr;": "\u2191", - "ubrcy;": "\u045e", - "ubreve;": "\u016d", - "ucirc": "\xfb", - "ucirc;": "\xfb", - "ucy;": "\u0443", - "udarr;": "\u21c5", - "udblac;": "\u0171", - "udhar;": "\u296e", - "ufisht;": "\u297e", - "ufr;": "\U0001d532", - "ugrave": "\xf9", - "ugrave;": "\xf9", - "uharl;": "\u21bf", - "uharr;": "\u21be", - "uhblk;": "\u2580", - "ulcorn;": "\u231c", - "ulcorner;": "\u231c", - "ulcrop;": "\u230f", - "ultri;": "\u25f8", - "umacr;": "\u016b", - "uml": "\xa8", - "uml;": "\xa8", - "uogon;": "\u0173", - "uopf;": "\U0001d566", - "uparrow;": "\u2191", - "updownarrow;": "\u2195", - "upharpoonleft;": "\u21bf", - "upharpoonright;": "\u21be", - "uplus;": "\u228e", - "upsi;": "\u03c5", - "upsih;": "\u03d2", - "upsilon;": "\u03c5", - "upuparrows;": "\u21c8", - "urcorn;": "\u231d", - "urcorner;": "\u231d", - "urcrop;": "\u230e", - "uring;": "\u016f", - "urtri;": "\u25f9", - "uscr;": "\U0001d4ca", - "utdot;": "\u22f0", - "utilde;": "\u0169", - "utri;": "\u25b5", - "utrif;": "\u25b4", - "uuarr;": "\u21c8", - "uuml": "\xfc", - "uuml;": "\xfc", - "uwangle;": "\u29a7", - "vArr;": "\u21d5", - "vBar;": "\u2ae8", - "vBarv;": "\u2ae9", - "vDash;": "\u22a8", - "vangrt;": "\u299c", - "varepsilon;": "\u03f5", - "varkappa;": "\u03f0", - "varnothing;": "\u2205", - "varphi;": "\u03d5", - "varpi;": "\u03d6", - "varpropto;": "\u221d", - "varr;": "\u2195", - "varrho;": "\u03f1", - "varsigma;": "\u03c2", - "varsubsetneq;": "\u228a\ufe00", - "varsubsetneqq;": "\u2acb\ufe00", - "varsupsetneq;": "\u228b\ufe00", - "varsupsetneqq;": "\u2acc\ufe00", - "vartheta;": "\u03d1", - "vartriangleleft;": "\u22b2", - "vartriangleright;": "\u22b3", - "vcy;": "\u0432", - "vdash;": "\u22a2", - "vee;": "\u2228", - "veebar;": "\u22bb", - "veeeq;": "\u225a", - "vellip;": "\u22ee", - "verbar;": "|", - "vert;": "|", - "vfr;": "\U0001d533", - "vltri;": "\u22b2", - "vnsub;": "\u2282\u20d2", - "vnsup;": "\u2283\u20d2", - "vopf;": "\U0001d567", - "vprop;": "\u221d", - "vrtri;": "\u22b3", - "vscr;": "\U0001d4cb", - "vsubnE;": "\u2acb\ufe00", - "vsubne;": "\u228a\ufe00", - "vsupnE;": "\u2acc\ufe00", - "vsupne;": "\u228b\ufe00", - "vzigzag;": "\u299a", - "wcirc;": "\u0175", - "wedbar;": "\u2a5f", - "wedge;": "\u2227", - "wedgeq;": "\u2259", - "weierp;": "\u2118", - "wfr;": "\U0001d534", - "wopf;": "\U0001d568", - "wp;": "\u2118", - "wr;": "\u2240", - "wreath;": "\u2240", - "wscr;": "\U0001d4cc", - "xcap;": "\u22c2", - "xcirc;": "\u25ef", - "xcup;": "\u22c3", - "xdtri;": "\u25bd", - "xfr;": "\U0001d535", - "xhArr;": "\u27fa", - "xharr;": "\u27f7", - "xi;": "\u03be", - "xlArr;": "\u27f8", - "xlarr;": "\u27f5", - "xmap;": "\u27fc", - "xnis;": "\u22fb", - "xodot;": "\u2a00", - "xopf;": "\U0001d569", - "xoplus;": "\u2a01", - "xotime;": "\u2a02", - "xrArr;": "\u27f9", - "xrarr;": "\u27f6", - "xscr;": "\U0001d4cd", - "xsqcup;": "\u2a06", - "xuplus;": "\u2a04", - "xutri;": "\u25b3", - "xvee;": "\u22c1", - "xwedge;": "\u22c0", - "yacute": "\xfd", - "yacute;": "\xfd", - "yacy;": "\u044f", - "ycirc;": "\u0177", - "ycy;": "\u044b", - "yen": "\xa5", - "yen;": "\xa5", - "yfr;": "\U0001d536", - "yicy;": "\u0457", - "yopf;": "\U0001d56a", - "yscr;": "\U0001d4ce", - "yucy;": "\u044e", - "yuml": "\xff", - "yuml;": "\xff", - "zacute;": "\u017a", - "zcaron;": "\u017e", - "zcy;": "\u0437", - "zdot;": "\u017c", - "zeetrf;": "\u2128", - "zeta;": "\u03b6", - "zfr;": "\U0001d537", - "zhcy;": "\u0436", - "zigrarr;": "\u21dd", - "zopf;": "\U0001d56b", - "zscr;": "\U0001d4cf", - "zwj;": "\u200d", - "zwnj;": "\u200c", -} - -replacementCharacters = { - 0x0: "\uFFFD", - 0x0d: "\u000D", - 0x80: "\u20AC", - 0x81: "\u0081", - 0x81: "\u0081", - 0x82: "\u201A", - 0x83: "\u0192", - 0x84: "\u201E", - 0x85: "\u2026", - 0x86: "\u2020", - 0x87: "\u2021", - 0x88: "\u02C6", - 0x89: "\u2030", - 0x8A: "\u0160", - 0x8B: "\u2039", - 0x8C: "\u0152", - 0x8D: "\u008D", - 0x8E: "\u017D", - 0x8F: "\u008F", - 0x90: "\u0090", - 0x91: "\u2018", - 0x92: "\u2019", - 0x93: "\u201C", - 0x94: "\u201D", - 0x95: "\u2022", - 0x96: "\u2013", - 0x97: "\u2014", - 0x98: "\u02DC", - 0x99: "\u2122", - 0x9A: "\u0161", - 0x9B: "\u203A", - 0x9C: "\u0153", - 0x9D: "\u009D", - 0x9E: "\u017E", - 0x9F: "\u0178", -} - -encodings = { - '437': 'cp437', - '850': 'cp850', - '852': 'cp852', - '855': 'cp855', - '857': 'cp857', - '860': 'cp860', - '861': 'cp861', - '862': 'cp862', - '863': 'cp863', - '865': 'cp865', - '866': 'cp866', - '869': 'cp869', - 'ansix341968': 'ascii', - 'ansix341986': 'ascii', - 'arabic': 'iso8859-6', - 'ascii': 'ascii', - 'asmo708': 'iso8859-6', - 'big5': 'big5', - 'big5hkscs': 'big5hkscs', - 'chinese': 'gbk', - 'cp037': 'cp037', - 'cp1026': 'cp1026', - 'cp154': 'ptcp154', - 'cp367': 'ascii', - 'cp424': 'cp424', - 'cp437': 'cp437', - 'cp500': 'cp500', - 'cp775': 'cp775', - 'cp819': 'windows-1252', - 'cp850': 'cp850', - 'cp852': 'cp852', - 'cp855': 'cp855', - 'cp857': 'cp857', - 'cp860': 'cp860', - 'cp861': 'cp861', - 'cp862': 'cp862', - 'cp863': 'cp863', - 'cp864': 'cp864', - 'cp865': 'cp865', - 'cp866': 'cp866', - 'cp869': 'cp869', - 'cp936': 'gbk', - 'cpgr': 'cp869', - 'cpis': 'cp861', - 'csascii': 'ascii', - 'csbig5': 'big5', - 'cseuckr': 'cp949', - 'cseucpkdfmtjapanese': 'euc_jp', - 'csgb2312': 'gbk', - 'cshproman8': 'hp-roman8', - 'csibm037': 'cp037', - 'csibm1026': 'cp1026', - 'csibm424': 'cp424', - 'csibm500': 'cp500', - 'csibm855': 'cp855', - 'csibm857': 'cp857', - 'csibm860': 'cp860', - 'csibm861': 'cp861', - 'csibm863': 'cp863', - 'csibm864': 'cp864', - 'csibm865': 'cp865', - 'csibm866': 'cp866', - 'csibm869': 'cp869', - 'csiso2022jp': 'iso2022_jp', - 'csiso2022jp2': 'iso2022_jp_2', - 'csiso2022kr': 'iso2022_kr', - 'csiso58gb231280': 'gbk', - 'csisolatin1': 'windows-1252', - 'csisolatin2': 'iso8859-2', - 'csisolatin3': 'iso8859-3', - 'csisolatin4': 'iso8859-4', - 'csisolatin5': 'windows-1254', - 'csisolatin6': 'iso8859-10', - 'csisolatinarabic': 'iso8859-6', - 'csisolatincyrillic': 'iso8859-5', - 'csisolatingreek': 'iso8859-7', - 'csisolatinhebrew': 'iso8859-8', - 'cskoi8r': 'koi8-r', - 'csksc56011987': 'cp949', - 'cspc775baltic': 'cp775', - 'cspc850multilingual': 'cp850', - 'cspc862latinhebrew': 'cp862', - 'cspc8codepage437': 'cp437', - 'cspcp852': 'cp852', - 'csptcp154': 'ptcp154', - 'csshiftjis': 'shift_jis', - 'csunicode11utf7': 'utf-7', - 'cyrillic': 'iso8859-5', - 'cyrillicasian': 'ptcp154', - 'ebcdiccpbe': 'cp500', - 'ebcdiccpca': 'cp037', - 'ebcdiccpch': 'cp500', - 'ebcdiccphe': 'cp424', - 'ebcdiccpnl': 'cp037', - 'ebcdiccpus': 'cp037', - 'ebcdiccpwt': 'cp037', - 'ecma114': 'iso8859-6', - 'ecma118': 'iso8859-7', - 'elot928': 'iso8859-7', - 'eucjp': 'euc_jp', - 'euckr': 'cp949', - 'extendedunixcodepackedformatforjapanese': 'euc_jp', - 'gb18030': 'gb18030', - 'gb2312': 'gbk', - 'gb231280': 'gbk', - 'gbk': 'gbk', - 'greek': 'iso8859-7', - 'greek8': 'iso8859-7', - 'hebrew': 'iso8859-8', - 'hproman8': 'hp-roman8', - 'hzgb2312': 'hz', - 'ibm037': 'cp037', - 'ibm1026': 'cp1026', - 'ibm367': 'ascii', - 'ibm424': 'cp424', - 'ibm437': 'cp437', - 'ibm500': 'cp500', - 'ibm775': 'cp775', - 'ibm819': 'windows-1252', - 'ibm850': 'cp850', - 'ibm852': 'cp852', - 'ibm855': 'cp855', - 'ibm857': 'cp857', - 'ibm860': 'cp860', - 'ibm861': 'cp861', - 'ibm862': 'cp862', - 'ibm863': 'cp863', - 'ibm864': 'cp864', - 'ibm865': 'cp865', - 'ibm866': 'cp866', - 'ibm869': 'cp869', - 'iso2022jp': 'iso2022_jp', - 'iso2022jp2': 'iso2022_jp_2', - 'iso2022kr': 'iso2022_kr', - 'iso646irv1991': 'ascii', - 'iso646us': 'ascii', - 'iso88591': 'windows-1252', - 'iso885910': 'iso8859-10', - 'iso8859101992': 'iso8859-10', - 'iso885911987': 'windows-1252', - 'iso885913': 'iso8859-13', - 'iso885914': 'iso8859-14', - 'iso8859141998': 'iso8859-14', - 'iso885915': 'iso8859-15', - 'iso885916': 'iso8859-16', - 'iso8859162001': 'iso8859-16', - 'iso88592': 'iso8859-2', - 'iso885921987': 'iso8859-2', - 'iso88593': 'iso8859-3', - 'iso885931988': 'iso8859-3', - 'iso88594': 'iso8859-4', - 'iso885941988': 'iso8859-4', - 'iso88595': 'iso8859-5', - 'iso885951988': 'iso8859-5', - 'iso88596': 'iso8859-6', - 'iso885961987': 'iso8859-6', - 'iso88597': 'iso8859-7', - 'iso885971987': 'iso8859-7', - 'iso88598': 'iso8859-8', - 'iso885981988': 'iso8859-8', - 'iso88599': 'windows-1254', - 'iso885991989': 'windows-1254', - 'isoceltic': 'iso8859-14', - 'isoir100': 'windows-1252', - 'isoir101': 'iso8859-2', - 'isoir109': 'iso8859-3', - 'isoir110': 'iso8859-4', - 'isoir126': 'iso8859-7', - 'isoir127': 'iso8859-6', - 'isoir138': 'iso8859-8', - 'isoir144': 'iso8859-5', - 'isoir148': 'windows-1254', - 'isoir149': 'cp949', - 'isoir157': 'iso8859-10', - 'isoir199': 'iso8859-14', - 'isoir226': 'iso8859-16', - 'isoir58': 'gbk', - 'isoir6': 'ascii', - 'koi8r': 'koi8-r', - 'koi8u': 'koi8-u', - 'korean': 'cp949', - 'ksc5601': 'cp949', - 'ksc56011987': 'cp949', - 'ksc56011989': 'cp949', - 'l1': 'windows-1252', - 'l10': 'iso8859-16', - 'l2': 'iso8859-2', - 'l3': 'iso8859-3', - 'l4': 'iso8859-4', - 'l5': 'windows-1254', - 'l6': 'iso8859-10', - 'l8': 'iso8859-14', - 'latin1': 'windows-1252', - 'latin10': 'iso8859-16', - 'latin2': 'iso8859-2', - 'latin3': 'iso8859-3', - 'latin4': 'iso8859-4', - 'latin5': 'windows-1254', - 'latin6': 'iso8859-10', - 'latin8': 'iso8859-14', - 'latin9': 'iso8859-15', - 'ms936': 'gbk', - 'mskanji': 'shift_jis', - 'pt154': 'ptcp154', - 'ptcp154': 'ptcp154', - 'r8': 'hp-roman8', - 'roman8': 'hp-roman8', - 'shiftjis': 'shift_jis', - 'tis620': 'cp874', - 'unicode11utf7': 'utf-7', - 'us': 'ascii', - 'usascii': 'ascii', - 'utf16': 'utf-16', - 'utf16be': 'utf-16-be', - 'utf16le': 'utf-16-le', - 'utf8': 'utf-8', - 'windows1250': 'cp1250', - 'windows1251': 'cp1251', - 'windows1252': 'cp1252', - 'windows1253': 'cp1253', - 'windows1254': 'cp1254', - 'windows1255': 'cp1255', - 'windows1256': 'cp1256', - 'windows1257': 'cp1257', - 'windows1258': 'cp1258', - 'windows936': 'gbk', - 'x-x-big5': 'big5'} - -tokenTypes = { - "Doctype": 0, - "Characters": 1, - "SpaceCharacters": 2, - "StartTag": 3, - "EndTag": 4, - "EmptyTag": 5, - "Comment": 6, - "ParseError": 7 -} - -tagTokenTypes = frozenset([tokenTypes["StartTag"], tokenTypes["EndTag"], - tokenTypes["EmptyTag"]]) - - -prefixes = dict([(v, k) for k, v in namespaces.items()]) -prefixes["http://www.w3.org/1998/Math/MathML"] = "math" - - -class DataLossWarning(UserWarning): - pass - - -class ReparseException(Exception): - pass diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/__init__.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/_base.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/_base.py deleted file mode 100644 index c7dbaed..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/_base.py +++ /dev/null @@ -1,12 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - - -class Filter(object): - def __init__(self, source): - self.source = source - - def __iter__(self): - return iter(self.source) - - def __getattr__(self, name): - return getattr(self.source, name) diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py deleted file mode 100644 index fed6996..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py +++ /dev/null @@ -1,20 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from . import _base - -try: - from collections import OrderedDict -except ImportError: - from ordereddict import OrderedDict - - -class Filter(_base.Filter): - def __iter__(self): - for token in _base.Filter.__iter__(self): - if token["type"] in ("StartTag", "EmptyTag"): - attrs = OrderedDict() - for name, value in sorted(token["data"].items(), - key=lambda x: x[0]): - attrs[name] = value - token["data"] = attrs - yield token diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py deleted file mode 100644 index ca33b70..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py +++ /dev/null @@ -1,65 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from . import _base - - -class Filter(_base.Filter): - def __init__(self, source, encoding): - _base.Filter.__init__(self, source) - self.encoding = encoding - - def __iter__(self): - state = "pre_head" - meta_found = (self.encoding is None) - pending = [] - - for token in _base.Filter.__iter__(self): - type = token["type"] - if type == "StartTag": - if token["name"].lower() == "head": - state = "in_head" - - elif type == "EmptyTag": - if token["name"].lower() == "meta": - # replace charset with actual encoding - has_http_equiv_content_type = False - for (namespace, name), value in token["data"].items(): - if namespace is not None: - continue - elif name.lower() == 'charset': - token["data"][(namespace, name)] = self.encoding - meta_found = True - break - elif name == 'http-equiv' and value.lower() == 'content-type': - has_http_equiv_content_type = True - else: - if has_http_equiv_content_type and (None, "content") in token["data"]: - token["data"][(None, "content")] = 'text/html; charset=%s' % self.encoding - meta_found = True - - elif token["name"].lower() == "head" and not meta_found: - # insert meta into empty head - yield {"type": "StartTag", "name": "head", - "data": token["data"]} - yield {"type": "EmptyTag", "name": "meta", - "data": {(None, "charset"): self.encoding}} - yield {"type": "EndTag", "name": "head"} - meta_found = True - continue - - elif type == "EndTag": - if token["name"].lower() == "head" and pending: - # insert meta into head (if necessary) and flush pending queue - yield pending.pop(0) - if not meta_found: - yield {"type": "EmptyTag", "name": "meta", - "data": {(None, "charset"): self.encoding}} - while pending: - yield pending.pop(0) - meta_found = True - state = "post_head" - - if state == "in_head": - pending.append(token) - else: - yield token diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/lint.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/lint.py deleted file mode 100644 index 8884696..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/lint.py +++ /dev/null @@ -1,90 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from . import _base -from ..constants import cdataElements, rcdataElements, voidElements - -from ..constants import spaceCharacters -spaceCharacters = "".join(spaceCharacters) - - -class LintError(Exception): - pass - - -class Filter(_base.Filter): - def __iter__(self): - open_elements = [] - contentModelFlag = "PCDATA" - for token in _base.Filter.__iter__(self): - type = token["type"] - if type in ("StartTag", "EmptyTag"): - name = token["name"] - if contentModelFlag != "PCDATA": - raise LintError("StartTag not in PCDATA content model flag: %(tag)s" % {"tag": name}) - if not isinstance(name, str): - raise LintError("Tag name is not a string: %(tag)r" % {"tag": name}) - if not name: - raise LintError("Empty tag name") - if type == "StartTag" and name in voidElements: - raise LintError("Void element reported as StartTag token: %(tag)s" % {"tag": name}) - elif type == "EmptyTag" and name not in voidElements: - raise LintError("Non-void element reported as EmptyTag token: %(tag)s" % {"tag": token["name"]}) - if type == "StartTag": - open_elements.append(name) - for name, value in token["data"]: - if not isinstance(name, str): - raise LintError("Attribute name is not a string: %(name)r" % {"name": name}) - if not name: - raise LintError("Empty attribute name") - if not isinstance(value, str): - raise LintError("Attribute value is not a string: %(value)r" % {"value": value}) - if name in cdataElements: - contentModelFlag = "CDATA" - elif name in rcdataElements: - contentModelFlag = "RCDATA" - elif name == "plaintext": - contentModelFlag = "PLAINTEXT" - - elif type == "EndTag": - name = token["name"] - if not isinstance(name, str): - raise LintError("Tag name is not a string: %(tag)r" % {"tag": name}) - if not name: - raise LintError("Empty tag name") - if name in voidElements: - raise LintError("Void element reported as EndTag token: %(tag)s" % {"tag": name}) - start_name = open_elements.pop() - if start_name != name: - raise LintError("EndTag (%(end)s) does not match StartTag (%(start)s)" % {"end": name, "start": start_name}) - contentModelFlag = "PCDATA" - - elif type == "Comment": - if contentModelFlag != "PCDATA": - raise LintError("Comment not in PCDATA content model flag") - - elif type in ("Characters", "SpaceCharacters"): - data = token["data"] - if not isinstance(data, str): - raise LintError("Attribute name is not a string: %(name)r" % {"name": data}) - if not data: - raise LintError("%(type)s token with empty data" % {"type": type}) - if type == "SpaceCharacters": - data = data.strip(spaceCharacters) - if data: - raise LintError("Non-space character(s) found in SpaceCharacters token: %(token)r" % {"token": data}) - - elif type == "Doctype": - name = token["name"] - if contentModelFlag != "PCDATA": - raise LintError("Doctype not in PCDATA content model flag: %(name)s" % {"name": name}) - if not isinstance(name, str): - raise LintError("Tag name is not a string: %(tag)r" % {"tag": name}) - # XXX: what to do with token["data"] ? - - elif type in ("ParseError", "SerializeError"): - pass - - else: - raise LintError("Unknown token type: %(type)s" % {"type": type}) - - yield token diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/optionaltags.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/optionaltags.py deleted file mode 100644 index fefe0b3..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/optionaltags.py +++ /dev/null @@ -1,205 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from . import _base - - -class Filter(_base.Filter): - def slider(self): - previous1 = previous2 = None - for token in self.source: - if previous1 is not None: - yield previous2, previous1, token - previous2 = previous1 - previous1 = token - yield previous2, previous1, None - - def __iter__(self): - for previous, token, next in self.slider(): - type = token["type"] - if type == "StartTag": - if (token["data"] or - not self.is_optional_start(token["name"], previous, next)): - yield token - elif type == "EndTag": - if not self.is_optional_end(token["name"], next): - yield token - else: - yield token - - def is_optional_start(self, tagname, previous, next): - type = next and next["type"] or None - if tagname in 'html': - # An html element's start tag may be omitted if the first thing - # inside the html element is not a space character or a comment. - return type not in ("Comment", "SpaceCharacters") - elif tagname == 'head': - # A head element's start tag may be omitted if the first thing - # inside the head element is an element. - # XXX: we also omit the start tag if the head element is empty - if type in ("StartTag", "EmptyTag"): - return True - elif type == "EndTag": - return next["name"] == "head" - elif tagname == 'body': - # A body element's start tag may be omitted if the first thing - # inside the body element is not a space character or a comment, - # except if the first thing inside the body element is a script - # or style element and the node immediately preceding the body - # element is a head element whose end tag has been omitted. - if type in ("Comment", "SpaceCharacters"): - return False - elif type == "StartTag": - # XXX: we do not look at the preceding event, so we never omit - # the body element's start tag if it's followed by a script or - # a style element. - return next["name"] not in ('script', 'style') - else: - return True - elif tagname == 'colgroup': - # A colgroup element's start tag may be omitted if the first thing - # inside the colgroup element is a col element, and if the element - # is not immediately preceeded by another colgroup element whose - # end tag has been omitted. - if type in ("StartTag", "EmptyTag"): - # XXX: we do not look at the preceding event, so instead we never - # omit the colgroup element's end tag when it is immediately - # followed by another colgroup element. See is_optional_end. - return next["name"] == "col" - else: - return False - elif tagname == 'tbody': - # A tbody element's start tag may be omitted if the first thing - # inside the tbody element is a tr element, and if the element is - # not immediately preceeded by a tbody, thead, or tfoot element - # whose end tag has been omitted. - if type == "StartTag": - # omit the thead and tfoot elements' end tag when they are - # immediately followed by a tbody element. See is_optional_end. - if previous and previous['type'] == 'EndTag' and \ - previous['name'] in ('tbody', 'thead', 'tfoot'): - return False - return next["name"] == 'tr' - else: - return False - return False - - def is_optional_end(self, tagname, next): - type = next and next["type"] or None - if tagname in ('html', 'head', 'body'): - # An html element's end tag may be omitted if the html element - # is not immediately followed by a space character or a comment. - return type not in ("Comment", "SpaceCharacters") - elif tagname in ('li', 'optgroup', 'tr'): - # A li element's end tag may be omitted if the li element is - # immediately followed by another li element or if there is - # no more content in the parent element. - # An optgroup element's end tag may be omitted if the optgroup - # element is immediately followed by another optgroup element, - # or if there is no more content in the parent element. - # A tr element's end tag may be omitted if the tr element is - # immediately followed by another tr element, or if there is - # no more content in the parent element. - if type == "StartTag": - return next["name"] == tagname - else: - return type == "EndTag" or type is None - elif tagname in ('dt', 'dd'): - # A dt element's end tag may be omitted if the dt element is - # immediately followed by another dt element or a dd element. - # A dd element's end tag may be omitted if the dd element is - # immediately followed by another dd element or a dt element, - # or if there is no more content in the parent element. - if type == "StartTag": - return next["name"] in ('dt', 'dd') - elif tagname == 'dd': - return type == "EndTag" or type is None - else: - return False - elif tagname == 'p': - # A p element's end tag may be omitted if the p element is - # immediately followed by an address, article, aside, - # blockquote, datagrid, dialog, dir, div, dl, fieldset, - # footer, form, h1, h2, h3, h4, h5, h6, header, hr, menu, - # nav, ol, p, pre, section, table, or ul, element, or if - # there is no more content in the parent element. - if type in ("StartTag", "EmptyTag"): - return next["name"] in ('address', 'article', 'aside', - 'blockquote', 'datagrid', 'dialog', - 'dir', 'div', 'dl', 'fieldset', 'footer', - 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', - 'header', 'hr', 'menu', 'nav', 'ol', - 'p', 'pre', 'section', 'table', 'ul') - else: - return type == "EndTag" or type is None - elif tagname == 'option': - # An option element's end tag may be omitted if the option - # element is immediately followed by another option element, - # or if it is immediately followed by an optgroup - # element, or if there is no more content in the parent - # element. - if type == "StartTag": - return next["name"] in ('option', 'optgroup') - else: - return type == "EndTag" or type is None - elif tagname in ('rt', 'rp'): - # An rt element's end tag may be omitted if the rt element is - # immediately followed by an rt or rp element, or if there is - # no more content in the parent element. - # An rp element's end tag may be omitted if the rp element is - # immediately followed by an rt or rp element, or if there is - # no more content in the parent element. - if type == "StartTag": - return next["name"] in ('rt', 'rp') - else: - return type == "EndTag" or type is None - elif tagname == 'colgroup': - # A colgroup element's end tag may be omitted if the colgroup - # element is not immediately followed by a space character or - # a comment. - if type in ("Comment", "SpaceCharacters"): - return False - elif type == "StartTag": - # XXX: we also look for an immediately following colgroup - # element. See is_optional_start. - return next["name"] != 'colgroup' - else: - return True - elif tagname in ('thead', 'tbody'): - # A thead element's end tag may be omitted if the thead element - # is immediately followed by a tbody or tfoot element. - # A tbody element's end tag may be omitted if the tbody element - # is immediately followed by a tbody or tfoot element, or if - # there is no more content in the parent element. - # A tfoot element's end tag may be omitted if the tfoot element - # is immediately followed by a tbody element, or if there is no - # more content in the parent element. - # XXX: we never omit the end tag when the following element is - # a tbody. See is_optional_start. - if type == "StartTag": - return next["name"] in ['tbody', 'tfoot'] - elif tagname == 'tbody': - return type == "EndTag" or type is None - else: - return False - elif tagname == 'tfoot': - # A tfoot element's end tag may be omitted if the tfoot element - # is immediately followed by a tbody element, or if there is no - # more content in the parent element. - # XXX: we never omit the end tag when the following element is - # a tbody. See is_optional_start. - if type == "StartTag": - return next["name"] == 'tbody' - else: - return type == "EndTag" or type is None - elif tagname in ('td', 'th'): - # A td element's end tag may be omitted if the td element is - # immediately followed by a td or th element, or if there is - # no more content in the parent element. - # A th element's end tag may be omitted if the th element is - # immediately followed by a td or th element, or if there is - # no more content in the parent element. - if type == "StartTag": - return next["name"] in ('td', 'th') - else: - return type == "EndTag" or type is None - return False diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/sanitizer.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/sanitizer.py deleted file mode 100644 index b206b54..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/sanitizer.py +++ /dev/null @@ -1,12 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from . import _base -from ..sanitizer import HTMLSanitizerMixin - - -class Filter(_base.Filter, HTMLSanitizerMixin): - def __iter__(self): - for token in _base.Filter.__iter__(self): - token = self.sanitize_token(token) - if token: - yield token diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/whitespace.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/whitespace.py deleted file mode 100644 index dfc60ee..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/filters/whitespace.py +++ /dev/null @@ -1,38 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -import re - -from . import _base -from ..constants import rcdataElements, spaceCharacters -spaceCharacters = "".join(spaceCharacters) - -SPACES_REGEX = re.compile("[%s]+" % spaceCharacters) - - -class Filter(_base.Filter): - - spacePreserveElements = frozenset(["pre", "textarea"] + list(rcdataElements)) - - def __iter__(self): - preserve = 0 - for token in _base.Filter.__iter__(self): - type = token["type"] - if type == "StartTag" \ - and (preserve or token["name"] in self.spacePreserveElements): - preserve += 1 - - elif type == "EndTag" and preserve: - preserve -= 1 - - elif not preserve and type == "SpaceCharacters" and token["data"]: - # Test on token["data"] above to not introduce spaces where there were not - token["data"] = " " - - elif not preserve and type == "Characters": - token["data"] = collapse_spaces(token["data"]) - - yield token - - -def collapse_spaces(text): - return SPACES_REGEX.sub(' ', text) diff --git a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/html5parser.py b/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/html5parser.py deleted file mode 100644 index 40f3d09..0000000 --- a/virtualenv/lib/python3.5/site-packages/pip/_vendor/html5lib/html5parser.py +++ /dev/null @@ -1,2724 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals -from pip._vendor.six import with_metaclass - -import types - -from . import inputstream -from . import tokenizer - -from . import treebuilders -from .treebuilders._base import Marker - -from . import utils -from . import constants -from .constants import spaceCharacters, asciiUpper2Lower -from .constants import specialElements -from .constants import headingElements -from .constants import cdataElements, rcdataElements -from .constants import tokenTypes, ReparseException, namespaces -from .constants import htmlIntegrationPointElements, mathmlTextIntegrationPointElements -from .constants import adjustForeignAttributes as adjustForeignAttributesMap -from .constants import E - - -def parse(doc, treebuilder="etree", encoding=None, - namespaceHTMLElements=True): - """Parse a string or file-like object into a tree""" - tb = treebuilders.getTreeBuilder(treebuilder) - p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements) - return p.parse(doc, encoding=encoding) - - -def parseFragment(doc, container="div", treebuilder="etree", encoding=None, - namespaceHTMLElements=True): - tb = treebuilders.getTreeBuilder(treebuilder) - p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements) - return p.parseFragment(doc, container=container, encoding=encoding) - - -def method_decorator_metaclass(function): - class Decorated(type): - def __new__(meta, classname, bases, classDict): - for attributeName, attribute in classDict.items(): - if isinstance(attribute, types.FunctionType): - attribute = function(attribute) - - classDict[attributeName] = attribute - return type.__new__(meta, classname, bases, classDict) - return Decorated - - -class HTMLParser(object): - """HTML parser. Generates a tree structure from a stream of (possibly - malformed) HTML""" - - def __init__(self, tree=None, tokenizer=tokenizer.HTMLTokenizer, - strict=False, namespaceHTMLElements=True, debug=False): - """ - strict - raise an exception when a parse error is encountered - - tree - a treebuilder class controlling the type of tree that will be - returned. Built in treebuilders can be accessed through - html5lib.treebuilders.getTreeBuilder(treeType) - - tokenizer - a class that provides a stream of tokens to the treebuilder. - This may be replaced for e.g. a sanitizer which converts some tags to - text - """ - - # Raise an exception on the first error encountered - self.strict = strict - - if tree is None: - tree = treebuilders.getTreeBuilder("etree") - self.tree = tree(namespaceHTMLElements) - self.tokenizer_class = tokenizer - self.errors = [] - - self.phases = dict([(name, cls(self, self.tree)) for name, cls in - getPhases(debug).items()]) - - def _parse(self, stream, innerHTML=False, container="div", - encoding=None, parseMeta=True, useChardet=True, **kwargs): - - self.innerHTMLMode = innerHTML - self.container = container - self.tokenizer = self.tokenizer_class(stream, encoding=encoding, - parseMeta=parseMeta, - useChardet=useChardet, - parser=self, **kwargs) - self.reset() - - while True: - try: - self.mainLoop() - break - except ReparseException: - self.reset() - - def reset(self): - self.tree.reset() - self.firstStartTag = False - self.errors = [] - self.log = [] # only used with debug mode - # "quirks" / "limited quirks" / "no quirks" - self.compatMode = "no quirks" - - if self.innerHTMLMode: - self.innerHTML = self.container.lower() - - if self.innerHTML in cdataElements: - self.tokenizer.state = self.tokenizer.rcdataState - elif self.innerHTML in rcdataElements: - self.tokenizer.state = self.tokenizer.rawtextState - elif self.innerHTML == 'plaintext': - self.tokenizer.state = self.tokenizer.plaintextState - else: - # state already is data state - # self.tokenizer.state = self.tokenizer.dataState - pass - self.phase = self.phases["beforeHtml"] - self.phase.insertHtmlElement() - self.resetInsertionMode() - else: - self.innerHTML = False - self.phase = self.phases["initial"] - - self.lastPhase = None - - self.beforeRCDataPhase = None - - self.framesetOK = True - - @property - def documentEncoding(self): - """The name of the character encoding - that was used to decode the input stream, - or :obj:`None` if that is not determined yet. - - """ - if not hasattr(self, 'tokenizer'): - return None - return self.tokenizer.stream.charEncoding[0] - - def isHTMLIntegrationPoint(self, element): - if (element.name == "annotation-xml" and - element.namespace == namespaces["mathml"]): - return ("encoding" in element.attributes and - element.attributes["encoding"].translate( - asciiUpper2Lower) in - ("text/html", "application/xhtml+xml")) - else: - return (element.namespace, element.name) in htmlIntegrationPointElements - - def isMathMLTextIntegrationPoint(self, element): - return (element.namespace, element.name) in mathmlTextIntegrationPointElements - - def mainLoop(self): - CharactersToken = tokenTypes["Characters"] - SpaceCharactersToken = tokenTypes["SpaceCharacters"] - StartTagToken = tokenTypes["StartTag"] - EndTagToken = tokenTypes["EndTag"] - CommentToken = tokenTypes["Comment"] - DoctypeToken = tokenTypes["Doctype"] - ParseErrorToken = tokenTypes["ParseError"] - - for token in self.normalizedTokens(): - new_token = token - while new_token is not None: - currentNode = self.tree.openElements[-1] if self.tree.openElements else None - currentNodeNamespace = currentNode.namespace if currentNode else None - currentNodeName = currentNode.name if currentNode else None - - type = new_token["type"] - - if type == ParseErrorToken: - self.parseError(new_token["data"], new_token.get("datavars", {})) - new_token = None - else: - if (len(self.tree.openElements) == 0 or - currentNodeNamespace == self.tree.defaultNamespace or - (self.isMathMLTextIntegrationPoint(currentNode) and - ((type == StartTagToken and - token["name"] not in frozenset(["mglyph", "malignmark"])) or - type in (CharactersToken, SpaceCharactersToken))) or - (currentNodeNamespace == namespaces["mathml"] and - currentNodeName == "annotation-xml" and - token["name"] == "svg") or - (self.isHTMLIntegrationPoint(currentNode) and - type in (StartTagToken, CharactersToken, SpaceCharactersToken))): - phase = self.phase - else: - phase = self.phases["inForeignContent"] - - if type == CharactersToken: - new_token = phase.processCharacters(new_token) - elif type == SpaceCharactersToken: - new_token = phase.processSpaceCharacters(new_token) - elif type == StartTagToken: - new_token = phase.processStartTag(new_token) - elif type == EndTagToken: - new_token = phase.processEndTag(new_token) - elif type == CommentToken: - new_token = phase.processComment(new_token) - elif type == DoctypeToken: - new_token = phase.processDoctype(new_token) - - if (type == StartTagToken and token["selfClosing"] - and not token["selfClosingAcknowledged"]): - self.parseError("non-void-element-with-trailing-solidus", - {"name": token["name"]}) - - # When the loop finishes it's EOF - reprocess = True - phases = [] - while reprocess: - phases.append(self.phase) - reprocess = self.phase.processEOF() - if reprocess: - assert self.phase not in phases - - def normalizedTokens(self): - for token in self.tokenizer: - yield self.normalizeToken(token) - - def parse(self, stream, encoding=None, parseMeta=True, useChardet=True): - """Parse a HTML document into a well-formed tree - - stream - a filelike object or string containing the HTML to be parsed - - The optional encoding parameter must be a string that indicates - the encoding. If specified, that encoding will be used, - regardless of any BOM or later declaration (such as in a meta - element) - """ - self._parse(stream, innerHTML=False, encoding=encoding, - parseMeta=parseMeta, useChardet=useChardet) - return self.tree.getDocument() - - def parseFragment(self, stream, container="div", encoding=None, - parseMeta=False, useChardet=True): - """Parse a HTML fragment into a well-formed tree fragment - - container - name of the element we're setting the innerHTML property - if set to None, default to 'div' - - stream - a filelike object or string containing the HTML to be parsed - - The optional encoding parameter must be a string that indicates - the encoding. If specified, that encoding will be used, - regardless of any BOM or later declaration (such as in a meta - element) - """ - self._parse(stream, True, container=container, encoding=encoding) - return self.tree.getFragment() - - def parseError(self, errorcode="XXX-undefined-error", datavars={}): - # XXX The idea is to make errorcode mandatory. - self.errors.append((self.tokenizer.stream.position(), errorcode, datavars)) - if self.strict: - raise ParseError(E[errorcode] % datavars) - - def normalizeToken(self, token): - """ HTML5 specific normalizations to the token stream """ - - if token["type"] == tokenTypes["StartTag"]: - token["data"] = dict(token["data"][::-1]) - - return token - - def adjustMathMLAttributes(self, token): - replacements = {"definitionurl": "definitionURL"} - for k, v in replacements.items(): - if k in token["data"]: - token["data"][v] = token["data"][k] - del token["data"][k] - - def adjustSVGAttributes(self, token): - replacements = { - "attributename": "attributeName", - "attributetype": "attributeType", - "basefrequency": "baseFrequency", - "baseprofile": "baseProfile", - "calcmode": "calcMode", - "clippathunits": "clipPathUnits", - "contentscripttype": "contentScriptType", - "contentstyletype": "contentStyleType", - "diffuseconstant": "diffuseConstant", - "edgemode": "edgeMode", - "externalresourcesrequired": "externalResourcesRequired", - "filterres": "filterRes", - "filterunits": "filterUnits", - "glyphref": "glyphRef", - "gradienttransform": "gradientTransform", - "gradientunits": "gradientUnits", - "kernelmatrix": "kernelMatrix", - "kernelunitlength": "kernelUnitLength", - "keypoints": "keyPoints", - "keysplines": "keySplines", - "keytimes": "keyTimes", - "lengthadjust": "lengthAdjust", - "limitingconeangle": "limitingConeAngle", - "markerheight": "markerHeight", - "markerunits": "markerUnits", - "markerwidth": "markerWidth", - "maskcontentunits": "maskContentUnits", - "maskunits": "maskUnits", - "numoctaves": "numOctaves", - "pathlength": "pathLength", - "patterncontentunits": "patternContentUnits", - "patterntransform": "patternTransform", - "patternunits": "patternUnits", - "pointsatx": "pointsAtX", - "pointsaty": "pointsAtY", - "pointsatz": "pointsAtZ", - "preservealpha": "preserveAlpha", - "preserveaspectratio": "preserveAspectRatio", - "primitiveunits": "primitiveUnits", - "refx": "refX", - "refy": "refY", - "repeatcount": "repeatCount", - "repeatdur": "repeatDur", - "requiredextensions": "requiredExtensions", - "requiredfeatures": "requiredFeatures", - "specularconstant": "specularConstant", - "specularexponent": "specularExponent", - "spreadmethod": "spreadMethod", - "startoffset": "startOffset", - "stddeviation": "stdDeviation", - "stitchtiles": "stitchTiles", - "surfacescale": "surfaceScale", - "systemlanguage": "systemLanguage", - "tablevalues": "tableValues", - "targetx": "targetX", - "targety": "targetY", - "textlength": "textLength", - "viewbox": "viewBox", - "viewtarget": "viewTarget", - "xchannelselector": "xChannelSelector", - "ychannelselector": "yChannelSelector", - "zoomandpan": "zoomAndPan" - } - for originalName in list(token["data"].keys()): - if originalName in replacements: - svgName = replacements[originalName] - token["data"][svgName] = token["data"][originalName] - del token["data"][originalName] - - def adjustForeignAttributes(self, token): - replacements = adjustForeignAttributesMap - - for originalName in token["data"].keys(): - if originalName in replacements: - foreignName = replacements[originalName] - token["data"][foreignName] = token["data"][originalName] - del token["data"][originalName] - - def reparseTokenNormal(self, token): - self.parser.phase() - - def resetInsertionMode(self): - # The name of this method is mostly historical. (It's also used in the - # specification.) - last = False - newModes = { - "select": "inSelect", - "td": "inCell", - "th": "inCell", - "tr": "inRow", - "tbody": "inTableBody", - "thead": "inTableBody", - "tfoot": "inTableBody", - "caption": "inCaption", - "colgroup": "inColumnGroup", - "table": "inTable", - "head": "inBody", - "body": "inBody", - "frameset": "inFrameset", - "html": "beforeHead" - } - for node in self.tree.openElements[::-1]: - nodeName = node.name - new_phase = None - if node == self.tree.openElements[0]: - assert self.innerHTML - last = True - nodeName = self.innerHTML - # Check for conditions that should only happen in the innerHTML - # case - if nodeName in ("select", "colgroup", "head", "html"): - assert self.innerHTML - - if not last and node.namespace != self.tree.defaultNamespace: - continue - - if nodeName in newModes: - new_phase = self.phases[newModes[nodeName]] - break - elif last: - new_phase = self.phases["inBody"] - break - - self.phase = new_phase - - def parseRCDataRawtext(self, token, contentType): - """Generic RCDATA/RAWTEXT Parsing algorithm - contentType - RCDATA or RAWTEXT - """ - assert contentType in ("RAWTEXT", "RCDATA") - - self.tree.insertElement(token) - - if contentType == "RAWTEXT": - self.tokenizer.state = self.tokenizer.rawtextState - else: - self.tokenizer.state = self.tokenizer.rcdataState - - self.originalPhase = self.phase - - self.phase = self.phases["text"] - - -def getPhases(debug): - def log(function): - """Logger that records which phase processes each token""" - type_names = dict((value, key) for key, value in - constants.tokenTypes.items()) - - def wrapped(self, *args, **kwargs): - if function.__name__.startswith("process") and len(args) > 0: - token = args[0] - try: - info = {"type": type_names[token['type']]} - except: - raise - if token['type'] in constants.tagTokenTypes: - info["name"] = token['name'] - - self.parser.log.append((self.parser.tokenizer.state.__name__, - self.parser.phase.__class__.__name__, - self.__class__.__name__, - function.__name__, - info)) - return function(self, *args, **kwargs) - else: - return function(self, *args, **kwargs) - return wrapped - - def getMetaclass(use_metaclass, metaclass_func): - if use_metaclass: - return method_decorator_metaclass(metaclass_func) - else: - return type - - class Phase(with_metaclass(getMetaclass(debug, log))): - """Base class for helper object that implements each phase of processing - """ - - def __init__(self, parser, tree): - self.parser = parser - self.tree = tree - - def processEOF(self): - raise NotImplementedError - - def processComment(self, token): - # For most phases the following is correct. Where it's not it will be - # overridden. - self.tree.insertComment(token, self.tree.openElements[-1]) - - def processDoctype(self, token): - self.parser.parseError("unexpected-doctype") - - def processCharacters(self, token): - self.tree.insertText(token["data"]) - - def processSpaceCharacters(self, token): - self.tree.insertText(token["data"]) - - def processStartTag(self, token): - return self.startTagHandler[token["name"]](token) - - def startTagHtml(self, token): - if not self.parser.firstStartTag and token["name"] == "html": - self.parser.parseError("non-html-root") - # XXX Need a check here to see if the first start tag token emitted is - # this token... If it's not, invoke self.parser.parseError(). - for attr, value in token["data"].items(): - if attr not in self.tree.openElements[0].attributes: - self.tree.openElements[0].attributes[attr] = value - self.parser.firstStartTag = False - - def processEndTag(self, token): - return self.endTagHandler[token["name"]](token) - - class InitialPhase(Phase): - def processSpaceCharacters(self, token): - pass - - def processComment(self, token): - self.tree.insertComment(token, self.tree.document) - - def processDoctype(self, token): - name = token["name"] - publicId = token["publicId"] - systemId = token["systemId"] - correct = token["correct"] - - if (name != "html" or publicId is not None or - systemId is not None and systemId != "about:legacy-compat"): - self.parser.parseError("unknown-doctype") - - if publicId is None: - publicId = "" - - self.tree.insertDoctype(token) - - if publicId != "": - publicId = publicId.translate(asciiUpper2Lower) - - if (not correct or token["name"] != "html" - or publicId.startswith( - ("+//silmaril//dtd html pro v0r11 19970101//", - "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", - "-//as//dtd html 3.0 aswedit + extensions//", - "-//ietf//dtd html 2.0 level 1//", - "-//ietf//dtd html 2.0 level 2//", - "-//ietf//dtd html 2.0 strict level 1//", - "-//ietf//dtd html 2.0 strict level 2//", - "-//ietf//dtd html 2.0 strict//", - "-//ietf//dtd html 2.0//", - "-//ietf//dtd html 2.1e//", - "-//ietf//dtd html 3.0//", - "-//ietf//dtd html 3.2 final//", - "-//ietf//dtd html 3.2//", - "-//ietf//dtd html 3//", - "-//ietf//dtd html level 0//", - "-//ietf//dtd html level 1//", - "-//ietf//dtd html level 2//", - "-//ietf//dtd html level 3//", - "-//ietf//dtd html strict level 0//", - "-//ietf//dtd html strict level 1//", - "-//ietf//dtd html strict level 2//", - "-//ietf//dtd html strict level 3//", - "-//ietf//dtd html strict//", - "-//ietf//dtd html//", - "-//metrius//dtd metrius presentational//", - "-//microsoft//dtd internet explorer 2.0 html strict//", - "-//microsoft//dtd internet explorer 2.0 html//", - "-//microsoft//dtd internet explorer 2.0 tables//", - "-//microsoft//dtd internet explorer 3.0 html strict//", - "-//microsoft//dtd internet explorer 3.0 html//", - "-//microsoft//dtd internet explorer 3.0 tables//", - "-//netscape comm. corp.//dtd html//", - "-//netscape comm. corp.//dtd strict html//", - "-//o'reilly and associates//dtd html 2.0//", - "-//o'reilly and associates//dtd html extended 1.0//", - "-//o'reilly and associates//dtd html extended relaxed 1.0//", - "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", - "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", - "-//spyglass//dtd html 2.0 extended//", - "-//sq//dtd html 2.0 hotmetal + extensions//", - "-//sun microsystems corp.//dtd hotjava html//", - "-//sun microsystems corp.//dtd hotjava strict html//", - "-//w3c//dtd html 3 1995-03-24//", - "-//w3c//dtd html 3.2 draft//", - "-//w3c//dtd html 3.2 final//", - "-//w3c//dtd html 3.2//", - "-//w3c//dtd html 3.2s draft//", - "-//w3c//dtd html 4.0 frameset//", - "-//w3c//dtd html 4.0 transitional//", - "-//w3c//dtd html experimental 19960712//", - "-//w3c//dtd html experimental 970421//", - "-//w3c//dtd w3 html//", - "-//w3o//dtd w3 html 3.0//", - "-//webtechs//dtd mozilla html 2.0//", - "-//webtechs//dtd mozilla html//")) - or publicId in - ("-//w3o//dtd w3 html strict 3.0//en//", - "-/w3c/dtd html 4.0 transitional/en", - "html") - or publicId.startswith( - ("-//w3c//dtd html 4.01 frameset//", - "-//w3c//dtd html 4.01 transitional//")) and - systemId is None - or systemId and systemId.lower() == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"): - self.parser.compatMode = "quirks" - elif (publicId.startswith( - ("-//w3c//dtd xhtml 1.0 frameset//", - "-//w3c//dtd xhtml 1.0 transitional//")) - or publicId.startswith( - ("-//w3c//dtd html 4.01 frameset//", - "-//w3c//dtd html 4.01 transitional//")) and - systemId is not None): - self.parser.compatMode = "limited quirks" - - self.parser.phase = self.parser.phases["beforeHtml"] - - def anythingElse(self): - self.parser.compatMode = "quirks" - self.parser.phase = self.parser.phases["beforeHtml"] - - def processCharacters(self, token): - self.parser.parseError("expected-doctype-but-got-chars") - self.anythingElse() - return token - - def processStartTag(self, token): - self.parser.parseError("expected-doctype-but-got-start-tag", - {"name": token["name"]}) - self.anythingElse() - return token - - def processEndTag(self, token): - self.parser.parseError("expected-doctype-but-got-end-tag", - {"name": token["name"]}) - self.anythingElse() - return token - - def processEOF(self): - self.parser.parseError("expected-doctype-but-got-eof") - self.anythingElse() - return True - - class BeforeHtmlPhase(Phase): - # helper methods - def insertHtmlElement(self): - self.tree.insertRoot(impliedTagToken("html", "StartTag")) - self.parser.phase = self.parser.phases["beforeHead"] - - # other - def processEOF(self): - self.insertHtmlElement() - return True - - def processComment(self, token): - self.tree.insertComment(token, self.tree.document) - - def processSpaceCharacters(self, token): - pass - - def processCharacters(self, token): - self.insertHtmlElement() - return token - - def processStartTag(self, token): - if token["name"] == "html": - self.parser.firstStartTag = True - self.insertHtmlElement() - return token - - def processEndTag(self, token): - if token["name"] not in ("head", "body", "html", "br"): - self.parser.parseError("unexpected-end-tag-before-html", - {"name": token["name"]}) - else: - self.insertHtmlElement() - return token - - class BeforeHeadPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("head", self.startTagHead) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = utils.MethodDispatcher([ - (("head", "body", "html", "br"), self.endTagImplyHead) - ]) - self.endTagHandler.default = self.endTagOther - - def processEOF(self): - self.startTagHead(impliedTagToken("head", "StartTag")) - return True - - def processSpaceCharacters(self, token): - pass - - def processCharacters(self, token): - self.startTagHead(impliedTagToken("head", "StartTag")) - return token - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagHead(self, token): - self.tree.insertElement(token) - self.tree.headPointer = self.tree.openElements[-1] - self.parser.phase = self.parser.phases["inHead"] - - def startTagOther(self, token): - self.startTagHead(impliedTagToken("head", "StartTag")) - return token - - def endTagImplyHead(self, token): - self.startTagHead(impliedTagToken("head", "StartTag")) - return token - - def endTagOther(self, token): - self.parser.parseError("end-tag-after-implied-root", - {"name": token["name"]}) - - class InHeadPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("title", self.startTagTitle), - (("noscript", "noframes", "style"), self.startTagNoScriptNoFramesStyle), - ("script", self.startTagScript), - (("base", "basefont", "bgsound", "command", "link"), - self.startTagBaseLinkCommand), - ("meta", self.startTagMeta), - ("head", self.startTagHead) - ]) - self.startTagHandler.default = self.startTagOther - - self. endTagHandler = utils.MethodDispatcher([ - ("head", self.endTagHead), - (("br", "html", "body"), self.endTagHtmlBodyBr) - ]) - self.endTagHandler.default = self.endTagOther - - # the real thing - def processEOF(self): - self.anythingElse() - return True - - def processCharacters(self, token): - self.anythingElse() - return token - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagHead(self, token): - self.parser.parseError("two-heads-are-not-better-than-one") - - def startTagBaseLinkCommand(self, token): - self.tree.insertElement(token) - self.tree.openElements.pop() - token["selfClosingAcknowledged"] = True - - def startTagMeta(self, token): - self.tree.insertElement(token) - self.tree.openElements.pop() - token["selfClosingAcknowledged"] = True - - attributes = token["data"] - if self.parser.tokenizer.stream.charEncoding[1] == "tentative": - if "charset" in attributes: - self.parser.tokenizer.stream.changeEncoding(attributes["charset"]) - elif ("content" in attributes and - "http-equiv" in attributes and - attributes["http-equiv"].lower() == "content-type"): - # Encoding it as UTF-8 here is a hack, as really we should pass - # the abstract Unicode string, and just use the - # ContentAttrParser on that, but using UTF-8 allows all chars - # to be encoded and as a ASCII-superset works. - data = inputstream.EncodingBytes(attributes["content"].encode("utf-8")) - parser = inputstream.ContentAttrParser(data) - codec = parser.parse() - self.parser.tokenizer.stream.changeEncoding(codec) - - def startTagTitle(self, token): - self.parser.parseRCDataRawtext(token, "RCDATA") - - def startTagNoScriptNoFramesStyle(self, token): - # Need to decide whether to implement the scripting-disabled case - self.parser.parseRCDataRawtext(token, "RAWTEXT") - - def startTagScript(self, token): - self.tree.insertElement(token) - self.parser.tokenizer.state = self.parser.tokenizer.scriptDataState - self.parser.originalPhase = self.parser.phase - self.parser.phase = self.parser.phases["text"] - - def startTagOther(self, token): - self.anythingElse() - return token - - def endTagHead(self, token): - node = self.parser.tree.openElements.pop() - assert node.name == "head", "Expected head got %s" % node.name - self.parser.phase = self.parser.phases["afterHead"] - - def endTagHtmlBodyBr(self, token): - self.anythingElse() - return token - - def endTagOther(self, token): - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - - def anythingElse(self): - self.endTagHead(impliedTagToken("head")) - - # XXX If we implement a parser for which scripting is disabled we need to - # implement this phase. - # - # class InHeadNoScriptPhase(Phase): - class AfterHeadPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("body", self.startTagBody), - ("frameset", self.startTagFrameset), - (("base", "basefont", "bgsound", "link", "meta", "noframes", "script", - "style", "title"), - self.startTagFromHead), - ("head", self.startTagHead) - ]) - self.startTagHandler.default = self.startTagOther - self.endTagHandler = utils.MethodDispatcher([(("body", "html", "br"), - self.endTagHtmlBodyBr)]) - self.endTagHandler.default = self.endTagOther - - def processEOF(self): - self.anythingElse() - return True - - def processCharacters(self, token): - self.anythingElse() - return token - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagBody(self, token): - self.parser.framesetOK = False - self.tree.insertElement(token) - self.parser.phase = self.parser.phases["inBody"] - - def startTagFrameset(self, token): - self.tree.insertElement(token) - self.parser.phase = self.parser.phases["inFrameset"] - - def startTagFromHead(self, token): - self.parser.parseError("unexpected-start-tag-out-of-my-head", - {"name": token["name"]}) - self.tree.openElements.append(self.tree.headPointer) - self.parser.phases["inHead"].processStartTag(token) - for node in self.tree.openElements[::-1]: - if node.name == "head": - self.tree.openElements.remove(node) - break - - def startTagHead(self, token): - self.parser.parseError("unexpected-start-tag", {"name": token["name"]}) - - def startTagOther(self, token): - self.anythingElse() - return token - - def endTagHtmlBodyBr(self, token): - self.anythingElse() - return token - - def endTagOther(self, token): - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - - def anythingElse(self): - self.tree.insertElement(impliedTagToken("body", "StartTag")) - self.parser.phase = self.parser.phases["inBody"] - self.parser.framesetOK = True - - class InBodyPhase(Phase): - # http://www.whatwg.org/specs/web-apps/current-work/#parsing-main-inbody - # the really-really-really-very crazy mode - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - # Keep a ref to this for special handling of whitespace in

-            self.processSpaceCharactersNonPre = self.processSpaceCharacters
-
-            self.startTagHandler = utils.MethodDispatcher([
-                ("html", self.startTagHtml),
-                (("base", "basefont", "bgsound", "command", "link", "meta",
-                  "script", "style", "title"),
-                 self.startTagProcessInHead),
-                ("body", self.startTagBody),
-                ("frameset", self.startTagFrameset),
-                (("address", "article", "aside", "blockquote", "center", "details",
-                  "details", "dir", "div", "dl", "fieldset", "figcaption", "figure",
-                  "footer", "header", "hgroup", "main", "menu", "nav", "ol", "p",
-                  "section", "summary", "ul"),
-                 self.startTagCloseP),
-                (headingElements, self.startTagHeading),
-                (("pre", "listing"), self.startTagPreListing),
-                ("form", self.startTagForm),
-                (("li", "dd", "dt"), self.startTagListItem),
-                ("plaintext", self.startTagPlaintext),
-                ("a", self.startTagA),
-                (("b", "big", "code", "em", "font", "i", "s", "small", "strike",
-                  "strong", "tt", "u"), self.startTagFormatting),
-                ("nobr", self.startTagNobr),
-                ("button", self.startTagButton),
-                (("applet", "marquee", "object"), self.startTagAppletMarqueeObject),
-                ("xmp", self.startTagXmp),
-                ("table", self.startTagTable),
-                (("area", "br", "embed", "img", "keygen", "wbr"),
-                 self.startTagVoidFormatting),
-                (("param", "source", "track"), self.startTagParamSource),
-                ("input", self.startTagInput),
-                ("hr", self.startTagHr),
-                ("image", self.startTagImage),
-                ("isindex", self.startTagIsIndex),
-                ("textarea", self.startTagTextarea),
-                ("iframe", self.startTagIFrame),
-                (("noembed", "noframes", "noscript"), self.startTagRawtext),
-                ("select", self.startTagSelect),
-                (("rp", "rt"), self.startTagRpRt),
-                (("option", "optgroup"), self.startTagOpt),
-                (("math"), self.startTagMath),
-                (("svg"), self.startTagSvg),
-                (("caption", "col", "colgroup", "frame", "head",
-                  "tbody", "td", "tfoot", "th", "thead",
-                  "tr"), self.startTagMisplaced)
-            ])
-            self.startTagHandler.default = self.startTagOther
-
-            self.endTagHandler = utils.MethodDispatcher([
-                ("body", self.endTagBody),
-                ("html", self.endTagHtml),
-                (("address", "article", "aside", "blockquote", "button", "center",
-                  "details", "dialog", "dir", "div", "dl", "fieldset", "figcaption", "figure",
-                  "footer", "header", "hgroup", "listing", "main", "menu", "nav", "ol", "pre",
-                  "section", "summary", "ul"), self.endTagBlock),
-                ("form", self.endTagForm),
-                ("p", self.endTagP),
-                (("dd", "dt", "li"), self.endTagListItem),
-                (headingElements, self.endTagHeading),
-                (("a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small",
-                  "strike", "strong", "tt", "u"), self.endTagFormatting),
-                (("applet", "marquee", "object"), self.endTagAppletMarqueeObject),
-                ("br", self.endTagBr),
-            ])
-            self.endTagHandler.default = self.endTagOther
-
-        def isMatchingFormattingElement(self, node1, node2):
-            if node1.name != node2.name or node1.namespace != node2.namespace:
-                return False
-            elif len(node1.attributes) != len(node2.attributes):
-                return False
-            else:
-                attributes1 = sorted(node1.attributes.items())
-                attributes2 = sorted(node2.attributes.items())
-                for attr1, attr2 in zip(attributes1, attributes2):
-                    if attr1 != attr2:
-                        return False
-            return True
-
-        # helper
-        def addFormattingElement(self, token):
-            self.tree.insertElement(token)
-            element = self.tree.openElements[-1]
-
-            matchingElements = []
-            for node in self.tree.activeFormattingElements[::-1]:
-                if node is Marker:
-                    break
-                elif self.isMatchingFormattingElement(node, element):
-                    matchingElements.append(node)
-
-            assert len(matchingElements) <= 3
-            if len(matchingElements) == 3:
-                self.tree.activeFormattingElements.remove(matchingElements[-1])
-            self.tree.activeFormattingElements.append(element)
-
-        # the real deal
-        def processEOF(self):
-            allowed_elements = frozenset(("dd", "dt", "li", "p", "tbody", "td",
-                                          "tfoot", "th", "thead", "tr", "body",
-                                          "html"))
-            for node in self.tree.openElements[::-1]:
-                if node.name not in allowed_elements:
-                    self.parser.parseError("expected-closing-tag-but-got-eof")
-                    break
-            # Stop parsing
-
-        def processSpaceCharactersDropNewline(self, token):
-            # Sometimes (start of 
, , and